Flutter SDK

SDK Installation


Pub VersionPub Version

Package Installation

pubspec Setup

Please add the following dependency under the dependencies block in your pubspec.yaml file

dependencies:
  airbridge_flutter_sdk: 2.1.0

Open Terminal at the topmost level of the project and execute the following command.

flutter pub get

The Airbridge Flutter SDK supports >= Flutter 1.20.0 and >= Dart 2.12.0


Project Setup

airbridge.json

  1. Please add the following under the flutter/assets block in your pubspec.yaml file.
flutter:
  assets:
    - assets/airbridge.json
  1. Create an assets/airbridge.json file at the topmost level of the project.
  2. Configure settings in JSON format.
{
    "sessionTimeoutSeconds": 300,
    "autoStartTrackingEnabled": true,
    "userInfoHashEnabled": true,
    "trackAirbridgeLinkOnly": false,
    "facebookDeferredAppLinkEnabled": false,
    "locationCollectionEnabled": false,
    "trackingAuthorizeTimeoutSeconds": 0
}

iOS Setup

Add the following code to the ios/[Project Name]/AppDelegate.m file.

import airbridge_flutter_sdk

override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    AirbridgeFlutter.initSDK(appName: "YOUR_APP_NAME", appToken: "YOUR_APP_TOKEN", withLaunchOptions: launchOptions)
}
#import <airbridge_flutter_sdk/AirbridgeFlutter.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [AirbridgeFlutter initSDKWithAppName:@"APP_NAME" appToken:@"APP_TOKEN" withLaunchOptions:launchOptions];
}

APP_NAME can be found on the dashboard at Settings → Tokens → App Name.
APP_TOKEN can be found on the dashboard at Settings → Tokens → App SDK Token.

25202520

Android Setup

Add the following code to the onCreate function within the android/app/src/main/java/.../MainApplication.java file.

import co.ab180.airbridge.flutter.AirbridgeFlutter;
import io.flutter.app.FlutterApplication;

public class MainApplication extends FlutterApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        AirbridgeFlutter.init(this, "YOUR_APP_NAME", "YOUR_APP_TOKEN");
    }
}
import co.ab180.airbridge.flutter.AirbridgeFlutter
import io.flutter.app.FlutterApplication

class MainApplication: FlutterApplication() {
    override fun onCreate() {
        super.onCreate()
        AirbridgeFlutter.init(this, "YOUR_APP_NAME", "YOUR_APP_TOKEN")
    }
}

APP_NAME can be found on the dashboard at Settings → Tokens → App Name.
APP_TOKEN can be found on the dashboard at Settings → Tokens → App SDK Token.

25202520

Register the MainApplication class created above in the AndroidManifest.xml file.

<application
    android:name=".MainApplication"
    ...>
    ...
</application>

Testing the SDK

Check if install events are sent when the application is installed and opened.

Check in the Airbridge Dashboard

Events from the Airbridge SDK are shown at the "Airbridge Dashboard → Raw Data → App Real-time Logs".

  1. Go to Airbridge Dashboard → Raw Data → App Real-time Logs.
  2. Search for the device's ADID (IDFA, IDFV, GAID).
25202520

🚧

Logs may be delayed for up to 5 minutes.



Deep Link Setup


Dashboard Setup

Please refer to the guides below to setup your deep links in the Airbridge dashboard.

  • iOS Deep Link Dashboard Setup Guide
  • Android Deep Link Dashboard Setup Guide

Project Setup

iOS Deep Link Setup

  • URL Scheme Setup
  1. Go to "Xcode → Project file → Info → URL Types".
  2. From the Airbridge dashboard, copy "iOS URI Scheme" to Xcode's "URL Schemes". (Do not include ://)
17941794
  • Universal Link Setup
  1. Go to "Xcode → Project file → Signing & Capabilities".
  2. Click "+ Capability" and add "Associated Domains".
  3. Add applinks:YOUR_APP_NAME.airbridge.io to "Associated Domains".
  4. Add applinks:YOUR_APP_NAME.deeplink.page to "Associated Domains".
17941794

