FirebaseのDynamic Linksを使ってWebからアプリに誘導してみた

## 背景
Webからアプリに遷移させたくてFirebaseの[Dynamic Links](https://firebase.google.com/docs/dynamic-links/)を使って実装をしてみました。
やりたかった事は、WEB側でアプリのインストール判定をして、アプリに飛ばす or ストアに飛ばすといった事でした。
自前で実装するよりも大分楽だったので、使ってみて良かった点と躓いた点を書きたいと思います。他の方が使うときの参考になれば良いなぁと思います。

## Dynamic Linksの良いところ

- **簡単に設定することができる**  
Dynamic Linksの生成は、Firebaseのコンソール画面から聞かれることをポチポチと入力をするだけです。
また、iOSとAndroidの両OSを同時に設定することも出来るため、リンクの管理も楽です。
- **OSを気にする必要がない**  
Dynamic Linksを使う前は、OSの判定やOSのバージョンによって処理を分けるといったことをやっていましたが、Dynamic Linksを使えば生成されたURLを貼るだけです。
- **関連付けファイルを勝手に作ってくれる**  
自前でやる場合、iOSのUniversal Linkであれば`apple-app-site-association`、AndroidのApp Linksであれば`assetlinks.json`といったファイルをWEBサーバに配置する必要がありますが、全てFirebaseが用意してくれます。Firebaseで用意されたドメイン配下に勝手に置かれるイメージです。
- **クリック数の集計が出来る**  
以下の図のように、Dynamic Links が押されたイベント数も勝手に集計してくれます。Firebaseのコンソール画面上でいつでも確認できます。（すごいシンプルですが・・・）
<img width="960" alt="dynamic linksの集計.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/538625a4-2bdd-dcd3-def4-7bdba8d9c16c.png">


## Dynamic Linksの良くないところ
- **一度作ると削除出来ない**  
何故か一度作ると編集も削除も出来ません。。今後出来るようになることを期待してます。
- **動的なURLは対応していない？**  
https://www.hoge.com/items/:item_id といった可変するURLは対応していませんでした。自分はこれをDynamic Linksを使ってやりたかったのですが、試行錯誤した結果うまくいかず、結果的にqueryパラメータで渡すというやりかたに落ち着きました。

## 導入手順
Firebaseのプロジェクトの初期設定はここでは割愛します。
コンソール上で親切に教えてくれるので特に躓くことはないと思います。


### Dynamic Linksを生成する
Firebaseのコンソール画面で[**Dynamic Links**]を選びます。
そして[**新しいダイナミック リンク**]を押します。
<img width="1072" alt="dl1.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/46f2a96a-ec52-eb45-6b92-628481312fec.png">



**１. Set up your Dynamic Links** 
ディープリンクのURIとリンク名を入力します。
リンク名はコンソール上で表示される名前です。
<img width="686" alt="スクリーンショット 2016-11-07 1.18.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/bb7a39fb-772c-4e02-3667-ea7b5cc05607.png">



**2. Define link behavior for Android**
Androidでの挙動を設定します。
今回はAndroidアプリに遷移させたかったので「Androidアプリ内でディープリンクを開きます」を選びました。また、アプリがインストールされていない場合はストアに遷移させたかったので「アプリのGoogle Playページ」を選びました。
<img width="683" alt="dl2.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/4f196904-6967-af55-6c98-4bd402103389.png">



**3. Define link behavior for iOS**
次にiOSでの挙動を設定します。
こちらもiOSアプリに遷移させたかったので「ディープリンクをiOSアプリで開く」を選びました。同様にアプリがインストールされていない場合はストアに遷移させたいので「アプリのApp Storeページ」を選びました。
<img width="681" alt="dl3.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/57ad5682-f311-ff2c-89a6-c0a6ebb53e5d.png">

**4.Track a campaign with UTM parameters (optional)**
**5.Add social meta tags for better sharing (optional)**
こちらはoptionalでキャンペーンコードの設定や、ソーシャルタグの上書きが出来るようでしたが、特に必要なかったので設定しませんでした。


最後に「**ダイナミック リンクを生成**」を押すとコンソール上に表示されるようになります。
<img width="983" alt="dl4.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/1642e9a1-37fd-5bde-ee49-de2efbce71d5.png">

### アプリへ誘導する側（WEB）の設定
WEBからアプリに遷移させたいので、WEB側では先ほど生成されたDynamic Linksを仕込むだけです。

```html
<a href="https://app_code.app.goo.gl/4M9Y">アプリで開く</a>
```

### iOSの設定

Podfileに以下を追加して pod install します。

```
pod 'Firebase/DynamicLinks'
```

XCodeを開き[**Capabilities**]の[**Associated Domains**]をONにしてDynamic Linksの生成で出来たリンクのドメインをココに追加します。
<img width="879" alt="スクリーンショット 2016-11-07 1.51.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/a48a5776-db58-d868-54d9-5052882498f3.png">

AppDelegate.swiftを開き、以下の実装を追加していきます。

```swift
import Firebase
import FirebaseDynamicLinks

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        FIROptions.defaultOptions().deepLinkURLScheme = self.CUSTOM_URL_SCHEME
        FIRApp.configure()

        return true
    }

    // iOS9以降で呼ばれる
    func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
        return application(app, openURL: url, sourceApplication: nil, annotation: [:])
    }
    
    // カスタムURLスキームを受信したとき、インストールした後にアプリが初めて開かれたときに呼ばれる
    func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
        if let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLinkFromCustomSchemeURL(url) {
            if self.handleUniversalLink(URL: dynamicLink.url!) {
                return true 
            }
        }
        
        // カスタムURLスキームのハンドリング
        return openURL(url)
    }

    @available(iOS 8.0, *)
    func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
        
        if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
            
            if let url = userActivity.webpageURL {
                let handled = FIRDynamicLinks.dynamicLinks()?.handleUniversalLink(url) { (dynamiclink, error) in
                    if !self.handleUniversalLink(URL: (dynamiclink?.url)!) {
                        // コンテンツをアプリで開けない場合は、Safariに戻す
                        UIApplication.sharedApplication().openURL(userActivity.webpageURL!)
                    }
                }
                return handled!
            }
        }
        
        return true
    }
    
    private func handleUniversalLink(URL url: NSURL) -> Bool {
        
        guard let host = url.host, let path = url.path else {
            return false
        }
        
        if host == "www.hoge.com" && path.hasPrefix("/app/top") {
            
            // ここでアプリトップ画面へ遷移させる処理
            
            return true
        }
        
        return false
    }

```

### Androidの設定
Androidはあまり詳しくないのでソースコードを書きませんが、Firebaseのドキュメントの通りで沿って実装するだけで特に難しいことはありませんでした。
- https://firebase.google.com/docs/dynamic-links/android
- http://tech.furyu.jp/blog/?p=4850

## 所感
アプリ側のSDKの導入も簡単で、WEB側は生成されたリンクを貼るだけだったので簡単に実装出来てしまいました。
ただ、良くないところでも書いたように動的なURLを使う場合は少し工夫が必要でしたので、その件については別で書きたいと思います。