WebViewにおける同意:ネイティブとWebの同意を同期させる
二重バナーの問題
多くのアプリは、一部がネイティブで一部がウェブです。ゲームがストアやニュース、ヘルプページをWebViewで表示したり、ユーティリティアプリが自社サイトの記事を表示したり、ハイブリッドアプリがインターフェースの大半をウェブコンテンツで包んだりします。それぞれの側に独自の同意の仕組みがあります。ネイティブアプリはアプリ内CMPやSDKを使い、ウェブページはウェブCMPを読み込みます。両者がつながっていなければ、ユーザーは2回尋ねられ、一方で行った選択は他方で無視され、WebView内からの広告リクエストは誤ったシグナルを付けて送信されます。
このガイドでは、ネイティブとウェブの同意を一致させる方法を説明します。ユーザーが一度答えれば、すべての広告リクエストが同じ決定を伝えるようにするためです。
それぞれが同意を保存する場所
ネイティブ
IAB TCFは、アプリ内CMPが同意を保存する方法を定めています。iOSではNSUserDefaults、AndroidではSharedPreferencesに、IABTCF_TCString、IABTCF_gdprApplies、IABTCF_PurposeConsentsなどの標準キーを使って保存します。広告SDKはこれらのキーを直接読み取ります。IAB GPPも、IABGPP_というプレフィックスを持つ同様のキー(IABGPP_HDR_GppStringなど)を定義しています。
ウェブ
ウェブCMPは通常、サイトのドメインのファーストパーティCookieまたはローカルストレージに決定を保存し、__tcfapiと__gppのJavaScript関数を通じて公開します。ページ内の広告タグは、ネイティブストレージではなくこれらの関数を呼び出します。
ギャップ
WebViewには独自のCookieとストレージの領域があり、デバイスのブラウザとも、アプリのネイティブな設定とも別です。iOSでは、永続的でないデータストアを使うWKWebViewは、閉じるとすべてを忘れてしまいます。自分で構築しない限り、両者の間では何も流れません。
信頼できる唯一の情報源を決める
最初の決定は、どちらの側が同意を所有するかです。ほとんどのアプリでは答えはネイティブCMPです。理由は次のとおりです。
- WebViewが開かれる前に、最初に実行される。
- 通常は収益の大半を稼ぐネイティブ広告SDKが、ネイティブストレージを読み取る。
- iOSでは、App Tracking Transparencyのプロンプトと連携させられる。
インターフェース全体がウェブコンテンツであるハイブリッドアプリでは、ウェブ優先にも意味がありますが、その場合はネイティブSDKのために、決定をネイティブストレージに書き戻さなければなりません。
ネイティブの同意をWebViewに渡す
ネイティブを唯一の情報源とする場合、WebViewも同じ決定を見る必要があります。一般的なパターンは次のとおりです。
__tcfapiの実装をインジェクションする。ページのスクリプトが実行される前に、__tcfapi(必要なら__gppも)を定義し、ネイティブストレージから読み取ったTC stringと値で呼び出しに応答する小さなスクリプトをインジェクションします。これで、ページ内の広告タグは標準APIを通じてネイティブの決定を取得できます。- ウェブバナーを抑制する。ページがアプリ内で読み込まれたときは、ウェブCMPが非表示のままになるよう、たとえばクエリパラメータや自分で管理するカスタムのユーザーエージェントトークンに基づいて設定します。そうしないと、ユーザーに2つ目のバナーが表示されます。
- 読み込み時に文字列を渡す。一部のウェブCMPは、初期化時に既存の同意文字列を受け取って採用できます。サポートされている方法については、お使いのウェブCMPのドキュメントを確認してください。
どのパターンを使うにせよ、インジェクションした値は、次回のアプリ起動時だけでなく、ユーザーがネイティブの設定画面で選択を変更したときにも更新されるようにしてください。
ウェブの同意をネイティブに戻す
ユーザーがWebView内で、たとえばプライバシー設定ページを通じて同意を変更できる場合、アプリはそれを知る必要があります。JavaScriptブリッジ(iOSのメッセージハンドラまたはAndroidのJavaScriptインターフェース)を使います。ウェブ側が__tcfapi('addEventListener', ...)でリッスンし、新しい文字列をネイティブコードに送ると、ネイティブコードが標準キーに書き込みます。書き込む前にWebViewからの入力を検証し、自社のコンテンツからのメッセージのみを受け付けてください。
WebView内の広告
WebViewにレンダリングされる広告はウェブ広告です。広告SDKが両者をリンクする方法を提供していない限り、同意はネイティブストレージではなくページから読み取ります。たとえばGoogleのMobile Ads SDKは、WebViewを登録して、その中の広告がアプリのシグナルを使えるようにするAPIを提供しています。お使いのSDKの最新のドキュメントを確認してください。いずれにせよ、テストによって、WebViewからの広告リクエストがネイティブの広告リクエストと同じTCまたはGPP文字列を伝えていることを確認してください。
テストチェックリスト
- 新規インストール:同意のプロンプトは2回ではなく1回。
- ネイティブCMPですべて拒否し、WebViewを開いて広告リクエストを調べる:文字列が拒否を反映しているはず。
- ネイティブの設定で同意を変更し、開いているWebViewに戻る:ページが新しい決定を認識するはず。
- ウェブ側の設定がある場合は、そこで同意を変更し、ネイティブのキーが更新されることを確認する。
- アプリを強制終了して再起動する:決定が両側で保持される。
- WebViewのストレージの挙動はそれぞれ異なるため、iOSとAndroidの両方でテストする。
重要なポイント
- ネイティブとWebViewの同意は別々のストアにあり、デフォルトでは同期されません。
- 信頼できる唯一の情報源を選びます。ほとんどのアプリではネイティブCMPです。
- インジェクションした
__tcfapiまたは__gppを通じてネイティブの同意をウェブコンテンツに公開し、ウェブバナーを非表示にします。 - JavaScriptブリッジを使って、ウェブでの変更をネイティブストレージに戻します。
- WebViewからの広告リクエストが、ネイティブのものと同じ同意文字列を伝えていることを確認します。