Consent Mode v2, and the day the analytics went quiet
A site can be fully instrumented, pass every check, and still record nothing. Here is the failure we hit on our own site, why it is invisible, and how to prove your tag is alive.
The worst kind of analytics bug is not the one that reports wrong numbers. It is the one that reports zero, because zero looks like a quiet month.
The failure
We rebuilt this site with Google Analytics 4 behind a consent layer. The tag was on the page. The measurement ID was right. The property existed and the data stream was configured. Realtime showed nothing at all for weeks, and the obvious explanations, ad blockers and low traffic, were both plausible enough to keep us from looking harder.
The cause was four characters. Google's snippet defines the tag function like this:
function gtag(){dataLayer.push(arguments);}It pushes the arguments object, not an array. We had modernised it to a rest parameter, which pushes an array instead. Every call still ran, the queue still filled, and Google's library silently discarded every entry because the shape was wrong. No error, no warning, no failed request. Just nothing.
Why nobody catches this
Because every check you would run passes. The script loads. The network tab shows the collect request. The console is clean. The only way to see it is to inspect what actually landed in the dataLayer, where the entries read as an array rather than an Arguments object.
Consent Mode is a second place to lose data
Consent Mode v2 asks you to set defaults before the tag initialises, and denied is the correct default in the EU. That is not a switch that turns measurement off, though: with analytics_storage denied, the tag still sends a cookieless signal, so you keep aggregate traffic without setting an identifier. What you must not do is forget to update the state when someone accepts, which is the other way to have a perfectly compliant, permanently silent property.
How to prove the tag is alive
- Open the console on your own site and read dataLayer directly. Entries should report as Arguments, not Array
- Watch Realtime while you load the site from a phone on mobile data, which rules out your own network and extensions
- Accept the banner and confirm the consent update is pushed, not just the initial default
- Check that the measurement ID on the page matches the data stream you are watching, including the www prefix on the stream URL
We found ours by reading the queue. Two visitors appeared in Realtime within the minute.
