iOS Legacy APIs

Direct Deep Linking

Overview

Direct deep linking directs mobile users into a specific activity or content in an app, when the app is already installed.

This in-app routing to a specific activity in the app is possible due to the parameters passed to the app when the OS opens the app and the onAppOpenAttribution method is called. AppsFlyer's OneLink ensures that the correct value is passed along with the user's click, thus personalizing the user’s app experience.

Only the deep_link_value is required for deep linking. However, other parameters and values (such as custom attribution parameters) can also be added to the link and returned by the SDK as deep linking data.

The direct deep linking flow works as follows:
Direct Deep Linking flow

  1. 用户点击OneLink短URL。

  2. iOS读取应用程序的关联域权限。

  3. iOS打开应用程序。

  4. AppsFlyer SDK在应用程序内部触发。

  5. AppsFlyer SDK检索OneLink数据。

    • 在短URL中,数据从AppsFlyer服务器中的短URL解析器API中检索。
    • 在长URL中,直接从长URL中检索数据。
  6. AppsFlyer SDK triggers onAppOpenAttribution() with the retrieved parameters and cached attribution parameters (e.g.install_time).

  7. Asynchronously, onConversionDataSuccess() is called, holding the full cached attribution data. (You can exit this function by checking if is_first_launch is true.)

  8. onAppOpenAttribution() uses the attributionData map to dispatch other activities in the app and pass relevant data.

    • 这为用户创造了个性化体验,也是OneLink的主要目标。

Procedures

To implement the onAppOpenAttribution method and set up the parameter behaviors, the following action checklist of procedures must be completed.

程序核对表

  1. Deciding app behavior and deep_link_value (and other parameter names and values) - with the marketer
  2. Planning method input, i.e. deep_link_value (and other parameter names and values) - with the marketer
  3. Implementing the onAppOpenAttribution() logic
  4. Implementing the onAttributionFailure() logic

决定应用程序行为

要决定点击链接时应用程序的行为是什么

从营销人员处获取:点击链接时的预期行为。

计划方法输入

When a OneLink is clicked and the user has the app installed on their device, the onAppOpenAttribution method is called by the AppsFlyer SDK. This is referred to as a retargeting re-engagement.

The onAppOpenAttribution method gets variables as an input like this: AnyHashable: Any.
The input data structure is described here.

实现onAppOpenAttribution()逻辑

The deep link opens the onAppOpenAttribution method in the main activity. The OneLink parameters in the method input are used to implement the specific user experience when the application is opened.

Code Example:

func onAppOpenAttribution(_ attributionData: [AnyHashable: Any]) {
    //Handle Deep Link Data
    print("onAppOpenAttribution data:")
    for (key, value) in attributionData {
        print(key, ":",value)
    }
    walkToSceneWithParams(params: attributionData)
}

// User logic
fileprivate func walkToSceneWithParams(params: [AnyHashable:Any]) {
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true, completion: nil)

    var fruitNameStr = ""

    if let thisFruitName = params["deep_link_value"] as? String {
        fruitNameStr = thisFruitName
    } else if let linkParam = params["link"] as? String {
        guard let url = URLComponents(string: linkParam) else {
            print("Could not extract query params from link")
            return
        }
        if let thisFruitName = url.queryItems?.first(where: { $0.name == "deep_link_value" })?.value {
            fruitNameStr = thisFruitName
        }
    }

    let destVC = fruitNameStr + "_vc"
    if let newVC = storyBoard.instantiateVC(withIdentifier: destVC) {

        print("AppsFlyer routing to section: \(destVC)")
        newVC.attributionData = params

        UIApplication.shared.windows.first?.rootViewController?.present(newVC, animated: true, completion: nil)
    } else {
        print("AppsFlyer: could not find section: \(destVC)")
    }
}

⇲ Github链接:Swift

实现onAttributionFailure()逻辑

The onAttributionFailure method is called whenever the call to onAppOpenAttribution fails. The function should report the error and create an expected experience for the user.

func onAppOpenAttributionFailure(_ error: Error) {
    print("\(error)")
}

⇲ Github链接:Swift

延迟深度链接

❗️

注意事项

