Firebase Dynamic Links導入事例

行木千春氏:よろしくお願いします。株式会社サイバーエージェントの行木千春です。

自己紹介なんですけれども、2015年中途入社で、それ以降ずっとAmebaでiOSエンジニアをしています。WWDCに2回参加していまして、2015年にUniversal Linksが発表されて以来、ずっとディープリンクの仕組みを追っています。

さっそく「Dynamic Linksとは何か?」なんですが、特徴的なUIがありまして、(スライドを指して)これです。

「アプリで開く」ボタンですね。これを実現してくれるものになります。

これをタップすると、ユーザーの状態によって最適な遷移先に送客してもらえます。インストール済みでしたらアプリが開いて、リンクに該当する画面に遷移します。

まだインストールしていないユーザーに対してはストアを表示して、ダウンロードしてから起動してもらうと、リンクに該当する画面に遷移するというものになります。この「リンクに該当する画面に遷移する」っていうのを、「ディープリンク処理」と呼んだりします。

Dynamic Linksの特徴として、完全に無料です。本家Googleのドキュメントがしっかりしていまして、SDKはオープンソースです。iOS、Androidのサポートがしっかりしています。あとはパッケージングということで、短縮URLと解析の機能も付いています。

想定されている利用シーンとしては、まずはなんと言っても「アプリで開く」ボタンですね。アプリへの導線です。そして、プロモーション用のリンクをSNSで拡散するということも可能になっています。あとおもしろいところでは、アプリのユーザー同士でリンクを共有する、交換するような使い方も考えられています。

具体的なリンクの例を出してみました。アプリ用にサブドメインを取得して、そこにパラメータをたくさん付けていって使うということになります。実体は、必要な情報をたくさん付けられたURLです。これをいろんなところに仕込んで使うと(いうことです)。

主なパラメータとして、なんと言っても重要なのがこのlinkパラメータで、ここにディープリンクを設定します。アプリのバンドルIDなど、必要な情報をどんどん追加していきます。

ちょっとおもしろいところで、リッチプレビュー用のパラメータも付けられまして。これを付けると、Twitterなどでリッチなリンクを表示することができます。

ストアプレビューについて

もう1つ、ストアプレビューというものがあります。

ストアに遷移する前にFirebaseによって表示されるプレビューでして、いまのところiOSのみの機能です。「これ、何のために出してるんだろう?」って最初はわからなかったんですけれども、どうもストアのインストールを経由して、ユーザーの同一性を担保するっていうのがけっこう難しい、というかできなくてですね。

それを補助してやるために、ここ、すごく小さい文字なんですけど、「Save my place in the App」って書いてるんですね。ここのチェックマークを入れてやることで、クリップボードに情報をコピーして、それを補助的に使ってやることで、ユーザーの同一性を担保するということをしているようです。

ただ、この見た目はあんまりよろしくないので、「efr=1」というパラメータを付けると、実は表示がスキップ可能だったりします。

先ほどのリッチリンクのパラメータを指定すると、少しだけリッチにはできます。全部のパラメータと詳細は、公式ドキュメントをご覧ください。

生成には3つの方法があります。手動、コンソール上で作成、SDKで作成ですね。

コンソールはこんな感じです。

「新しいダイナミックリンク」っていうところをタップしますと、先ほどのパラメータをどんどん入れられるダイアログが出てきて、作成できます。

デバッグもできまして、linkに「d=1」というパラメータを付けてやると、こんな素敵な画面が出てきます。上のほうにワーニングとかも出てくるので、何かバグがあったときとか、問題があったときに助かります。

この、下で切れてるところがたぶんiOS的には気になると思うんですけども、大きくするとこのようになっています。

インストールしてるかどうかっていう判定にはUniversal Linksを使ってるっていうのがこれでわかります。

短縮URL機能の紹介です。このURLを短くすることができます。解決時にクリック数などが集計されます。取れるイベントは、ここにあるとおりです。

実はコンソール上で作成できるURLも短縮URLでして、その場合だけなんですけれども、集計結果もコンソールに出てきてくれます。

