CONSENTCHECK
← Blog

Google Consent Mode v2 not working? Here's what to check first

Jul 16, 2026

If you've set up Google Consent Mode v2 and it still looks like GA4 or Google Ads is firing before a visitor makes a choice, you're not alone — it's one of the easiest integrations to get technically present but functionally broken. The banner shows up, the consent categories look right, and tags still fire anyway. In practice, "not working" almost always comes down to one of four things. Here's what's actually happening in each case, and how to check which one you've got. (See Google's own Consent Mode documentation for the full technical reference this is based on.)

First, confirm it's actually broken

Before anything else: clear your cookies (or use a fresh incognito window) and reload the page. If you've already granted consent once, your browser is caching that choice — the site will look "broken" simply because it correctly remembers you already said yes. This single step accounts for a surprising number of false alarms.

With a clean session, open DevTools → Network tab, filter for collect or gtm.js, and reload the page without clicking anything on the banner. If you see requests to google-analytics.com/g/collect or similar before you've made a choice, it's really broken — keep reading.

1. The default consent state isn't actually "denied"

Consent Mode v2 works by setting a default state before any tag fires, then updating that state once the visitor chooses. The most common failure is a Google Tag Manager container-ordering issue: the default command never actually runs before Google Analytics or Google Ads loads, because the consent default tag fires on a trigger that isn't guaranteed to run first.

How to check: in the DevTools console, before interacting with the banner, run dataLayer and look for a consent entry with "default" — check whether ad_storage, analytics_storage, ad_user_data, and ad_personalization are all set to "denied". If any of them are missing, or the entry isn't there at all before your analytics tags load, that's your problem.

The fix: Google Tag Manager has a dedicated trigger type built exactly for this — Consent Initialization – All Pages. Setting the default-consent tag to fire on that trigger, rather than a regular Page View or DOM Ready trigger, guarantees it runs before any other tag in the container, closing the ordering gap directly.

2. The consent update never fires when someone clicks Accept or Reject

The default can be set correctly, and the banner can look and behave perfectly — but if clicking "Accept" doesn't actually call gtag('consent', 'update', {...}), nothing changes. This happens most often with a self-built or heavily customized banner, where the button's click handler was wired to update the on-screen UI but never connected to the actual consent API.

How to check: click through the banner, then check dataLayer again for a gtm.consent or a second consent entry with "update". If your first default entry is the only consent-related entry in dataLayer even after clicking Accept, the update call isn't firing.

The fix: connect the button's click handler directly to gtag('consent', 'update', {...}) with the categories the visitor actually chose — a UI state change alone, without that explicit call, never reaches Google's tags at all.

3. Basic vs. Advanced consent mode mismatch

Google Consent Mode v2 has two implementation modes. Basic mode blocks Google tags from loading at all until consent is granted. Advanced mode lets tags load immediately but sends cookieless "pings" instead of full data until consent is granted. Teams often intend one and accidentally implement the other. The most common version: someone expects Basic-mode blocking behavior, but the actual GTM configuration is set up for Advanced mode — which correctly sends some network traffic pre-consent by design, and gets mistaken for a broken integration.

How to check: those pre-consent network requests you saw in DevTools — do they have a gcs parameter in the URL (a short encoded consent-state string)? If yes, that's Advanced mode's cookieless ping behavior working as designed, not a leak. If there's no gcs parameter and full request payloads are going out anyway, tags aren't respecting consent mode at all.

If you actually wanted Basic mode: the fix is reconfiguring each tag's firing trigger to wait on the consent signal itself, rather than firing immediately on Page View — Advanced mode's pings are a deliberate design choice, not something you disable with a single setting.

4. The CMP isn't actually wired to Consent Mode

The most common root cause of all: the CMP — Consent Management Platform, the cookie banner tool itself (Cookiebot, OneTrust, Termly, or a custom one) — looks and functions correctly as a banner, but was never actually connected to Google's gtag('consent', ...) API in the first place. This happens frequently after a banner migration, a GTM container rebuild, or when a CMP's auto-blocking feature was disabled without anyone reconnecting the manual consent signal.

How to check: this is the same dataLayer check from #1 and #2 — if there's no consent entry at all, regardless of what the banner UI shows, the CMP was never connected to Consent Mode in the first place.

The fix: reconnect the CMP's native Consent Mode integration rather than relying on its blocking feature alone — Cookiebot, OneTrust, and Termly all ship a documented, built-in Consent Mode v2 integration; the fix is almost always re-enabling it, not building a custom bridge from scratch.

If you don't want to check this by hand

This is exactly what a pre-consent scan is built to catch automatically — which tags fired, whether a consent default was present before they did, and whether Basic or Advanced mode behavior actually matches what's configured. Worth running once you've fixed whichever of the four this turned out to be, just to confirm the fix actually took.

If you'd rather do the DevTools check yourself first, the underlying method — independent of Consent Mode specifically — is the same one covered in how to check if cookies fire before consent. And if what brought you here is a shrinking Google Ads or GA4 remarketing audience, see is consent gating shrinking your remarketing audience — items #2 and #3 there point straight back to the two failure modes above.

If Consent Mode is technically firing but ad_user_data or ad_personalization specifically is missing or stuck denied — a different, narrower failure than the four above — see Consent Mode v2 missing ad_user_data and ad_personalization for that specific fix.

Petrus, Founder — ConsentCheck. Built by a developer who implements this stack for a living — this is the exact troubleshooting order I actually work through.

FAQ

Why isn't the default consent state set to 'denied' in Google Consent Mode v2?

Usually a Google Tag Manager container-ordering issue: the consent default command never actually runs before Google Analytics or Google Ads loads, because the consent-default tag is set to fire on a regular Page View or DOM Ready trigger instead of one guaranteed to run first. Check dataLayer before interacting with the banner for a consent entry with "default" and confirm ad_storage, analytics_storage, ad_user_data, and ad_personalization are all "denied." If that entry is missing, or any of those four values isn't denied, tags are already running before the default is set. The fix is a dedicated Consent Initialization - All Pages trigger in GTM -- Google Tag Manager's trigger type built specifically for this -- which guarantees the consent default fires before every other tag in the container, closing the ordering gap directly rather than hoping a Page View trigger wins the race.

Why doesn't clicking Accept or Reject update Consent Mode status?

Most often this happens with a self-built or heavily customized cookie banner: the "Accept" button's click handler updates the on-screen UI (hiding the banner, changing its text) but was never wired to actually call gtag('consent', 'update', {...}). The default can be correct and the banner can look and behave perfectly, and tags will still never receive the updated consent state. Click through the banner, then check dataLayer again for a second consent entry with "update" -- if your first "default" entry is the only consent-related entry even after clicking Accept, the update call isn't firing. The fix is connecting the button's click handler directly to gtag('consent', 'update', {...}) with the categories the visitor actually chose, not just a UI state change.

What's the difference between Basic and Advanced Consent Mode, and why does it look like tags fire before consent?

Google Consent Mode v2 has two implementation modes, and teams often intend one but accidentally implement the other. Basic mode blocks Google tags from loading at all until consent is granted -- no tag, no request, full stop. Advanced mode lets tags load immediately but sends cookieless "pings" instead of full data until consent is granted; those pings are pre-consent network requests by design, not a leak or a bug. The most common confusion: someone expects Basic-mode blocking behavior, but the actual GTM configuration is set up for Advanced mode. Check for a gcs parameter (a short encoded consent-state string) in the request URL: present means Advanced mode's ping behavior working as designed; absent with full request payloads going out anyway means tags aren't respecting consent mode at all, regardless of which mode you intended.

Why isn't my cookie banner (CMP) actually connected to Google Consent Mode?

This is the most common root cause overall: the CMP -- the cookie banner tool itself, whether Cookiebot, OneTrust, Termly, or a custom build -- looks and functions correctly as a banner, but was never actually connected to Google's consent API in the first place. It happens frequently after a banner migration, a GTM container rebuild, or when a CMP's auto-blocking feature was disabled without anyone reconnecting the manual consent signal. Check dataLayer for any consent entry at all, before and after interacting with the banner; if there's none regardless of what the banner UI shows, the CMP was never connected to Consent Mode. The fix is reconnecting the CMP's native Consent Mode integration -- Cookiebot, OneTrust, and Termly all ship a documented, built-in integration for this -- rather than relying on the CMP's own blocking feature alone or building a custom bridge from scratch.

Want to know if your own site does this?

Scan your site free