Watch this video for a detailed view of the integration process. We recommend that you use both the video and the written guide below.
Before You Begin: SDK Prerequisites
The Singular SDK is available as a plug-in for Flutter. The instructions below show you how to integrate Singular into your Flutter app.
- This article assumes you have a functional Flutter app.
- To initialize the SDK, you need your Singular SDK Key and SDK Secret. You can get them in the Singular platform at "Developer Tools > SDK Integration > SDK Keys".
Integrate the SDK
To add the Singular plugin to your Flutter app, add the following lines to your pubspec.yaml file:
dependencies:
singular_flutter_sdk: ^1.6.2
Then navigate to your project in the terminal and run the following:
flutter packages get
Additional Steps for Android
Adding Dependencies
For Android apps, you need to add the Singular library to the dependencies list in app/build.gradle, as follows:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
//...
}
The Singular SDK requires the Google Mobile Ads API, part of the Google Play Services APIs 17.0.0+. If you've already integrated Google Play Services into your app, the requirement is fulfilled. If you haven't, you can integrate Google Mobile Ads individually, by including the following dependency in your app's build.gradle:
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
If you have disabled transitive dependencies for the Singular SDK, add the following to your app's build.gradle.
implementation 'com.android.installreferrer:installreferrer:2.2'
implementation 'com.google.android.gms:play-services-appset:16.0.2'
Additionally, add the following to support the Samsung Galaxy Store's install referrer if your app is distributed through the Samsung Galaxy Store:
implementation 'store.galaxy.samsung.installreferrer:samsung_galaxystore_install_referrer:4.0.0'
Note: If you are presented with a DuplicateClasses error at build time, you may already have Google play-services, and you can comment out the dependency.
Adding Permissions
Add these permissions under the <manifest> tag in your AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="BIND_GET_INSTALL_REFERRER_SERVICE" />
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
Additionally, add the following to support Samsung Galaxy Store's install referrer if your app is distributed through the Samsung Galaxy Store and targets Android 11 or higher:
<queries>
<package android:name="com.sec.android.app.samsungapps" />
</queries>
If your app build is targeting Android 12/API level 31 or higher, add permissions to access the Google Advertising ID:
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
Note: Do not add this permission if you're integrating the Kids SDK.
Additional Steps for iOS
To use the Singular plugin, you have to add the AdServices framework.
Initializing the Singular SDK
The Singular SDK initialization code should be called every time your app is opened. It is a prerequisite to all Singular attribution functionality, and it also sends a new user session to Singular (sessions are used to calculate user retention).
The initialization code goes in your main app widget (ie. main.dart) - the first one that loads when the app is opened. This widget has to be stateful, and the code has to be added in the widget's initState() method.
- First, you have to create a SingularConfig object. The object contains your Singular SDK Key and Secret.
- Optionally, you can add settings to enable various SDK features. See the full list of options.
- META Install Referrer Attribution Support
Required SDK configuration to enable "Meta Install Referrer" attribution:
- Provide your Facebook App Id in the Singular Configuration Object.
// To enable META Install Referrer config.facebookAppId = "INSERT YOUR FACEBOOK APP ID HERE";
- Provide your Facebook App Id in the Singular Configuration Object.
Example:
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';
//...
class MyHomePage extends StatefulWidget {
//...
}
class _MyHomePageState extends State<MyHomePage> {
//...
@override
void initState() {
super.initState();
//...
SingularConfig config = new SingularConfig('SDK KEY', 'SDK SECRET');
// Set hashed User ID if available
config.customUserId = "b642b4217b34b1e8d3bd915fc65c4452";
// For iOS (Remove this if you are not displaying an ATT prompt)!
config.waitForTrackingAuthorizationWithTimeoutInterval = 300;
// To enable SkAdNetwork Support
config.skAdNetworkEnabled = true;
// To enable META Install Referrer
config.facebookAppId = "INSERT YOUR FACEBOOK APP ID HERE";
// (optional) Using Singular Global Properties feature to capture
// third party identifiers. The respective SDK(s) must be initialized
// before the Singular SDK. Example of passing the CleverTapID.
// var cleverTapId = CleverTapPlugin.getCleverTapID();
// config.withGlobalProperty("CLEVERTAPID", cleverTapId, true);
Singular.start(config);
}
Handling ATT Consent (Setting an Initialization Delay)
Displaying an ATT (App Tracking Transparency) Prompt
Starting with iOS 14.5, apps are required to ask for user consent (using the App Tracking Transparency framework) before they can access and share some user data that is helpful for tracking purposes, including the device's IDFA.
Singular highly benefits from having the IDFA to identify devices and perform install attribution (although there are ways to perform attribution without the IDFA). We strongly recommend that you ask for the user's consent to get the IDFA.
Delaying Initialization to Wait for ATT Response
By default, the Singular SDK sends a user session when it's initialized. When a session is sent from a new device, it immediately triggers Singular's attribution process - which is performed based only on the data available to Singular at that point. Therefore, it's essential to ask for consent and retrieve the IDFA before the Singular SDK sends the first session.
To delay the firing of a user session, initialize the Singular SDK with the waitForTrackingAuthorizationWithTimeoutInterval option in the Config object. This option is already included in the code sample above.
When using Flutter, you will need to rely on a 3rd-Party package to implement App Tracking Transparency. For example: the app_tracking_transparency plugin to your Flutter
Tip: When you set an initialization delay, the app flow is as follows:
- When the app opens, the Singular SDK starts recording a session and user events but does not send them to the Singular server yet.
- When App Tracking Transparency consent is granted/denied, or the set time elapses, the SDK sends the session and any queued events to the Singular server (with or without the IDFA).
- Singular then starts the attribution process, taking advantage of the IDFA if it is available.
The following table summarizes the possible scenarios using this integration:
Scenario | IDFA Availability |
The user sees the consent dialog and grants consent before the set time elapses. | IDFA is available |
The user sees the consent dialog and denies consent before the set time elapses. | IDFA is not available |
The set time expires, then the user is shown the consent dialog and grants consent. | IDFA is available only for the user events that are reported after the consent is granted |
The set time expires, then the user is shown the consent dialog and denies consent. | IDFA is not available |
The user is shown the consent dialog, exits the app without taking action, and later opens the app and grants consent after the set time has expired. | Any queued events are sent to the Singular server when the app is reopened. The IDFA is not available for these events. Any events tracked after consent is granted do have IDFA associated with them. |
The user is shown the consent dialog, exits the app without taking action, and later opens the app and denies consent. | Any queued events are sent to the Singular servers when the app is reopened. The IDFA is not available for these events or any of the events tracked afterward. |
Adding SKAdNetwork Support
To enable SKAdNetwork tracking for your app, enable the skAdNetworkEnabled configuration option before initializing Singular.
Managed Mode (Recommended)
In managed mode, Singular manages the SKAdNetwork conversion value for you automatically, based on a conversion model of your choice that you can set up in the Singular platform.
To learn more, see Understanding Singular's Conversion Value Management and the SKAdNetwork Model Configuration FAQ. For a step-by-step guide to using SKAdNetwork with Singular, see How to Get Started with SKAdNetwork.
Note: The SKAN Managed mode is already enabled in the Initialization code snippet above. Make sure that you have these configuration items set.
To enable SKAdNetwork in managed mode, use the following code:
SingularConfig config = new SingularConfig('<SDK KEY>', '<SDK SECRET>');
config.skAdNetworkEnabled = true;
config.waitForTrackingAuthorizationWithTimeoutInterval = 300;
Singular.init(config);
Manual Mode
If you already have your own strategy and tools for managing the SKAdNetwork conversion value, you can enable SKAdNetwork in manual mode.
SingularConfig config = new SingularConfig('SDK KEY', 'SDK SECRET');
config.skAdNetworkEnabled = true;
config.manualSkanConversionManagement = true;
config.waitForTrackingAuthorizationWithTimeoutInterval = 300;
Singular.init(config);
Then, to update the conversion value, use the following code:
ingular.skanUpdateConversionValue(conversionValue)
To track when the conversion value changes, use the following callback function:
config.conversionValueUpdatedCallback = (int conversionValue) {
print('Received conversionValueUpdatedCallback: ' + conversionValue.toString());
};
To retrieve the current conversion value, use the following code:
Singular.skanGetConversionValue().then((conversionValue) {
print('conversion value: ' + conversionValue.toString());
});