At a glance: Measure the success of push-notification campaigns for both iOS and Android platforms.
Important!
Some advertisers implement internal solutions of push notifications. As with any owned media, if you measure the performance of your push notifications with AppsFlyer, their conversions are attributed and reported.
SDK requirements
Push notification measurement requires an SDK API call within the app code.
SDK versions that support Push notification:
- Android: V4.8.0 and later
- iOS: V4.8.5 and later
To enable this feature, call the sendPushNotificationData
method inside the onCreate
method of every activity that is launched after clicking the notification.
AppsFlyerLib.getInstance().sendPushNotificationData(this);
To enable this feature, call the handlePushNotificationData
method inside AppDelegate.m.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { [[AppsFlyerLib shared] handlePushNotification:userInfo]; }
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { AppsFlyerLib.shared().handlePushNotification(userInfo) }
Setting up a push notification campaign
AppsFlyer supports the measurement of push notification campaigns from all vendors and can also support developers who use Google Cloud Messaging or Apple push notification services directly. The conversions, defined as app opens originating from push notification messages, display in the Retargeting dashboard.
The following parameters are inserted into the Push notification payload. These parameters must appear in an "af" object, as shown in the examples below:
- C
- The name of the campaign.
- is_retargeting=true
- This parameter enables AppsFlyer to recognize a retargeting campaign.
- pid
- The media source, which in this case is the push notification provider (e.g mixpanel_int, urbanairship_int, swrve_int)
A list of available parameters can be found here.
Note
The solution is indifferent to the push provider.
Configure push notification deep link resolution
The addPushNotificationDeepLinkPath
method provides app owners with a flexible interface for configuring how deep links are extracted from push notification payloads.
By default, the SDK looks for a deep link value in the af
key of a push notification’s JSON
payload. Many push providers use proprietary JSON
schemas that the SDK can’t resolve without additional configuration.
addPushNotificationDeepLinkPath
enables you to configure which key in the push notification’s JSON payload the SDK should use for the deep link value.
Use this method if you’re integrating your app with push providers that don’t use the default push notification JSON schema the SDK expects.
When calling addPushNotificationDeepLinkPath
the SDK verifies that:
- The required key exists in the payload.
- The key contains a valid OneLink URL.
Basic configuration
Consider the following call to addPushNotificationDeepLinkPath
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("deeply", "nested", "deep_link");
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("deeply", "nested", "deep_link")
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"deeply", @"nested", @"deep_link"]]
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["deeply", "nested", "deep_link"])
and these scenarios:
Scenario 1
Your app is invoked via push notification. It contains a payload structured as follows.
{
...
"deeply": {
"nested": {
"deep_link": "https://yourdeeplink2.onelink.me"
}
}
...
}
In this scenario, the SDK extracts the value of deep_link
and proceeds with the deep linking flow.
Scenario 2
Your app is invoked via push notification. It contains a payload structured as follows.
{
...
"deeply": {
"nested": {
"banana": "https://yourdeeplink2.onelink.me"
}
},
...
}
In this scenario, when the call executes the SDK can't find the deep_link
key in the payload. Therefore, nothing happens.
Scenario 3
Your app is invoked via push notification. It contains a payload structured as follows.
{
...
"deeply": {
"nested": {
"deep_link": "Corrupted url or regular string"
}
},
...
}
In this scenario, although the SDK finds the deep_link
key, its deep link value is invalid. Therefore, when the above call executes, nothing happens.
Advanced configuration
To configure multiple possible payload structures, call addPushNotificationDeepLinkPath
multiple times:
- The first call that yields a valid deep link value is used
- Other calls are ignored
If none of the payload structures match or no valid OneLink URL is found in the payload, nothing happens.
For example, consider the following payload
{
...
"deeply": {
"nested": {
“deep_link”: “https://yourdeeplink2.onelink.me”
}
},
“this”: {
“is”: {
"banana": "phone"
}
}
...
}
and the following calls to addPushNotificationDeepLinkPath
.
// this.is.deep_link key isn’t found - nothing happens
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("this", "is", "deep_link");
// this.is.banana key found, but contains invalid OneLink URL - nothing happens
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("this", "is", "banana");
// deeply.nested.deep_link key found and contains valid OneLink URL - proceed deep linking flow
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("deeply", "nested", "deep_link");
// this.is.deep_link key isn’t found - nothing happens
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("this", "is", "deep_link");
// this.is.banana key found, but contains invalid OneLink URL - nothing happens
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("this", "is", "banana");
// deeply.nested.deep_link key found and contains valid OneLink URL - proceed deep linking flow
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath("deeply", "nested", "deep_link");
// this.is.deep_link key isn’t found - nothing happens
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"this", @"is", @"deep_link"]]
// this.is.banana key found, but contains invalid OneLink URL - nothing happens
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"this", @"is", @"banana"]]
// deeply.nested.deep_link key found and contains valid OneLink URL - proceed deep linking flow
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"deeply", @"nested", @"deep_link"]]
// this.is.deep_link key isn’t found - nothing happens
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["this", "is", "deep_link"]);
// this.is.banana key found, but contains invalid OneLink URL - nothing happens
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["this", "is", "banana"])
// deeply.nested.deep_link key found and contains valid OneLink URL - proceed deep linking flow
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["deeply", "nested", "deep_link"])
Payload examples
See the following list of payload examples by OS and vendor.
Payload for iOS via APNS:
Payload example:
{
"af":{
"c":"test_campaign",
"is_retargeting":"true",
"pid":"push_provider_int"
},
"aps":{
"alert":"Get 5000 Coins",
"badge":"37",
"sound":"default"
}
}
Payload for Android and iOS via Firebase Cloud Messaging
Firebase Cloud Messaging has several API endpoints through which you can send push notifications:
- Legacy HTTP Server Protocol - this API receives the default payload structure as appears above.
"data":{ "af":{ "pid":"braze_int", "is_retargeting":"true", "c":"test_campaign" } }
- HTTP V1 API - this API doesn't accept payloads with nested objects like the Legacy API does. The correct payload format should stringify the
af
object. For example:
"data": { "af": "{\"pid\":\"media_int\",\"is_retargeting\":\"true\", \"c\":\"test_campaign\"}" }
- Firebase console UI - you can send push notifications using Firebase console UI. The payload is added at the last stage (Additional options). Under custom data, add af as Key and the payload as Value. See the following screenshot:
{"pid":"MY_MEDIA_SOURCE","is_retargeting":"true","c":"test_campaign"}
Other third-party vendors
Airship API:
{
"audience":"all",
"notification":{
"alert":"A broadcast message",
"extra":{
"af":{
"pid":"urbanairship_int",
"is_retargeting":"true",
"c":"test_campaign"
}
}
},
"device_types":"ios"
}
For more information, see: https://docs.airship.com/api/ua/
Swrve API:
{
"af":{
"pid":"swrve_int",
"is_retargeting":"true",
"c":"test_campaign"
}
}
For more information, see: http://docs.swrve.com/user-documentation/push-notifications/creating-push-notifications/
Braze API:
{
"app_group_id":"getFromBrazeDashboard",
"segment_id":"getFromBrazeDashboard",
"broadcast":true,
"messages":{
"apple_push":{
"alert":"Alert A Message",
"title":"Not Visible, Yet Required",
"body":"Message Body",
"extra":{
"af":{
"pid":"braze_int",
"is_retargeting":"true",
"c":"test_campaign"
}
}
}
}
}
For more information, see Braze push notifications API.
Mixpanel API:
For iOS, see: https://mixpanel.com/help/reference/ios-push-notifications
For Android, see: https://mixpanel.com/help/reference/android-push-notifications
Iterable API:
For iOS, see: https://support.iterable.com/hc/en-us/articles/115000315806
For Android, see: https://support.iterable.com/hc/en-us/articles/115000331943
Localytics API:
For iOS, see: http://docs.localytics.com/dev/ios.html#push-messaging-ios
For Android, see: http://docs.localytics.com/dev/android.html#push-messaging-android
Leanplum API:
See: https://docs.leanplum.com/
Adobe Analytics (Omniture) API:
See: https://marketing.adobe.com/resources/help/en_US/mobile/t_create_push_message.html
Appoxee (Teradata) API:
See: https://appoxee-wiki.atlassian.net/wiki/display/MIC/Push+Message+API
Upsight API:
See: http://help.upsight.com/push/
Accengage API:
For iOS, see: http://docs.accengage.com/display/IOS/iOS#iOS-Notificationscustomparameters
For Android, see: http://docs.accengage.com/display/AND/Android#Android-RetrievingIn-App/Push/InboxandotherCustomParameterswithaBroadcastReceiver
For further information about AppsFlyer retargeting solution, see the following article: