RoomClip 開発者ブログ

[Android] Firebase Dynamic Linksを試してみた!

こんにちは。
TunnelでAndroidアプリの開発を担当しています冨永です。

RoomClipでは昨年、主要なページを対象にAppIndexingの対応を行いました。
これによりWebの検索からシームレスにアプリを開くことができるようになっています。

また検索結果からだけではなく、RoomClipのページ内に「アプリで見る」等のボタンを配置してアプリを開くということもできるようになりました。
しかし、AppIndexingはアプリをインストールしていることが前提となっています。

そこでアプリをインストールしていない方にもWebから快適にアプリを使用していただくために、Firebaseの機能の1つであるDynamic Linksを導入したい!と思い、今回実際にリンクを作成して動作を確認してみました。


Dynamic Linksとは?

Firebaseの機能

Firebaseは、Google I/O 2016で話題となった開発をサポートするモバイルプラットフォームです。Firebaseには、Analyticsを中心に様々な機能があります。

Dynamic Linksはその中でもGROWカテゴリに属する機能で、「さまざまプラットフォームで最適に動作するよう、動的に動作を変更できる便利な URL です」と紹介されています。

Dynamic Linksは、リンクを開いたユーザーの端末にアプリがインストールされていれば、そのリンクに紐づくコンテンツをアプリ上で表示し、インストールされていなければ、指定したGoogle Play ストアのページが開きインストールすることができます。
それだけでなく、インストール後も開いたURLを取得することができ適切にユーザーの求めるコンテンツを提供することができます。


実際に試してみる!

それでは、実際にリンクを作成して動かしてみたいと思います。

Firebaseのコンソールでリンクを作成

Firebaseのプロジェクト作成方法・初期設定は割愛します。

左メニューからDynamicLinksを選択 左メニューからDynamic Linksを選択します。
パッケージ名やIDが公的に入手可能なアセット/関連ファイルに追加されますがいいですか?と聞かれるので内容を確認して「始める」をクリックします。

Androidのアセットに関してはApp Links、iOSの関連ファイルに関してはUniversal Linksを確認してください。

ディープリンクURLを設定 質問に答えていくことでリンクが作成されます。
まず、ディープリンクURLとダイナミックリンク名を設定します。リンク名はコンソール画面での判別用の名前です。ディープリンクURLは、タグページがすでにディープリンクに対応しているのでこちらを使用します。

ちなみに、このURLでは西海岸インテリアのタグがついた実例写真一覧が表示されます。RoomClip Award 2016で見事1位に輝いた2016年主役のインテリアスタイルです。ぜひチェックしてみてください!

Androidでの動きを設定 今回はiOSでの動作確認は割愛します。

Androidではアプリでディープリンクを開き、インストールされていない場合はGoogle Play ストアへ遷移するように設定します。
カスタムURLやアプリのバージョンで動きを変えることもできるのでサービスに合わせて設定してください。

残りの項目では、解析用のパラメータ設定やリンクがシェアされた際のプレビュータイトルなどの指定ができます。必要な場合は設定してください。

一通り設定して「ダイナミックリンクを作成」ボタンをクリックするとURLが作成されます。 URLが作成される

動作を確認

それでは、実際にリンクを開いて動作を確認していきたいと思います。 まず以下の2つの場合を確認しました。使用したアプリは、記事公開時点でGoogle Play ストアに公開されているものでディープリンクに対応しています。

  1. アプリをインストールしていない状態でリンクを開く
  2. アプリをインストールした状態でリンクを開く

1. アプリをインストールしていない状態でリンクを開く

コンソールで設定したRoomClipのGoogle Play ストアのページが開きました。
ストアでインストール完了後、通常では「開く」と表示される部分が「次へ」となっています。
「次へ」をタップするとアプリが起動し、西海岸インテリアの写真一覧が表示されました。 Google Play ストア

2. アプリをインストールした状態でリンクを開く

こちらの場合も適切に西海岸インテリアの写真一覧が表示されました。

IntentFilterおよび受信したIntentとDynamic Linksの関係

アプリ側を変更せずに理想的な動作をしてしまいました。
理想的すぎて不安になったので動作を理解するために、IntentFilterおよび受信したIntentとDynamic Linksの関係を調べてみました。

確認には以下のコードを使用しました。action, data, ResultCallbackで取得できるディープリンクURLを確認しています。
コードは、公式のドキュメントで紹介されているものを使用しています。Firebaseそのものの実装はこちらの公式ドキュメントをご確認ください。

タグページのIntentFilterのみ実装しリンクを開く

受信したIntentからactionandroid.intent.action.VIEWdataは設定したディープリンクURLが取得できました。 また、ResultCallbackでもディープリンクURLを取得できています。

通常のディープリンクによる遷移は、actionがIntent.ACTION_VIEWであること、dataがnullでないことの2点の条件に当てはまるかどうかで判定し、dataに格納されているURLを解析して適切な画面を表示しています。