YOUR_APP_NAME can be found at the "Airbridge dashboard → Settings → Tokens → App Name".
Please refer to Troubleshooting → Webcredentials if you want to use the autofill feature.

  • AppDelegate Setup
  1. Open ios/[Project name]/AppDelegate.
  2. Add the following methods. (handleUniversalLink, handleURLSchemeDeeplink)
override func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
    if let universalLink = userActivity.webpageURL {
        AirbridgeFlutter.deeplink.handleUniversalLink(universalLink)
    }
    
    return true
}

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    AirbridgeFlutter.deeplink.handleURLSchemeDeeplink(url)
    
    return true
}
-  (BOOL)application:(UIApplication*)application
continueUserActivity:(NSUserActivity*)userActivity
  restorationHandler:(void (^)(NSArray* _Nullable))restorationHandler
{
    [AirbridgeFlutter.deeplink handleUniversalLink:userActivity.webpageURL];

    return YES;
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options
{
    [AirbridgeFlutter.deeplink handleURLSchemeDeeplink:url];

    return YES;
}

Android Deep Link Setup

  • AndroidManifest.xml Setup
  1. Open AndroidManifest.xml
  2. Add the following intent-filter to the activity that will process the deep link.
<activity ...>
    ...
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="http" android:host="YOUR_APP_NAME.deeplink.page" />
        <data android:scheme="https" android:host="YOUR_APP_NAME.deeplink.page" />
    </intent-filter>
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="http" android:host="YOUR_APP_NAME.airbridge.io" />
        <data android:scheme="https" android:host="YOUR_APP_NAME.airbridge.io" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="YOUR_APP_URI_SCHEME" />
    </intent-filter>
    ...
</activity>

Enter your app name at YOUR_APP_NAME.
Enter your scheme value set in the Airbridge dashboard at YOUR_APP_URI_SCHEME. (e.g. abc://)

  • MainActivity Setup

Insert the following code to the android/app/src/main/java/.../MainActivity.java file.

@Override
protected void onResume() {
    super.onResume();
    AirbridgeFlutter.processDeeplink(intent);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}
override fun onResume() {
    super.onResume()
    AirbridgeFlutter.processDeeplink(intent)
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
}

Callback Setup

Register a function that will be called whenever a "deep link" or a "deferred deep link" opens the application.

Airbridge.deeplink.setDeeplinkListener((deeplink) {
    // airbridge deeplink = SCHEME://...
    print('$deeplink');
});

If setDeeplinkListener is called from the main function, make sure that WidgetsFlutterBinding.ensureInitialized(); is called first.

Custom Domain (Optional)

When using the custom domain feature with Airbridge tracking links, please refer to the guides below.

iOS: Guide
Android: Guide


Test Deep Link

Click on your URI scheme to test if your deep link has been properly set up in the Airbridge SDK.

  • YOUR_APP_URI_SCHEME://

The results will show on the "Airbridge dashboard → Row Data → App Real-time Log" tab if everything is working.

33603360



User Setup


User Identifier Setup

User Identifier Setup

To measure the fragmented contributions of users between web and app, Airbridge collects the following user identifier information.

  • User Email: Email address
  • User Phone: Phone number
  • User ID: Unique User ID (The ID value that specifies the user must be the same in both web and mobile)
  • User Alias: Identifiers that can represent users (e.g. loyalty program ID, affiliate integrated ID, etc)

📘

The user's email and phone numbers are hashed (SHA256) by default and then sent to servers.

You can set the user identifier as below for the Airbridge Flutter SDK.

Airbridge.state.setUser(
    User(
    id: 'personID',
    email: '[email protected]',
    phone: '1(123)123-1234',
    alias: {
        'alias_key': 'alias_value',
    },
    )
);

Name

Description

Limitations

id

User ID

email

User email

Hashed by default
(SHA256, can be disabled)

phone

User phone number

Hashed by default
(SHA256, can be disabled)

alias

User alias

  • Maximum 10 aliases
  • "key" type is String, maximum 128 characters
  • "key" must satisfy ^[a-z_][a-z0-9_]*$ regex
  • `"value" type is String, maximum 1024 characters

Once the user identifier has been configured, all events will be forwarded with the corresponding identity information.

🚧

The user identifier properties can be reset or overwritten through user events.

📘

Below is an example of how a particular field can be updated.

Airbridge.state.updateUser(
    User(
        id: 'sam1234',
    )
);

User Attribute Setup

Additional user attributes can be used for more accurate Multi-Touch Attribution (MTA) analyses, additional internal data analyses, and linking third-party solutions.

Airbridge.state.setUser(
    User(
    attributes: {
        'attr_key': 'attr_value',
    },
    )
);

Name

Description

Limitations

attributes

User attribute

  • Maximum 100 attributes
  • "key" type is string, maximum 128 characters
  • "key" must satisfy ^[a-z_][a-z0-9_]*$ regex
  • "value" type is primitive or string
  • Maximum 1024 characters when "value" is string

🚧

The user attribute information can be reset or overwritten through user events.


Testing

Make sure that your user information settings are being properly sent through the SDK.

  1. Configure user identifier information.
  2. Send an event using the SDK.
  3. Click the event at "Airbridge dashboard → Raw Data → App Real-time Logs"
  4. Check if the user information is correctly sent under the user block.
33603360



Event Setup


When important user actions occur, in-app events can be sent to measure performance by channel.

All event parameters are optional. However, more information about the event will help provide a more accurate analysis.

All events called by the Airbridge SDK can be sent with the following fields.

Name

Type

Description

Event Category

String

Name of the event
Required

Event Action

String

Event attribute 1

Event Label

String

Event attribute 2

Event Value

Float

Event attribute value

Event Custom Attributes

Map<String, Object>

Custom attributes

Event Semantic Attributes

Semantic Attributes Class

Semantic attributes


Standard Events

Send standard user events with the SDK.

action, label, value, attributes can also be used when sending standard events.

Sign Up

Airbridge.event.send(SignUpEvent(
    user: User(
        id: 'personID',
        email: '[email protected]',
        phone: '1(123)123-1234',
    )
));

Sign In

Airbridge.event.send(SignInEvent(
    user: User(
        id: 'personID',
        email: '[email protected]',
        phone: '1(123)123-1234',
    )
));

Sign Out

Airbridge.event.send(SignOutEvent());

🚧

All user identifier properties will disappear after sign out is called.

View Home Screen

Airbridge.event.send(ViewHomeEvent());

View Search Result

Airbridge.event.send(ViewSearchResultEvent(
  query: 'SELECT * FROM beverages',
  products: [
    Product(
      id: 'beverage_1'
      name: 'Coca cola',
      price: 1.25,
      currency: 'USD',
      quantity: 1,
      position: 0
    ),
    Product(
      id: 'beverage_2'
      name: 'Fanta',
      price: 1.50,
      currency: 'USD',
      quantity: 1,
      position: 1
    ),
  ],
));

View Product List

Airbridge.event.send(ViewProductListEvent(
  listID: 'beverage_list_0',
  products: [
    Product(
      id: 'beverage_1'
      name: 'Coca cola',
      price: 1.25,
      currency: 'USD',
      quantity: 1,
      position: 0
    ),
    Product(
      id: 'beverage_2'
      name: 'Fanta',
      price: 1.50,
      currency: 'USD',
      quantity: 1,
      position: 1
    ),
  ],
));

View Product Detail

Airbridge.event.send(ViewProductDetailEvent(
  products: [
    Product(
      id: 'beverage_1'
      name: 'Coca cola',
      price: 1.25,
      currency: 'USD',
      quantity: 1,
      position: 0
    ),
  ],
);

Add To Cart

Airbridge.event.send(AddToCartEvent(
  cartID: 'cart_0',
  currency: 'USD',
  total: 2.75,
  products: [
    Product(
      id: 'beverage_1'
      name: 'Coca cola',
      price: 1.25,
      currency: 'USD',
      quantity: 1,
      position: 0
    ),
    Product(
      id: 'beverage_2'
      name: 'Fanta',
      price: 1.50,
      currency: 'USD',
      quantity: 1,
      position: 1
    ),
  ],
);

Purchase

Airbridge.event.send(PurchaseEvent(
  transactionID: 'transaction_0',
  products: [
    Product(
      id: 'beverage_1'
      name: 'Coca cola',
      price: 1.25,
      currency: 'USD',
      quantity: 1,
      position: 0
    ),
    Product(
      id: 'beverage_2'
      name: 'Fanta',
      price: 1.50,
      currency: 'USD',
      quantity: 1,
      position: 1
    ),
  ],
  isInAppPurchase: true,
  currency: 'USD',
  total: 2.75,
);

Custom Events

Send custom events with the SDK.

Airbridge.event.send(Event(
  'category',
  option: EventOption(
    action: 'action',
    label: 'label',
    value: 9999,
    attributes: {
      'custom_key': 'value',
    },
    semantics: {
      'query': 'query_123',
    },
  ),
));

📘

To configure and deliver Semantic Attributes directly, please refer to this guide.


Verify Event Transmission

Make sure that the events are being properly sent through the SDK.

  1. Send an event with the SDK.
  2. Check if the event shows up at "Airbridge dashboard → Raw Data → App Real-time Logs".
33603360



Advanced Setup


Hash User Indentifier

Email addresses and phone numbers are hashed by default. (SHA256)
Configure the userInfoHashEnabled parameter of airbridge.json.

❗️

Other security measures must be taken internally when sensitive personal information such as "User Email" and "User Phone" is being handled.


Session Timeout

Configure the sessionTimeoutSeconds parameter of airbridge.json.

Session timeout is in milliseconds and must range between 0 and 604800000 (7 days).
Default value is 1000 60 5 (5 minutes).


Privacy Protection

Configure the autoStartTrackingEnabled parameter of airbridge.json if privacy laws apply. Data should only be collected and transferred with consent. (e.g GDPR, CCPA).

📘

When this feature is disabled, the following functions must be explicitly called for proper data collection.

dart
Airbridge.state.startTracking();

Track Airbridge Link Only

It may be difficult to see the re-engagement performance through Airbridge if there are too many deep link actions within the advertiser's app. Configure the autoStartTrackingEnabled parameter of airbridge.json to track Airbridge deep links only.

This option will measure deep links only if the following requirements are met.

  • The app is opened through a airbridge.io link
  • The app is opened through a deeplink.page link
  • The app is opened through a Custom Domain Setup that is registered on the Airbridge dashboard
  • The app is opened through a link that contains airbridge_referrer information in the query

Location Collection (Android only)

Configure the locationCollectionEnabled parameter of airbridge.json to collect user location information.

❗️

Location information must be collected for legal purposes through legal methods.


Track Facebook Deferred App Links

The Airbridge SDK can track Facebook deferred App Links through the following settings.

  1. Install the Facebook SDK: https://developers.facebook.com/docs/ios/getting-started.
  2. Set facebookDeferredAppLinkEnabled of airbridge.json to true.

Tracking Authorize Timeout (iOS only)

When the AppTrackingTransparency.framework is used to present an app-tracking authorization request to the user, IDFA will not be collected when the install event occurs because the install event occurs before the selection.

When trackingAuthorizeTimeoutSeconds of airbridge.json is set to true, the install event will be sent after the timeout period or delayed until an ATT option is selected.



Troubleshooting


settings.gradle (Android only)

If a Plugin project ... not found. Please update settings.gradle error occurs, please edit the android/settings.gradle file as below.

include ':app'

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
    include ":$name"
    project(":$name").projectDir = pluginDirectory
}

Could not find or use auto-linked library...

Flutter issue: https://github.com/flutter/flutter/issues/16049

Airbridge Flutter SDK is a Swift plugin, and Flutter has an issue when a 100% Objective C project uses the Swift Plugin.
Click File → New > File... → Swift File to create an empty Swift file and a bridge header.

Issue does not exist with an "Objective C & Swift Project" or a "100% Swift Project".


Update 1.X.X to 2.X.X

  • iOS
  1. Change the AirbridgeFL classes to AirbridgeFlutter in the AppDelegate file.
  • Android
  1. Change the AirbridgeFL classes to AirbridgeFlutter in MainApplication and MainActivity.
  2. Change the processDeeplinkData method to processDeeplink in MainActivity.