All posts
5 min readdebugging, gtm, browser-extension

How to debug tags in the browser (without GTM Preview)

GTM Preview is great until you can't use it — a client site you don't have container access to, a production-only bug, a competitor teardown. You can debug almost any tag from the browser alone.


GTM Preview is the right tool when you own the container. When you do not — auditing a competitor, inheriting a client site, checking a production page from a phone, or verifying what a real user actually experiences — the browser's own devtools tell you everything. The network panel is the ground truth: if a request left the browser, the tag fired, whatever any interface claims.

Start with the network panel, not the console

Open devtools, go to Network, and filter by what you are looking for. These four filters cover most of what you will ever need:

FilterShows
collectGA4 hits (google-analytics.com/g/collect)
gtm.js or gtag/jsContainer and Google tag loading
/tr or facebookMeta Pixel events
googleads or /pageadGoogle Ads conversions and remarketing

Then perform the action — click the button, submit the form, complete the checkout — and watch what appears. A request appearing is proof the tag fired. No request means it did not, regardless of what a dashboard says.

Reading a GA4 hit

Click a collect request and open the payload. The parameters are terse but readable:

  • en — the event name. This is the first thing to check: is it the event you expected, spelled the way you expected?
  • tid — the measurement ID. Two different values across requests means two properties.
  • cid — the client ID. Changing between page loads means cookies are being blocked or reset.
  • ep. prefixed — your event parameters.
  • up. prefixed — user properties.
  • gcs — the consent state, encoded. G100 means denied; G111 means granted. This one parameter answers most consent questions instantly.
  • dl — the document location. Check it for anything that looks like an email address or phone number.

Two useful habits: enable "Preserve log" before testing a flow that navigates, or the confirmation page load will wipe the evidence, and sort by size to spot the giant payloads that indicate something is being sent that should not be.

Reading a Meta Pixel hit

Meta requests go to /tr with query parameters:

  • id — the pixel ID.
  • ev — the event name (PageView, Purchase, Lead).
  • cd[...] — custom data, including value and currency.
  • eid — the event ID used for deduplication with the Conversions API. If this is missing and you run CAPI, your conversions are double-counting.

The console tricks worth knowing

Inspect the dataLayer directly — it is just an array on the page:

// Everything pushed so far
window.dataLayer

// Just the event names, in order
window.dataLayer.filter(function (i) { return i.event; })
                .map(function (i) { return i.event; })

// Watch pushes live, as they happen
(function () {
  var push = window.dataLayer.push;
  window.dataLayer.push = function () {
    console.log('dataLayer push:', arguments[0]);
    return push.apply(window.dataLayer, arguments);
  };
})();

That last snippet is the closest thing to Preview mode you get without container access. Paste it early in the page's life and every subsequent push prints as it happens, in order, with its full payload.

Also worth checking in the console:

// Which Google tags are present
Object.keys(window).filter(function (k) {
  return /^(ga|gtag|dataLayer|fbq|ttq|_fbp)/.test(k);
})

Test the way a real user experiences the site

Debugging in your everyday browser profile produces false results in both directions.

  • Use a clean profile or incognito, with extensions disabled. Your own ad blocker will make working tags look broken.
  • Then test with a blocker on, deliberately, to see what a blocked visitor's data looks like. That gap is real and worth knowing.
  • Test on mobile. Remote-debug a real phone rather than trusting the desktop emulator — in-app browsers behave differently, and a meaningful share of your traffic is in one.
  • Test from the relevant geography if consent behaviour differs by region. A VPN is enough to see what an EEA visitor gets.

Verifying consent behaviour without container access

This is the check most worth doing on a site you do not own:

  1. Load with a fresh profile. Before choosing anything, look at the gcs parameter on Google requests — it should be G100 (denied) and no advertising cookies should be set.
  2. Accept. New requests should show G111, and cookies should appear.
  3. Reject, then navigate to a second page. The denied state must persist rather than resetting.

If step 1 shows granted signals before any choice, tags are firing without consent. If step 2 never changes, consent updates are not reaching Google — the failure that quietly zeroes out EU data. Verifying Consent Mode properly covers both.

Finding duplicate tags from the outside

Duplicates are the most common problem you can diagnose without any access at all:

  1. View source and count distinct G-, AW-, and GTM- identifiers.
  2. In the network panel, count collect requests per page load. One page view event per page is correct; two means duplicate configuration tags.
  3. Check for the theme-plus-container pattern — a hardcoded gtag snippet in the HTML and a GA4 tag inside GTM. This one is invisible from within the container, which is why so many teams miss it.

When you do have container access

Preview mode is still better for one specific thing: understanding why a tag did not fire. It shows the trigger evaluation — which condition failed, which variable was undefined. The network panel tells you what happened; Preview tells you why.

Use both: Preview to build and diagnose, network panel to verify what production actually does. Preview runs with a debug cookie and a different code path, so "works in Preview" is not the same claim as "works in production".

FAQ

How do I know if a GA4 event fired without GTM Preview?

Filter the network panel for collect and check the en parameter of the request that appears when you perform the action. A request with the right event name is proof it fired.

Can I debug tags on a site I do not own?

Yes — everything in this article works from the outside, because it inspects what the browser actually does. You cannot see trigger logic, but you can see every request, parameter, and consent state.

Why does a tag work in Preview but not in production?

Preview mode runs with a debug cookie and can behave differently around consent, timing, and ad blockers. Always verify in a clean production session, not just in Preview.

What is the gcs parameter in a GA4 request?

The encoded consent state. G100 means storage denied, G111 means granted. It is the fastest way to confirm whether Consent Mode is working, on any site.

How do I debug tags on a mobile device?

Remote-debug a real device over USB rather than using the desktop emulator. In-app browsers — inside social apps — behave differently from mobile Chrome or Safari, and they carry a lot of paid traffic.

For a fast outside-in check before you open devtools at all, the free tracking audit reports tags, duplicates, script weight, and consent signals for any URL.


See where your tracking stands

Run the same 13-check audit referenced in this post against any URL. No signup, results in seconds.

Run a free audit