Skip to main content
Google Consent Mode v2

§ 04 · Concepts

Google Consent Mode v2

What it is, why EU merchants need it, and how TrackLayer integrates with your CMP.

Consent Mode v2 is Google's solution for tracking users in the EU without violating GDPR. Misconfigured, it silently drops 20-40% of your EU ad data.

That number surprises teams because the site often still "works." The banner shows, Google tags load, and campaigns keep spending. The problem is subtler: attribution gets thinner, remarketing audiences shrink, and performance reporting drifts away from reality specifically for regulated traffic. By the time someone notices, the missing data is already baked into bidding and reporting.

Consent Mode v2 is Google's attempt to keep measurement functional when full cookie-based tracking is not allowed. It does not mean "ignore consent." It means your site communicates consent state to Google in a structured way so Google can decide what kind of signal it is allowed to receive from each user.

Without Consent Mode, many teams choose between two bad extremes: fire everything before consent, or fire nothing at all until consent is granted. The first is a compliance risk. The second destroys measurement for users who decline cookies.

Consent Mode v2 introduces a middle path. Instead of not firing at all when consent is denied, your site can send cookieless pings. These are limited signals without personal data or durable advertising storage. Google uses those constrained signals and machine learning modeling to estimate the conversions and journeys that would otherwise disappear from the reporting gap.

Operationally, Consent Mode v2 depends on two distinct calls:

  1. gtag('consent', 'default', ...) before any Google tag fires.
  2. gtag('consent', 'update', ...) when the user's consent state changes.

The order matters. If the default call comes too late, Google tags can initialize under the wrong assumptions and set or read storage before your CMP has spoken. That is the classic broken setup: the banner is present, but the tags already fired.

This is the correct initialization pattern:

// ABOVE your gtag/GTM loader, BEFORE any tag fires
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
 
gtag('consent', 'default', {
  ad_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
  analytics_storage: 'denied',
  wait_for_update: 500,
  region: ['BE','BG','CZ','DK','DE','EE','IE','GR','ES','FR','HR','IT','CY','LV','LT','LU','HU','MT','NL','AT','PL','PT','RO','SI','SK','FI','SE','GB','NO','IS','LI']
});

Put this above the gtag.js or Google Tag Manager loader, not below it. If a tag can fire before the default consent state exists, you no longer have a reliable consent boundary.

The region scoping

Two fields in the default call deserve specific attention: wait_for_update and region.

wait_for_update: 500 tells Google tags to pause briefly so your CMP has time to load and publish the user's choice before downstream tags decide how to behave. The value is milliseconds. Five hundred is a practical default for most storefronts. Lower than that and slow CMPs can miss the window. Much higher than that and you start delaying legitimate tracking for users who would have granted consent immediately.

The region list scopes the restrictive default to EU and EEA traffic. That matters because not every visitor needs to be treated under the same storage default. If you apply a denied-by-default posture globally with no region scoping, you can degrade measurement for non-EU traffic unnecessarily. The country codes in the example cover the standard European footprint many merchants care about, including the EEA and closely related markets.

The core idea is simple: default-denied where regulation requires it, avoid needless gating where it does not.

Update call from your CMP

The second half of the implementation is the update call. This happens after the user acts on the banner. If the visitor accepts, your CMP should publish the granted state immediately:

gtag('consent', 'update', {
  ad_storage: 'granted',
  ad_user_data: 'granted',
  ad_personalization: 'granted',
  analytics_storage: 'granted',
});

If the user rejects, your CMP should still call update, but keep the denied values. That part is often missed. Teams wire only the accept path and assume "do nothing" covers rejection. It does not. The system should move from an explicit default state to an explicit live state based on the user's choice.

Your CMP is the source of truth here. Cookiebot, OneTrust, iubenda, and other tools expose hooks for banner decisions. Use those hooks to trigger the update call exactly once per consent change, and make sure the state is also available to any non-Google systems that need to respect the same choice.

url_passthrough: true

When cookies are denied, attribution gets harder because durable client storage is unavailable. That is where url_passthrough: true becomes important. It preserves click identifiers like gclid and fbclid in the URL across navigation so session continuity does not collapse immediately when storage is unavailable.

Add it to the default consent call:

gtag('consent', 'default', {
  ad_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
  analytics_storage: 'denied',
  url_passthrough: true,
  wait_for_update: 500,
  region: ['BE','BG','CZ','DK','DE','EE','IE','GR','ES','FR','HR','IT','CY','LV','LT','LU','HU','MT','NL','AT','PL','PT','RO','SI','SK','FI','SE','GB','NO','IS','LI']
});

This flag is easy to skip because the page still loads without it. But if you care about ad attribution when cookies are denied, it is one of the highest-leverage settings in the whole setup.

ads_data_redaction: true (optional)

Some teams want stricter privacy than Google's minimum behavior. ads_data_redaction: true is the flag for that. It strips more precise data, such as IP and detailed user agent information, from eligible pings even when consent is granted.

That is optional because it is a policy choice, not a universal best practice. The tradeoff is straightforward: more privacy, less measurement fidelity. If your legal posture or internal standards demand higher minimization, this is the flag to evaluate. If your goal is only to satisfy Consent Mode v2 requirements while preserving as much reporting quality as possible, you may decide not to enable it.

How TrackLayer integrates

Consent configuration usually goes wrong when each downstream platform is wired separately. The CMP talks to Google one way, Meta another way, TikTok not at all, and server-side events ignore the banner entirely. That is how teams end up "compliant" on the frontend and non-compliant in the backend.

TrackLayer centralizes that state. Our server-side pipeline receives the consent signal from your CMP through dataLayer or a meta tag, then applies the relevant flags per event before routing to Meta, TikTok, Google Ads, and the rest of your enabled destinations.

That means you do not need to hand-build platform-specific plumbing for every destination. You still need a correct CMP implementation and the right default/update sequencing, but once the consent state exists, TrackLayer carries it through the fan-out path consistently.

The practical benefit is not just less code. It is fewer silent mismatches between browser-side and server-side behavior. One consent source, one pipeline.

CMPs we've tested with

We have tested the standard template above with these CMPs:

  • Cookiebot
  • OneTrust
  • iubenda
  • Pandectes
  • Osano
  • Usercentrics
  • CookieYes

All work out of the box if you follow the template above. The integration mistakes we see are rarely CMP-specific. They are almost always sequencing errors, missing update calls, or region scoping applied too broadly.

Before rolling this to production, test with an EU VPN, clear browser state, and watch the network and tag behavior from first page load through banner interaction. If tags fire before the default call, or if the update never happens after a click, the setup is not done.

Run /tools/consent-check to see if your current setup is EU-compliant.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.