Deferred deep linking using the legacy method of onConversionDataSuccess may not work for iOS 14.5+, since it requires attribution data that may not be available due to privacy protection.
We recommend using unified deep linking (UDL). UDL conforms to the iOS 14.5+ privacy standards and only returns parameters relevant to deep linking and deferred deep linking: deep_link_value and deep_link_sub1-10. Attribution parameters (such as media_source, campaign, af_sub1-5, etc.), return null and can’t be used for deep linking purposes.
Learn more

Overview

延迟深度链接会将新用户首先引导到正确的应用商店安装应用程序,然后在第一次打开后,指向特定的应用程序体验(例如,应用程序中的特定页面)。

When the user first launches the app, the onConversionDataSuccess callback function receives both the conversion data of the new user, and OneLink data. The OneLink data makes in-app routing possible due to the deep_link_value or other that is passed to the app when the OS opens the app.

Only the deep_link_value is required for deep linking. However, other parameters and values (such as custom attribution parameters) can also be added to the link and returned by the SDK as deep linking data. The AppsFlyer OneLink ensures that the correct parameters are passed along with the user's click, thus personalizing the user’s app experience.

The marketer and developer must coordinate regarding desired app behavior and deep_link_value. The marketer uses the parameters to create deep links, and the developer customizes the behavior of the app based on the value received.

开发者有责任确保在应用程序中正确处理参数,无论是应用内路由还是个性化链接中的数据。

The deferred deep linking flow works as follows:
Deferred Deep Linking flow!

  1. 用户在未安装该应用程序的设备上点击OneLink。
  2. AppsFlyer记录点击并将用户重定向到正确的应用商店或登陆页。
  3. 用户安装应用程序并启动它。
  4. AppsFlyer SDK被初始化,并且安装归因于AppsFlyer服务器。
  5. The SDK triggers the onConversionDataSuccess method. The function receives input that includes both the deep_link_value, and the attribution data/parameters defined in the OneLink data.
  6. The parameter is_first_launch has the value true, which signals the deferred deep link flow.
    The developer uses the data received in the onConversionDataSuccess function to create a personalized experience for the user for the application’s first launch.

Procedures

To implement the onConversionDataSuccess method and set up the parameter behaviors, the following action checklist of procedures need to be completed.

  1. Deciding app behavior on first launch, and deep_link_value (and other parameter names and values) - with the marketer
  2. Planning method input, i.e. deep_link_value (and other parameter names and values) - with the marketer
  3. Implementing the onConversionDataSuccess() logic
  4. Implementing the onConversionDataFail() logic

决定应用程序在首次启动时的行为

决定应用程序在首次启动时的行为

从营销人员处获取:当链接被点击并首次打开应用程序时的预期行为。

计划方法输入

For deferred deep linking, the onConversionDataSuccess method input must be planned and the input decided in the previous section (for deep linking) is made relevant for the first time the app is launched.

The onConversionDataSuccess method gets the deep_link_value and other variables as an input like this: AnyHashable: Any.

映射中包含两种数据:

  • 归因数据
  • Data defined by the marketer in the link (deep_link_value and other parameters and values)
    Other parameters can be either:
    • AppsFlyer官方参数。
    • 由营销人员和开发者选择的自定义参数和值。
    • 此处描述输入数据结构。

The marketer and developers need to plan the deep_link_value (and other possible parameters and values) together based on the desired app behavior when the link is clicked.

To plan the deep_link_value, and other parameter names and values based on the expected link behavior:

  1. 告诉营销人员需要哪些参数和值才能实现所需的应用程序行为。
  2. Decide on naming conventions for the deep_link_value and other parameters and values.
    Note:
    • 自定义参数不会出现在AppsFlyer中收集的原始数据中。
    • 转化数据不会返回名为“name”,有着小写“n”的自定义参数。

实现onConversionDataSuccess()逻辑

When the app is opened for the first time, the onConversionDataSuccess method is triggered in the main activity. The deep_link_value and other parameters in the method input are used to implement the specific user experience when the app is first launched.

为了实现该逻辑

  1. 根据选择的参数和值实现逻辑。请参阅以下代码示例。
  2. 完成后,向营销人员发送确认,确认应用程序有相应的行为。

示例代码

