ComplianzのクッキーバナーをEU圏だけに表示する|キャッシュと共存するJavaScript方式の実装

キャッシュ環境でのGDPR対応 JavaScript方式で国判定! WordPress
この記事は約15分で読めます。

ComplianzのクッキーバナーをEU圏のユーザーにだけ表示し、日本からのアクセスでは一瞬も表示させない方法を解説します。キャッシュプラグインと完全に共存するJavaScript方式で、コードはコピペでそのまま使えます。

Complianzの基本設定については、TCDの記事が詳しく解説しています。ただし、そこで紹介されているPHPとGeoLite2データベースによる国判定は、WP RocketやLiteSpeed Cacheなどのキャッシュプラグインを使っている環境では正しく機能しません。

筆者のブログでもWP Fastest Cacheを使っていた際にこの問題に直面しました。最初のアクセス時にキャッシュされたHTMLが、別の国のユーザーにもそのまま配信されてしまい、国判定が意味をなさなくなるのです。

この記事では、クライアントサイドのJavaScriptで国判定を行うことで、キャッシュの影響を完全に回避する方法を紹介します。

日本からアクセス(バナー非表示)
図.日本からアクセス(バナー非表示)

EU圏からVPNでアクセス(バナー表示)
図.EU圏からVPNでアクセス(バナー表示)

PHP方式がキャッシュ環境で破綻する理由

サーバーサイドのPHP判定は、ページがキャッシュされた時点で機能しなくなります。

たとえば、ドイツからのアクセスでページがキャッシュされると、バナー表示込みのHTMLが保存されます。次に日本からアクセスしても、サーバーはキャッシュ済みの同じHTML(バナー表示あり)を返します。逆のケースも同様で、日本のアクセスでキャッシュが生成されると、ドイツからアクセスしてもバナーが表示されません。

DONOTCACHEPAGE定数で回避する方法もありますが、キャッシュプラグインによっては無視されるケースがあります。つまり、サーバーサイドで国判定してHTMLを出し分ける方式は、キャッシュとは根本的に相性が悪いのです。

解決策はシンプルです。サーバーが返すHTMLを全ユーザー共通にし、国判定をクライアント側のJavaScriptで行います。これならキャッシュされたHTMLが誰に配信されても、ブラウザ上で正しく判定できます。

JavaScript方式の完成コード

functions.phpまたはCode Snippetsプラグインに追加してください。WP Rocket対応済み、タイムゾーンフォールバック付きです。

コードの仕組みを解説

処理の流れは「CSSでバナーを隠す → JSでEU圏か判定 → EU圏ならCSSを外してバナー表示」の3ステップです。

CSSでデフォルト非表示にする

ページ読み込み直後、<head>内でバナーを非表示にするCSSを出力します。どの国からアクセスしても、初期状態ではバナーは見えません。id="cmplz-geo-hide"を付与しているのは、後からJavaScriptでこのstyle要素を削除できるようにするためです。

Cookieキャッシュで2回目以降はAPI不要

判定結果は24時間Cookieに保存されます。2回目以降のアクセスではAPIを呼ばずに即座に判定が完了するため、ページ表示速度への影響はありません。

DevToolsでCookieを確認している画面

GeoIP APIによる国判定(タイムアウト・フォールバック付き)

メインAPIのipwho.isに3秒のタイムアウトを設定し、失敗した場合はapi.country.isにフォールバックします。

両方のAPIが失敗した場合は、ブラウザのタイムゾーンで判定します。Intl.DateTimeFormat().resolvedOptions().timeZoneEurope/で始まればEU圏、Asia/TokyoなどならEU圏外と判定します。この仕組みにより、WP Rocketの「Delay JavaScript execution」や広告ブロッカーがAPIをブロックしても、日本のユーザーにバナーが誤表示されることはありません。

WP Rocket対応

WP Rocketの「Delay JavaScript execution」は、すべてのJSをユーザー操作(スクロールやクリック)まで遅延させる機能です。バナー制御のJSが遅延されると、判定そのものが実行されなくなります。

このフィルターで、GeoIP判定スクリプトを遅延対象から除外しています。scriptタグ内の/* cmplz-geo-init */コメントが除外キーワードとして機能します。data-cfasync="false"はCloudflare Rocket Loader向けの除外指定です。

EU圏の判定対象について

