1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js App RouterでGoogle Consent Mode v2を正しく実装する

1
Last updated at Posted at 2026-03-28

はじめに

Google Consent Mode v2 は、ユーザーのCookie同意状態に応じてGA4やGoogle広告のデータ収集を制御する仕組みです。2024年3月からEEA向けに必須化されましたが、日本の改正電気通信事業法への対応としても有効です。

本記事では、Next.js 15 App Routerで Google Consent Mode v2 を正しく実装する方法を、実際のプロダクト(Bitcoin Simulator)のコードをベースに解説します。

Google Consent Mode v2 とは

Consent Mode v2 では、以下の4つの同意パラメータを管理します。

パラメータ 用途
analytics_storage GA4のCookie
ad_storage 広告Cookie
ad_user_data 広告目的のユーザーデータ送信
ad_personalization 広告パーソナライゼーション

重要なのは、GA4スクリプトを読み込む前に gtag('consent', 'default', ...) を呼び出すことです。

実装の全体像

Next.js App Routerでの実装は3ステップです。

  1. Cookie同意バナーで同意レベルを取得・保存
  2. GA4コンポーネントで Consent Mode default/update を発行
  3. 同意変更イベントでリアルタイムに状態を更新

ステップ1: Cookie同意の管理

まず、Cookie同意の状態を管理する仕組みを作ります。

export function getConsentLevel(): 'all' | 'essential' | null {
  try {
    const val = localStorage.getItem('cookie_consent');
    if (val === 'all' || val === 'essential') return val;
    if (val === '1') {
      localStorage.setItem('cookie_consent', 'all');
      return 'all';
    }
  } catch { /* storage unavailable */ }
  return null;
}

同意変更時にはカスタムイベントを発火します。

function handleAccept(level: 'all' | 'essential') {
  localStorage.setItem('cookie_consent', level);
  window.dispatchEvent(new Event('cookie-consent-changed'));
}

ステップ2: GA4コンポーネントにConsent Modeを統合

ここが本記事の核心です。

'use client';
import { useEffect, useRef } from 'react';
import { getConsentLevel } from './cookie-consent';

const GA_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;

function gtag(...args: unknown[]) {
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push(args);
}

export default function GoogleAnalytics() {
  const loaded = useRef(false);
  const consentDefaultSet = useRef(false);

  useEffect(() => {
    if (!GA_ID) return;
    if (!consentDefaultSet.current) {
      consentDefaultSet.current = true;
      const ok = getConsentLevel() === 'all';
      gtag('consent', 'default', {
        analytics_storage: ok ? 'granted' : 'denied',
        ad_storage: 'denied',
        ad_user_data: 'denied',
        ad_personalization: 'denied',
      });
    }
    const load = () => {
      if (loaded.current) return;
      if (getConsentLevel() !== 'all') return;
      loaded.current = true;
      gtag('consent', 'update', { analytics_storage: 'granted' });
      const s = document.createElement('script');
      s.src = 'https://www.googletagmanager.com/gtag/js?id=' + GA_ID;
      s.async = true;
      document.head.appendChild(s);
      gtag('js', new Date());
      gtag('config', GA_ID, { anonymize_ip: true });
    };
    load();
    window.addEventListener('cookie-consent-changed', load);
    return () => window.removeEventListener('cookie-consent-changed', load);
  }, []);
  return null;
}

実装のポイント

1. default は GA スクリプトより前に

gtag('consent', 'default', ...) はdataLayerへのpushなので、GAスクリプト読み込み前に実行できます。

2. useRefで重複防止

React 18のStrict Modeでのダブル実行を防止します。

3. 同意前はスクリプト自体を読み込まない

Consent Mode の denied 設定だけでなく、スクリプト読み込み自体を制御します。

4. cookie-consent-changed イベント

同意バナーで許可した瞬間にページリロードなしでGA4が有効化されます。

Root Layoutへの配置

<body>
  {children}
  <CookieConsent />
  <GoogleAnalytics />
</body>

まとめ

  1. consent default をGAスクリプト読み込み前に発行
  2. 同意取得後に consent update + スクリプト読み込み
  3. カスタムイベントで同意変更をリアルタイム反映

この実装は Bitcoin Simulator で実際に稼働しているコードをベースにしています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?