Add the following repository under the allproject/repositores
block in your project/build.gradle
file.
allprojects {
...
repositories {
...
maven { url "https://sdk-download.airbridge.io/maven" }
...
}
...
}
If you're using Android Studio Arctic Fox (2020.3.1) or to create your project, or if your repository settings are done within the settings.gradle
file, add the following to your project/settings.gradle
file under the dependencyResolutionManagement/repositories
block.
dependencyResolutionManagement {
...
repositories {
...
maven { url "https://sdk-download.airbridge.io/maven" }
...
}
...
}
Add the following to the dependencies
block in your app/build.gradle
file
dependencies {
...
implementation "io.airbridge:sdk-android:2.+"
...
}
The Airbridge SDK uses JetBrains' Kotlin and Coroutines libraries for better stability and productivity. Please add following dependency libraries in your project when setting up using an ARR
file.
Attention
Airbridge Android SDK requires Kotlin stdlib and Kotlinx coroutines library version 1.4 or higher.
From Airbridge Android SDK v2.24.2 onwards, the addition of the Play Services Appset library dependency for collecting appSetId is required.
Add the following permissions in your AndroidManifest.xml
file.
<manifest ...>
...
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
...
</manifest>
Add the following code under the onCreate
method of the Application
class file registered in the AndroidManifest.xml
file.
@Override
public void onCreate() {
super.onCreate();
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.build();
Airbridge.init(this, config);
}
override fun onCreate() {
super.onCreate()
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.build()
Airbridge.init(this, config)
}
Attention
Make sure that the
initalizeSDK
function is called within theonCreate
method of theApplication
class for proper functionality.
You can find YOUR_APP_NAME
and YOUR_APP_SDK_TOKEN
in the "Airbridge Dashboard → Settings → Tokens" tab.
Once the basic installation and configuration of the Airbridge SDK are complete, you can test whether it has been correctly set up using the following methods.
Install and open the app on the device that you want to test.
Go to [Raw Data]>[App Real-time Logs] in the Airbridge dashboard.
Enter Google Advertising ID of the device in the search box.
Please re-check the guide above if you do not see any install event with your Google Advertising ID
You can find the Google Advertising ID of a device at
Settings
→Ads
→Your advertising ID
.
Use the following method if you want to use LogCat to see a more detailed log of the app.
Attention
Since this method may expose user information, please make sure the method is executed only for the
Build.DEBUG
case.
// Default log level = Log.INFO
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLogLevel(Log.DEBUG)
.build();
Airbridge.init(this, config);
// Default log level = Log.INFO
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLogLevel(Log.DEBUG)
.build()
Airbridge.init(this, config)
The following information must be registered on the [Tracking Link]>[Deep Link] page in your Airbridge dashboard.
URI Scheme
Package name
sha256_cert_fingerprints
Enter the Android URI scheme, including ://
, into the URI scheme field. Only lowercase letters, numbers, -
, and +
are supported.
Attention
The URI scheme must be entered differently for the production app, which is the app that has already been released on app stores or is planning to be released, and the test app.
If the same URI scheme is entered for the production app and test app, the deep link may open an unintended app page.
The package name of the production app already released on app stores will be automatically filled.
The package names of the production app that has not been released on app stores yet and the test app must be entered manually in the Android package name field.
Follow the below steps to obtain the sha256_cert_fingerprint
.
Prepare the keystore
file that you used to register your app with Google Play Store.
Execute the following command in Linux.
keytool -list -v -keystore my-release-key.keystore
3. Copy the SHA256
value under the Certificate Fingerprints section and paste it under Android sha256_cert_fingerprints
as shown in the picture above.
Certificate fingerprints:
MD5: 4C:65:04:52:F0:3F:F8:65:08:D3:71:86:FC:EF:C3:49
SHA1: C8:BF:B7:B8:94:EA:5D:9D:38:59:FE:99:63:ED:47:B2:D9:5A:4E:CC
SHA256: B5:EF:4D:F9:DC:95:E6:9B:F3:9A:5E:E9:D6:E0:D8:F6:7B:AB:79:C8:78:67:34:D9:A7:01:AB:6A:86:01:0E:99
Attention
Multiple
Android sha256_cert_fingerprints
can be entered by separating them with commas.
Follow these steps to setup the intent-filter
Open AndroidManifest.xml
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.abr.ge" />
<data android:scheme="https" android:host="YOUR_APP_NAME.abr.ge" />
</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>
YOUR_APP_NAME.deeplink.page
: Airbridge App Links Version 2
YOUR_APP_NAME.airbridge.io
: Airbridge App Links Version 1
YOUR_APP_URI_SCHEME
: URI Scheme of the deep link
The deeplink.page
or abr.ge
domains are available when creating a tracking link at the Airbridge dashboard. Customized URLs such as go.my_company.com/abcd
can also be used as tracking links to improve the branding and CTR (Click Through Rate).
Please follow this guide to setup custom domains.
Create a /res/values/airbridge.xml
file and edit it as below
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string-array name="co_ab180_airbridge_custom_domains">
<item>YOUR_CUSTOM_DOMAIN</item>
</string-array>
</resources>
3. 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_CUSTOM_DOMAIN" />
<data android:scheme="https" android:host="YOUR_CUSTOM_DOMAIN" />
</intent-filter>
...
</activity>
Attention
YOUR_CUSTOM_DOMAIN
should match the information in the Airbridge dashboard
The edit below is needed to process the deep link as defined by the intent-filter
above.
@Override
protected void onResume() {
super.onResume();
Airbridge.getDeeplink(getIntent(), new AirbridgeCallback<Uri>() {
@Override
public void onSuccess(Uri uri) {
// Process deeplink data
}
@Override
public void onFailure(Throwable throwable) {
// Error
}
@Override
public void onComplete() {
// After process deeplink data
}
});
}
// The code below is required for proper deeplink processing
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
override fun onResume() {
super.onResume()
Airbridge.getDeeplink(intent, object : AirbridgeCallback<Uri> {
override fun onSuccess(uri: Uri) {
// Process deeplink data
}
override fun onFailure(throwable: Throwable) {
// Error
}
override fun onComplete() {
// After process deeplink data
}
})
}
// The code below is required for proper deeplink processing
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
setIntent(intent)
}
In the general case of a deferred deep link in Airbridge SDK, the intent-filter
automatically calls the corresponding activity
and can be processed in the same way as a deep link callback.
When the corresponding
activity
is called through an Airbridge deferred deep link, thedeferred=true
query parameter is also passed on.
You can use the following method if you do not want the deferred deep link to automatically call an activity
, or want to process a specific job with the information obtained through the deferred deep link.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnDeferredDeeplinkReceiveListener(new OnDeferredDeeplinkReceiveListener() {
@Override
public boolean shouldLaunchReceivedDeferredDeeplink(Uri uri) {
// If you want to open the target activity, please return true otherwise false
// Default returning value = true
return true;
}
})
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnDeferredDeeplinkReceiveListener(object : OnDeferredDeeplinkReceiveListener {
override fun shouldLaunchReceivedDeferredDeeplink(uri: Uri): Boolean {
// If you want to open the target activity, please return true otherwise false
// Default returning value = true
return true
}
})
.build()
Airbridge.init(this, config)
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 → Raw Data → App Real-time Log" tab if everything is working.
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 SDK.
// Automatically hashed on client side using SHA256
// Can turn off hashing feature with special flag
Airbridge.getCurrentUser().setEmail("testID@ab180.co");
Airbridge.getCurrentUser().setPhone("821012341234");
// Does not hash
Airbridge.getCurrentUser().setId("testID");
Airbridge.getCurrentUser().setAlias("key", "value");
// Clear user data
Airbridge.expireUser()
// Automatically hashed on client side using SHA256
// Can turn off hashing feature with special flag
Airbridge.getCurrentUser().email = "testID@ab180.co"
Airbridge.getCurrentUser().phone = "821012341234"
// Does not hash
Airbridge.getCurrentUser().id = "testID"
Airbridge.getCurrentUser().setAlias("key", "value")
// Clear user data
Airbridge.expireUser()
Name | Description | Limitations |
---|---|---|
| User email | Hashed by default |
| User phone number | Hashed by default |
| User ID | - |
| User alias | - Maximum 10 aliases |
Once the user identifier has been setup, all events will be forwarded with the corresponding identity information.
Additional user attributes can be used for more accurate Multi-Touch Attribution (MTA) analyses, additional internal data analysis, and linking third-party solutions.
Airbridge.getCurrentUser().setAttribute("key", "value");
Airbridge.getCurrentUser().setAttribute("key", "value")
Name | Description | Limitations |
---|---|---|
| User attribute | - Maximum 100 attributes |
Check your user information settings at "Airbridge Dashboard → Raw Data → App Real-time Log".
Setup a device alias through the Airbridge SDK. The alias will be sustained even after the app closes, unless otherwise deleted.
Airbridge.setDeviceAlias("ADD_YOUR_KEY", "AND_YOUR_VALUE")
Airbridge.removeDeviceAlias("DELETE_THIS_KEY")
Airbridge.clearDeviceAlias()
Airbridge.setDeviceAlias("ADD_YOUR_KEY", "AND_YOUR_VALUE");
Airbridge.removeDeviceAlias("DELETE_THIS_KEY");
Airbridge.clearDeviceAlias();
Method | Description |
---|---|
| Add the key value pair to the device identifier. |
| Delete the corresponding device alias. |
| Delete all device aliases. |
All events called by the Airbridge SDK can be sent with the following fields.
Name | Type | Description |
---|---|---|
| String | Name of the event Required |
| String | Event attribute 1 |
| String | Event attribute 2 |
| Number | Event attribute value |
| Map<String, Object> | Custom attributes |
| Semantic attributes class | Semantic attributes |
Below is an example of how you can send a standard event using the Airbridge SDK.
Number eventValue = 10;
Map<String, Object> eventAttributes = new HashMap<String, Object>();
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.put(SemanticAttributes.KEY_CURRENCY, "USD");
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW, "event_action", "event_label", eventValue, eventAttributes, semanticAttributes);
val eventValue = 10
val eventAttributes = mutableMapOf<String, String>()
val semanticAttributes = mutableMapOf<String, String>()
semanticAttributes[SemanticAttributes.KEY_CURRENCY] = "USD"
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW, "event_action", "event_label", eventValue, eventAttributes, semanticAttributes)
If your application has specific needs that are not covered by a standard event category, you can log custom events as below.
Number eventValue = 10;
Map<String, String> eventAttributes = new HashMap<String, String>();
Map<String, String> semanticAttributes = new HashMap<String, String>();
semanticAttributes.put(SemanticAttributes.KEY_CURRENCY, "USD");
Airbridge.trackEvent("event_category", "event_action", "event_label", eventValue, eventAttributes, semanticAttributes);
val eventValue = 10
val eventAttributes = mutableMapOf<String, String>()
val semanticAttributes = mutableMapOf<String, String>()
semanticAttributes[SemanticAttributes.KEY_CURRENCY] = "USD"
Airbridge.trackEvent("event_category", "event_action", "event_label", eventValue, eventAttributes, semanticAttributes)
Please refer to guide for more details on semantic attributes supported by the Airbridge SDK.
Alternatively, you can pre-define classes and inherit them depending on the event your app needs.
class MyAppEvent extends Event {
public MyAppEvent() {
super("my_custom_category");
}
}
...
Airbridge.trackEvent(new MyAppEvent());
...
class MyAppEvent : Event("my_custom_category")
...
Airbridge.trackEvent(MyAppEvent())
...
Airbridge.getCurrentUser().setEmail("me@sample.com");
Airbridge.getCurrentUser().setPhone("821012341234");
Airbridge.getCurrentUser().setId("12345");
Airbridge.getCurrentUser().setAlias("alias1", "value");
Airbridge.getCurrentUser().setAttributes("attr1", 1234);
Airbridge.trackEvent(StandardEventCategory.SIGN_UP);
Airbridge.getCurrentUser().email = "testID@ab180.co"
Airbridge.getCurrentUser().phone = "821012341234"
Airbridge.getCurrentUser().id = "testID"
Airbridge.getCurrentUser().setAlias("alias1", "value")
Airbridge.getCurrentUser().setAttribute("attr1", 1234)
Airbridge.trackEvent(StandardEventCategory.SIGN_UP)
Airbridge.getCurrentUser().setEmail("me@sample.com");
Airbridge.getCurrentUser().setPhone("821012341234");
Airbridge.getCurrentUser().setId("12345");
Airbridge.getCurrentUser().setAlias("alias1", "value");
Airbridge.getCurrentUser().setAttributes("attr1", 1234);
Airbridge.trackEvent(StandardEventCategory.SIGN_IN);
Airbridge.getCurrentUser().email = "testID@ab180.co"
Airbridge.getCurrentUser().phone = "821012341234"
Airbridge.getCurrentUser().id = "testID"
Airbridge.getCurrentUser().setAlias("alias1", "value")
Airbridge.getCurrentUser().setAttribute("attr1", 1234)
Airbridge.trackEvent(StandardEventCategory.SIGN_IN)
Airbridge.trackEvent(StandardEventCategory.SIGN_OUT);
Airbridge.expireUser();
Airbridge.trackEvent(StandardEventCategory.SIGN_OUT)
Airbridge.expireUser()
View Home Screen
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW);
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW)
View Search Results
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setQuery("Coca Cola");
Airbridge.trackEvent(StandardEventCategory.SEARCH_RESULT_VIEW, null, null, null, null, semanticAttributes);
val semanticAttributes = SemanticAttributes()
semanticAttributes.query = "Coca Cola"
Airbridge.trackEvent(StandardEventCategory.SEARCH_RESULT_VIEW, null, null, null, null, semanticAttributes)
View Product List
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setProductListId("beverage_1");
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
Airbridge.trackEvent(StandardEventCategory.PRODUCT_LIST_VIEW, null, null, null, null, semanticAttributes);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val semanticAttributes = SemanticAttributes()
semanticAttributes.productListId = "beverage_1"
semanticAttributes.products = listOf(fanta, cocacola)
Airbridge.trackEvent(StandardEventCategory.PRODUCT_LIST_VIEW, null, null, null, null, semanticAttributes)
View Product Details
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
Airbridge.trackEvent(StandardEventCategory.PRODUCT_DETAILS_VIEW, null, null, null, null, semanticAttributes);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val semanticAttributes = SemanticAttributes()
semanticAttributes.products = listOf(fanta, cocacola)
Airbridge.trackEvent(StandardEventCategory.PRODUCT_DETAILS_VIEW, null, null, null, null, semanticAttributes)
Add to Cart
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setCartId("cart_123");
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
semanticAttributes.setCurrency("usd");
Event event = new Event(StandardEventCategory.ADD_TO_CART);
event.setValue(4.98);
event.setSemanticAttributes(semanticAttributes);
Airbridge.trackEvent(event);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val event = Event(StandardEventCategory.ADD_TO_CART).apply {
value = 4.98
semanticAttributes = SemanticAttributes().apply {
cartId = "cart_123"
products = listOf(fanta, cocacola)
currency = "usd"
}
}
Airbridge.trackEvent(event)
Order Complete
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
semanticAttributes.setCurrency("usd");
semanticAttributes.setInAppPurchased(true);
Event event = new Event(StandardEventCategory.ORDER_COMPLETED);
event.setValue(4.98);
event.setSemanticAttributes(semanticAttributes);
Airbridge.trackEvent(event);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val event = Event(StandardEventCategory.ORDER_COMPLETED).apply {
value = 4.98
semanticAttributes = SemanticAttributes().apply {
products = listOf(fanta, cocacola)
currency = "usd"
inAppPurchased = true
}
}
Airbridge.trackEvent(event)
Event information sent from the Airbridge SDK should be seen in the "Airbridge dashboard → Raw Data → App Real-time Log" tab.
Restricted SDK does not collect device IDs, including Ad ID. The restricted SDK will be available starting from v2.22.2
.
Add the following line within the dependencies
block in the app/build.gradle
file instead of the existing library.
dependencies {
...
implementation "io.airbridge:sdk-android-restricted:2.+"
...
}
Library | Link |
---|---|
Airbridge SDK restricted |
Protection against SDK spoofing is available once you set up the app's SDK signature. Settings can be changed by calling setSDKSignatureSecret
before the SDK initialization code.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSDKSignatureSecret("YOUR_SDK_SIGNATURE_SECRET_ID", "YOUR_SDK_SIGNATURE_SECRET")
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSDKSignatureSecret("YOUR_SDK_SIGNATURE_SECRET_ID", "YOUR_SDK_SIGNATURE_SECRET")
.build()
Airbridge.init(this, config)
The SDK Signature Credentials are required for the SDK Signature setup. Refer to this article to learn how to create them.
If you want to send user identity information without hashing it for internal data analysis, you can disable hashing by turning off the following option.
Attention
Other security measures must be taken internally when sensitive personal information such as "User Email" and "User Phone" is being handled.
// Default User Info Hash Enabled = true
val option = AirbridgeOptionBuilder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setHashUserInformationEnabled(false)
.build()
Airbridge.initializeSDK(this, option)
// Default User Info Hash Enabled = true
AirbridgeOption option = new AirbridgeOptionBuilder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setHashUserInformationEnabled(false)
.build();
Airbridge.initializeSDK(this, option);
Airbridge SDK does not resend an app open event if the user relaunches the app within the set session time. It will only send an app open event when the user opens the app after the set session time.
// Default Session Timeout = 5 minutes
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSessionTimeoutSeconds(300)
.build();
Airbridge.init(this, config);
// Default Session Timeout = 5 minutes
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSessionTimeoutSeconds(15)
.build()
Airbridge.init(this, config)
Use this function if privacy laws apply, and data should only be collected and transferred with consent. (e.g GDPR, CCPA)
// Default Auto Start Tracking Enabled = true
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAutoStartTrackingEnabled(false)
.build();
Airbridge.init(this, config);
...
// Set a variable like below
if (properties.isGDPRAccepted) {
Airbridge.startTracking();
}
// Default Auto Start Tracking Enabled = true
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAutoStartTrackingEnabled(false)
.build()
Airbridge.init(this, config)
...
// Set a variable like below
if (properties.isGDPRAccepted) {
Airbridge.startTracking()
}
Attention
This is not an essential setting function. Please check if it's a necessary function before you set it up.
Opt-out is a policy that uses user information until the user refuses.
After setting the setAutoStartTrackingEnabled
configuration to true, call the stopTracking
function at a point where event data cannot be collected. From the point where the stopTracking
function is called, events are not collected.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAutoStartTrackingEnabled(true)
.build();
Airbridge.init(this, config);
...
Airbridge.stopTracking();
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAutoStartTrackingEnabled(true)
.build()
Airbridge.init(this, config)
...
Airbridge.stopTracking()
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. The following option can be used to receive deep link events for 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
// Default Airbridge Link Only = false
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackAirbridgeLinkOnly(true)
.build();
Airbridge.init(this, config);
// Default Airbridge Link Only = false
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackAirbridgeLinkOnly(true)
.build()
Airbridge.init(this, config)
The settings below will allow Airbridge SDK to utilize Facebook's deferred app link information.
Reference - https://developers.facebook.com/docs/app-events/getting-started-app-events-android Reference - https://developers.facebook.com/docs/app-ads/deep-linking
Add the following repository to the project/build.gradle
file.
allprojects {
...
repositories {
...
mavenCentral()
...
}
...
}
Add the following under the dependencies
block of the app/build.gradle
file.
dependencies {
...
implementation 'com.facebook.android:facebook-android-sdk:latest.release'
...
}
Add the following string in the app/res/values/string.xml
file.
...
<string name="facebook_app_id">FACEBOOK_APP_ID</string>
<string name="facebook_client_token">FACEBOOK_CLIENT_TOKEN</string>
...
Add the following meta-data
under the application
element in the AndroidManifest.xml
file.
...
<application android:label="@string/app_name" ...>
...
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>
...
</application>
...
Set the below option to true
.
// Default Facebook Deferred App Link Enabled = false
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setFacebookDeferredAppLinkEnabled(true)
.build();
Airbridge.init(this, config);
// Default Facebook Deferred App Link Enabled = false
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setFacebookDeferredAppLinkEnabled(true)
.build()
Airbridge.init(this, config)
App uninstallation tracking through Firebase Messaging is supported by Airbridge Android SDK
v2.6.0
and above.
Please refer to this page for more information on app uninstallation tracking.
Airbridge SDK can collect user location information through the following method.
Attention
Location information must be collected for legal purposes through legal methods.
// Choose one
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
...
// Default Location Collection Enabled = false
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLocationCollectionEnabled(true)
.build();
Airbridge.init(this, config);
// Default Location Collection Enabled = false
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLocationCollectionEnabled(true)
.build()
Airbridge.init(this, config)
Attention
Airbridge SDK collects
LastKnownLocation
information. If the GPS information is not obtained, the value may not exist even if the corresponding permissions and settings are complete.
If advertisers need to analyze their application inflow performance for each market separately(e.g. Google Play Store, One Store, Huawei Store), you can set identifiers for each application and it will be reflected on the Airbridge dashboard.
Insert the app market's name(e.g. playStore
, oneStore
, huaweiStore
) at andriod:value
.
...
<application android:label="@string/app_name" ...>
...
<meta-data android:name="co.ab180.airbridge.app_market_identifier" android:value="playStore"/>
...
</application>
...
Insert the app market's name(e.g. playStore
, oneStore
, huaweiStore
) at setAppMarketIdentifier
.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAppMarketIdentifier("playStore")
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAppMarketIdentifier("playStore") // oneStore, huaweiStore ...
.build()
Airbridge.init(this, config)
The data can be utilized at the Airbridge dashboard through "Reports → Actuals → GroupBy → Event Property → App Market Identifier" and "Raw Data → App Raw Data → Export Raw Data → Select Property → App Market Identifier".
Installations per App Market
Error logs of the SDK are sent to the Airbridge server to improve the quality of the Airbridge SDK. These error logs only include the SDK's internal operations. You can disable this by turning off the following option.
// Default Error Log Collection Enabled = true
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setErrorLogCollectionEnabled(false)
.build();
Airbridge.init(this, config);
// Default Error Log Collection Enabled = true
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setErrorLogCollectionEnabled(false)
.build()
Airbridge.init(this, config)
When an event transmission failure occurs, the Airbridge SDK will store the event and retry at a later time. The following settings will allow you to limit the storage used for such events.
int count = 10;
long bytes = 1000000L;
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventMaximumBufferCount(count)
.setEventMaximumBufferSize(bytes)
.build();
Airbridge.init(this, config);
val count = 1_000
val bytes = 1_000_000L
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventMaximumBufferCount(count)
.setEventMaximumBufferSize(bytes)
.build()
Airbridge.init(this, config)
Event buffer size is slightly smaller than the actual size of the data due to metadata management.
Meta install referrer (MIR) Colection Setup supported by Airbridge Android SDK in version 2.22.3 or higher. To collect data, set as below.
After adding the settings, you must enter the decryption key to see decrypted MIR. Refer to this article to learn about MIR.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setMetaInstallReferrer("YOUR_FACEBOOK_APP_ID")
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setMetaInstallReferrer("YOUR_FACEBOOK_APP_ID")
.build()
Airbridge.init(this, config)
To comply with the Digital Markets Act (DMA), user consent must be shared with Airbridge. For detailed information about the DMA and the guidelines for advertisers, refer to this article.
Note that consent from all end users in the European Economic Area (EEA) should always be shared with Airbridge.
1. Confirm whether the end user launched the app in the EEA. If the end user did launch the app in the EEA (eea=1
) and DMA applies, confirm whether the consent values are already stored for the session. If there are consent values stored, continue to Step 3.
If the end user launched the app from outside the EEA, it is not necessary to collect user consent.
Note
Airbridge cannot provide guidance on storing the user response data and implementing the prompts. For assistance, consult legal professionals.
2. If there are no consent values stored, proceed to obtain user consent, such as with a privacy prompt. You must collect the adPersonalization
and adUserData
values in this step.
Attention
Advertisers must collect user consent data from all existing and new users in the EEA region at least once starting March 6, 2024.
The table below illustrates the consent data that must be sent to Airbridge. The eea
value is neither a direct response from the user nor automatically filled in by Airbridge. Advertisers should determine the eea
value based on whether the user is in the EEA and the DMA applies or not.
Field Name in Airbridge |
Field Name in Google |
Description |
---|---|---|
<string> |
| Indicates whether the user is in the EEA and the DMA applies or not. The value is neither a direct response from the user nor automatically filled in by Airbridge. Determine the appropriate value based on whether the user is located and whether the DMA applies or not. Values other than - - |
<string> |
| Indicates whether the user gave Google consent to use their data for ad personalization. Values other than - - |
<string> |
| Indicates whether the user gave consent to send their data to Google for ad-related purposes. Values other than - - |
3. Initialize the Airbridge SDK and share the consent values with Airbridge before collecting the end user’s personal data.
Attention
Pay attention to the following.
Use the field names specified by Airbridge:
eea
,adPersonalization
, andadUserData
.Fill in
0
or1
in accordance with the consent data collected.
// MainApplication.kt
override fun onCreate() {
super.onCreate()
// Initialize Airbridge SDK
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
// Make Airbridge SDK explicitly start tracking
.setAutoStartTrackingEnabled(false)
.build()
Airbridge.init(this, config)
// Set device alias into Airbridge SDK
// Based on actual region
Airbridge.setDeviceAlias("eea", "0" or "1")
// Based on actual user consent
Airbridge.setDeviceAlias("adPersonalization", "0" or "1")
Airbridge.setDeviceAlias("adUserData", "0" or "1")
// Explicitly start tracking
Airbridge.startTracking()
// MainApplication.java
@Override
public void onCreate() {
super.onCreate();
// Initialize Airbridge SDK
AirbridgeConfig config = new AirbridgeConfig.Builder("APP_NAME", "APP_TOKEN")
// Make Airbridge SDK explicitly start tracking
.setAutoStartTrackingEnabled(false)
.build();
Airbridge.init(this, config);
// Set device alias into Airbridge SDK
// Based on actual region
Airbridge.setDeviceAlias("eea", "0" or "1");
// Based on actual user consent
Airbridge.setDeviceAlias("adPersonalization", "0" or "1");
Airbridge.setDeviceAlias("adUserData", "0" or "1");
// Explicitly start tracking
Airbridge.startTracking();
}
Get attribution result data using the Airbridge SDK.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnAttributionResultReceiveListener(new OnAttributionResultReceiveListener() {
@Override
public void onAttributionResultReceived(@NonNull Map<String, String> result) {
// Process attribution data
}
})
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnAttributionResultReceiveListener(object : OnAttributionResultReceiveListener {
override fun onAttributionResultReceived(result: Map<String, String>) {
// Process attribution data
}
})
.build()
Airbridge.init(this, config)
Below is a list of data fields that will be retrieved through the callback.
Field | Description |
---|---|
attributedChannel | Channel (String) |
attributedCampaign | Campaign (String) |
attributedAdGroup | Ad Group (String) |
attributedAdCreative | Ad Creative (String) |
attributedContent | Content (String) |
attributedTerm | Keyword (String) |
attributedSubPublisher | Sub Publisher (String) |
attributedSubSubPublisher1 | Sub-sub Publisher 1 (String) |
attributedSubSubPublisher2 | Sub-sub Publisher 2 (String) |
attributedSubSubPublisher3 | Sub-sub Publisher 3 (String) |
If the event is unattributed, below is an example of the response you'll get.
{
"attributedChannel": "unattributed"
}
Guidelines for using attribution result data
Attribution data exists
Attribution data is forwarded within 40 seconds of SDK initialization.
If the app was closed and attribution data wasn't received, attribution data is forwarded within 40 seconds when the app is opened again.
On very rare occasions, attribution data could take up to 5 minutes to be received.
Attribution data does not exist
Attribution data will be received 3 hours after SDK initialization.
It is not recommended to utilize these attribution values for real-time processing
It is possible to setup event transmission intervals using the below code.
// Default Event Transmit Interval = 0 millisecond
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventTransmitInterval(3000)
.build();
Airbridge.init(this, config);
// Default Event Transmit Interval = 0 millisecond
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventTransmitInterval(3000)
.build()
Airbridge.init(this, config)
Attention
An
IllegalArgumentExcpeion
runtime error will occur ifsetEventTransmitInterval
is set to a negative number.
The following code allows you to collect lifecycle events (ORGANIC_REOPEN
, FOREGROUND
) within the session timeframe.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackInSessionLifeCycleEventEnabled(true)
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackInSessionLifeCycleEventEnabled(true)
.build()
Airbridge.init(this, config)
Empty the device's internal DB of unprocessed events that were not sent to Airbridge.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setResetEventBufferEnabled(true)
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setResetEventBufferEnabled(true)
.build()
Airbridge.init(this, config)
Redirect users to other pages without going through a browser by using the below feature.
Airbridge.click("https://abr.ge/~~~")
Airbridge.impression("https://abr.ge/~~~")
Attention
Custom domain tracking links with custom short IDs can't be used.
http://deeplink.ab180.co/custom: Invalid
https://abr.ge/a3b1c2: Valid
All Airbridge functions can be turned off.
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSdkEnabled(false)
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSdkEnabled(false)
.build()
Airbridge.init(this, config)
Attention
If
setResetEventBufferEnabled
is set to true andsetSdkEnabled
is set to false, thensetSdkEnabled
is prioritized andsetResetEventBufferEnabled
isn't processed.
While basic events (e.g. "install", "open", "deep link open") can be automatically tracked by only installing the Android SDK in your hybrid app, in-app events (e.g. sign-up, purchase, etc.) cannot be tracked as they are actually in-browser events that occur within a website of the WebView environment. Airbridge provides a simpler way to track in-app events by enabling the Android SDK to automatically pull all events from the web SDK that is installed on the website of the WebView environment. This replaces the hassle of having to create bridge functions between native and WebView environments.
Attention
Before proceeding with the hybrid app settings, install the Android SDK and Web SDK.
Reference - Building Web Apps in WebView
Reference - Understanding Android WebView Javascript Interface
Please call the Airbridge::setJavascriptInterface
method in the target WebView as below.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initWebView();
}
void initWebView() {
webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
Airbridge.setJavascriptInterface(webView, "YOUR_WEB_SDK_TOKEN");
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("http://dev.blog.airbridge.io/websdk-web-app/");
}
}
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initWebView()
}
fun initWebView() {
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
Airbridge.setJavascriptInterface(webView, "YOUR_WEB_TOKEN")
webView.webChromeClient = WebChromeClient()
webView.webViewClient = WebViewClient()
webView.loadUrl("http://my_company.com/main")
}
}
You can find YOUR_WEB_TOKEN
in the "Airbridge dashboard → Settings → Tokens" tab
Setup the SDK on the actual web page by following the Web SDK guide
(function(a_,i_,r_,_b,_r,_i,_d,_g,_e){if(!a_[_b]||!a_[_b].queue){_g=i_.getElementsByTagName(r_)[0];a_[_b]={queue:[]};_d={};for(_i=0;_i<_r.length;_d={$jscomp$loop$prop$m$2:_d.$jscomp$loop$prop$m$2},_i++)_d.$jscomp$loop$prop$m$2=_r[_i],~_d.$jscomp$loop$prop$m$2.indexOf(".")&&(_e=_d.$jscomp$loop$prop$m$2.split(".")[0],a_[_b][_e]=a_[_b][_e]||{},a_[_b][_e][_d.$jscomp$loop$prop$m$2.split(".")[1]]=function(_d){return function(){a_[_b].queue.push([_d.$jscomp$loop$prop$m$2,arguments])}}(_d)),a_[_b][_d.$jscomp$loop$prop$m$2]=function(_d){return function(){a_[_b].queue.push([_d.$jscomp$loop$prop$m$2,arguments])}}(_d);_d=i_.createElement(r_);_d.async=1;_d.src="//static.airbridge.io/sdk/latest/airbridge.min.js";_g.parentNode.insertBefore(_d,_g)}})(window,document,"script","airbridge","init setBanner setDownload setDeeplinks sendSMS sendWeb setUserAgent setUserAlias addUserAlias setMobileAppData setUserId setUserEmail setUserPhone setUserAttributes setDeviceIFV setDeviceIFA setDeviceGAID events.send events.signIn events.signUp events.signOut events.purchased events.addedToCart events.productDetailsViewEvent events.homeViewEvent events.productListViewEvent events.searchResultViewEvent".split(" "));
airbridge.init({
app: 'YOUR_APP_NAME',
webToken: 'YOUR_WEB_SDK_TOKEN'
});
java.lang.NoClassDefFoundError: kotlin/coroutines/AbstractCoroutineContextKey
Error
<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>
Reference - https://github.com/Kotlin/kotlinx.coroutines/issues/1879
According to @qwwdfsad, the use of "kotlin-stdlib 1.3.70" and above is enforced when using "kotlinx-coroutines-core 1.3.5" and above.
Make sure that you're using "kotlin-stdlib 1.3.70" and above if you're using "kotlinx-coroutines-core 1.3.5" and above through the gradlew dependencies
command.
Reference - https://developer.android.com/guide/topics/data/autobackup
Airbridge SDK defines airbridge_auto_backup_rules.xml
in AndroidManifest.xml
to prevent automatic replication of internal data. If you need Auto Backup
for your Android app, you have to merge with airbridge_auto_backup_rules.xml
file yourself
When errors like Manifest merger failed : Attribute application@fullBackupContent value=(true)
occur, please add the following rules in your backup_rules.xml
file and add tools:replace="android:fullBackupContent"
inside application
element
Airbridge SDK defines airbridge_auto_backup_rules.xml
in AndroidManifest.xml
to prevent automatic replication of internal data. You may have to configure your auto backup rules if your app uses auto backup, which in turn might cause conflicts such as Manifest merger failed : Attribute application@fullBackupContent value=(true)
.
If such errors occur, you will need to set tools:replace="android:fullBackupContent"
under the application
element and merge the following rules to your backup_rules.xml
file.
Below are the auto backup rules defined in the Airbridge SDK.
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="airbridge-internal" />
<exclude domain="sharedpref" path="airbridge-install" />
<exclude domain="sharedpref" path="airbridge-user-info" />
<exclude domain="sharedpref" path="airbridge-user-alias" />
<exclude domain="sharedpref" path="airbridge-user-attributes" />
<exclude domain="database" path="airbridge.db" />
</full-backup-content>
Was this page helpful?