// Handle Organic/Non-organic installation
func onConversionDataSuccess(_ data: [AnyHashable: Any]) {

    print("onConversionDataSuccess data:")
    for (key, value) in data {
        print(key, ":", value)
    }

    if let status = data["af_status"] as? String {
        if (status == "Non-organic") {
            if let sourceID = data["media_source"],
                let campaign = data["campaign"] {
                print("This is a Non-Organic install. Media source: \(sourceID)  Campaign: \(campaign)")
            }
        } else {
            print("This is an organic install.")
        }
        if let is_first_launch = data["is_first_launch"] as? Bool,
            is_first_launch {
            print("First Launch")
            if let fruit_name = data["deep_link_value"]
            {
                // The key 'deep_link_value' exists only in OneLink originated installs
                print("deferred deep-linking to \(fruit_name)")
                walkToSceneWithParams(params: data)
            }
            else {
                print("Install from a non-owned media")
            }
        } else {
            print("Not First Launch")
        }
    }
}

⇲ Github链接:Swift

实现onConversionDataFailure()逻辑

The onConversionDataFailure method is called whenever the call to onConversionDataSuccess fails. The function should report the error and create an expected experience for the user.

To implement the onConversionDataFailure method:

func onConversionDataFail(_ error: Error) {
    print("\(error)")
}

⇲ Github链接:Swift

iOS示例有效负载

有关通用链接、URI方案和延迟的深度链接,请参阅以下示例有效负载。示例包含完整的有效负载,这与OneLink自定义链接设置页面中所有参数包含数据的时间相关。

注意:有效负载以映射形式返回。但是,为了清楚起见,以下示例有效负载以JSON形式显示。

Universal Links

输入到 onAppOpenAttribution(_ attributionData: [AnyHashable: Any])

{
   "af_ad": "my_adname",
   "af_adset": "my_adset",
   "af_android_url": "https://isitchristmas.com/",
   "af_channel": "my_channel",
   "af_click_lookback": "20d",
   "af_cost_currency": "USD",
   "af_cost_value": 6,
   "af_dp": "afbasicapp://mainactivity",
   "af_ios_url": "https://isitchristmas.com/",
   "af_sub1": "my_sub1",
   "af_sub2": "my_sub2",
   "c": "fruit_of_the_month",
   "campaign": "fruit_of_the_month",
   "fruit_amount": 26,
   "fruit_name": "apples",
   "is_retargeting": true,
   "link": "https://onelink-basic-app.onelink.me/H5hv/6d66214a",
   "media_source": "Email",
   "pid": "Email"
}
{
   "path": "/H5hv",
   "af_android_url": "https://my_android_lp.com",
   "af_channel": "my_channel",
   "host": "onelink-basic-app.onelink.me",
   "af_adset": "my_adset",
   "pid": "Email",
   "scheme": "https",
   "af_dp": "afbasicapp://mainactivity",
   "af_sub1": "my_sub1",
   "fruit_name": "apples",
   "af_ad": "my_adname",
   "af_click_lookback": "20d",
   "fruit_amount": 16,
   "af_sub2": "my_sub2",
   "link": "https://onelink-basic-app.onelink.me/H5hv?pid=Email&c=fruit_of_the_month&af_channel=my_channel&af_adset=my_adset&af_ad=my_adname&af_sub1=my_sub1&af_sub2=my_sub2&fruit_name=apples&fruit_amount=16&af_cost_currency=USD&af_cost_value=6&af_click_lookback=20d&af_dp=afbasicapp%3A%2F%2Fmainactivity&af_ios_url=https%3A%2F%2Fmy_ios_lp.com&af_android_url=https%3A%2F%2Fmy_android_lp.com",
   "af_cost_currency": "USD",
   "c": "fruit_of_the_month",
   "af_ios_url": "https://my_ios_lp.com",
   "af_cost_value": 6
}

URI scheme

输入到 onAppOpenAttribution(_ attributionData: [AnyHashable: Any])

