Hero image
作成日:

AstroにCookie同意バナーを追加しようとしたらハマった話


目次

はじめに

AstroでGoogle Analyticsを導入する際、Google同意モードの実装が必要になりました。Cookie同意バナーの実装には、当初Cookiebot🔗を選択しました。しかし、手順通りに実装してもCookiebotのバナーが表示されなかったためCookieyesに変更し、Cookie同意バナーの表示とGoogle同意モードの有効化を確認できました。

⚠️前置きが長いので、実装内容を知りたい方はCookieyesへの移行からどうぞ。

前提

  1. Google Tag Manager(GTM)は使わずにGoogleタグ(gtag.js)を使用
  2. 環境変数からGoogle Analyticsの測定IDや同意管理プラットフォーム(CMP)のIDを取得

Cookie同意バナーとGoogle同意モードとGoogle Analytics(Googleタグ)の関係性と役割

Google同意モード、Cookie同意バナー、Google Analyticsは、ウェブサイト運営におけるユーザープライバシーの尊重とデータ活用のバランスを取る上で、密接に関連しています。それぞれの役割と関係性は以下の通りです。

1. Cookie同意バナー

  • 役割: ウェブサイト訪問者に対して、Cookie(とくに分析や広告目的のもの)の使用について通知し、その使用に対する同意(または拒否)を取得するためのインターフェイスです。GDPR(EU一般データ保護規則)やePrivacy指令、改正個人情報保護法(日本)などのプライバシー規制に対応するために設置されます。
  • 機能: ユーザーが「同意する」「拒否する」「設定をカスタマイズする」といった選択肢をクリックすることで、そのユーザーの同意ステータス(許可/拒否)を記録します。

2. Google同意モード

  • 役割: Cookie同意バナーで取得したユーザーの同意ステータスを、Googleの各種タグ(Google Analytics、Google広告など)に伝達する仕組み(API)です。同意モード自体が同意バナーではありません。
  • 機能:
    • ユーザーが同意した場合: Googleタグは通常通り動作し、Cookieを使用して詳細な計測(ユーザー識別、行動追跡、コンバージョン測定など)を行います。
    • ユーザーが拒否した場合: GoogleタグはCookieを使用せずに動作します。個人を特定しない、限定的な情報(Pingと呼ばれる信号)をGoogleに送信します。これには、アクセスがあったこと、コンバージョンが発生したこと(個人紐付けなし)などの集計情報が含まれます。
  • メリット: ユーザーが同意しなかった場合でも、Google AnalyticsやGoogle広告では、この限定的な情報と機械学習(モデリング)を組み合わせることで、失われたデータを推計してレポートのギャップを補完しようとします。これにより、プライバシーを尊重しつつも、ある程度の分析や広告効果測定の継続を目指します。

3. Google Analytics

  • 役割: ウェブサイトのトラフィックやユーザー行動を計測・分析するためのツールです。通常、Cookieを利用してユーザーのセッションや行動を追跡します。
  • 同意モードとの連携:同意モードから受け取ったユーザーの同意ステータスに基づいて、データ収集方法を動的に調整します。
    • 同意がある場合: Cookieを用いた標準的なデータ収集を行います。
    • 同意がない場合: Cookieを使用せず、同意モード経由で送信されるPing(限定情報)を受け取ります。Google Analytics 4 (GA4) では、この情報をもとに行動モデリングを行い、同意しなかったユーザーの行動を推計してレポートに反映させることが可能です(一定のデータ量などの条件あり)。

関係性

ユーザーがウェブサイトを訪れると、まず① Cookie同意バナーが表示され、同意を求められます。ユーザーが選択した同意状況(同意/拒否)は、② Google同意モードを通じて③ Google AnalyticsなどのGoogleタグに伝えられます。Google Analyticsはその情報に基づき、Cookieを使って詳細なデータを収集するか、Cookieを使わずに限定的な情報(Ping)を送信してモデリングで補完するかを決定します。

このように、これら3つは連携して、プライバシー規制を遵守しながら、可能な限り正確なデータ分析を行うための仕組みを構成しています。とくにGoogle同意モードは、Cookie同意取得(バナー)とデータ計測(Analyticsなど)の橋渡し役として重要な役割を担っています。

Cookie同意バナーとGoogle同意モードとGoogle Analytics(Googleタグ)の関係性と役割

CMPの選定基準

CMPとは、Consent Management Platform(同意管理プラットフォーム)の略で、Webサイトでのユーザーのプライバシー設定やCookie使用の同意を管理するためのツールです。GDPRなどのプライバシー規制に準拠したCookie同意バナーの表示や、ユーザーの同意状態の追跡、同意の記録管理などの機能を提供します。

Googleが認定しているCMPパートナー🔗の中から、以下の基準でCookiebotを選択しました。どんなCMPがあるかはこのリンクからフィルタリングできるので気になる方は見に行ってください。

  1. Google CMPパートナーであること
  2. 無料プランの提供
  3. 日本語対応のCookie同意バナー
  4. SDKによる手軽な導入

