Flutter SDK - Basic Integration

New: Video Guide

Watch this video for a detailed view of the integration process. We recommend that you use both the video and the written guide below.

Prerequisites

Complete these prerequisite steps before installing the Singular Flutter SDK to ensure a smooth integration process.

Required Prerequisites:

  • Complete planning steps: Follow the guide in Integrating a Singular SDK: Planning and Prerequisites. These steps are mandatory for any Singular SDK integration.
  • Flutter version: Verify you have a functional Flutter application with Flutter SDK installed.
  • SDK credentials: Obtain your SDK Key and Secret from the Singular platform at Developer Tools > SDK Integration > SDK Keys.

Installation

Installing the SDK Package

Add the Singular Flutter SDK to your project using the pubspec.yaml dependency manager. The SDK provides Dart bindings to the native Singular SDKs for iOS and Android.

Add SDK Dependency

  1. Update pubspec.yaml: Add the Singular Flutter SDK dependency to your project's pubspec.yaml file:
    pubspec.yaml
    dependencies:
      flutter:
        sdk: flutter
      singular_flutter_sdk: ^1.8.0
  2. Install dependencies: Navigate to your project directory in the terminal and run:
    bash
    flutter packages get

Platform Configuration

iOS Configuration

Complete iOS-specific setup to enable AdServices framework support for iOS attribution tracking.

Add AdServices Framework

The AdServices framework is required for Apple Search Ads attribution and iOS 14.3+ SKAdNetwork integration.

  1. Navigate to iOS project: Open your Flutter project's iOS directory and locate the Xcode workspace.
    • Navigate to the ios folder of your Flutter project.
    • Open Runner.xcworkspace in Xcode (use .xcworkspace if you use CocoaPods, otherwise use .xcodeproj).
  2. Add AdServices framework: Configure the framework in your Xcode project settings.
    • In Xcode, select your project's target (e.g., "Runner").
    • Go to the General tab.
    • Scroll to the Frameworks, Libraries, and Embedded Content section.
    • Click the + button.
    • Search for AdServices.framework and add it.
    • Set the framework status to Optional (ensures compatibility with older iOS versions).

Why Optional? Setting AdServices as optional ensures your app remains compatible with iOS versions that don't include this framework (iOS 14.2 and earlier).

Android Configuration

Configure your Android build files to add required permissions and dependencies for proper SDK functionality.

Add Required Permissions

Add these permissions to your AndroidManifest.xml file under the <manifest> tag to enable core SDK functionality.

AndroidManifest.xml
<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" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

Important: Exclude the com.google.android.gms.permission.AD_ID permission if you're integrating the Kids SDK. This permission is required for GAID collection in standard apps but must be omitted for apps targeting children under 13.

Samsung Galaxy Store Support

To enable install referrer tracking from Samsung Galaxy Store, add the following to your AndroidManifest.xml:

AndroidManifest.xml
<queries>
   <package android:name="com.sec.android.app.samsungapps" />
</queries>

Transitive Dependencies

If you've disabled transitive dependencies for the Singular SDK in your Gradle configuration, manually add these required dependencies:

android/app/build.gradle
dependencies {
    // Required for install referrer tracking
    implementation 'com.android.installreferrer:installreferrer:2.2'

    // Required for App Set ID
    implementation 'com.google.android.gms:play-services-appset:16.0.0'
}

ProGuard Configuration

When building release APKs, ProGuard (or R8) may strip or obfuscate SDK classes. Add these keep rules to preserve Singular functionality.

Why This Matters: ProGuard is enabled by default in Flutter Android release builds. Without proper keep rules, the SDK may not function correctly in production.

  1. Locate ProGuard file: Navigate to android/app/proguard-rules.pro in your Flutter project.
  2. Add keep rules: Append the following rules to preserve SDK classes:
    android/app/proguard-rules.pro
    # Preserve Singular SDK classes
    -keep class com.singular.sdk.** { *; }
    
    # Preserve Android Install Referrer library
    -keep public class com.android.installreferrer.** { *; }
    
    # Uncomment if using Singular revenue tracking with Google Play Billing Library
    #-keep public class com.android.billingclient.** { *; }

