Tags: analytics concept

Instrumentation Debugging

Date: 2026-08-16


Three questions, three different tools: did it fire, did it leave the browser, did it land. Most wasted debugging time is spent answering one of them while believing you answered another.


What it is

Instrumentation debugging is establishing where in the chain an event was lost or malformed. The chain has three links and each fails differently.

1  FIRED     the code ran, the data layer received it
2  SENT      a network request left the browser
3  LANDED    the destination stored it correctly

An event can fire and never send (blocked, queued at unload). It can send and never land (rejected, malformed, wrong property). Checking the wrong link is why “it’s not tracking” investigations run long.

1. Did it fire?

The data layer, in the console. Type dataLayer and read the array — every push is there in order, with the payload as the site actually produced it.

dataLayer                       // full history, in order
dataLayer.slice(-3)             // the last three pushes

To watch pushes as they happen, wrap push before the container loads:

const orig = dataLayer.push;
dataLayer.push = function (...args) {
  console.log('DL →', ...args);
  return orig.apply(this, args);
};

The tag manager’s preview mode is the other route: it shows every trigger evaluation, which tags fired and which didn’t, and the variable values at that moment. It answers “why didn’t the tag fire” better than anything else, because it shows the trigger conditions failing.

2. Did it leave the browser?

DevTools → Network, filtered to the collection endpoint. What you’re checking:

  • Does a request appear at all? No request means blocked, or the tag never fired — check link 1 first
  • Status code. A 204 or 200 means accepted. A 4xx means the payload was rejected, and the response body usually says why
  • The payload. Expand the request and read what was actually sent. Compare it against the tracking plan, field by field
  • How many times. Two identical requests is Double Counting

Check with an ad blocker enabled as well as disabled. A request that fires clean for you and never arrives for a share of users is Ad Blockers and Tracking Loss, and it’s invisible if you always test with blockers off.

For events that fire on unload, tick Preserve log or the evidence is destroyed by the navigation you’re trying to measure — Event Batching and Delivery.

3. Did it land?

The destination’s debug view, where one exists — most tools have a real-time stream showing events as they arrive, with properties and any validation errors.

Then, an hour or a day later, query the destination. Debug views show what arrived; they don’t show what was stored after processing, filtering and bot removal. An event visible in a debug view and absent from the table has been dropped downstream, which is a different problem entirely.

Reproducing what you can’t see

  • Force a variant or state with a query parameter override rather than clicking through — much faster, and it reaches states that are hard to produce naturally
  • Test the failure paths. Declined payment, out of stock, validation error. Whether purchase fires on a failed order is the highest-value single check there is
  • Test with consent denied, not just granted. Half of implementations have never been through this path — Consent Management
  • Test on Safari and on a real Android device. Storage and blocking behaviour differ enough to change what you see — Browser Privacy Restrictions

The habits that save time

  • Check the links in order. Fired, sent, landed. Skipping to the query wastes the most time
  • Read the payload rather than trusting the tag name. A tag firing with the wrong value is more common than a tag not firing
  • Compare against the plan, not against expectation. “That looks right” isn’t a check — Guide - Auditing a Tracking Plan
  • Write down what you found, because the same event will be questioned again in six months