Skip to content
Consent ModeGDPRDMACompliance

Consent Mode v2 in 2026: The ad_user_data Signal Most Audits Miss

·9 min read

Since March 2024, Google requires Consent Mode v2 for EU/EEA traffic. Every major CMP (Cookiebot, OneTrust, Usercentrics, Iubenda, Didomi…) updated their consent banners to comply. Every analytics engineer added a gtag('consent', 'default', {…}) call. Every client was told the setup was fixed.

Most of those setups are still broken. Not because Consent Mode v2 is hard — but because the audit tools used to verify it are checking only 2 of the 4 required signals.

The 4 signals Google actually requires

Consent Mode v2 has four separate consent signals:

The first two existed in Consent Mode v1. They are encoded in thegcs parameter every GA4 request carries — a compact 3-bit string like G100 where the bits represent (version, ad_storage, analytics_storage).

The other two were added for v2. They do not fit in gcs. They are carried in a separate parameter: gcd. Example: 11l1l1l1l5 where each lmeans "denied."

Why most audits miss it

When an audit tool reads a GA4 request and sees gcs=G100, it concludes "ad_storage and analytics_storage are both denied — Consent Mode v2 is working." That is only half true.

A site can have gcs=G100 AND gcd=11l1l1t1l5. That t in the 3rd position means ad_user_data: granted. The site is sending user-identifying ad data to Google before the user has consented. Under the DMA and GDPR, that is exactly what Consent Mode v2 was designed to prevent.

If your audit tool reads only gcs, it will happily report this site as compliant.

How to verify all 4 signals

There are two reliable methods:

Method 1: Read google_tag_data.ics.entries

Google exposes the current consent state as a JavaScript object at window.google_tag_data.ics.entries. Open DevTools on any site with GA4, paste this in the console before accepting the cookie banner:

Object.fromEntries(
  Object.entries(google_tag_data.ics.entries).map(
    ([k, v]) => [k, v.default ? 'granted' : 'denied']
  )
)

A fully-compliant Consent Mode v2 setup returns:

{
  ad_storage: 'denied',
  analytics_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied'
}

If any value is granted before the user has clicked accept, or if any of the 4 signals is missing entirely, your setup is not compliant.

Method 2: Inspect the gcd parameter

If JS state is unavailable (some sGTM setups strip it), read thegcd query parameter on any GA4 /g/collect request. The 4 letters after the leading version digits represent the 4 signals in order: ad_storage, analytics_storage, ad_user_data, ad_personalization.

Letter mapping:

A compliant pre-consent gcd looks like 11l1l1l1l5 or 13r3r3r3r5. Anything with a t in positions 3 or 4 is a red flag.

The partial-setup trap

Even more common than wrong values: the 4th signal is missing entirely. A site ships:

gtag('consent', 'default', {
  ad_storage: 'denied',
  analytics_storage: 'denied',
  ad_user_data: 'denied',
  // ad_personalization is never set
});

This passes naive tools because all declared signals are "denied." But the missing signal defaults to granted in some CMPs and to unknownin Google's own logic, which Google Ads then treats as non-EEA-compliant and excludes the user from conversion modeling.

You lose compliance and attribution — the worst possible outcome.

DMA "denied by regulation"

One 2024+ addition worth knowing about: Google introduced the r letter to mark signals denied by the Digital Markets Act for EU/EEA users. If your CMP marks a user as being in the DMA region, the signals arrive as r instead of l. For compliance purposes, both mean denied, butr specifically tells Google to apply the DMA constraints even if the user tries to override them.

A good audit tool should report the regulation: "dma" state separately so you can confirm your EEA detection is working.

What a fully-compliant setup looks like

Minimum viable Consent Mode v2 defaults call:

gtag('consent', 'default', {
  ad_storage: 'denied',
  analytics_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
  wait_for_update: 500,  // ms to wait for CMP before tags fire
});

Then the CMP calls gtag('consent', 'update', {…}) with the user's choices. All four signals must be present in both calls.

Run this check automatically

Our free scan runs exactly this validation. It reads google_tag_data.ics.entries via headless Chromium, parses the gcd parameter for every captured GA4 request, and flags any signal that is granted pre-consent or missing entirely. The same logic that caught production bugs on a dozen major EU sites during the development of our audit engine.