By Shehab Waleed, Founder, Cairo Studio 2 min read
Three weeks after we launched the new site, Google Analytics had recorded nothing. The tag was there, the script loaded with a 200, and the console was clean. Umami, the other analytics tool on the same pages, was counting visitors as usual. We only found out when someone went to install the snippet, assuming it had never been added.
The two versions
This is the stub Google gives you.
function gtag() {
dataLayer.push(arguments);
}This is the one we shipped.
function gtag(...args) {
dataLayer.push(args);
}They look the same, and most reviewers would prefer the second. ESLint has a rule, prefer-rest-params, that asks for exactly that change. The difference is what lands in dataLayer: the first pushes an arguments object and the second pushes a real array. gtag.js treats those differently. Our commands went into the queue and stayed there.
Proving it
We ran both stubs in headless Chromium with the same tag and the same calls, and blocked the outgoing hits so no test data reached the account.
await page.route('**/g/collect*', (route) => {
hits += 1;
return route.abort();
});With the array version, the script returned 200 and we counted 0 hits and 0 errors. With arguments, we counted 4 hits. Nothing on the page tells you which one you have.
What counts as checking
We had checked that the script loaded, and that only proves the script loaded. The proof that analytics works is the outgoing request, so look for that in the network panel or in a test.
- Filter for /g/collect. That is the request that carries the hit.
- Give it a few seconds, because hits are batched and can arrive late.
- Test on the live host if your analytics only runs in production, as ours does.
A second tool is what makes this kind of failure visible, as long as someone compares the two. Google Analytics cannot recover those 22 days, but Umami has them.
For more on the setup behind this site, read why we moved it to our own server.