今回、Dynamic Linksのリンクを開きましたが、アプリ側では通常のディープリンクとして処理されていることがわかりました。

IntentFilterをすべて削除してリンクを開く

IntentFilterをすべて削除してリンクを開いたところ、アプリが起動しトップ画面が表示されました。

actionandroid.intent.action.MAINdataは設定したディープリンクURLが取得できました。 また、ResultCallbackでもディープリンクURLを取得できています。

IntentFilterを設定していない場合は、通常起動と同じように起動されるようです。

Dynamic Linksに対応したIntentFilterを設定する

今回生成したリンクに対応したIntentFilterを設定し、以下の2パターンを確認しました。

  1. Dynamic LinksのIntentFilterのみ設定した場合
    actionandroid.intent.action.MAINdataは設定したディープリンクURLが取得できました。

  2. Dynamic Linksとタグページの両方のIntentFilterを設定した場合
    actionandroid.intent.action.VIEWdataは設定したディープリンクURLが取得できました。

1,2どちらの場合も、ResultCallbackでもディープリンクURLを取得できています。

Dynamic Linksを開いた際の動作まとめ

どうやら以下のような関係となっているようです。

  • ディープリンクURLに対応するIntentFilterが設定されている場合、対応するActivityが開かれ、ブラウザ等でディープリンクを開いた際と同じ動作をする
  • 通常のディープリンクとDynamic Linksを区別するにはResultCallbackで取得できる値を確認する必要があるが、非同期のため処理を工夫する必要がある
  • IntentFilterを設定していない場合、通常起動と同じ動作をする

今回の調査でdataにディープリンクURLが入っていたことが予想外でした。
実装前は、通常のディープリンクの場合はdataにURLが入っていて、Dynamic Linksの場合は、dataは空でResultCallbackでURLが取得できてコンテンツを表示するという動きを期待していました。

まとめ

良いところ

  • コンソールを使用するとURLの生成が簡単
  • Android, iOSの両方に対応したURLが作成できる
  • バージョン指定でアップデートにも対応できる
  • ディープリンクに対応していれば、そのURLを設定することで簡単にDynamic Linksに対応することができる
  • インストール後もすぐにユーザーの求めるコンテンツを表示することができる
  • コンソールでURLを生成した場合は、クリック数を確認することができる

良くないところ

  • アプリをインストール済みでリンクを開いた場合と、Google Play ストアでインストールした場合で表示するコンテンツを変えたい場合、実装が難しい
  • コンソールでは、一度作成したリンクの内容を変更できない

使いどころ

今回URLはコンソールで作成しましたが、プログラムによってダイナミック リンクを作成することもできるようです。プログラムで作ることができると様々なページに対応することができます。
新規インストールしたユーザーを判別すれば、チュートリアルを表示した上で適切なコンテンツを表示することもできるので理想的な動作になり良いなと思いました。

また、広告で使用することも想定されているようですので、広告内容とリンク先内容の組み合わせを適切に設定することでより満足度の高い体験をしてもらえるのではないかと思いました。


以上となります。
今回は、弊社のRoomClipにDynamic Linksをテスト実装してみました。もともとのアプリの作り次第では、良くないところとして上げた点もうまく解消できる可能性があります。

URLの自動生成やiOSの実装に関してはまたの機会に。
ここまでお付き合いいただきありがとうございました!


<参考>
Firebase
Firebase Dynamic Links


この記事を書いた人:Tominaga

Androidエンジニア。 ドロイドくんが好き。


プロダクトKPIと数値取得方法について

こんにちは。TunnelでRoomClipのプロダクト改善を担当しております高橋です。

プロダクトと一言で言っても色んな捉え方があるかと思いますが、弊社のプロダクトチームでは、ユーザーが普段一番触れるところであるアプリの機能追加や改修、バグ修正などの開発業務から、ユーザーの課題解決や満足度向上のための諸々の施策の実行など、サービス改善につながること全般をやっております。

私自身は元々アプリのエンジニアで、現在はRoomClipのアプリを中心としたプロダクト改善のための施策運用をやっております。(その関係で、最近はアプリ開発のためのコードを書くというよりもむしろ、数値分析のためのSQLを書いていたりすることが多かったりします^^;)

今回は最初ということもあるので、プロダクトチームとして、どのような指標を扱っていて、それをどのように数値として取得しているかについて、以降で簡単にお話ししようと思います!

■ アクティブユーザー数

何はともあれ最重要指標です。何人のユーザーが使ってくれているのか。これが伸びないとにっちもさっちもいかないので、まず真っ先に見なければならない数値です。

■ 継続率

前月起動したユーザーのうち、何%が翌月も起動したか。前述のアクティブユーザー数は、DL数と継続者数に分解されますが、その後者にあたります。DL数は外部要因によるところもありますが、継続率はダイレクトにアプリ自体の質を表す指標にもなります。

