UDLとよくあるお問い合わせ

ハッピーホリデー！本日はわたくしアラがAppsFlyerのアドベントカレンダーを書かせていただきます。

###### 自己紹介
AppsFlyer入社3年目のサポートエンジニアです。弊社入社前はウェブアプリやモバイルアプリのエンジニアをしていました。
毎日AppsFlyerをご利用いただいている皆様からの技術的なお問い合わせやシステムの調査依頼等を対応しています。日本語でお問い合わせいただくと高確率で私が出現します。(全ての言語で対応しておりますのでお気軽にご連絡ください！)

本日は多くの皆様にご利用いただいているUDLというAppsFlyer SDKの機能の一部と、よくあるお問い合わせ、その解決方法をご紹介したいと思います。

## そもそもAppsFlyer SDKで何ができるの？
AppsFlyer SDKでは主にインストールデータやアプリ内イベントデータの送信、アトリビューション時のパラメータの取得が行えます。
アトリビューションとはどの広告(リンク)からアプリがインストールされたかを決定する仕組みで、**AppsFlyer SDKではそのリンクのパラメータが取得可能**という訳です。
アトリビューションや対応プラットフォームにつきましては、弊社ソリューションアーキテクトが書いたこちらの記事を是非ご覧ください。
https://qiita.com/maktag/items/0a6d9a3969393aa8dcb4


## パラメータの取得方法

ではここで、どのようにSDKでパラメータが取得できるのか見ていきましょう。
今回はiOSネイティブアプリ用のAppsFlyer SDKで例を紹介致します。
###### onConversionDataSuccess
```swift
func onConversionDataSuccess(_ installData: [AnyHashable: Any]) {}
```
https://dev.appsflyer.com/hc/docs/ios-sdk-reference-appsflyerlibdelegate#onconversiondatasuccess

こちらのAPIでは新規インストールのきっかけとなった広告のリンクパラメータがDictionary型で取得できます。

###### onAppOpenAttribution
```swift
func onAppOpenAttribution(_ attributionData: [AnyHashable: Any]) {}
```
https://dev.appsflyer.com/hc/docs/ios-sdk-reference-appsflyerlibdelegate#onappopenattribution

こちらのAPIでは既にアプリをインストールしているユーザー(既存ユーザー)がアプリを再び開くきっかけとなった広告のリンクパラメータが取得できます。
Universal Links等でアプリが起動された際にこのAPIが呼ばれるという形です。

アプリ開発者は上記のようなAPIで取得したパラメータ情報を利用し、例えばキャンペーン広告から流入してきたユーザーを特典ページへ遷移する仕組み等を実装することになります。
しかし、モバイルアプリのマーケティングを行なっている方々であればこれらは必要な機能となるかと思いますが、どちらにしても広告からの流入なのにわざわざ複数のAPIを実装するのはあまりやりたくないですよね。

そこで私たちは現在新しいAPIを提供しており、**それがUDLなのです。**



## UDLとは？
Unified Deep Linkingの略であり、名前の通り上記で紹介した2つのAPIの機能を1つのAPI実装でご利用いただけます。

###### didResolveDeepLink
```swift
func didResolveDeepLink(_ result: DeepLinkResult) {}
```
https://dev.appsflyer.com/hc/docs/unified-deep-linking-udl-1

このAPIをご利用いただくと、新規ユーザーと既存ユーザーの広告パラメータどちらも取得可能となります。

サンプルコード
```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  ...
  AppsFlyerLib.shared().deepLinkDelegate = self
  ...
}

extension AppDelegate: DeepLinkDelegate {
    func didResolveDeepLink(_ result: DeepLinkResult) {
        var fruitNameStr: String?
        switch result.status {
        case .notFound:
            NSLog("[AFSDK] Deep link not found")
            return
        case .failure:
            print("Error %@", result.error!)
            return
        case .found:
            NSLog("[AFSDK] Deep link found")
        }
        
        guard let deepLinkObj:DeepLink = result.deepLink else {
            NSLog("[AFSDK] Could not extract deep link object")
            return
        }
        
        // 取得したいパラメータの有無チェックサンプル
        if deepLinkObj.clickEvent.keys.contains("deep_link_sub2") {
            let ReferrerId:String = deepLinkObj.clickEvent["deep_link_sub2"] as! String
            NSLog("[AFSDK] AppsFlyer: Referrer ID: \(ReferrerId)")
        } else {
            NSLog("[AFSDK] Could not extract referrerId")
        }        
      
        fruitNameStr = deepLinkObj.deeplinkValue
        walkToSceneWithParams(fruitName: fruitNameStr!, deepLinkData: deepLinkObj.clickEvent) // 取得したデータでページ遷移処理
    }
}
```
このように、少々めんどくさいパラメータ取得の処理も一箇所にまとめられるという訳です。



## UDLに関するよくあるお問い合わせ
それでは最後にこのUDLをご利用いただいている皆様からよくいただくお問い合わせとその解決方法をご紹介したいと思います。

### UDL APIが呼ばれない
以下の点を確認してみてください！
* deepLinkDelegateプロトコルにselfが代入されていますか？
```swift
AppsFlyerLib.shared().deepLinkDelegate = self
```
* continueUserActivity内で`continue`メソッドが呼ばれていますか？
```swift
AppsFlyerLib.shared().continue(userActivity: NSUserActivity?, restorationHandler: (([Any]?) -> Void)?)
```
https://dev.appsflyer.com/hc/docs/ios-sdk-reference-appsflyerlib#continue

### UDL API内でパラメータが取得できない
貴社独自のドメイン(OneLinkブランドドメイン)をご利用いただいている場合は、`start`メソッドより前に以下の追加実装が必要となります。
```swift
AppsFlyerLib.shared().oneLinkCustomDomains = ["<ドメイン名>"]
```
https://dev.appsflyer.com/hc/docs/ios-sdk-reference-appsflyerlib#onelinkcustomdomains

Firebaseライブラリを同時に利用されている場合は、FirebaseがAppsFlyer SDKよりも先にパラメータ情報を取得してしまうケースがございます。continueUserActivity内でAppsFlyerのリンクであるかどうかの条件を追加し`continue`メソッドが呼ばれるように実装してみてください。

サンプルコード(SceneDelegateご利用の場合)
```swift
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    if let urlString = userActivity.webpageURL?.absoluteString, urlString.contains("<リンクパス等>") {
        AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
    }
}
```


## 最後に
ここまで読んでいただきありがとうございました。この記事が少しでも皆様の参考になりましたら幸いです。
今回ご紹介した内容以外にも私たちは様々なプラグインやWeb SDK等で多くの機能を提供しておりますので機会があればまた何か書きたいと思います。
AppsFlyerをご利用いただく中でお困りの際はお気軽に私たちまでご連絡くださいね！