No login to the tag manager. The container told me everything anyway.

Nine months of zero purchase events, diagnosed without account access. The tag wasn't missing — its trigger group was assembled differently from every sibling.

I picked up a problem that had been sitting still since last November. The main storefront of a home & living group was reporting zero purchase events to its ad platform. Nine months of a conversion signal flatlined at nothing. The diagnosis I inherited, written by someone competent, was one line: the purchase tag is missing.

It wasn't missing. It was there, correctly built, and it had been waiting nine months for a permission that never came.

Verify the premise before you verify anything else

An inherited diagnosis is the most expensive object in a handover. It's plausible, it's free, and it arrives pre-agreed, so nobody re-derives it. Everyone who touches the project after that is debugging the summary rather than the system.

So I split it in two. The premise — zero purchases since November — I checked against the ad platform's own dataset statistics for the last week. It held. That mattered, because if the events had actually been arriving under a different name, everything downstream would have been wasted effort. The diagnosis I threw away and started again.

I had no access. It didn't matter.

The blocker was that the tag container for that storefront isn't on my account. No publish rights, not even read.

Except a published tag container isn't secret and was never designed to be. It has to be readable by every browser that loads the site — that's the entire mechanism. Request the container file the way a visitor's browser does and you get the whole configuration back: every tag, every trigger, every variable, every group. Ninety-three tags, in this case, parsed in a couple of minutes.

Worth sitting with that for a second if you run a site: your tagging setup is public. Not leaked, not exposed by a mistake — public by design. Anyone can read which vendors you fire, on what conditions, with what parameters. It is a diagnostic gift when you're locked out of your own stack, and it's also a reason not to put anything clever in a variable name.

The tag was fine. Its trigger group wasn't.

A trigger group evaluates several triggers as one unit, and fires only after every trigger in it has fired at least once. It's the right tool when a tag must not run before consent has been resolved and the data layer is populated — the canonical use case.

Laid side by side, every working group for that vendor had the same shape: the consent-and-initialisation trigger, plus its own ecommerce trigger. Except one. The purchase group was the only group in the container without the initialisation trigger in it. In its place were a cookie-state-change event and an add-payment-info event.

Both of those are real events. Neither is a mistake on its own. They just never both occur on the order-confirmation page. The group could never complete, so it never fired, so a perfectly good tag sat inert for nine months while the reporting quietly showed a zero that everyone had stopped questioning. I've written before about systems that return a clean status code all the way to nowhere — this is that, at a scale that costs real budget, because not every zero on a dashboard means the same thing.

Nobody had to break it. One group was assembled differently from its eleven siblings, and the difference was invisible from every screen anyone actually looks at.

There was a second fault, and fixing one alone makes things worse

The same parse turned up a split-brain data layer. The analytics tags read the current-generation keys. The ad platform's tags still read the legacy ones from the previous schema. Nobody had migrated the second set when the first moved.

So if I'd only repaired the trigger group, purchase would have started firing — with undefined value, undefined currency and no contents, because those parameters come off the data layer keys the tags were told to look at. That's a downgrade, not a fix. A silent failure at least announces itself as a zero. A noisy failure reporting conversions worth nothing gets built into a bid strategy and spends money. Both changes have to ship together.

One thing I deliberately didn't do: fire a test purchase into the live pixel to confirm the theory. It would have proved the point and polluted the client's reporting with a transaction that never happened, in a dataset feeding an optimiser. Static analysis and read-only inspection are slower and leave the evidence intact. Being able to tell a convincing shortcut from a defensible method is most of what experience buys you, and it's the same instinct as knowing which numbers on a dashboard were ever really yours.

The fix is a few minutes of work. Finding it took a day, and none of that day was spent in the tool I wasn't allowed into.

Sources & further reading

External: Trigger group — Tag Manager Help · Trigger groups in Google Tag Manager, Simo Ahava · Meta Pixel reference — standard events and parameters

Related posts: Everything returned 200 · Which zeros were real · The AI handed me a number wrong in the most convincing way · Your brand search isn't the hero your dashboard thinks

Subscribe to Remco Livain

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe
Work with me →×