Analytics that looked perfectly healthy and recorded nothing.
Page views arrived normally, so the tag was obviously working. Every custom event — form submissions, product clicks, purchases — never reached the platform at all. There is no confidentiality constraint on this one, which is why the whole of it can be shown.
The worst kind of broken: the kind that reports.
Analytics that is entirely dead gets noticed. Traffic drops to zero, somebody asks, and it is fixed that week. Analytics that reports page views and drops everything else does not get noticed, because every check anyone casually runs comes back green.
The tag was in the page. It loaded. Page views were arriving. The dashboard looked normal, so the natural reading of an empty conversions report was that nobody was converting.
What made it hard to catch is that the failure produced no error. Not an exception, not a failed request, not a red line anywhere. One of the symptoms was a console warning rather than an error, which is to say it was in a stream nobody watches on a working site.
Left alone this becomes a decision-making problem rather than a technical one. Every subsequent judgement about which pages convert is made on data that was never collected.
Three assumptions. One of them true.
Each of these looks correct from the code, and each was disproved the same way: by watching what actually left the browser rather than what appeared in the queue.
"The queue means order does not matter"
The data layer is a queue, and the tag drains whatever is waiting when it loads. So an event pushed early should simply be picked up later.
False.An event that arrives ahead of the tag's config call is read and discarded — at that moment there is no property configured to attribute it to. The queue only helps once config is in front of you.
"Pushing to the data layer is pushing an event"
The helper function pushes its arguments onto an array. Pushing an equivalent array directly should be identical, and inspecting the data layer afterwards shows exactly the same contents.
False. A plain array is not processed. The helper pushes an arguments object and the tag reads that shape; a literal array is skipped. It looks correct in the queue and transmits nothing.
"The helper existing means the tag is ready"
Once the global function is defined, the tag must be up, so it is safe to start sending events.
False. An inline snippet defines it as a queue shim before the remote script has loaded. Events emitted in that window go nowhere — while the config calls beside them still produce a page view, so the tag looks alive.
How each one was settled
Not by reading the code, which supports all three readings, and not by inspecting the queue, which is what made the second assumption so convincing. By opening the network panel and asking a narrower question: did a request leave the browser for this event, and did it carry the event name?
Firing both shapes side by side on the same page settled the second one in about a minute — the helper's call produced a request, the hand-pushed array produced none. Everything else followed from being willing to look one layer lower than the tool's own reporting.
Hold the event until it can actually be sent.
Emit only through the official helper
No hand-rolled pushes. The documented call is the one shape the tag reliably reads, and it is the one we proved transmits.
Buffer anything fired too early
Events raised before the tag is genuinely up wait in memory instead of being thrown at a queue that will discard them, and go out once it is ready. There is a deadline on the wait, so a tag blocked by an extension does not leave a buffer being retried for the life of the page.
Test readiness properly
Readiness is checked against an object the remote script creates when it loads, rather than the shim that exists before it. That is the difference between the tag being present and the tag being able to send.
One place that knows all this
Every event on the site goes through a single function, so the ordering rules live in one file with the reasoning written next to them. Nobody adding an event later has to rediscover any of it, which is how this class of bug comes back.
A tag that loads is not a tag that reports.
- +Page views arriving tells you the script loaded. It tells you nothing about whether your events do, and those are two separate systems that fail independently.
- +Check events by watching the network, not the queue. Seeing the event in the data layer is exactly the observation that made the wrong assumption here look right.
- +Events fired as a page loads are the ones most likely to vanish, because they race the tag. If a conversion fires on arrival at a thank-you page, test that one specifically.
- +Silence is not proof of correctness. This whole failure announced itself as one console warning on a site that otherwise looked entirely healthy.
The same principle drives the paid ads audit written up here — establish that the instrument works before you believe, or act on, anything it says.
Sure your events are arriving?
Tell us which actions you believe you are measuring and we will tell you which ones actually reach the platform. We reply within one working day. No calls required.