App Conversions Installation for Flutter

Send in-app conversion events server-side from your Flutter app: collect device info with device_info_plus and package_info_plus, then POST events to SignalSight App Conversions — full Dart example included.

In This Page

Introduction

App Conversions lets your Flutter app send conversion events — purchases, registrations, and any custom action — directly to SignalSight. One Dart codebase covers both iOS and Android: the example below detects the platform at runtime, collects the device parameters the API expects, and sends the event server-side.

Note

This example shows how to gather most of the parameters you're interested in. However, some specific ones like install_referrer, installer_package, url_schemes, and windows_attribution_id might not be directly accessible via Flutter packages and could require custom native code integration.

Add Dependencies

First, make sure to add dependencies in your pubspec.yaml for device_info_plus, package_info_plus, flutter_screenutil (for screen size and density), and any other package you find necessary based on the parameters you wish to collect:

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.3
  device_info_plus: ^5.0.0
  package_info_plus: ^1.0.6
  flutter_screenutil: ^5.0.0+2

After adding these dependencies, run flutter pub get to install them.

Full Example

Here's the full example code, including the function to gather device information and the function to send the event. This example assumes you have a basic understanding of Flutter and Dart:

main.dart
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:device_info_plus/device_info_plus.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Device Info Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () => sendEvent(context),
            child: Text('Send Device Info'),
          ),
        ),
      ),
    );
  }
}

Future<void> sendEvent(BuildContext context) async {
  final deviceInfo = await getDeviceInfo(context);
  final url = Uri.parse('https://cpi.ssevt.com/push');
  final headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_BEARER_TOKEN',
  };

  // Merge deviceInfo with p parameters
  final body = jsonEncode({
    "eid": "d290f1ee-6c54-4b01-90e6-d701748f0851",
    "et": "PurchaseTest",
    "ua": "App",
    "p": {
      // Merge deviceInfo with p parameters
      ...deviceInfo,

      // Required
      "att": 1,
      "ate": 1,
      "event_time": 1644778428,
      "currency": "USD",
      "value": 142.54,
      "app_id": "com.example.myapp",

      // Required
      "contents": [
        {"id": "ABC123", "quantity": 1},
        {"id": "DEF456", "quantity": 1}
      ],

      // Required
      "content_type": "product"
    },

    // Advanced Matching Parameters
    "amp": {
      // Required
      "anon_id": "123456abc",
      "madid": "7497f910905fb413fe27a64a557778063",

      // Optional
      "ph": "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf",
      "em": "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149",
      "ge": "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111",
      "db": "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf",
      "ct": "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5",
      "zp": "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233",
      "cn": "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621"
    }
  });

  try {
    final response = await http.post(url, headers: headers, body: body);
    if (response.statusCode == 200) {
      print('Event sent successfully');
    } else {
      print('Failed to send event. StatusCode: ${response.statusCode}');
    }
  } catch (e) {
    print('Error sending event: $e');
  }
}

Future<Map<String, dynamic>> getDeviceInfo(BuildContext context) async {
  DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
  PackageInfo packageInfo = await PackageInfo.fromPlatform();

  ScreenUtil.init(BoxConstraints(
      maxWidth: MediaQuery.of(context).size.width,
      maxHeight: MediaQuery.of(context).size.height),
      designSize: Size(360, 690), context: context, minTextAdapt: true);

  String platform = Platform.operatingSystem;
  String deviceModel;
  String osVersion;

  if (Platform.isAndroid) {
    AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo;
    deviceModel = androidInfo.model!;
    osVersion = androidInfo.version.release!;
  } else if (Platform.isIOS) {
    IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo;
    deviceModel = iosInfo.utsname.machine!;
    osVersion = iosInfo.systemVersion!;
  }

  return {
    // Required
    "platform": platform,
    "os_version": osVersion,
    "device_model": deviceModel,

    // Optional
    "short_version": packageInfo.version,
    "long_version": packageInfo.buildNumber,
    "locale": Platform.localeName,
    "timezone": DateTime.now().timeZoneName,
    "screen_width": ScreenUtil().screenWidth.toString(),
    "screen_height": ScreenUtil().screenHeight.toString(),
    "screen_density": ScreenUtil().pixelRatio.toString(),
    // Add other optional properties here
    // ...
  };
}

void main() {
  runApp(MyApp());
}

This code demonstrates how to:

  • Initialize ScreenUtil for screen size and density calculations within a widget context.
  • Collect various device and app details using device_info_plus and package_info_plus.
  • Prepare and send a POST request with the collected device information.

Permissions & Configuration

Make sure you have proper permissions and configurations set up in your AndroidManifest.xml and Info.plist for accessing certain device information, especially if you're targeting Android API level 29+ or using iOS. Some information, like install_referrer or installer_package, requires additional setup or native code integration which is not covered in this example.

Keep your token out of the codebase

Replace YOUR_BEARER_TOKEN with the token generated in your SignalSight panel. Prefer loading it from remote config or your backend rather than hardcoding it in the app bundle.

Advanced Matching Parameters

Advanced Matching Parameters — * required fields
User informationParameterFormatExample
Anonymous ID*anon_idUnique ID — do not hash123456abc
Advertising ID (IDFA / GAID)*madidUnique ID — do not hash7497f910905fb413fe27a64a557778063
E-mailemLowercase + SHA256 hash[email protected]
First namefnLowercase + SHA256 hashjohn
Last namelnLowercase + SHA256 hashdoe
TelephonephOnly numbers, incl. country and area code + SHA256 hash12125357525
GendergeA single lowercase letter, f or m + SHA256 hashf
BirthdaydbOnly numbers: year, month, day + SHA256 hash19910526 for May 26, 1991
CityctLowercase, no spaces + SHA256 hashnewyork
Postal / zip codezpOnly numbers + SHA256 hash34000
CountrycnTwo-letter country code, lowercase + SHA256 hashtr

PII Hashing

Every personal identifier except anon_id and madid must be normalized and SHA256-hashed before sending. Use our PII Hashing guide and live tool to verify your hashes.