Google Ads and GA4 report that Consent Mode v2 signals are missing — remarketing audiences stop populating and Tag Assistant flags the consent state as incomplete — because the CMP you chose emits the two legacy signals but not the two v2 signals ad_user_data and ad_personalization.

Triage: Confirming the Missing v2 Signals

Work through these checks before changing any configuration. The goal is to prove the CMP is the source of the gap, not GTM or the tag itself.

  1. Open GA4 DebugView or Tag Assistant. Load the site in a fresh session with storage cleared. Trigger the consent banner and accept all.

  2. Inspect the consent state event. In Tag Assistant, click the consent update event. A correct v2 implementation shows four rows: ad_storage, analytics_storage, ad_user_data, ad_personalization. If only the first two are present, the CMP is emitting a Consent Mode v1 payload.

  3. Read the live state from the console. Google exposes the resolved consent state internally; the fastest external check is to inspect the dataLayer for the consent commands:

    // List every consent command the page pushed, in order.
    window.dataLayer
      .filter((e) => Array.isArray(e) && e[0] === 'consent')
      .forEach((e) => console.log(e[1], e[2]));

    A healthy trace shows a default with all four keys set to denied, then an update with the four keys reflecting the user’s choice. Missing ad_user_data/ad_personalization in either call confirms the defect.

  4. Run the reproduction checklist:

Root Cause: CMP Emits v1 Signals or Fires update() Too Late

Google Consent Mode v2 became mandatory in March 2024 for advertisers serving EEA users through Google’s advertising products. Version 2 added two signals on top of the original set:

  • ad_user_data — governs whether user data may be sent to Google for advertising purposes at all.
  • ad_personalization — governs whether that data may be used for personalized advertising (remarketing, similar audiences).

A CMP built for the original Consent Mode only writes ad_storage, analytics_storage, functionality_storage, personalization_storage, and security_storage. Google’s newer tags read ad_user_data/ad_personalization and, finding them undefined, withhold data from advertising features even when the user consented. The remarketing audience simply stops growing.

There are two distinct failure shapes. The first is a missing-signal defect: the CMP template predates v2 and never writes the two new keys. The second is a timing defect: the CMP writes all four keys but calls update() after the Google tag has already read the default state, so the tag operates on stale denied values. Both surface identically in Tag Assistant, which is why the triage above distinguishes them by checking command order in the dataLayer, not just presence.

Selecting a CMP for Consent Mode v2 therefore reduces to three hard requirements. The CMP must (1) write all four signals in both default and update, (2) emit the default synchronously before the Google tag loads, and (3) integrate through Google’s certified CMP partner program or a maintained template so signal names stay in sync as Google evolves them. This sits under the broader guidance on selecting and integrating a consent management platform, which is the governing reference for the source-of-truth architecture this fix plugs into.

Note the relationship to basic vs advanced Consent Mode. In basic mode the Google tags do not load until consent is granted, so the default denied state simply prevents loading. In advanced mode the tags load immediately and send cookieless, anonymized pings under the denied default, then upgrade on update. Advanced mode is what feeds Google’s conversion modeling — but it only works if the four v2 signals are present in the default, because the modeled pings are tagged with the consent state at send time.

Resolution: Emit All Four Signals in the Correct Order

The minimal fix has two halves: a hardcoded default you control directly in <head>, and a CMP update that carries all four signals. Do not rely on the CMP for the default if you can set it yourself — owning the default guarantees signal completeness and correct ordering regardless of CMP quirks.

<!-- head: BEFORE the CMP bundle and BEFORE gtm.js / gtag.js -->
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag() { dataLayer.push(arguments); }

  // Consent Mode v2 default: all four ad/analytics signals denied.
  // Omitting ad_user_data or ad_personalization here is the exact bug
  // that stops remarketing audiences from populating.
  gtag('consent', 'default', {
    ad_storage: 'denied',
    analytics_storage: 'denied',
    ad_user_data: 'denied',        // v2 — required
    ad_personalization: 'denied',  // v2 — required
    functionality_storage: 'granted',
    security_storage: 'granted',
    wait_for_update: 500 // ms Google waits for update() before acting on default
  });
</script>

<!-- then the CMP bundle, then the Google tag -->

When the user answers the banner, translate the CMP’s choice into a single update carrying all four signals. Drive it from the one place that reads the CMP, so the mapping lives in exactly one module:

// Called from your CMP adapter on every resolved consent change.
function pushConsentModeV2(choice) {
  // choice is your normalized object: { analytics, ads } booleans.
  // Map both v2 ad signals off the advertising consent, and analytics
  // off the analytics consent. Keep the update atomic — one call, four keys.
  gtag('consent', 'update', {
    analytics_storage: choice.analytics ? 'granted' : 'denied',
    ad_storage:        choice.ads ? 'granted' : 'denied',
    ad_user_data:      choice.ads ? 'granted' : 'denied',
    ad_personalization: choice.ads ? 'granted' : 'denied'
  });
}

// TCF v2.2 CMP: derive the choice, then push. Only act on resolved states.
window.__tcfapi('addEventListener', 2, (tcData, ok) => {
  if (!ok) return;
  if (tcData.eventStatus !== 'tcloaded' && tcData.eventStatus !== 'useractioncomplete') return;
  const p = tcData.purpose.consents;
  pushConsentModeV2({
    analytics: p[1] === true && p[8] === true,       // store + measure content
    ads: p[1] === true && p[3] === true && p[4] === true // store + create/select ads profile
  });
});

If you use a certified CMP template (OneTrust’s or Cookiebot’s Consent Mode v2 build), the vendor emits these calls for you — your selection criterion is simply to confirm the template is the v2 version and that it is configured to fire the update from the same purpose mapping. Do not run both your own update and the CMP’s; pick one owner for the mapping.

Verification

Reload with storage cleared, open GA4 DebugView, and accept all consent. In the consent state panel the four signals must read: analytics_storage: granted, ad_storage: granted, ad_user_data: granted, ad_personalization: granted. Then reload and reject: all four must read denied. The single decisive check is that ad_user_data and ad_personalization appear and change — their presence and correct toggling is what Google Ads reads to resume audience collection. Within 24–48 hours, the Google Ads audience that had plateaued should resume growing.

Common Pitfalls

  • Setting the default after the CMP loads. If the default command is not synchronous in <head> before the Google tag, the tag reads an undefined state and assumes granted, firing pre-consent. The default must be the first dataLayer push.
  • Mapping only ad_storage from the ads choice and leaving the two v2 signals denied. All three advertising signals (ad_storage, ad_user_data, ad_personalization) should derive from the same advertising consent unless your legal basis deliberately splits them. Leaving the v2 pair hardwired to denied silently kills remarketing.
  • Running two owners of the update call. A hand-rolled update plus the CMP template’s update race each other; the loser overwrites the winner. Pick one owner, as covered in the CMP integration guide.

Up: Selecting and Integrating a Consent Management Platform