Google Tag Manager

Consent Mode v2 in GTM: A Technical Implementation Guide

Published 

Someone working across a laptop and a phone at a cafe table

Consent Mode v2 is one of those implementations that is either done properly or done in a way that produces a green checkmark and no actual compliance. The failure is subtle: the CMP is installed, the banner appears, the tags have consent settings configured — and tags still fire before consent is granted, because the default state was never set early enough in the page lifecycle.

This walks through the implementation in the order the browser executes it, which is the only order in which the timing problems become obvious.

What Consent Mode actually is

Consent Mode is not a consent banner and it is not a blocking mechanism. It is a signalling protocol: a way for your site to tell Google's tags what the user has consented to, so those tags can adjust their behaviour rather than being blocked outright.

Two consequences follow from that, and both surprise people.

It only applies to Google tags. GA4, Google Ads, Floodlight. A Meta pixel, a LinkedIn Insight Tag, or a TikTok pixel ignores Consent Mode entirely — those need to be gated separately, which is covered below.

Tags may still fire when consent is denied. In "basic" implementations you block tags outright. In "advanced" implementations Google tags still send a cookieless ping carrying the consent state, which feeds conversion modelling. Which of these you want is a legal decision, not a technical one, and it should be made with whoever owns privacy at your organisation.

The four signals

v2 added two signals to the original two. All four are required for Google Ads features in the EEA.

  • ad_storage — cookies and identifiers for advertising.
  • analytics_storage — cookies and identifiers for analytics.
  • ad_user_data — whether user data may be sent to Google for advertising purposes at all.
  • ad_personalization — whether that data may be used for personalised advertising.

The distinction between ad_storage and ad_user_data catches people out. The first is about storing something on the device. The second is about transmitting data to Google at all. They are independent, and consent to one is not consent to the other.

Two more exist and are less commonly used: functionality_storage and personalization_storage, plus security_storage which is generally always granted.

Step one: the default state, before everything

This is where implementations fail. The default consent state must be set before any tag that reads it loads — which means before the GTM container itself, or in a tag that fires on Consent Initialization, which is the very first trigger GTM evaluates.

If you use a CMP with a native GTM template (Cookiebot, OneTrust, Usercentrics, CookieYes, and most others ship one), use its Consent Initialization tag and skip the manual approach. If you are doing it by hand:

1window.dataLayer = window.dataLayer || [];
2function gtag(){dataLayer.push(arguments);}
3
4// Denied by default for EEA + UK
5gtag('consent', 'default', {
6 ad_storage: 'denied',
7 ad_user_data: 'denied',
8 ad_personalization: 'denied',
9 analytics_storage: 'denied',
10 region: ['AT','BE','BG','HR','CY','CZ','DK','EE','FI','FR','DE','GR','HU',
11 'IE','IT','LV','LT','LU','MT','NL','PL','PT','RO','SK','SI','ES',
12 'SE','IS','LI','NO','GB','CH'],
13 wait_for_update: 500
14});
15
16// Granted elsewhere — adjust to your own legal position
17gtag('consent', 'default', {
18 ad_storage: 'granted',
19 ad_user_data: 'granted',
20 ad_personalization: 'granted',
21 analytics_storage: 'granted'
22});

Three details that matter:

region is an array of ISO 3166-2 codes. A region-specific default overrides the global one for matching visitors. Region matching happens on Google's side using the request IP.

wait_for_update tells Google's tags to wait this many milliseconds for a consent update before proceeding. Without it, tags evaluate the default and move on, so a CMP that resolves in 300ms is too late. 500 is a reasonable starting point; too high and you delay every tag on every page load.

Order. The more specific (regional) default should come first, then the global fallback. Put the whole block in a Custom HTML tag on the Consent Initialization — All Pages trigger, and nothing else on that trigger.

Consent Initialization is not the same as All Pages. GTM fires triggers in a fixed order: Consent Initialization, then Initialization, then Page View, then everything else. A Custom HTML tag on All Pages will run after tags that have already read the consent state. This is the single most common Consent Mode v2 bug and it is invisible in the GTM interface.

Step two: the CMP updates the state

When the user makes a choice, the CMP calls gtag('consent', 'update', {...}) with the granted signals. Native CMP templates do this for you.

If you are wiring it manually, the pattern is:

1// Called by your CMP's callback when the user accepts analytics + ads
2gtag('consent', 'update', {
3 ad_storage: 'granted',
4 ad_user_data: 'granted',
5 ad_personalization: 'granted',
6 analytics_storage: 'granted'
7});
8
9// Push an event so GTM triggers can react
10dataLayer.push({ event: 'consent_update' });

