Google Consent Mode v2: basic vs. advanced, and what your banner actually sends

Published on

Consent Mode v2 is four signals and one timing rule. Here's what each signal means, how a banner's categories map onto them, and the difference between basic and advanced mode — with what Croombit does in each case.

Since March 2024, Google requires sites with visitors in the EEA to send Consent Mode v2 signals if they want to keep using measurement and ads personalization features. Most of the confusion around it comes from treating it as a product setting. It isn't. It's a small, well-defined protocol between your consent banner and Google's tags: a default state before anyone decides, and an update once they do.

The signals, in plain terms

SignalWhat it controlsCroombit maps it from
analytics_storageAnalytics cookies (e.g. Google Analytics _ga)The ANALYTICS category
ad_storageAdvertising cookiesThe MARKETING category
ad_user_dataSending user data to Google for advertising — new in v2The MARKETING category
ad_personalizationPersonalized ads and remarketing — new in v2MARKETING or PERSONALIZATION
functionality_storage / personalization_storageSite features and personalization storageFUNCTIONAL / PERSONALIZATION
security_storageSecurity (fraud prevention, authentication)Always granted

The mapping is by category, not by purpose name. A purpose called newsletter_tracking with category MARKETING drives the three ad signals; one called marketing with category ANALYTICS drives only analytics_storage. That distinction is the source of most "Consent Mode isn't working" tickets — see Cookie categories.

The timing rule: default first, update second

Before any Google tag runs, the page must declare a default — everything not yet decided is denied. Once the visitor chooses, the banner sends an update with the real values. If the default arrives after a tag has already fired, that tag has already behaved as if consent were granted, and no later update can undo it.

// What the Croombit banner (cmp.js) pushes before any Google tag:
gtag('consent', 'default', {
  ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied',
  analytics_storage: 'denied', functionality_storage: 'denied',
  personalization_storage: 'denied', security_storage: 'granted',
  wait_for_update: 500,
});

// …and once the visitor decides (here: analytics yes, marketing no):
gtag('consent', 'update', { analytics_storage: 'granted', ad_storage: 'denied', /* … */ });

wait_for_update: 500 gives a returning visitor's stored choice half a second to arrive before tags fall back to the default.

Basic vs. advanced mode

  • Basic mode: Google's tags don't load at all until the visitor grants the matching category. Nothing reaches Google before a decision; if they decline, nothing reaches it at all. Google models less, because it receives less.
  • Advanced mode: the tags load immediately with the denied defaults and send cookieless pings, which Google uses for conversion and behavioral modeling. You get better modeled numbers; you also send Google requests before anyone has said yes, which your legal team needs to have assessed.

The hosted banner behaves as basic mode. It holds back gtag/js and gtm.js — along with every other known tracker — until the matching category is granted, and still pushes the denied defaults first for anything that runs earlier. That's the conservative default for an EU site.

If you've decided on advanced mode, use the custom integration: load gtag yourself, push the defaults, and let tc.applyConsentMode(visitor, gtag) send the update from the stored state. The same state is also available server-side from GET /v1/consent/google-consent-mode — see TCF, Consent Mode and GPP.

Consent Mode tells Google what it may do. It records nothing on your side. If a regulator asks what a given visitor agreed to, the answer has to come from your own records: the exact text shown, the decision and when it was made. In Croombit that's the vault entry behind every decision and its signed receipt — Consent Mode is only the last step, the one that tells the tags.