Google Consent Mode v2

Markdown
Loading…

Tell Google tags what the visitor allowed: add one default snippet, and the SDK sends every update.

Google Analytics 4, Google Ads and Google Tag Manager read consent through Google Consent Mode. It has two halves: a default that says "denied" before any Google tag runs, and an update each time the visitor decides. The SDK sends the updates on its own, on page load and on every change. You add the default.

Skip this page if you use no Google product.

Add the default

Add <GoogleConsentMode /> to the root layout from Installation, as the first thing in <body>. It prints one inline script, so it runs before anything else on the page. Everything else stays as it is: <CookieYesRoot /> still renders the banner and dialogs.

app/layout.tsx
import { GoogleConsentMode } from "@cookieyes/nextjs/server";
import { CookieYesRoot } from "./consent-manager";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <GoogleConsentMode />
        <CookieYesRoot />
        {children}
      </body>
    </html>
  );
}

Then add the Google tool itself: Google Analytics 4, Google Tag Manager or Google Ads.

If the default is missing, the Google integration sets one itself when it loads and logs this warning. The SDK's first update, sent on page load, has already been skipped by then, so a returning visitor who accepted on an earlier visit is treated as denied until they change their choice again:

[cookieyes] Google Consent Mode default was not set before init: add the <head> snippet (googleConsentModeSnippet / @cookieyes/nextjs) for correct first-paint behaviour. Falling back to a deny-by-default now.

Which category controls which signal

CategoryGoogle signals it grants
necessarynone
functionalfunctionality_storage, personalization_storage
analyticsanalytics_storage
performancenone
advertisementad_storage, ad_user_data, ad_personalization

security_storage is always granted. A signal with no category stays denied. If you define your own categories, give each one a gcm list of the signals it grants: see Configuration → Consent categories.

Every Google integration takes a consentMode option:

  • "advanced" (default): the tag loads at once. While consent is denied, Google receives only cookieless pings, as Consent Mode allows. The tag stays loaded when consent is withdrawn.
  • "basic": the tag loads only after its category is granted, and is removed when consent is withdrawn. Nothing reaches Google before a yes.
ga4({ measurementId: "G-XXXXXXX", consentMode: "basic" })

On withdrawal, "basic" clears that product's own cookies, and removes the shared Google library once no other Google product on the page is still active.

Common mistakes

A returning visitor is treated as denied, although they accepted last time. The default snippet is missing, so the update sent on page load was skipped. Look for the warning above, then add the default as shown.

GA4 events are counted twice. Both googleTagManager() and ga4() load the same property. Use one of them for each product. The SDK logs a warning when it sees both.

With "basic", the tag never loads. Its category is not granted yet. That is the point of "basic".

Next steps

On this page