けっこう良いことがある短縮URL機能なんですけれども、1つイケてないところがありまして、リンクを解決するために受信後にどうしても通信を1回行わなければいけないので、スムーズなディープリンク処理の妨げになってしまうようなケースが出てきます。

iOSアプリに組み込む

やっと組み込む話になりました。まず、FDLに利用されているiOSの仕組みについて少し話そうと思います。主にUniversal Linksについてですね。iOS 9で登場したディープリンクの仕組みは、ドメインとアプリを関連付けてやって、リンクを開くときに該当のアプリがあったら、そのアプリを起動してやるという仕組みになります。

動作の特徴として、同一ドメイン内の場合はアプリを起動しません。それから、アプリを起動するかどうかは、長押しのメニューでユーザーが選択可能だったりします。

あと、注意点としては、ユーザーの端末のOSによって制御されている機能なので、挙動を変えるトリガーになるのは、アプリのアップデートだったりします。なので、手軽に切り戻しをするとかそういうことが難しいです。

導入の流れは、ここに書いてある通りで、順番に見ていきますね。

まず、プロジェクトにアプリを結び付けます。

指示どおりにポチポチとコンソールでやっていくんですけれども、アプリの情報を入力していって、設定ファイルをダウンロードして、ビルドするというようなものになっています。

1個だけ注意点があって、「チームID」って書いてるんですけれども、Provisioning ProfileのApp IDのPrefixのほうを入れてください。

SDKもCocoaPodsで入れます。

Firebaseコンソールでサブドメインを取得します。先ほど言っていたものです。

これ「早い者勝ちかな」と思ってたんですけれども、amebloというのを取ろうとしたらこんな画面が出てきまして。

「『ameblo』ブランドを保護するため、このドメインはameblo.jpのオーナー用に予約されています」と書かれているんですよ(笑)。こういうことをやった覚えがなかったんですけど、手順どおりにやってみたら無事に取ることができました。

そして、Entitlementsに先ほど取ったドメインを追加してやって、Universal Linksの準備をしてやります。

受信処理の実装

いよいよ実装ですね。Firebaseをインポートして、FirebaseApp.configure()で共通インスタンスをセットアップします。

あとやることは、アプリに渡ってきたURLをパースして、リンクを取り出して、そのリンクを見て、該当する画面に遷移させてやるということなんですけれども、このパースのところにSDKを使います。

SDKの中を見てみましょう。処理を行うインターフェースは、FIRDynamicLinks.hに書かれています。1つお断りしておきますと、実際はObjective-Cですが、Swiftで書きました(笑)。

だいぶ文字文字してるんですけれども、このなかで重要なのは、というか使うのは、dynamiclink(fromCustomSchemeURL:)という、カスタムスキーマURLをパースするものと、handleUniversalLink(_:completion:)という、長いURL、短いURLも処理できるメソッドです。

このDynamicLinkというオブジェクトがありまして、このurlのところにFDLのlinkが入ってくるというかたちになります。

実装で直面した問題

それで実装してみたら、いろいろとあったわけですよ(笑)。そういうことをこれからご紹介していこうと思います。

テストチームから「テストで何度もリンクを踏んでいたためか、リンクを踏んでいなくてもアプリを起動したらディープリンク処理が走るようになってしまいました」というのが来ました。「efr=1」を指定して、プレビューページを飛ばすようにしていたんですね。

この場合は、ユーザーの同一性というのが保証されません。なのでタイムスタンプだったり、いろんな情報を組み合わせて、「けっこう苦しいことをやってるのかな?」というのがここで見え隠れして、ちょっとおもしろかったです。

こういった不確実性があるので、何かを確定するような処理の前には、必ず確認を入れてやらなきゃいけないのかなっていうのがあります。これについては時間経過で解消しました。

ディレクターさんからも来ました、「たまに起動後すぐではなく、少し遅れて表示されるんだけど大丈夫?」。このときは長いままのURLだったので、すぐに発動するはずだったんですね。

