Google Consent Mode v2 setup for agencies (the version that actually works)
A Consent Mode v2 setup can block EU conversions without an error. The setup that works: what each signal does, the GTM wiring, and the verification habit.
TL;DR
Consent mode has seven consent types, and Google's own tags read four of them: ad_storage, analytics_storage, and the two v2 added, ad_user_data and ad_personalization (functionality_storage, personalization_storage and security_storage are there for your other tags). Set the defaults without wiring the cookie banner's "update consent" callback through to GTM, and every EU user shows as denied forever. The setup that works: (1) default consent set to denied for ad/analytics in EU regions only, (2) update consent triggered by the cookie banner's accept/decline callback, (3) the advanced implementation — Google's tags load before the visitor answers and send cookieless pings Google can model from; no account setting turns it on, (4) per-tag consent requirements verified in GTM Preview: required on other vendors' tags, not on Google's, which check consent themselves. Verification takes 15 minutes per client. Skip any step and EU conversions go missing with no error anywhere.
The problem with Consent Mode v2 isn't that it's hard. It's that it has seven consent types (four that Google's tags read), two consent states (default vs. update), regional behavior, and a fork between "basic" and "advanced" implementations — and a cookie-banner integration can get any one of those wrong in a way that doesn't surface until the EU client's quarterly review shows ad spend that produced no measurable conversions.
This is the agency version. Not the official Google walkthrough; the setup plus the checks that prove it works.
What Consent Mode v2 actually does
Consent Mode is Google's mechanism for letting Google tags (gtag.js, GA4, Google Ads) respect user consent without blocking the tags entirely. When consent is granted, tags fire normally with cookies. When consent is denied, tags fire in a degraded mode that:
- Does NOT set or read cookies
- Does NOT send personally-identifiable data
- DOES send "consent-less pings" with anonymized session info that Google uses to model unobservable conversions
The advanced implementation (the one you want) loads Google's tags before the visitor answers the banner, so a decline still sends consent-less pings that Google can model conversions from. The basic implementation doesn't load the tags until consent, so a declined visitor sends nothing (Google's consent mode overview). The difference is the decliners — as large a share as the banner's decline rate. Basic sends Google nothing about them, so Google Ads can model their conversions only from its general model, and GA4 not at all; advanced sends their cookieless pings, so Google Ads models from the client's own traffic (an advertiser-specific model, in Google's words — Google Ads Help) and GA4 can model their behaviour. How much comes back is Google's claim to make, not ours: its own early results put it at more than 70% of the ad-click-to-conversion journeys lost to consent choices, varying with consent rates and setup (Google).
V2 added two signals (ad_user_data, ad_personalization) that separate "may Google receive this user's data for ads" from "may Google use it to personalize ads" — before v2, consent mode could only say whether ad and analytics cookies may be stored. Since March 2024 Google has required them for users in the EEA (Analytics asks for them from the UK and Switzerland too): without them, those users drop out of measurement, ad personalization and remarketing features (Google Ads Help). Modeling predates v2; v2 is what keeps it, and the audience features, available for that traffic.
The seven consent types (and what each blocks)
Get these wrong and you'll either over-block (lose conversions) or under-block (regulator visit).
| Consent type | Controls | Default in EU |
|---|---|---|
ad_storage | Cookies for ads (DoubleClick, conversion linker) | denied |
analytics_storage | Cookies for analytics (GA4, conversion measurement) | denied |
ad_user_data | Whether Google receives user data for ads | denied |
ad_personalization | Whether Google can use data for personalized ads | denied |
functionality_storage | Site functionality (preferences, language) | granted (usually) |
personalization_storage | Personalization such as recommendations | denied (usually) |
security_storage | Security features (authentication, fraud prevention) | granted (always) |
Google's tags read the first four. The last three exist for your other tags: GTM's consent settings can require them before a tag fires. The four ad and analytics denied defaults are what differentiate EU compliance from US; in the US (and most non-EU regions) agencies usually default all seven to granted, and the cookie banner informs rather than gates.
The setup that works
Five steps. Each one is independently a place to break things.
Step 1: Pick a cookie banner that supports Consent Mode v2
Not every cookie banner does. As of mid-2026, working integrations: OneTrust, Cookiebot, Iubenda, Usercentrics, CookieYes, Termly. NOT working / partial: homegrown banners nobody wired to consent mode, some older WordPress plugins.
The banner needs to:
- Set the
default consentstate on page load (before any other Google tags fire) - Update the consent state when the user accepts/declines
- Persist the user's choice (cookie + localStorage)
- Re-apply on subsequent page loads
If the banner only does (1), every user looks denied forever. If it skips (2), accepting consent doesn't actually grant anything. Both are common.
Step 2: Wire default consent BEFORE any Google tags fire
In your <head>, before the GTM container snippet:
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
// Default to denied for EU; granted elsewhere. Region detection
// runs on the server (or via a CDN edge function) — never trust
// client-side region detection for compliance purposes.
gtag('consent', 'default', {
'ad_storage': 'denied',
'analytics_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied',
'functionality_storage': 'granted',
'personalization_storage': 'denied',
'security_storage': 'granted',
'wait_for_update': 500 // ms to wait for the banner to call gtag('consent', 'update', ...)
});
</script>
<!-- Now the GTM container snippet -->
The wait_for_update: 500 tells gtag to hold tag firing for 500ms while the cookie banner has a chance to call gtag('consent', 'update', ...). Without this, tags fire under the default denied state even if the user has consented in a previous session.
Step 3: The cookie banner must call gtag('consent', 'update', ...)
Most cookie-banner platforms have a built-in Google Consent Mode integration that handles this — OneTrust, Cookiebot and Iubenda among them. Where the switch lives, and what it's called, differs by vendor and changes between versions, so follow the vendor's current consent mode guide, map each banner category to the consent types it covers, and confirm the result in GTM Preview (Check 1 below) rather than trusting the setting.
If your banner doesn't have a built-in integration, you write the JS yourself in the banner's accept/decline callback:
// In the banner's `onAccept` callback:
gtag('consent', 'update', {
'ad_storage': 'granted',
'analytics_storage': 'granted',
'ad_user_data': 'granted',
'ad_personalization': 'granted'
});
// In the banner's `onDecline` callback:
// (Don't need to call update — defaults are already 'denied'.)
Step 4: Load Google's tags before the answer (the advanced implementation)
Advanced consent mode isn't a switch in Google Ads or GA4 — it's how the tags load. In the advanced implementation, Google's tags load on every page under the defaults from Step 2 and send cookieless pings while consent is denied; in the basic implementation they don't load until the visitor accepts, so a decline sends nothing. In GTM that means the Google tag, GA4 event and Google Ads tags fire on their normal triggers — not on a "consent granted" trigger — and carry no additional consent requirement (Step 5).
Modeling then needs volume. GA4's behavioral modeling needs a property that collects at least 1,000 events a day with analytics_storage denied for at least 7 days, and has at least 1,000 daily users with it granted on at least 7 of the previous 28 days; the modeled users then show under the Blended reporting identity (Analytics Help). Below that, a small client's EU numbers stay observed-only, however clean the setup.
Without the advanced implementation, declined visitors contribute zero data — Google Ads falls back to its general model, and GA4 models nothing. With it, their consent-less pings feed the modeling — how much comes back depends on the client's consent rate and volume, and Google Ads shows it per domain and country (Check 3).
Step 5: Per-tag consent requirements in GTM
Every tag in GTM has consent settings (Advanced Settings → Consent Settings), and what to set depends on the tag:
- Google's tags check consent themselves. The Google tag, GA4 events, Google Ads conversion tracking and remarketing, and the Conversion Linker list their built-in consent checks there, and adjust to the consent state on their own. Leave their additional consent checks at "Not set" or "No additional consent required": "Require additional consent for tag to fire" holds a tag until every type you tick is granted, which turns the advanced implementation back into basic for that tag (Tag Manager Help).
- Everything else needs the requirement set. Custom HTML tags, and any other vendor's tag whose Consent Settings list no built-in checks (templates differ, so look at each one), fire regardless of consent until you tick "Require additional consent for tag to fire" and the types each one depends on: usually
ad_storagefor an ad pixel,analytics_storagefor an analytics tool.
The mistake to check first: leaving Custom HTML and third-party tags with no consent requirement, so they fire even when consent is denied. Regulator-visible. The other is the reverse — requiring consent on the GA4 or Google Ads tags, which quietly throws away the pings Step 4 was for.
How to verify it actually works
Three checks, 15 minutes total per client:
Check 1: GTM Preview mode
Open Preview on the live container. Refresh the page in Preview tab. Look at the "Consent" tab:
- Default state should match what your
<head>script sets (deniedfor ad/analytics in EU) - After accepting consent in the banner, "Update" event should appear with all four ad/analytics signals →
granted - Tags listed under "Tags Fired" should match expected consent-respecting behavior
If "Update" event doesn't appear when you accept consent: your banner isn't calling gtag('consent', 'update', ...). Step 3 is broken.
Check 2: Tag Assistant Companion (Chrome extension)
Install Tag Assistant. Visit the live site. Tag Assistant shows the consent state in real time + which tags fired with which consent. Easier than GTM Preview for non-developers on the agency team.
Check 3: The consent screens in Google Ads and GA4
- Google Ads: open a conversion action and its Diagnostics tab. It shows the consent mode status and, once the volume thresholds are met (as soon as about 7 days after the rollout), the consent mode impact: the uplift in conversions from modeling, per domain and country, refreshed weekly (Google Ads Help).
- GA4: Admin → Data collection and modification → Consent settings shows, per data stream, whether the consent signals arrive, and what share of the traffic comes from the EEA (Analytics Help).
Then compare the EU segment in GA4 before and after the rollout. Observed EU events should fall by about the banner's decline rate — declined visitors aren't in the observed numbers — with modeled users back under the Blended reporting identity once the property clears Step 4's thresholds. If EU conversions fall by much more than the decline rate, or the Diagnostics tab doesn't show consent mode as active, the banner integration isn't wired (Step 3) or Google's tags aren't loading before consent (Steps 4 and 5).
The agency-side discipline
Consent Mode is a per-client setup, but the discipline is per-agency. Three things to standardize:
- A house standard cookie banner. Pick one (OneTrust, Cookiebot, Iubenda, etc.) and use it on every EU-touching client. Per-client banner choice fragments your engineer's debugging skill.
- A house template for the
<head>consent block. The 5-step setup above as a snippet you paste into every client. Variations are bug surfaces. - A monthly EU-traffic delta check. Add it to the 21-item checklist. If EU conversions drop more than 70% month over month — a starting line; tune it per client — treat the banner as broken until proven otherwise.
What's NOT in this post
We're deliberately not covering:
- The legal/regulatory side of consent (CMP requirements, IAB TCF, country-specific rules) — that's a lawyer question
- Server-side consent enforcement (advanced topic; not needed for a first setup)
- Consent-aware audience segmentation (V2 of consent maturity; most agencies should get the basics right first)
The setup above is the minimum that works. Get this right, then layer on the advanced topics as the client engagement matures.
The takeaway
Consent Mode v2 is five steps, and any of them can fail without an error. The one to re-check most is Step 3 — the banner's gtag('consent', 'update', ...) call — because every banner change can break it silently. Verify with GTM Preview after every banner change, every banner version upgrade, and every quarterly review. Skip the verification and the EU conversions go missing without anyone noticing until the renewal conversation.
Try Phloz free if you want the stack consent gates — GTM, GA4, the pixels — tracked as typed nodes per client with a "last verified" timestamp baked in (the banner itself goes on as a Custom node).