NextJS中Google Analytics与Adsense的Cookie合规集成问询
核心思路
不用直接移除 GTM,而是通过GTM 变量+触发器结合用户 Cookie 选择,精准控制代码加载:
- Analytics:仅在用户同意分析类 Cookie 时触发采集
- AdSense:区分两种模式——用户拒绝广告 Cookie 时加载非个性化广告,同意时加载个性化广告(无需移除广告)
- 用 localStorage 持久化用户的 Cookie 选择,下次访问自动生效
1. 实现 Cookie 同意状态管理
创建上下文组件统一管理同意状态,并同步到 GTM 数据层:
// contexts/CookieConsentContext.js import { createContext, useContext, useState, useEffect } from 'react'; const CookieConsentContext = createContext(); export function CookieConsentProvider({ children }) { const [consent, setConsent] = useState({ analytics: false, advertising: false, isAccepted: false, }); // 页面加载时读取本地存储的同意状态,并同步到GTM useEffect(() => { const saved = localStorage.getItem('cookieConsent'); if (saved) { const parsed = JSON.parse(saved); setConsent(parsed); window.dataLayer?.push({ event: 'consent_updated', user_consent_analytics: parsed.analytics, user_consent_advertising: parsed.advertising, }); } }, []); // 更新同意状态并同步到GTM和本地存储 const updateConsent = (newConsent) => { const updated = { ...consent, ...newConsent, isAccepted: true }; setConsent(updated); localStorage.setItem('cookieConsent', JSON.stringify(updated)); window.dataLayer?.push({ event: 'consent_updated', user_consent_analytics: updated.analytics, user_consent_advertising: updated.advertising, }); }; return ( <CookieConsentContext.Provider value={{ consent, updateConsent }}> {children} </CookieConsentContext.Provider> ); } export function useCookieConsent() { return useContext(CookieConsentContext); }
2. 在 _app.js 中集成 GTM 和上下文
GTM 始终加载,但内部标签根据同意状态触发:
// pages/_app.js import { CookieConsentProvider } from '../contexts/CookieConsentContext'; import Script from 'next/script'; import CookieConsent from '../components/CookieConsent'; export default function MyApp({ Component, pageProps }) { return ( <CookieConsentProvider> {/* GTM 脚本(始终加载) */} <Script id="gtm-script" strategy="afterInteractive" dangerouslySetInnerHTML={{ __html: ` (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-XYZ'); `, }} /> {/* GTM noscript 备用标签 */} <noscript> <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XYZ" height="0" width="0" style={{ display: 'none', visibility: 'hidden' }} ></iframe> </noscript> <Component {...pageProps} /> <CookieConsent /> </CookieConsentProvider> ); }
3. 实现 Cookie 同意弹窗组件
让用户自主选择 Cookie 类型:
// components/CookieConsent.js import { useCookieConsent } from '../contexts/CookieConsentContext'; export default function CookieConsent() { const { consent, updateConsent } = useCookieConsent(); if (consent.isAccepted) return null; return ( <div style={{ position: 'fixed', bottom: 0, left: 0, right: 0, padding: '1.5rem', background: '#fff', boxShadow: '0 -2px 12px rgba(0,0,0,0.1)' }}> <p style={{ margin: 0, marginBottom: '1rem' }}> 我们使用 Cookie 优化体验和提供广告,您可以选择接受的类型。 </p> <div style={{ display: 'flex', gap: '0.8rem', flexWrap: 'wrap' }}> <button onClick={() => updateConsent({ analytics: false, advertising: false })}> 拒绝全部 </button> <button onClick={() => updateConsent({ analytics: true, advertising: true })}> 接受全部 </button> <button onClick={() => updateConsent({ analytics: true, advertising: false })}> 仅接受分析 </button> <button onClick={() => updateConsent({ analytics: false, advertising: true })}> 仅接受广告 </button> </div> </div> ); }
4. 动态控制 AdSense 广告模式
创建 AdSense 组件,根据同意状态切换个性化/非个性化广告:
// components/AdSenseAd.js import { useCookieConsent } from '../contexts/CookieConsentContext'; import { useEffect, useRef } from 'react'; export default function AdSenseAd({ adSlot, adClient }) { const { consent } = useCookieConsent(); const adContainer = useRef(null); useEffect(() => { if (!adContainer.current) return; // 清空现有广告并创建新单元 adContainer.current.innerHTML = ''; const adElement = document.createElement('ins'); adElement.className = 'adsbygoogle'; adElement.style.display = 'block'; adElement.setAttribute('data-ad-client', adClient); adElement.setAttribute('data-ad-slot', adSlot); adElement.setAttribute('data-ad-format', 'auto'); adElement.setAttribute('data-full-width-responsive', 'true'); // 关键:data-npa=true 表示非个性化广告,false 表示个性化 adElement.setAttribute('data-npa', consent.advertising ? 'false' : 'true'); adContainer.current.appendChild(adElement); // 加载AdSense脚本(仅首次执行) if (!window.adsbygoogle) { const script = document.createElement('script'); script.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'; script.async = true; document.body.appendChild(script); } // 触发广告加载 (window.adsbygoogle = window.adsbygoogle || []).push({}); }, [consent.advertising, adSlot, adClient]); return <div ref={adContainer} />; }
使用示例:
// 在页面中引入广告 <AdSenseAd adClient="ca-pub-XXXXXXXXXXXXXXXX" adSlot="YYYYYYYYYY" />
5. GTM 后台配置 Analytics
- 创建自定义变量:
- 变量名:
user_consent_analytics,类型:数据层变量,数据层变量名:user_consent_analytics
- 变量名:
- 配置 GA4 标签:
- 填入你的 Measurement ID,触发条件设置为:
- 事件名称:
consent_updated - 且
user_consent_analytics等于true
- 事件名称:
- 填入你的 Measurement ID,触发条件设置为:
- 可选:添加页面视图触发器,同样设置为仅当
user_consent_analytics为true时触发
关键注意事项
- AdSense 账户获批后,替换组件中的
adClient和adSlot为实际值 - 非个性化广告无需用户同意,即使拒绝广告 Cookie 也会正常显示,仅不会基于用户兴趣投放
- 分析类 Cookie 拒绝时,GTM 中的 GA 标签不会触发,不会收集用户行为数据
内容的提问来源于stack exchange,提问作者Korer
相关产品推荐
相关产品推荐