デバッグしてみたらSDKの短いURLかどうかを判定するメソッドから、なんとtrueが返ってきていました。長いURLなのに。

実際にOSSのコードを見てみたら、長いリンクかどうかを見るときに、パスの長さを見ていたんですけれども、パスとして「/」が入っていたときに、短いリンクだと判定されてしまうようなコードになっていまして、これはワークアラウンドで対応しました。

デザイナーさんからも「リンクを踏むのが2回目だから、表示されないんですね!」って来たんですけれども、不具合だったんですね。

何が起こっていたかというと、短縮URLの解決にときどき失敗してしまっていました。ネットワーク通信が必要になるわけですけれども、「application(_continue:restorationHandler:)」はこのタイミングではアプリが前面に来てないことがあって、そのときに通信をしようとして、そうするとときどき通信エラーが起こってしまう。これはタイミングを調整して対応しました。

まだあります。

フロントエンジニアさんから、「アプリをインストール済みなのに、ストアに行ってしまう端末があるんですけど」と来ました。

これはUniversal Linksを利用してるがゆえの課題でして、どちらで開くかはユーザーが選べるという特徴があったと思うんですけれども、この端末は該当ドメインをアプリで開かないようにしていたということです。

このときにストアに行くと、一応インストールボタンではなく「開く」ボタンにはなっているんですけれども、このボタンで開いたときには残念ながらディープリンク処理は行われませんでした。「プレビューページを経由したら、あるいは……?」と思ってるんですけどまだ試せていなくて、こちらについては未解決です。

「みなさん、いっぱい見ていただいてありがとうございます」(と、チームには)すごく感謝しています。

運用するにあたって行ったこと

それでは、実際に運用するにあたって準備したことを紹介します。

まずは何よりも存在を知ってもらう必要があるので、勉強会を開催しました。

それから、「簡単かつ安全に使えるように」ということで。

実際に使うのはキャンペーンの担当者だったりするわけです。彼らがリンクを作成して、管理して分析が手軽にできて、変な失敗がないように、というものが求められました。

いろいろと考えた結果なんですけれども、一番シンプルにやっていこうということで、まずはlinkを入力したら長いFDLが生成されるスプレッドシートを用意しました。ちょっと原始的なんですけれども。

あと、クリックでしたり、そういった計測に関しては、Amebaでもともと利用している既存の仕組みを使うことにしました。だいたいこんな感じの工夫をして、リリースに至っています。

最後にApp Store ConnectのApp Analyticsのパラメータについてご紹介します。

これをFDLに付けると、なんとApp Analyticsのほうで、どのリンクからのインストールかというものが、キャンペーンページに出てきてくれたりします。ただ、ちょっと扱いづらいので、ここにまとめてみました。

ctっていうのがキャンペーン名で、40文字以内にする必要があります。これだけ付けても集計はしてくれなくて、ptというプロバイダIDを付ける必要があります。こちらはApp Store Connectで確認することができます。

もう1つ、これには「デバッグしづらいな」と思ったんですけれども、結果で表示されるには5つ以上のApple IDにインストールされる必要があります。しかも、診断情報の送信に同意したユーザーのみの数字なので、実際のユーザーの数字というよりは、比較して、「どのキャンペーンが刺さってるのか?」みたいな、そういったことに使う感じになります。

最後に所感で、まとめに代えさせていただきます。

このあたりの関連技術は、セキュリティと利便性のトレードオフというか、セキュリティが向上するにつれて、アプリ間でユーザーの行動をトラッキングするとか、そういったことが難しくなってるなという印象です。

ただ、Firebase Dynamic Linksは必要十分な機能を持っていますし、とくに同一ドメイン内でのアプリ導線っていうのがUniversal Linksでは実現できないことなので、そこには非常に「使いやすいものだな」と思っています。

リリースしたてで、実は今週(リリースしたばかり)なんですけれども、ドキドキしながら見守ってるところです(笑)。

ご清聴ありがとうございました。

(会場拍手)