GA4 consent mode: the sessions your banner hides, measured against Search Console clicks
- measurement
- ad-platforms
- field-notes
GA4 consent mode is how a site tells the Google tag what the visitor allowed: store cookies, send cookieless pings, or send nothing. This site runs the basic version, and since 12 October 2026 it loads no Google tag and sends nothing to Google Analytics before you choose or after you decline. In August I set consent mode up for a European store selling car parts on a hosted e-commerce platform. There a denied default with no banner left eight days of zero GA4 sessions while Search Console kept counting clicks. This post covers the mechanism, both implementations and the numbers from both sites.
- What it is. Four consent types, two commands:
defaultbeforeconfigon every page,updatewhen the visitor clicks. Analytics readsanalytics_storage. - Basic or advanced. Basic keeps the tag off the page until consent; advanced loads it and pings without cookies while denied. This site ran advanced until 12 October 2026 and runs basic since.
- The gap. Store, 16 to 23 August: no GA4 session rows against 178 to 241 Search Console impressions and 1 to 6 clicks a day. 24 August to 1 September: 229 GA4 sessions against 367 clicks.
- Behavioral modeling. GA4 fills report gaps with modeled data only above thresholds: 1,000 denied events a day for 7 days and 1,000 consenting users a day on 7 of 28 days, and meeting them does not guarantee eligibility. Basic is not eligible at all. Both sites' volumes, read on 4 and 15 September, were small next to those bars.
- The rule. Every number gets its instrument, window and blind spot. The second instrument is Search Console, pulled for the same days through this site's Search Console API review.
What is consent mode in GA4?
Consent mode carries the visitor's answer to the Google tag as four signals, each set to
granted or denied: ad_storage, analytics_storage, ad_user_data and
ad_personalization. The first two control cookies, and Analytics reads
analytics_storage to decide whether it may set its cookie. Whether GA4 measures
anything before consent depends on the implementation, not on the signals. Under basic,
nothing leaves the browser until the visitor accepts. Under advanced, cookieless pings
leave from the first page view.
Order matters as much as the values. Google's
consent guide
wants the default command on every page "before any commands that send measurement
data" and warns that consent defaults won't work when the consent code is called out of
order. On an advanced gtag.js site that ordering is the first thing I look for in the
source, before any of the checks further down.
Basic vs Advanced Consent Mode: what the tag does before the click
The difference is whether the Google tag exists on the page before the visitor answers. Basic, per the concepts page, keeps Google tags from loading until the visitor interacts with the consent banner. Advanced loads them when the page opens and, while consent is denied, sends cookieless pings. Per About consent mode, those pings may include a timestamp, the user agent, the referrer, a flag for ad-click information such as a GCLID in the URL, the consent state as Boolean values, a random number and the ID of the consent management platform.
| Basic consent mode | Advanced consent mode | |
|---|---|---|
| Google tag before the click | Not loaded | Loaded on page open |
| Data before the click | None, not even the consent state | Cookieless pings |
| After Decline | Still nothing | Cookieless pings continue |
| After Accept | Tag loads and measures with cookies | Update to granted, cookies from then on |
| Conversion and key event modeling | "a general model" | "an advertiser-specific model" |
| GA4 behavioral modeling | Not eligible | Possible above thresholds, if Google judges the property eligible |
What this site does before you click
No Google tag and no Analytics hits. Until you answer the banner, the page loads no
gtag.js and sends nothing to Google Analytics, and Decline keeps it that way. Accept
loads the tag once, with one config call. The choice is stored in the browser, so on
the next page load the tag either loads straight away or stays off.
The pattern looks like this. It is a simplified sketch, not the production file:
function loadAnalytics() {
if (window.gtag) return;
window.dataLayer = window.dataLayer || [];
window.gtag = function () { window.dataLayer.push(arguments); };
gtag('consent', 'default', {
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
analytics_storage: 'granted'
});
gtag('js', new Date());
gtag('config', 'G-XXXXXXX');
const s = document.createElement('script');
s.async = true;
s.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX';
document.head.appendChild(s);
}
// stored choice: 'granted' loads the tag, 'denied' or nothing loads nothing
if (storedChoice === 'granted') loadAnalytics();
// Accept: store 'granted', then loadAnalytics(). Decline: store 'denied', load nothing.
Read it from the bottom. Nothing runs unless the stored choice is granted, and the
<script> element for gtag.js is only created inside loadAnalytics(), so a visitor
who declines or never answers never downloads the library. That is what makes it basic.
Inside the function, the check on window.gtag stops a second call from loading the tag
twice. The consent default comes before config, as the consent guide requires, with
the three ad signals denied and analytics_storage granted, because by the time this
code runs the visitor has already said yes. The ad types never change; this site runs
no ads. After Accept, the hits that leave carry gcs=G101: Analytics cookies allowed,
Ads cookies not.
What the sketch leaves out is the awkward case: a browser where storage is unavailable, so there is no stored choice to read. The production code has a fallback for that; the sketch does not.
Until 12 October this site ran the advanced version. gtag.js arrived on every page
load, every first visit started denied, and the first page view left as a cookieless
ping. The banner said "Analytics stays off until you accept" the whole time. Under
advanced that was half true: the cookie stayed off, the tag was loaded and pinging. The
banner text did not change in the switch. The behavior changed to match it.
For scale, not comparison, the 15 September read, taken under the advanced setup, shows 59 GA4 users here since 25 July against 6,931 Search Console impressions and 10 clicks since launch: different windows, traffic and units.
Google Consent Mode v2: the two extra parameters
Consent Mode v2 added two signals to the original ad_storage and analytics_storage.
Per Simo Ahava,
ad_user_data asks whether the visitor consents to their personal data being used for
advertising, and ad_personalization whether their data may be used for remarketing.
Neither touches Analytics reports. They matter when the same tag serves Google Ads to
visitors in the European Economic Area, where Google's
EEA update says "you need to
pass through end-user consent choices to Google"; for the upload side of conversions,
see our Google Ads API review. Here the three ad signals stay
denied. On the store, which was about to run Shopping, the banner came first: without
granted consent, purchases would not be counted in full, and a campaign would have
nothing to optimize on.
How do I enable Google consent mode?
It depends on which version you want and where your tags live. For advanced with
gtag.js, call gtag('consent', 'default', ...) on every page before any config or
event command, with the four types set to denied, then call
gtag('consent', 'update', ...) the moment the visitor answers the banner. For basic,
keep the tag off the page until the visitor accepts, then load it with the consent state
already set, as in the sketch above.
With Google Tag Manager, the states come from a consent management platform template or
your own template built on Tag Manager's consent APIs, setDefaultConsentState and
updateConsentState, fired on the Consent Initialization trigger. Google's
consent guide says
not to use gtag('consent','update',...) in their place, because "gtag commands are
queued after all other pending messages and may not be processed before the next event
begins".
Advanced has two options worth setting. wait_for_update is "a millisecond value to
control how long to wait before data is sent", so the first ping waits for a banner that
loads asynchronously. Region defaults let you "set defaults for specific regions, and
then set a different default for all other regions". A consent management platform runs
both commands and keeps the record; the store used a hosted one fired from the
container.
GTM consent mode: the same two states, set through a template
In Tag Manager the mechanism is the same, a default and an update, but they come from a template and a trigger, with a per-tag setting on top. Per Tag Manager consent mode support, every web container includes a Consent Initialization - All Pages trigger by default, and it fires before all other tags, so that is where the default and the CMP tag belong. Google's own tags carry built-in consent checks; everything else gets a per-tag "Require additional consent for tag to fire" setting.
The store's container history is this post in short: a default-denied consent tag on
11 August, the day measurement went live; the CMP tag that could turn denied into
granted on 24 August. In between, the default was the only consent state any visitor
had.
The gap: a store where Search Console counted clicks on days GA4 counted nothing
Search Console clicks and GA4 sessions will not match even on a healthy site. Search Console counts clicks from Google Search; GA4 counts visits from every channel, and only the visits it was allowed to measure. On this store the gap went further: for eight days GA4 counted nothing at all.
Both instruments were read on 4 September: GA4 through the Data API, window 6 August to 4 September, last day in progress; Search Console through its API, 28 days from 6 August, with 1 September the last day carrying data. GA4 had no rows from 16 to 23 August, while Search Console shows 178 to 241 impressions and 1 to 6 clicks a day for those dates. People arrived and the instrument was not listening. Counting resumed on 24 August, the day the banner went live.
| Day (2026) | GA4 sessions | Search Console clicks | Search Console impressions |
|---|---|---|---|
| 16 to 23 Aug | no rows | 1 to 6 a day | 178 to 241 a day |
| 24 Aug | 11 | 21 | 1,100 |
| 25 Aug | 33 | 48 | 1,843 |
| 26 Aug | 40 | 72 | 2,162 |
| 27 Aug | 39 | 63 | 2,155 |
| 28 Aug | 30 | 47 | 1,797 |
| 29 Aug | 21 | 27 | 931 |
| 30 Aug | 13 | 23 | 884 |
| 31 Aug | 23 | 42 | 1,103 |
| 1 Sept | 19 | 24 | 923 |
| 24 Aug to 1 Sept | 229 | 367 | 12,898 |
GA4: all channels. Search Console: by date, Google Search only.
Four things the table does not say. The columns are different units: Search Console counts "How often someone clicked a link from Google to your site" (metrics article), while a GA4 session is any consented visit from any channel, and Organic Search was 213 of the 270 sessions in the 30-day window; 229 against 367 is roughly six in ten, not a consent rate. Second, 264 of the 270 sessions fall in the 12 days from 24 August: a 30-day baseline says 9 a day, the 12 measured days say 22. Third, the Search Console jump on 24 August is not the banner; a sitemap index for the whole catalogue went in on 23 August. Fourth, Search Console hides too: by date the 28 days hold 409 clicks, by query only 30 appear across 1,970 rows, and the other 379, 92.7 percent, sit behind "anonymized (rare) results are omitted from the table, but are included in the chart totals" (troubleshooting article).
My first draft of the client report made two mistakes a reviewer caught. It turned GA4's zero add-to-cart events and zero purchases for 24 August to 4 September into "this traffic does not buy", though GA4 counts consenting visitors and I had not read the store's order panel since 11 August. And it set the best Search Console day, 72 clicks, against a ten-day average of GA4 sessions. Peak against mean is not a comparison.
Behavioral modeling: the thresholds a small site is far from
Advanced consent mode is sold on modeling: denied pings feed a model that fills the gap in reports. The behavioral modeling article sets the bar: consent mode on all pages, "at least 1,000 events per day with analytics_storage='denied' for at least 7 days", and "at least 1,000 daily users sending events with analytics_storage='granted' for at least 7 of the previous 28 days". The same article says meeting these prerequisites "doesn't guarantee eligibility". Blended is the reporting identity that shows modeled data in reports; it does not change what the tag collects. Modeled data never reaches "Audiences", "Retention reports" or the BigQuery export. Conversion modeling for Ads is a separate model: per the concepts page, basic gets "a general model" and advanced "an advertiser-specific model", as in the table above.
For scale, not as an eligibility test: the store averaged about 22 GA4 sessions a day, all channels, from 24 August to 4 September 2026, with the last day still in progress, and this site had 59 users between 25 July and 15 September, while it still ran advanced. Sessions are not daily consenting users, so neither figure measures eligibility, but both are small next to a bar of 1,000 consenting users a day. Under basic this site is not eligible for behavioral modeling at all. I have no October read of its traffic, so I make no claim about what the switch on 12 October cost.
Is Google consent mode mandatory?
Google requires consent signals for EEA traffic; whether the law requires a banner is a separate question this post does not answer. Google's EEA update says that to keep using its tags "for measurement, and for ad personalization, and remarketing features" you must collect consent from EEA users and share consent signals with Google.
The EU user consent policy requires "legally valid consent to: the use of cookies or other local storage where legally required; and the collection, sharing, and use of personal data for personalization of ads". Consent mode does not obtain consent; a banner does. It reports the answer, and when nothing is reported Google assumes "a consented state unless a specific choice has been made, though there may be regional behavioral differences for specific areas like the EEA, Switzerland, and the UK" (About consent mode, linked above).
How do I turn off Google consent mode?
First decide what you want off. To stop Analytics, pause or remove the GA4 tag and keep
the banner. To stop the advanced pings, switch to basic: keep the Google tag off the page
until the visitor accepts, which is what this site did on 12 October. To remove consent
mode itself, remove the consent signals, the gtag('consent', ...) calls or the consent
settings in your CMP's Google integration. I would not remove the whole CMP: it is what
collects the visitor's choice, and tags that wait for consent depend on it.
With no consent values set, Google's Ads help calls the state consented, with regional differences possible for the EEA, Switzerland and the UK. The consent guide's starting point is "By default, no consent mode values are set." Turning consent mode off does not turn measurement off; it turns the question off. I would not do it, and the store is the reason: its gap was not consent mode but half of it, a denied default with no update path. Deleting the default would probably have restored the numbers too, at the price of measuring every EEA visitor without asking.
Google Consent Mode checker: four ways I verify it
No single checker exists; I use four views of the same handshake.
View source first. On an advanced gtag.js site, search for gtag('consent'; the
default block must sit before gtag('config'. On a basic site like this one, what
matters is what loads before the click, and the source alone does not show that. A Tag
Manager site shows only the container snippet. Either way this step only tells you which
of the next checks you need.
Tag Assistant for the sequence. Google's verification article has you "select the earliest Consent event" at tagassistant.google.com, then in the tag's Consent tab "check the 'On-page Default' column. Ensure it's set to 'Denied'", and after the click the 'On-page Update' column for 'Granted'. On the store that test showed the interim state agreed on 11 August: a Default column and no Update until the consent banner went live on 24 August.
The network tab for what left. Each hit carries the state in its query string as
gcs, where per Simo Ahava x "stands for consent to Google Ads cookies" and y
"stands for consent to Google Analytics cookies": G100 none, G110 Ads only, G101
Analytics only, G111 both. Under basic there is no gcs to read before the click,
because there is no hit. The acceptance check of this site's banner on 12 October found
no request for gtag.js or Analytics before a choice or after Decline, then one tag and
one config after Accept, with hits carrying G101. The choice held after a refresh.
The slow fourth check is GA4 Admin. Per Verify and update consent settings, "under Data collection and modification, click Consent settings"; the page shows "the percentage of your website traffic and conversions coming from the EEA" and "may alert you to potential issues with your consent signals", with "48-72 hours" of lag. It is the only check that reports a share of traffic rather than one browser.
What I do with GA4 numbers now
Name the instrument and the window, including the last day with data: on 4 September, Search Console ended on 1 September while GA4 had a partial 4 September. Name the blind spot: a denied visitor for GA4, an anonymized query for Search Console, an untagged event for both.
Compare the same days. Inside GA4, the Search Console link adds a "Google Organic Search Traffic" report that "Displays landing pages with associated Search Console and Analytics metrics"; a landing page with clicks and no sessions is the gap, one row at a time. For anything scripted I pull the Search Console API first.
Treat a zero as a question: zero purchases in GA4 is a reason to open the order panel, not a finding about demand. This site's 59 users by 15 September is what consenting visitors amounted to here; under basic, a visitor who declines leaves no trace in GA4 at all. The banner promises "No ads, no cross-site tracking" either way. What consent mode changes is what I am allowed to believe about the count.
The verdict
A measurement note, so no RUNNING or TESTED label. Consent mode does what the docs say: the tag stores nothing until told it may, and in the advanced version sends cookieless pings that become modeled report data only on a property Google judges eligible. This site now runs basic, so before the click there is nothing to ping. The failure I keep meeting is a default without an update, a report that forgets its instrument, and a zero read as a fact about the world. Search Console was counting the whole time.