{
  "af_click_lookback ": "25d",
  "af_sub1 ": "my_sub1",
  "shortlink ": "9270d092",
  "af_deeplink ": true,
  "media_source ": "Email",
  "campaign ": "my_campaign",
  "af_cost_currency ": "NZD",
  "host ": "mainactivity",
  "af_ios_url ": "https://my_ios_lp.com",
  "scheme ": "afbasicapp",
  "path ": "",
  "af_cost_value ": 5,
  "af_adset ": "my_adset",
  "af_ad ": "my_adname",
  "af_android_url ": "https://my_android_lp.com",
  "af_sub2 ": "my_sub2",
  "af_force_deeplink ": true,
  "fruit_amount ": 15,
  "af_dp ": "afbasicapp://mainactivity",
  "link ": "afbasicapp://mainactivity?af_ad=my_adname&af_adset=my_adset&af_android_url=https%3A%2F%2Fmy_android_lp.com&af_channel=my_channel&af_click_lookback=25d&af_cost_currency=NZD&af_cost_value=5&af_deeplink=true&af_dp=afbasicapp%3A%2F%2Fmainactivity&af_force_deeplink=true&af_ios_url=https%3A%2F%2Fmy_ios_lp.com&af_sub1=my_sub1&af_sub2=my_sub2&af_web_id=56441f02-377b-47c6-9648-7a7f88268130-o&campaign=my_campaign&fruit_amount=15&fruit_name=apples&is_retargeting=true&media_source=Email&shortlink=9270d092",
  "af_channel ": "my_channel",
  "is_retargeting ": true,
  "af_web_id ": "56441f02-377b-47c6-9648-7a7f88268130-o",
  "fruit_name ": "apples"
}
{
  "af_ad ": "my_adname",
  "fruit_name ": "apples",
  "host ": "mainactivity",
  "af_channel ": "my_channel",
  "link ": "afbasicapp://mainactivity?af_ad=my_adname&af_adset=my_adset&af_android_url=https%3A%2F%2Fmy_android_lp.com&af_channel=my_channel&af_click_lookback=25d&af_cost_currency=NZD&af_cost_value=5&af_deeplink=true&af_dp=afbasicapp%3A%2F%2Fmainactivity&af_force_deeplink=true&af_ios_url=https%3A%2F%2Fmy_ios_lp.com&af_sub1=my_sub1&af_sub2=my_sub2&af_web_id=56441f02-377b-47c6-9648-7a7f88268130-o&campaign=my_campaign&fruit_amount=15&fruit_name=apples&is_retargeting=true&media_source=Email",
  "af_deeplink ": true,
  "campaign ": "my_campaign",
  "af_sub1 ": "my_sub1",
  "af_click_lookback ": "25d",
  "af_web_id ": "56441f02-377b-47c6-9648-7a7f88268130-o",
  "path ": "",
  "af_sub2 ": "my_sub2",
  "af_ios_url ": "https://my_ios_lp.com",
  "af_cost_value ": 5,
  "fruit_amount ": 15,
  "is_retargeting ": true,
  "scheme ": "afbasicapp",
  "af_force_deeplink ": true,
  "af_adset ": "my_adset",
  "media_source ": "Email",
  "af_cost_currency ": "NZD",
  "af_dp ": "afbasicapp://mainactivity",
  "af_android_url ": "https://my_android_lp.com"
}

Deferred deep linking

输入到 onConversionDataSuccess(_ data: [AnyHashable: Any])

{
  "adgroup": null,
  "adgroup_id": null,
  "adset": null,
  "adset_id": null,
  "af_ad": "my_adname",
  "af_adset": "my_adset",
  "af_android_url": "https://isitchristmas.com/",
  "af_channel": "my_channel",
  "af_click_lookback": "20d",
  "af_cost_currency": "USD",
  "af_cost_value": 6,
  "af_cpi": null,
  "af_dp": "afbasicapp://mainactivity",
  "af_ios_url": "https://isitchristmas.com/",
  "af_siteid": null,
  "af_status": "Non-organic",
  "af_sub1": "my_sub1",
  "af_sub2": "my_sub2",
  "af_sub3": null,
  "af_sub4": null,
  "af_sub5": null,
  "agency": null,
  "campaign": "fruit_of_the_month ",
  "campaign_id": null,
  "click_time": "2020-08-12 15:08:00.770",
  "cost_cents_USD": 600,
  "engmnt_source": null,
  "esp_name": null,
  "fruit_amount": 26,
  "fruit_name": "apples",
  "http_referrer": null,
  "install_time": "2020-08-12 15:08:33.335",
  "is_branded_link": null,
  "is_first_launch": 1,
  "is_retargeting": true,
  "is_universal_link": null,
  "iscache": 1,
  "match_type": "probabilistic",
  "media_source": "Email",
  "orig_cost": "6.0",
  "redirect_response_data": null,
  "retargeting_conversion_type": "none",
  "shortlink": "6d66214a"
}