__tcfapiイベントリスナーの使い方:同意対応スクリプトの開発者向けチュートリアル
スクリプトはポーリングではなくリッスンすべき理由
同意に依存するスクリプト(広告タグ、アナリティクスローダー、ヘッダービディングのラッパーなど)は、2つのことを知る必要があります。CMPがすでに決定を持っているかどうか、そしてその決定が何か、です。よくある間違いは、ページ読み込み時にCookieを読むことや、何かが現れるまでタイマーでCMPをポーリングすることです。どちらの方法も予測可能な形で破綻します。Cookieの形式はCMP内部のものであり変更される可能性がありますし、ポーリングは早すぎるタイミングで発火するか、待つだけで時間を無駄にします。
IAB TCFには、まさにこの目的のための標準JavaScriptインターフェース、__tcfapi関数が定義されています。このチュートリアルでは、実際に必要なコマンド、受け取るイベント、本番環境で最もよく見られるバグを順に説明します。
スタブとキュー
TCF対応のCMPは、完全なCMPスクリプトが読み込まれる前の、できるだけ早い段階で、小さなスタブをページに配置することが期待されています。スタブはwindow.__tcfapiを定義し、CMPの準備が整う前に行われた呼び出しをキューに入れます。CMPの読み込みが完了すると、キューを処理して各呼び出しに応答します。
これにより、他のスクリプトが__tcfapiをすぐに呼び出しても安全になります。スタブがそれらより前にページに存在していれば、呼び出しは失われません。__tcfapiが未定義であるためにスクリプトが例外を投げる場合、スタブが存在しないか、読み込みが遅すぎます。再試行を追加するのではなく、読み込み順序を修正してください。
重要なコマンド
ping
__tcfapi('ping', 2, callback)は、ユーザーの決定を待たずに基本的なステータスを返します。レスポンスにはcmpLoaded、cmpStatus(stub、loading、loaded、errorのいずれか)、そしてdisplayStatus(visible、hidden、disabledのいずれか)が含まれます。また、判明した時点でgdprAppliesも報告します。診断のために使うほか、この訪問者にそもそもTCFが関係するかどうかを判断するのにも使えます。
addEventListener
__tcfapi('addEventListener', 2, callback)は、ほとんどの統合で使うべきコマンドです。コールバックはtcDataオブジェクトと成功フラグを受け取り、同意状態が変わるたびに再び呼び出されます。TCF v2.2以降、同意データを取得する推奨方法はこれであり、従来のgetTCDataコマンドは非推奨になりました。
removeEventListener
各tcDataオブジェクトにはlistenerIdが含まれます。スクリプトが更新を必要としなくなったとき(たとえば、すでに判断を終えた一度きりのローダー)には、これを__tcfapi('removeEventListener', 2, callback, listenerId)に渡します。
eventStatusの読み方
tcDataの重要なフィールドはeventStatusです。値は3つあります。
tcloaded— CMPが有効な保存済みの決定を見つけ、バナーは表示されません。データにすぐに基づいて動作できます。cmpuishown— バナーが表示されています。データは以前の状態を反映しており、ユーザーがこれから変更する可能性があります。useractioncomplete— ユーザーがたった今選択を行った、または確定しました。新しいデータに基づいて動作します。
典型的なローダーはtcloadedまたはuseractioncompleteのいずれかを待ち、そのうえで必要な目的とベンダーを確認します。cmpuishownは、バナーが表示されたことをログに残す程度を除いて無視します。
目的とベンダーの確認
tcDataの中では、同意と正当な利益がIDをキーとするオブジェクトとして公開されています。
tcData.purpose.consents[1]— 目的1(デバイスへの保存)に対する同意。tcData.purpose.legitimateInterests[7]— 目的7の正当な利益のステータス。tcData.vendor.consents[ID]とtcData.vendor.legitimateInterests[ID]— ベンダーごとのステータス。ベンダーのグローバルベンダーリストIDを使用します。tcData.gdprApplies— CMPがこの訪問者にGDPRが適用されると判断したかどうか。falseの場合、スクリプトは非TCFのロジックに従うべきです。tcData.tcString— エンコードされた文字列。これを必要とするパートナーに渡します。
目的とベンダーの両方を確認してください。目的の同意だけでベンダーの同意がない場合、またはその逆の場合、ほとんどのベンダーはデータを処理するのに十分とは見なしません。
iframeとクロスフレーム呼び出し
広告やウィジェットは、親ページの__tcfapiを参照できないiframe内で動作していることがよくあります。TCFはpostMessageプロトコルでこれを解決します。CMPがトップページに__tcfapiLocatorという名前のフレームを追加し、iframe内のコードはそれを見つけて__tcfapiCallメッセージを送り、__tcfapiReturnレスポンスを受け取ることができます。ほとんどの広告SDKはすでにこれを行っています。独自のiframeコードを書く場合は、フレームをまたいでCookieを読むのではなく、同じパターンを実装してください。
よくあるバグと見つけ方
cmpuishownで動作してしまう。何らかのコールバックが発火した時点で読み込まれるスクリプトは、ユーザーが決定する前に実行されます。eventStatusでフィルタリングしてください。- リスナーを早く削除しすぎる。最初のコールバックの後で削除すると、後の
useractioncompleteを逃し、読み込まれないままになります。 - 撤回を無視する。常駐するスクリプトはリスナーを維持し続け、同意が撤回されたら自身を停止または再構成する必要があります。
gdprAppliesを無視する。TCF対象地域外では目的オブジェクトが空になることがあります。それを「同意なし」と扱うと、得ることが許されている収益を止めてしまう可能性があります。- 成功フラグを確認しない。
successがfalseの場合はログに残してください。通常はCMPの設定が壊れていることを示します。
統合のテスト
ブラウザのコンソールで__tcfapi('ping', 2, console.log)を呼び出してCMPが存在することを確認し、次にconsole.logをコールバックにしてリスナーを登録し、バナーを操作してみます。初回訪問ではcmpuishownに続いてuseractioncomplete、再読み込みではtcloadedが表示されるはずです。すべて許可、すべて拒否、カスタム選択のそれぞれで繰り返し、スクリプトがどのケースでも正しく動作することを確認してください。
重要なポイント
- CMPのCookieを読んだりポーリングしたりせず、
__tcfapiを使いましょう。 - APIを呼び出すどのスクリプトよりも先に、CMPスタブが読み込まれるようにします。
addEventListenerを使い、tcloadedまたはuseractioncompleteのときにのみ動作します。- 目的とベンダーの両方のステータスを確認し、
gdprAppliesを尊重します。 - iframe内では
__tcfapiLocatorのpostMessageパターンを使います。