GTM · · Last updated: June 2, 2026

How to debug tracking like a pro

Tag Assistant is just the beginning. Here's the full toolkit and process I use to find tracking bugs that nobody else can find.

How to debug tracking like a pro

Most analytics setups break silently. No error messages. No alerts. Just data that stops being accurate and nobody notices for weeks or months. When someone finally does notice, they open Tag Assistant, see green checkmarks, and conclude everything is fine. It’s not fine. Tag Assistant tells you tags fired. It doesn’t tell you if they fired correctly, with the right data, at the right time.

Debugging tracking is a distinct skill from setting up tracking. I’ve spent years developing a process and toolkit for finding bugs that standard validation tools miss entirely. This is that process.

The toolkit

Before we talk about process, let’s talk about tools. You need more than one, because different tools reveal different problems.

GTM Preview Mode

The obvious starting point. GTM’s preview mode shows you which tags fired, in what order, and what data they received. It’s useful for verifying that your GTM configuration works as expected.

What most people miss: the Variables tab in preview mode. Don’t just check if the tag fired. Click into the tag, look at the variables it consumed, and verify every single value. I’ve found countless bugs where the tag fires but a variable resolves to undefined because the data layer push happened in the wrong order. Many of these are the same GTM mistakes I find in every audit.

Also pay attention to the timing. Preview mode shows you the Tags tab for each event in the timeline. Click through them sequentially. If your Purchase tag fires before the transaction data layer push, the tag will fire with empty values. The tag still shows as “fired” in the summary. But it sent garbage data.

Google Tag Assistant (Legacy and Companion)

Tag Assistant Companion is the Chrome extension that powers GTM preview. But Tag Assistant Legacy (the standalone extension) still works and shows you something different: raw hit data for GA4 and other Google tags. You can see the exact parameters being sent with each event.

I use both. Preview mode for understanding the GTM logic. Tag Assistant Legacy for seeing what actually left the browser.

GA4 DebugView

DebugView shows events arriving in GA4 in real time, with all their parameters. It’s the only way to verify that GA4 actually received the event, not just that it was sent.

Enable it by either: adding debug_mode: true to your GA4 config tag in GTM, or installing the GA Debug Chrome extension. I prefer the GTM approach because you can use a custom variable to enable debug mode only for specific users (like your own IP or a cookie flag).

What DebugView reveals that nothing else does: parameter limits. GA4 silently truncates parameter values that exceed character limits. DebugView shows you the truncated values. I once spent two hours debugging why a content_group parameter wasn’t matching reports, only to discover GA4 was cutting it off at 100 characters.

Browser DevTools Network Tab

This is where intermediate debugging ends and advanced debugging begins.

Open DevTools, go to the Network tab, and filter for the requests that matter. For GA4, filter for collect. For Meta pixel, filter for facebook.com/tr. For GTM, filter for googletagmanager.com.

What you’re looking at: the actual HTTP requests leaving the browser. Every parameter. Every header. The response status code. The timing.

I always check:

  • Status codes. A 200 means the request was received. A 204 is normal for tracking pixels. Anything else is a problem.
  • Query parameters. The actual data being sent, URL-encoded. Decode it and read every parameter.
  • Request timing. If a tracking request takes 3 seconds, it might get cancelled by page navigation.
  • Request size. GA4 has payload limits. If you’re sending too many parameters, the request might get split or truncated.

Charles Proxy / Fiddler

When you need to see HTTPS traffic that DevTools can’t show you (like traffic from mobile apps or server-side requests), a proxy tool is essential.

I use Charles Proxy on macOS. Set it up as a system proxy, install its SSL certificate, and you can inspect every HTTP/HTTPS request from any application. This is how I debug mobile app tracking, server-side CAPI events, and anything that doesn’t originate from a browser tab.

Charles also lets you throttle network speed, which is invaluable for testing tracking behavior on slow connections. Does your purchase event still fire if the network drops to 2G speeds? Charles will tell you.

