こんにちは。エンジニアの濱田 (@hamakou108) です。
2022年4月に施行された個人情報保護法改正についてご存知でしょうか? 法改正に伴い、 Cookie 等の取り扱いについてユーザに確認を取ることが必須になりました。 弊社プラットフォームのM&Aクラウドでは、個人情報保護法改正にともなって Cookie policy, Privacy policy を改訂するとともに、ポップアップを表示することでユーザに明示的にCookieの取扱について確認するようにしています。
背景
個人情報保護法の改正
2022年4月に改正個人情報保護法が施行されました。 この法改正には、個人関連情報 1 の第三者提供の制限等が付け加えられており、第三者が個人関連情報を個人データとして取得することが想定される場合の確認義務が定められています。
専門家ではないので厳密なことは言えませんが、 Web サイト上で Cookie 等を介して第三者にデータを提供する前に、多くのケースにおいてユーザーの同意を得る必要が生じています。
Cookie 同意のツールの環境
海外でも GDPR 等の個人データ保護規則の遵守に関する関心が高まっており、様々な同意管理プラットフォーム(以下 CMP と表記)が出現しています。 また Google Tag Manager (以下 GTM と表記)などの既存ツールも同意モードに対応しつつあります。
CMP の特徴と使わなかった理由
CMP を使うと、ユーザー同意を得るためのポップアップを埋め込む、サードパーティースクリプトの実行を制御するといった機能が簡単に実現できます。 多くの CMP は様々な要件に対応するために豊富な機能を提供している一方、その分定額課金となっています。 弊社のケースではシンプルに同意する・同意しないの二択を選択できれば良かったため、自前で実装してもペイするだろうと判断し、 CMP の利用は見送りました。
Google Tag Manager の同意モード概要
GTM では同意の状況に応じてGTMタグを発火させるかブロックさせるべきか選択できます。 例えば以下のGTMタグですと、赤枠で囲った部分が該当の設定になります。
「追加同意チェック」のところにユーザに許可されるべき同意モードを設定しておくと、それらの同意がされていない場合にはGTMが発火しないようにできます。これにより、該当のスクリプトがHTMLに差し込まれないので、当然ユーザの個人関連情報を送信することはなくなります。
対応
GTMの同意モードを用いることで、包括的にスクリプトを差し込む/差し込まないを管理できることがわかりました。弊社ではサードパーティ製スクリプトをGTMに乗せることを原則とし、GTMの同意モードで管理することにしました。
Google Tag Manager の設定
まずソースコード中で追加していたスクリプトタグは GTM に移行しました 2 。
元々なぜソースコード中に埋め込んでいたかと言うと、ユーザー ID など、ソースコード上でなければ取得できない値を使用するからでした。
今回はソースコード上で window
のプロパティにこれらの値を仕込み、 GTM からその値を参照する形を取りました。
次に GTM の同意設定です。 任意のタグについて、設定の「追加同意チェック」から「タグの配信時に追加同意が必要」をチェックして必要な同意を追加します。 3 この設定により、ユーザーから同意を得られていない場合はタグが発火しないようになります。
また同意タイプを設定することで、ユーザーが行った同意の種類(機能性 Cookie には同意する、広告には同意しないなど)に応じてタグの発火を制御できます。 そのタグが発火する条件として適切な同意を設定することで、ユーザーが何について同意するか細かく選択できる仕様を実現できるでしょう。
ちなみに上記のようにタグごとに設定することもできますが、複数のタグをまとめて設定変更することも可能です。
Cookie 同意状況の初期化
GTM に現在の同意状況を読み込んでもらうには、 window.dataLayer
にデータを追加します。
各サイトに以下のようなコードを埋め込み、ページ表示時に同意状況が初期化されるようにしています。
export class GoogleTagManager { private setConsentMode() { // Define dataLayer and the gtag function. window.dataLayer = window.dataLayer || [] function gtag() { window.dataLayer.push(arguments) } // デフォルトではすべての同意タイプについて 'denied' を設定 gtag('consent', 'default', { ad_storage: 'denied', analytics_storage: 'denied' }) // localStorage に過去の同意記録が残っていた場合に 'granted' を設定(詳細は後述) if (localStorage.getItem('cookie-consent-granted')) { gtag('consent', 'update', { ad_storage: 'granted', analytics_storage: 'granted' }) } window.dataLayer.push({ event: 'default_consent' }) } }
consent default を設定するタイミングについては注意が必要です。後述する Consent Initialization トリガーで発火するCookie同意ポップアップの中で 同意状況の初期化をしようとしたのですがそれは上手くいきませんでした。 それは、consent defualt の設定は必ずGTM自身のスクリプトを読み込む前に設定しておく必要があるためです。ドキュメントの中で(2022/05/27時点では文章中のタブの中に隠れていて分かりづらいのですが)以下のように書かれています。
サイトのすべてのページで、タグが呼び出される前に以下を行う必要があります。
dataLayer オブジェクトが定義されていることを確認する。
gtag() 関数が定義されていることを確認する。
gtag('consent', ...) コマンドを使用して測定機能を設定する。
dataLayer.push() を使用して default_consent イベントを送信する。
Cookie 同意ポップアップ
Cookie 同意ポップアップは各サイト共通の独立した社内ライブラリとして開発して、 GTM を使って各サイトに埋め込んでいます。
実装詳細
Cookie 同意ポップアップのメインの実装は以下の通りです。他にこれを読み込む薄い index.ts や scss もありますが、本筋に無関係なので省略します。
export class CookieConsentPopup { private popupElement: Node private storageKey = 'cookie-consent-granted' private static gtag(..._: any) { (window as any).dataLayer = (window as any).dataLayer || [] // オリジナルのgtagファンクションを参考に arguments を直接使うように実装。 // @ts-ignore (window as any).dataLayer.push(arguments) } private static gtmEventPush(eventName: string) { (window as any).dataLayer = (window as any).dataLayer || [] (window as any).dataLayer.push({ event: eventName }) } constructor() { this.init() } private init() { const isAlreadyConsentGranted = localStorage.getItem(this.storageKey) if (isAlreadyConsentGranted) { return } this.showPopup() document.querySelector('.cookie-consent-popup__disagree').addEventListener('click', () => { this.disagree() }) document.querySelector('.cookie-consent-popup__agree').addEventListener('click', () => { this.agree() }) } private showPopup() { const popupElement = document.createElement('div') as HTMLDivElement this.popupElement = popupElement popupElement.innerHTML = ` <div class="cookie-consent-popup"> <div class="cookie-consent-popup__content"> <p>当サイトを引き続きご利用いただく場合は、当社のプライバシーポリシー及びCookieガイドラインをよくお読みいただき、これらに対する「同意する」ボタンを押して下さい。</p> <div class="cookie-consent-popup__button_wrapper"> <button class="cookie-consent-popup__disagree">同意しない</button> <button class="cookie-consent-popup__agree">同意する</button> </div> </div> </div>` document.body.appendChild(popupElement) } public agree() { CookieConsentPopup.gtag('consent', 'update', { 'ad_storage': 'granted', 'analytics_storage': 'granted', }) this.destroy() localStorage.setItem(this.storageKey, 'true') // gtm event. Trigger for many gtm tags. CookieConsentPopup.gtmEventPush('cookieConsentGrantedGtmEvent') } public disagree() { this.destroy() } private destroy() { document.body.removeChild(this.popupElement) } }
Cookie 同意ポップアップを表示するトリガー
GTMにおいて今回のような同意モードに関するトリガーはConsent Initialization - All Pages
を使用するのがベストプラクティスだとされています。
「同意の初期化」トリガーは、他のトリガーが起動する前にすべての同意設定が適用されるように設計されています。
Cookie同意された時にGTMのタグを発火させる
Cookie 同意されていない時点では、All Pages のトリガーのうち「タグの配信時に追加同意が必要」なトリガーは発火がブロックされています。
ページが表示し終わった後にユーザがボタンクリックで同意した場合でも、すでにAll Pages のトリガーはGTMのContainer Loadedのタイミングで実行されているので、ユーザが同意したタイミングではすでに発火タイミングを逃してしまっている状態です。
このため、ボタンクリックのタイミングで発火する追加のトリガーを設定しておく必要があります。それが前述の実装コードにおけるCookieConsentGrantedGtmEvent
イベントです。
このイベントをAll Pages のトリガーを持つタグに追加で設定しておけば、ユーザが同意したタイミングでタグを発火させることができます。
例外として組み込み同意モードがあるGoogle 系のスクリプトの扱い
google 系のスクリプトは「組み込み同意チェック」という機能が最初から入っています。 組み込み同意チェックが入っているかどうかはGTMタグの設定の中の”同意設定”の項目を見るとわかります。 以下の画像のものですと、 ad_storage と analytics_storage については組み込みされており、これらの同意がされなければ個人関連情報を送信しないようになっています。詳細についてはドキュメントを参照してください。
このような組み込み同意チェックがあるケースだと、GTMタグ自体は同意モードの発火してスクリプトが差し込まれても問題がないため、追加同意チェックの設定は「追加同意は不要」という設定にしておきます。
最後に
いかがでしたか? 個人情報保護法改正に伴って同じように Cookie 同意の対応を検討されている方の参考になれば嬉しいです。