こんにちは!ソウゾウの Software Engineer の@gentleです。連載:メルカリShops 開発の裏側 Vol.2の10日目を担当させていただきます。
メルカリShopsはメルカリのアプリ内でサービスを提供しており、メルカリShopsの機能に直接アクセスするためのディープリンクを実装しています。この記事では主にiOSにおけるディープリンクの基礎的な解説と、メルカリShopsではどのようにディープリンクを使用しているかを解説していきます。
はじめに
ディープリンクとは、モバイルアプリの特定の機能に直接アクセスできるURLのことです。なお、ディープリンクにはWebサイトのトップではなく特定のコンテンツのページに直接遷移するURLのことを指す意味もありますが、本記事ではモバイルアプリにおけるディープリンクの話となります。
ディープリンクを使用すると、Webページからアプリを起動したり、アプリから別のアプリを起動することができます。Webサービスとアプリの両方でサービスを提供している場合、サービス提供側としてはモバイルデバイスではアプリの方を使って欲しい場合が多いため、アプリを起動してもらうための手段として利用されています。メルカリShopsでは、メルカリShopsのWebページhttps://mercari-shops.comにiPhoneのSafariでアクセスすると、メルカリのアプリを開いてメルカリShopsの画面を表示するようにしています。
また、1つの複雑なアプリですべてのサービスを提供するのではなく、一部の機能をもった複数のアプリでサービスを提供している場合、あるアプリから関連する別のアプリを起動する手段としても利用されています。例としては、会計アプリのfreeeは会計を作成するアプリと電子申告をするアプリが分かれています。申告作業の際は、会計アプリで申告書類を作成した後、会計アプリから電子申告アプリを起動して申告処理を行う流れになっています。
このディープリンクを実際の動作として実現するための仕組みがいくつか存在しています。
ディープリンクを実現する仕組み
iOSでディープリンクを実現するために最初に提供された機能はCustom URL Schemesです。Custom URL Schemesはアプリで独自のSchemesを定義したURLを使用します。しかし、このCustom URL Schemesには後述するいくつかの問題があり、iOS9からUniversalLinksという機能が提供されました。UniversalLinksは通常のWebページのURLをディープリンクとして扱い、アプリを起動できるようになる仕組みです。Androidにもversion6からAppLinksという同等の機能を提供する仕組みがあります。しかし、UniversalLinksはCustom URL Schemesを完全に置き換えできるものではなく、UniversalLinksにもいくつもの問題点があるため、状況によって使い分けをする必要があります。
Third Partyとしてディープリンクの機能を提供しているサービスも存在しています。代表的なものとしてはFirebase DynamicLinksがあります。Firebase DynamicLinksを使うとiOS / Androidで共通の仕組みでディープリンクのURLを発行したり、Webサイト/ ドメインを持っていなくてもDynamicLinks用のドメインを発行してディープリンクを実現することができるなどの特徴があります。
また、ディープリンクの一種として、アプリに対応するWebページの上部にアプリを起動するためのバナーを表示するSmart App Bannerという仕組みもAppleから提供されています。前述したUniversalLinksに対応したWebサイトにもアプリを起動するためのバナーが自動的に表示される仕組みがあり、アプリの起動を促すことができます。
Smart App Banner | UniversalLinks対応サイトのバナー |
---|---|
メルカリShopsにおけるディープリンク
メルカリShopsでは下記のようなケースでディープリンクを利用しています。
- 商品・ショップのシェア機能
- 取引に関する通知
- お問い合わせの通知
- キャンペーンなどに使うLPのページ
メルカリShopsではこれらのディープリンクにFirebase DynamicLinksを利用しています。同時に対応機能へのCustom URL Schemes / UniversalLinksも実装していますが、後述する問題があり、公開・共有するディープリンクとしては使用していませんでした。
メルカリShopsのディープリンクで問題となったのは、メルカリShopsのリリース当初はメルカリアプリへのリリースを優先したため、Web版が未公開であったことでした。そのため、UniversalLinksを使用することができなかった他、PC / Macでアクセスした時のページを用意する必要がありました。メルカリShopsでは、PC / Macでディープリンクをタップした場合、ディープリンクをQRコードで表示するページに遷移するようにしました。そのページに表示されているQRコードを手持ちのモバイルデバイスで読み込んだURLに遷移すると、アプリが起動して該当のページに遷移します。
現在ではWeb版メルカリShopsも公開されているため、PC / Macでは単純にWebページを表示できるようになりました。そこで、この機能を削除しつつ、共有するディープリンクをFirebase DynamicLinksからUniversalLinksへの置き換えを行っています。
以下、各ディープリンクの技術についてその問題点と共に解説いたします。
Custom URL Schemes / UniversalLinks
Custom URL Schemesはアプリを起動するために指定する特殊なURLスキームです。例えばiPhoneのSafariでアドレスバーにinstagram://
と入力するとインスタグラムが、comgooglemaps://
と入力するとGoogle Mapsが起動します。アプリがインストールされていない場合、URLは無効となり何も起きません。
この特殊なURLスキームはアプリ側でどのスキームで起動するかを任意に定義できるため、複数のアプリが同一のCustom URL Schemesを定義することができるという問題があります。その場合、iOSではどのアプリが起動するのか不定になります。iOSのバージョンによっても動作が異なるようです。Androidの場合はユーザーがどのアプリを起動するか選択することができます。
上記の問題を解決するためにiOS9からUniversalLinksという仕組みが登場しました。UniversalLinksは通常のhttp / httpsから始まるURLをディープリンクとして扱うことができます。UniversalLinksは通常のURLの形式なので、PC / Macなどでアクセスした場合やアプリがインストールされていない場合はそのURLのWebページに遷移し、アプリがインストールされている場合はアプリを起動して指定の画面に遷移します。
UniversalLinksの実装には、アプリ側でディープリンクとして扱いたいURLのドメインを指定し、そのドメインの.well-known/
以下に apple-app-site-association
というファイルを設置する必要があります。
apple-app-site-association
のファイルの中にディープリンクとして扱うパスと起動するアプリの組み合わせを記述しています。apple-app-site-association
はアプリの初回起動時やアップデート時などにAppleのCDNを通して自動的にデバイスにダウンロードされています。アプリ側でのドメインの定義とWebサイト側でのファイルの定義が揃うことでディープリンクとして機能するため、自分の管理下にないドメインのURLをディープリンクとして定義することはできない仕組みになっています。そのため、Custom URL Schemesで起きていたディープリンクの重複の問題は解決されています。
Custom URL Schemesの問題点
Custom URL Schemes / UniversalLinksにはいくつか問題があり、完全なディープリンクを実現する仕組みという訳ではありません。
Custom URL Schemesの最大の問題はセキュアではないことで、前述したように複数のアプリで重複したURL Schemesを定義できてしまいます。特定のアプリのCustom URL Schemesに被せて、別のアプリがそのCustom URL Schemesを定義することで、当初設定したディープリンクのURLで別のアプリを起動させることができてしまいます。
Custom URL Schemesはアプリの内部を調査すると簡単に判明するため、秘密の情報という訳ではありません。しかし、上記の通り別のアプリを起動させる可能性がある以上、開発側からは積極的に公開したい情報ではありません。メルカリのアプリもCustom URL Schemesを定義していますが、これを積極的に公開し広範囲に利用してもらいたかったとしても、別のアプリがそれに被せてCustom URL Schemesを実装される恐れがあります。そうすると、こちらが公開しているURLで別のアプリを(確実ではないですが)起動させることができてしまいます。また、Custom URL Schemesはあくまでアプリがインストールされていると正常に動作するURLなので、それ以外アプリがインストールされていない場合やPCのブラウザでのアクセスでは不正なURLとなり、何も動作しない状態になります。
上記のような問題があり、Custom URL Schemesは一般的なディープリンクとして使用されるケースは少なくなりました。しかし、後述するようにUniversalLinksにもいくつかの問題があるため、Webページからでなく特定のアプリから別のアプリを確実に起動する手段としてはCustom URL Schemesが引き続き利用されています。
UniversalLinksの問題点
UniversalLinksの問題はアプリの各機能に対応するWebページが必要なこと、確実にアプリを起動する機能ではないこと、デバッグが難しいことなどが挙げられます。
アプリに対応するWebページが必要なことは、アプリのみで完結するサービスやWeb版まで開発する余力がない場合はUniversalLinks採用するのが難しい理由になります。メルカリShopsでも、前述したようにリリース当初はWeb版が公開されていなかったため、ディープリンクにUniversalLinksを採用することはできませんでした。
また、UniversalLinks対応のURLを起動しても下記のようなケースではアプリが立ち上がらず、該当のページがブラウザでそのまま表示されます。
- UniversalLinksをSafariで開く動作をした
- 同一ドメイン内のUniversalLinksを開く
- Safari以外のThirdPartyのブラウザを使用している
apple-app-site-association
ファイルがダウンロードされていない
1.のケースでは、UniveralLinksのリンクを長押ししてSafariで開く動作をすると、アプリでなくSafariでページ遷移し、以後そのリンクはディープリンクとして機能しないようデバイス内に保存されます。解除するには、開いた先のページ上部のバナーからアプリを起動するか、再度リンクを長押ししてアプリで起動するを選択します。ユーザーにとっては便利な仕組みですが、アプリ側から見るとURLがディープリンクとして動作するのかブラウザで開くのか制御できない状況となっています。
2.のケースでは、同一のWebサイト内でUniversalLinksに対応していないページからUniversalLinksに対応したURLのリンクを設置しても、ページ遷移するだけでディープリンクとしては動作しません。これもユーザー側からすると自然な動きですが、Webサイト内にアプリを起動したいリンクを設置するのが難しいということにもなります。
3.のケースでは、Safari以外のブラウザの場合各ブラウザアプリはWebページの表示をWebViewで実装することになります。このWebViewは標準動作ではUniversalLinksはディープリンクとして機能しないため、UniversalLinksをディープリンクとして扱うかどうかは各アプリのWebViewの実装次第という状況です。
4.のケースでは、Webサイトに設置しているapple-app-site-association
のファイルはアプリの初回起動時にデバイスに自動的にダウンロードされています。しかし、何らかの原因でダウンロードできていない場合、UniversalLinksが有効になりません。これは特に開発中の状態では頻発しており、デバッグの難しさに拍車をかけています。とりわけ、iOS14からapple-app-site-association
が各サイト直接ではなくAppleのCDNを通してダウンロードするように変更されており、アクセス制限のかかっている開発環境などにapple-app-site-association
が設置されていた場合、UniversalLinksが使えないことになります。これについては回避方法はあるのですが、開発モードでのビルドかつデバッグモードになっている実機にインストールした時のみ有効で、設定画面のデバッグメニューから設定を変更しなければならないなどの制約があります。
Firebase DynamicLinks
UniversalLinksの問題点のいくつかを解決してくれるのがFirebaseの提供しているDynamicLinksです。一番のメリットはディープリンクに対応するWebサイトが不要なことで、apple-app-site-association
のファイルはFirebaseが提供する専用のサブドメインに設置してくれます。
また、アプリがインストールされていない場合はAppStoreやGooglePlayStoreに遷移させたり、PC / Macのブラウザで開いた場合は特定のページに遷移するなど、URLの動作を柔軟に制御できます。そのURLも動作をURLパラメータで直接指定する長いURLの形式や、それを短縮化させて短いURLを作成することができます。
しかし、Firebase DynamicLinksにも下記のような問題点が存在しています。
- アプリの内部的にはUniveralLinksを利用しているため、UniversalLinksの問題で述べたアプリを起動できないケースの問題が完全には解消されていない
- ディープリンクからアプリ起動される前に規定のプレビューページが表示される
- 短縮化URLの生成には回数制限がある
2.のアプリが起動する前のプレビューページはFirebaseが提供する固定の表示ページとなっており、見た目には多少の違和感があります。DynamicLinksの設定でこれをスキップする設定にすることもできますが、メルカリShopsでの実装中に試したところ、スキップする設定だとディープリンクが正常に動作しませんでした。
3.の短縮化URLの生成はメルカリShopsでは商品・ショップのシェア機能に利用しています。シェア機能のURLはSNS等で共有してもらいたいので短いURLが望ましく、かつリンク先のページが多数あるので、シェアボタンが押されたタイミングでアプリ内でFirebaseのAPIを使用してURLを生成しています。このAPIが、標準で1日あたり200,000回の制限があり、メルカリShopsでもこの制限によりAPIがエラーとなる問題が発生してしまいました。
Firebase DynamicLinksにも上記のような問題点はありますが、高機能で使いやすいディープリンクのため、メルカリShopsでも利用しています。しかし、そこまでの機能が必要でない場合は、UniversalLinksをそのまま使用する方が良いでしょう。メルカリShopsでも、Firebase DynamicLinksからUniversalLinksに置き換えを行なっていく予定です。
さいごに
モバイルアプリにおけるディープリンクと、メルカリShopsにおいてそれらをどう実装しているのかについて解説いたしました。特にiOSにおけるディープリンクはどの仕組みも完全なものではなく、状況によって使い分けていく必要があります。この記事がその参考になれば幸いです。
ソウゾウではメンバーを大募集中です。メルカリShopsの開発やソウゾウに興味を持った方がいればぜひご応募お待ちしています。詳しくは以下のページをご覧ください。
- Software Engineer
- Software Engineer, Site Reliability
- Software Engineer, Machine Learning
- Software Engineer, QA Test
- Software Engineer (Internship) – Mercari Group (※新卒採用に応募するにはまずインターンへの参加をお願いしています。)
またカジュアルに話だけ聞いてみたい、といった方も大歓迎です。こちらの申し込みフォームよりぜひご連絡ください。