BigQuery raw data

This is the ultimate debugging tool. When GA4 data reaches BigQuery (via the BigQuery export), you see every event with every parameter, unsampled, unfiltered, and unprocessed. If you’re new to BigQuery, my BigQuery for marketers guide covers the essentials.

I’ll cover this in more detail later because it deserves its own section.

The debugging process

Tools are just tools. What matters is the process. I follow the same five steps every time, regardless of the bug.

Step 1: Reproduce

Before you can fix something, you need to see it happen. Get specific about the reproduction steps. “The purchase event doesn’t fire” is too vague. “The purchase event doesn’t fire when a user checks out with PayPal on mobile Safari after being redirected from an email campaign” is something you can work with.

Ask for exact URLs, device types, browsers, and user flows. I keep a bug reproduction template that includes: browser/device, page URL, user journey steps, expected behavior, actual behavior, and screenshots of DevTools.

If you can’t reproduce it, you can’t debug it. This sounds obvious, but I’ve watched analysts spend hours guessing at problems they’ve never actually seen happen.

Step 2: Isolate

Once you can reproduce the bug, start removing variables. Does it happen in all browsers or just Safari? Does it happen on all pages or just the checkout? Does it happen with consent accepted and declined?

Isolation is about narrowing the scope until you find the specific condition that causes the problem. Each test eliminates a category of causes.

Tracking broken and you can't figure out why?I specialize in finding the bugs that standard audits miss.

Book a Free Audit →

Step 3: Identify

With the scope narrowed, dig into the technical cause. This is where you switch between tools based on what you’re looking for.

If the tag isn’t firing at all: GTM Preview Mode. Check triggers, check variable values, check blocking triggers.

If the tag fires but data is wrong: DevTools Network tab. Read the raw request and compare parameter values to what you expect.

If the data leaves the browser correctly but doesn’t appear in reports: GA4 DebugView, then BigQuery. The problem is downstream.

If it only fails for certain users: consent tool configuration, ad blocker interference, or browser-specific behavior.

Step 4: Fix

Fix the root cause, not the symptom. If a purchase event fires before the data layer push, don’t add a timeout to delay the tag. Fix the data layer push timing. Timeouts are band-aids that will fail under different conditions.

Document the fix. I keep a tracking changelog for every client that records what broke, why, and what was changed. Tracking bugs recur, and having that history saves hours.

Step 5: Verify

Don’t just check that your fix works in your browser. Verify across the conditions where the bug originally appeared. Test on multiple browsers. Test with consent accepted and declined. Test on mobile.

Then check the data the next day in GA4 reports and BigQuery. Did the fix hold in production? Are event counts back to expected levels? Real verification takes 24-48 hours of production data.

Common bugs and how to find them

Here are the bugs I encounter most frequently, with the specific debugging approach for each.

Race conditions

The most common tracking bug I see. A tag fires before the data it needs is available. The purchase tag fires before the transaction object is in the data layer. An event parameter references a DOM element that hasn’t rendered yet.

How to find it: GTM Preview Mode, look at the timeline. Click each event in sequence. If your tag fires on a gtm.dom or gtm.load event, but the data layer push happens after those events, you have a race condition.

Fix: use a Custom Event trigger that matches the data layer push event, not page lifecycle events.

Your consent management platform might be blocking tags you think are firing. This is especially sneaky because the behavior changes based on the user’s consent state, and you (the developer) almost always have consent accepted on your own machine.

How to find it: clear all cookies, reload the page, and decline consent. Open GTM Preview Mode and check which tags fired. Compare to the list that fires when you accept consent. If marketing tags fire in both states, your consent configuration is broken (the other way, but still broken). If they don’t fire when you expect them to after consent, check your consent categories.

A specific gotcha: some consent tools load asynchronously. GTM fires its Container Loaded event before the consent tool initializes, so tags triggered on Container Loaded bypass consent entirely. This is a compliance problem. Use GTM’s Consent Mode initialization triggers to handle this correctly.