The dataLayer.push is separate and deliberate. The gtag('consent', 'update') call tells Google's tags; the event gives you something to trigger non-Google tags on.

Consent must also be restored on the next page load — the CMP reads its own cookie and calls update again. If your implementation only calls update at the moment of the click, consent silently resets on every navigation.

Step three: tag-level consent settings

Each tag in GTM has a Consent Settings section (Advanced Settings → Consent Settings) with two options.

Built-in consent checks — the tag template declares what it needs. Google tags do this automatically. You cannot change them and you should not want to.

Additional consent checks — you specify signals the tag requires before firing. This is where non-Google pixels get gated. A Meta pixel with ad_storage set as an additional required consent will simply not fire until ad_storage is granted.

Set additional consent checks on every non-Google tag. This is the manual step that Consent Mode does not do for you, and it is where most containers are non-compliant. The GTM audit lists every tag that has no consent gate, which is the fastest way to find them.

Step four: verify it actually works

Nothing in the GTM interface proves that consent gating works. The proof is on the wire.

Load the page in a fresh incognito window with your network tab filtered to collect. Do not touch the banner.

Look at what fired. In a basic implementation, no GA4 hit should exist. In an advanced implementation you should see a hit carrying gcs=G100 — the consent state code, denied on both axes. The collect payload reference covers gcs and gcd in detail.

Check the non-Google pixels. Meta, LinkedIn, TikTok. These are the ones that fire when they should not, because Consent Mode does not touch them.

Accept consent and confirm subsequent hits carry gcs=G111.

Reload the page. Consent should persist — hits should carry G111 immediately, without you touching the banner again.

Decline, and repeat. Some CMPs handle Accept correctly and Reject not at all.

Then repeat the whole sequence from an EEA IP if your defaults are region-scoped, because a UK-only region list and a test from New York will show you the global default and tell you nothing.

Common failure modes

Default set on the wrong trigger. Covered above. If the consent default is not on Consent Initialization, assume it is too late.

wait_for_update missing or too short. Tags evaluate the default before the CMP resolves. The symptom is a measurable drop in conversions that appears the day consent mode went live, because tags are seeing "denied" on every first page view.

Only two signals set. v1 implementations that were never updated. ad_user_data and ad_personalization missing means Google Ads features degrade in the EEA regardless of what the user consented to.

Consent not restored on navigation. The update call happens on click but nothing re-reads the cookie on subsequent page loads. Every page looks like a first visit.

Non-Google tags ungated. The most common outright compliance failure.

No consent gate on Custom HTML. Custom HTML tags are arbitrary JavaScript and frequently load third-party scripts. They need explicit additional consent checks like any other tag — and they are easy to miss because they do not look like pixels. A consistent naming convention that prefixes Custom HTML tags makes them visible in the tag list.

Server-side containers ignored. If you run server-side GTM, the consent state travels with the event but the server container's tags need their own configuration. A second container is a second place to be non-compliant.

How Tagfire helps

Consent implementations are hard to verify because the failures are timing-dependent and invisible in the tools that manage them.

GTM Audit includes a dedicated Consent Mode v2 pass across its 50+ checks: whether a consent default exists and on which trigger, whether all four v2 signals are set, which tags have no consent gate, and which Custom HTML tags load third-party resources without one. It covers server-side containers too.

Tag Debugger is how you prove the runtime behaviour. Capture a session before consent and after, and the consent state on each hit is decoded and displayed next to it — no network tab, no manual gcs parsing. Because you can record the sequence (load → decline → reload → accept) as a journey, you can then have it replayed on a schedule so a CMP update six months from now does not silently break the gate.

Payload Decoder decodes gcs, gcd, dma, and npa from a single pasted request. No account needed, useful for a one-off check on a site you do not manage.

The GTM audit documentation covers the consent checks, and the live debugger docs cover capturing a consent sequence.

Related reading
Hand-drawn wireframes of three page layouts sketched side by side
GA4

The 2026 GA4 + GTM Setup Checklist

A complete technical checklist for Google Analytics 4 and Google Tag Manager — collection, configuration, consent, campaign tracking, and governance. Verify each item before you trust a single report.

Read article
A person grouping coloured sticky notes on a whiteboard during a workshop
Google Tag Manager

GTM Container Naming Conventions That Scale

A naming convention for GTM tags, triggers, and variables that stays readable past 200 assets — plus how to retrofit one onto a container that already has none.

Read article