コードではEU加盟27ヶ国に加え、EEA加盟3ヶ国(アイスランド、リヒテンシュタイン、ノルウェー)を対象にしています。イギリスはBrexit後もUK-GDPRが適用されるため含めています。スイスも2023年9月施行のnDSG(新データ保護法)によりGDPRに準じた同意取得が求められるため、対象に加えています。不要であれば、配列から'GB''CH'を削除してください。

動作の流れ

日本からのアクセスではAPI判定・Cookieキャッシュどちらのルートでもバナーは非表示のまま。EU圏からのアクセスでのみバナーが表示されます。API全滅時もタイムゾーンで正しく判定されます。

シナリオ 動作
日本から初回アクセス CSS非表示 → JS判定 → EU圏外 → 同意Cookie設定 → GA動作
日本から2回目以降 CSS非表示 → Cookie確認 → EU圏外 → バナー非表示のまま(API呼び出しなし)
EU圏から初回アクセス CSS非表示 → JS判定 → EU圏 → style削除 → バナー表示
EU圏から2回目以降 CSS非表示 → Cookie確認 → EU圏 → style削除 → バナー表示(API呼び出しなし)
API全滅(日本) CSS非表示 → API失敗 → タイムゾーン判定 → Asia/Tokyo → EU圏外 → バナー非表示
API全滅(EU圏) CSS非表示 → API失敗 → タイムゾーン判定 → Europe/* → EU圏 → バナー表示

PHP方式との比較

JavaScript方式はキャッシュ完全対応・GeoLite2 DB不要・日本での初回バナー非表示と、キャッシュプラグインを使う環境ではすべての面でPHP方式を上回ります。

項目 PHP方式 JavaScript方式(本記事)
キャッシュ共存 問題あり 完全対応
日本での初回表示 一瞬表示される場合あり 一瞬も表示されない
GeoLite2 DB 必要(定期更新も必要) 不要
サーバー負荷 やや高い 低い(クライアント処理)
外部API依存 なし あり(フォールバック付き)
WP Rocket対応 不要 除外フィルター1行で対応
API全滅時 影響なし(ローカルDB) タイムゾーンで判定

キャッシュプラグインを使っている環境であれば、JavaScript方式一択です。

動作確認の手順

日本からとEU圏から(VPN使用)の2パターンで確認しましょう。

日本からの確認

  1. ブラウザのキャッシュとCookieをクリア
  2. サイトにアクセス
  3. バナーが表示されないことを確認
  4. DevTools(F12)のConsoleで以下を実行

trueと表示されれば正常です。

DevToolsのNetworkタブでgoogletagmanager.comへのリクエスト確認

Google Analyticsの動作確認

DevToolsの「Network」タブを開き、フィルターにgoogleと入力してページをリロードします。googletagmanager.comへのリクエストが200または204で返ってくれば、Analyticsは正常に動作しています。

EU圏からの確認(VPN使用)

ProtonVPN(無料プランあり)やWindscribe(月間10GBまで無料)でEU圏のサーバーに接続し、Cookieをクリアしてからサイトにアクセスしてください。バナーが表示されれば成功です。

VPNで国を切り替えたのにバナーが表示されない場合は、前回の判定結果がCookieに残っています。以下をConsoleで実行してからリロードしてください。

注意点

運用にあたって、以下の3点に注意してください。

Complianzのバージョン:本記事のコードはComplianz 7.x系で動作確認しています。メジャーアップデートでCookie名が変更される可能性があるため、更新時はcmplz_系のCookie名を確認してください。

GeoIP APIのレート制限:ipwho.isは無料で利用できますが、高トラフィックサイトではレート制限に達する可能性があります。ただし、Cookieキャッシュにより実際のAPI呼び出しは初回訪問者のみに限定されるため、一般的なブログ規模であれば問題ありません。

WP Rocketのキャッシュクリア:コード設置後は必ずWP Rocketの「キャッシュをクリア」を実行してください。古いキャッシュにはこのスクリプトが含まれていないため、クリアしなければ動作しません。

まとめ

ComplianzのバナーをEU圏だけに表示するなら、キャッシュプラグインと共存できるJavaScript方式が最も確実です。

CSSでデフォルト非表示にしてからJSで国判定を行う方式のため、日本からのアクセスではバナーが一瞬も表示されません。GeoIP APIが全滅してもタイムゾーンでフォールバック判定するため、WP Rocketや広告ブロッカーの影響も受けません。判定結果はCookieにキャッシュされるので、2回目以降はAPI呼び出しゼロで即座に判定が完了します。

コメント

タイトルとURLをコピーしました