ユーザーの満足度を測る指標とは何かという議論は諸々あるかと思いますが、結局はこの数値が伸びているかどうかが、アプリにおけるユーザーの成功体験及び満足度に直結していると捉えています。

■ ECサイト送客回数/アクティブユーザー数

RoomClipでは投稿したユーザーが写真に商品情報を付与する機能があり、写真を見た人はそこに写っている商品を購入サイトに行って買うことができるようになっています。この指標は、その購入サイトを何回見に行ってもらえたかというもので、この数値が売上にも大きく関わってきます。

ユーザーの利便性と収益性をいかに両立させるかは、サービス運営上の非常に重要なテーマになるかと思いますが、ユーザーは写真から商品を見つけて購入→よりよい部屋を実現できる、運営側は購入が発生することで販売手数料が得られるという図式を実現するものとして非常に重視しています。

■ 写真閲覧数/アクティブユーザー数

一人のユーザーが何枚の写真を見ているかということになりますが、この枚数が多いほど、ユーザーがサービスに没入している、と捉えています。(ここは滞在時間でもいいのですが、RoomClipではユーザーがいかに「参考にしたい、実現したい」と思えるような写真に出会えるかを重視しているため、この指標を見ています)

タイムラインをどこまで見てもらえているか、検索からどれだけ写真が見られているかといったものがここに入ってきます。

■ 1投稿あたりリアクション数

ユーザーの写真投稿に対して、いいねやコメントなどのリアクションがいくつ付いたかを取得しています。RoomClipは写真投稿のCGMサービスであるということもあり、ユーザーが投稿者と閲覧者の2つに大きく分類されます。1つのプロダクトで異なる2つのタイプのユーザーを共存させないといけない、というところにCGMの難しさがありますが、この指標は投稿者の満足度、投稿モチベーションを担保できているかを見るものです。

いいねやコメントがつかないと投稿リテンションが下がることは判明しているため、例えば閲覧者に寄せすぎた施策を打った結果、この数値が大きく下がってしまうようなことがないかをチェックしています。


これらの数値はすべてre:dashで毎日更新するよう管理し、日ごとで大きな動きがないか、毎朝チーム内で確認しております。(こんな感じです。一部都合でぼかしてます。)

re:dashを導入してしばらくになりますが、このあたりを自動でわかりやすい形で出してくれるので、手間が省けた&メンバーとの共有をしやすくなった&他のメンバーがどんな数値取得してウォッチしているかがわかる、というメリットがありました。

技術ブログなので最後一応技術的な部分というところで、上で書いた指標の一つである「写真閲覧数/アクティブユーザー数」を例に、どのようなクエリを書いて数値を出力しているかを簡単にお話しして終わろうと思います。

データを格納しているのはRedshiftで、下記2つのテーブルに、それぞれユーザーの起動と写真閲覧のイベントが格納されているとします。(※テーブル構造、カラム名等については実際のものではない部分がありますのでご了承ください。)

access_log

date user_id os
2017-01-15 02:30:49 2 ios
2017-01-15 02:30:51 3 android
: : :

view_log

photo_id date user_id os
1 2017-01-15 02:39:49 2 ios
2 2017-01-15 02:39:51 3 android
: : : :

これを元に下記のクエリをre:dashで定期的に回しています。 (やたら長くなってしまってすみません笑)

ここでのポイントは、
① WITHを使ってネストを浅くして、可読性を上げる。
② OSごとに出す(日付とOSでまとめたデータを、縦持ちから横持ちに変換する)
③ データ欠損などによる日付の歯抜けに対応する。

普通に出力する分には3.の部分までで終わりなのですが、万が一計測がバグで止まっていて日付に歯抜けが発生する場合などに備えて、4,5で対処しています。

カレンダーテーブル作成については、最初generate_series関数を使ってやろうと思ったのですが、エラーになったので、ROW_NUMBER() OVER () で連番を出すことで対応しました。(このあたり他にうまいやり方あったら教えてください)

結果こんな感じになります。日ごとにios, androidそれぞれの一人あたり閲覧数が出力されるので、これをチャートにすればいいわけですね。

date ios android
2017-01-01 XXXX XXXX
2017-01-02 XXXX XXXX
2017-01-03 XXXX XXXX
2017-01-04 XXXX XXXX
2017-01-05 XXXX XXXX
: : :

以上、簡単ではありますが、RoomClipプロダクトチームのKPIと数値取得の方法についてお話ししました。 今後は、個々の施策に踏み込んだ話や細かい計測周りについてまたお話しできればと思っております!

またどうぞよろしくお願いします。


この記事を書いた人:高橋弘

RoomClipでアプリの開発及びUI/UXの設計、サービス成長のための施策の打ち出しなどのプロダクト改善を担当しています。