SDK Integration

Privacy Compliance: Comply with privacy laws in your operating regions, including GDPR, CCPA, COPPA, and others when implementing the Singular SDK. For guidance, see SDK Opt-In and Opt-Out Practices.

Initialize the Singular SDK every time your app launches. SDK initialization is essential for all Singular attribution functionality and creates a new session for calculating user retention metrics.

Import SDK Classes

Import the Singular SDK classes at the top of your main application file (typically main.dart).

Dart
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';

Initialize the SDK

Create a SingularConfig object with your SDK credentials, configure optional features, and initialize the SDK using the start() method.

Basic Initialization

  1. Get credentials: Log into your Singular account and navigate to Developer Tools > SDK Integration > SDK Keys to find your SDK Key and Secret.
  2. Create config: Instantiate a SingularConfig object with your credentials.
  3. Add configuration: Optionally configure SDK behavior using property setters (see Configuration Reference).
  4. Initialize SDK: Call Singular.start() to start the SDK.

Initialization Example

Initialize the SDK in your app's entry point, typically within the initState() method of your main StatefulWidget.

Dart
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();

    // Create configuration with credentials
    SingularConfig config = SingularConfig(
      'YOUR_SDK_KEY',
      'YOUR_SDK_SECRET'
    );

    // Enable debug logging
    config.enableLogging = true;
    config.logLevel = 4;

    // Set session timeout (in seconds)
    config.sessionTimeout = 60.0;

    // Initialize SDK
    Singular.start(config);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

Advanced Configuration Example

Configure multiple SDK features during initialization by setting additional properties on the SingularConfig object before calling start().

Dart
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';
import 'package:singular_flutter_sdk/singular_link_params.dart';
import 'package:singular_flutter_sdk/singular_global_property.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    initializeSingularSDK();
  }

  void initializeSingularSDK() {
    // Create configuration with credentials
    SingularConfig config = SingularConfig(
      'YOUR_SDK_KEY',
      'YOUR_SDK_SECRET'
    );

    // User identification
    config.customUserId = 'user_123456';

    // Privacy settings
    config.limitDataSharing = false;
    
    // Deep linking handler
    config.singularLinksHandler = (SingularLinkParams params) {
      print('Deep link received: ${params.deeplink}');
      print('Passthrough params: ${params.passthrough}');
      print('Is deferred: ${params.isDeferred}');
      // Handle navigation based on deep link
    };

    // Short link timeout
    config.shortLinkResolveTimeOut = 10.0;

    // Facebook integration
    config.facebookAppId = 'YOUR_FACEBOOK_APP_ID';

    // SKAdNetwork settings (iOS)
    config.skAdNetworkEnabled = true;
    config.manualSkanConversionManagement = false;
    config.waitForTrackingAuthorizationWithTimeoutInterval = 30;

    // Conversion value callbacks (iOS)
    config.conversionValueUpdatedCallback = (int conversionValue) {
      print('Conversion value updated: $conversionValue');
    };

    config.conversionValuesUpdatedCallback = (int cv, int coarse, bool lock) {
      print('Fine: $cv, Coarse: $coarse, Locked: $lock');
    };

    // Global properties
    config.globalProperties = [
      SingularGlobalProperty('app_version', '2.5.0', true),
      SingularGlobalProperty('user_tier', 'premium', false)
    ];

    // Debugging
    config.enableLogging = true;
    config.logLevel = 4;

    // Session timeout
    config.sessionTimeout = 60.0;

    // Initialize SDK
    Singular.start(config);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

Configuration Reference: For a complete list of available configuration options, see the Flutter SDK Configuration Reference.

Critical: Do NOT use the Singular Reporting API Key. Only use the SDK-specific credentials from the SDK Integration page. Using wrong credentials prevents data from reaching Singular.