SPA navigation issues

Single-page applications are tracking minefields. The page doesn’t reload on navigation, so gtm.js and gtm.dom events only fire once. If you rely on pageview triggers for tracking, you’ll capture the first page and miss every subsequent navigation.

How to find it: navigate through multiple pages in your SPA with GTM Preview open. Count the pageview events. If you see one where you expected five, your SPA tracking is broken.

Fix: push a custom event to the data layer on every route change. Most frameworks have router hooks for this. React Router, Vue Router, Next.js, and Angular all provide navigation events you can tap into. Then trigger your GA4 page_view event on that custom event, not on page load.

iframe isolation

Iframes create separate browsing contexts. Your GTM container in the parent page can’t see events inside an iframe, and a GTM container inside the iframe can’t access the parent’s data layer.

This breaks tracking for: embedded payment forms (Stripe, Braintree), embedded booking widgets, embedded chat tools, and cross-domain iframes.

How to find it: if you suspect an iframe is involved, right-click the area and check if “View Frame Source” appears. In DevTools, switch the JavaScript context dropdown from “top” to the iframe to inspect its network requests separately.

Fix: use postMessage to communicate between iframe and parent, or implement server-side tracking for the events that happen inside the iframe.

Redirect chains

Redirect chains eat tracking parameters. This is also a primary failure mode for cross-domain tracking in GA4. A user clicks an ad with utm_source=google&gclid=abc123, gets redirected through your email platform, then through a URL shortener, then to your site. Each redirect might strip or overwrite parameters.

How to find it: open DevTools Network tab. Navigate to the URL the user would click. Watch the redirect chain. Check each request’s URL for the parameters you care about. If gclid disappears at step 3 of 5, you found the problem.

Also check: server-side redirects (301/302) vs. JavaScript redirects. Server-side redirects usually preserve query parameters. JavaScript redirects often don’t.

BigQuery as the ultimate debugging tool

When everything else fails, BigQuery has the answer. GA4’s BigQuery export contains every event, every parameter, and every user property, unsampled and unmodified by GA4’s processing.

I use BigQuery to debug problems that can’t be reproduced in a browser:

Missing events for specific users. Query events filtered by user_pseudo_id. Did the event actually arrive? If it’s in BigQuery but not in GA4 reports, the problem is a report filter or data threshold, not a tracking issue.

Parameter values that look wrong in reports. Reports aggregate data. BigQuery shows individual events. If your average purchase value looks wrong, query the raw events and check for outliers, duplicate transactions, or events with missing values.

Time-based debugging. “Conversions dropped last Tuesday.” Query BigQuery for events around that date. Compare event counts hour by hour. Correlate with deployment logs. Did someone push a code change at 2pm that broke the data layer?

Consent state verification. If you’re sending consent parameters with your events, BigQuery lets you filter by consent state and verify that only consented events carry PII.

Here’s a query pattern I use constantly: count events by event name and date for the last 30 days, grouped by day. Plot it. Any sudden drops or spikes are candidates for investigation.

Building the debugging muscle

Debugging tracking is a craft. You develop intuition over time for where bugs hide and which tool will reveal them fastest. The process I described above is the framework, but speed comes from experience.

My advice: debug other people’s tracking. Volunteer to audit a friend’s website. Pick a random e-commerce site and open DevTools to see what they’re sending. The more implementations you examine, the faster you’ll spot patterns and recognize common mistakes.

And keep a personal bug database. Every bug you find, write down what it was, how you found it, and how you fixed it. After a year, you’ll have a reference that no documentation can match, because it’s based on real problems you’ve actually solved.

AR

Artem Reiter

Web Analytics Consultant

Related Articles

Need help with your analytics?

Free 30-minute discovery call. I'll look at your setup, tell you what's broken, and whether I can help. No commitment.

Or email directly: artem@reiterweb.com