発生した問題

Google同意モードは有効化できたものの、CookiebotのCookie同意バナーが表示されませんでした。以下の確認を行いましたが、とくに問題は見つかりませんでした:

  • CookiebotのCookieDeclaration🔗の実装確認
    • Cookie Declarationの表示
    • Cookiebot側の設定ドメインの一致
  • 環境変数の値と名前の確認
  • headタグ内のスクリプトの存在確認
  • スクリプトのステータス確認

Cookieyesへの移行

実装に問題がないにもかかわらず表示されないため、別のサービスを検討することにしました。Cookieyes🔗を選んだ理由は、前述のCMPの選定基準に加え、Astro Starter Kitでの実装例🔗を見つけたためです。

実装内容

以下のコードで実装を行いました。Cookieyesのサービス登録手順は省略します。なお、Cookieyesのスキャン機能により、data-cookieyes=ignoreなどの属性は不要です。

---
// src/components/CookieConsent.astro
// Cookieyesのバナーを表示するコンポーネント
type Props = { cookieyesId: string };
const props = Astro.props;
const { cookieyesId } = props;
---

<script
  is:inline
  id="cookieyes"
  type="text/javascript"
  src=`https://cdn-cookieyes.com/client_data/${cookieyesId}/script.js`></script>
---
// src/components/GoogleConsent.astro
// Google同意モードの初期設定を行うコンポーネント
---

<script is:inline>
  window.dataLayer = window.dataLayer || [];
  function gtag() {
    dataLayer.push(arguments); // eslint-disable-line prefer-rest-params
  }
  gtag("consent", "default", {
    ad_personalization: "denied",
    ad_storage: "denied",
    ad_user_data: "denied",
    analytics_storage: "denied",
    functionality_storage: "denied",
    personalization_storage: "denied",
    security_storage: "granted",
    wait_for_update: 500,
  });
  gtag("set", "ads_data_redaction", true);
  gtag("set", "url_passthrough", false);
</script>
---
// src/components/GoogleAnalytics.astro
// Google Analyticsの設定をするコンポーネント
type Props = { gaId: string };
const props = Astro.props as Props;
const gaId = props.gaId;
---

<script
  is:inline
  type="text/javascript"
  async
  crossorigin="anonymous"
  src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}></script>
<script is:inline type="text/javascript" define:vars={{ gaId }}>
  window.dataLayer = window.dataLayer || [];
  function gtag() {
    dataLayer.push(arguments); // eslint-disable-line prefer-rest-params
  }
  gtag("js", new Date());

  gtag("config", gaId);
</script>
---
// src\layouts\Layout.astro
// other import file

// ちゃんと型定義するのであれば、src/env.d.ts で定義して
// ref: https://docs.astro.build/ja/guides/environment-variables/#typescript%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%86%E3%83%AA%E3%82%BB%E3%83%B3%E3%82%B9
const gaId: string | undefined = import.meta.env.PUBLIC_GA_ID;
const cookieyesId: string | undefined = import.meta.env.PUBLIC_COOKIEYES_ID;

// 今回はgaIdやcookieyesIdあるかで判定しているが、本番環境かどうかで判定したいなら以下の変数で判定して
// const isProd = import.meta.env.PROD;
---

<html lang="ja">
  <head>
    {cookieyesId && <CookieConsent cookieyesId={cookieyesId} />}
    <GoogleConsent />
    {gaId && <GoogleAnalytics gaId={gaId} />}
    {/* other head content */}
  </head>
  {/* other content */}
</html>

まとめ

Cookiebotでの実装がうまくいかなかったため、Cookieyesに変更したところ、Cookie同意バナーの表示とGoogle同意モードの有効化に成功しました。

前提を踏まえてAstroでCookiebotのCookie同意バナー表示できたという方がいらっしゃれば是非記事にしていただければ嬉しいです。Cookiebotは無料プランの最大ページ数が少ないものの、バナーの言語切り替えできて魅力的なので。

学んだこと

代替サービスが複数存在する場合、実装がうまくいかない時点で早めに切り替えを検討することの重要性を学びました。個人プロジェクトではある意味で期限がないため、逆に時間をかけすぎてしまう傾向があることも気づきました。

また、Cookie同意バナーの表示の調査の際にpartytownを削除したが、partytownを有効化したらGoogle同意バナーの検知ができなくなったため、Google同意モードとpartytownは併用できないのだろうなと思っています。

ブログを書いている時に環境変数の型定義をsrc/env.d.tsで行った方が環境変数名のミスを防ぎ一覧性を向上させると思ったのでsrc/env.d.tsで環境変数の型定義し直したいと思います。

参考文献

もしこのブログが役に立ったら、コーヒーを一杯おごってくれると嬉しいです。

ko-fi でコーヒー一杯おごる