Loading tutorials…
Loading tutorials…
If a tag isn't firing — or worse, firing when it shouldn't — Tag Assistant is the only honest source of truth. Most operators use it wrong. This walks through the workflow specialists actually use.
Who this is forAnyone with a GTM container who has hit any debugging moment: 'tag fires in Preview but not in production,' 'wrong variable values,' 'event fires twice,' 'event fires never.' This tutorial is the playbook for each.
What you'll need
Step 1
GTM → Preview (top-right). Tag Assistant opens in a new tab. Enter the URL of the page you want to debug. Click Connect.
GTM → click the gray "Preview" button at the top-right of the workspace.
A new tab opens to tagassistant.google.com with your container pre-loaded.
Enter the URL you want to debug (e.g., https://yoursite.com/contact). Click Connect.
A SECOND tab opens — your site, with a debug overlay at the bottom. This is the "connected tab."
In the Tag Assistant tab, you see a sidebar with Tags, Triggers, Variables, Data Layer, Errors panels. The connected tab is where you interact (click, submit, scroll); the Tag Assistant tab is where you observe.
Step 2
The Summary tab lists every event that fired during the session: gtm.js (container load), gtm.dom (DOM ready), gtm.load (page fully loaded), plus your custom events.
Tag Assistant sidebar → Summary tab.
You'll see a chronological list: 'Container Loaded,' 'gtm.dom (DOM Ready),' 'gtm.load (Window Loaded),' then any custom dataLayer events that have fired.
Click any event name in the list. The right pane updates to show:
- Tags Fired (what tags fired on this event)
- Tags Not Fired (what tags were considered but their trigger conditions failed)
- Variables (the snapshot of all variable values at that moment)
- Data Layer (the full dataLayer state at that moment)
Read Tags Not Fired carefully. This is usually where bugs live — a tag is configured but its trigger condition isn't matching.
Step 3
Click a tag in 'Tags Not Fired.' The detail pane shows which trigger condition failed and the actual value at fire time.
Find your problematic tag in the 'Tags Not Fired' list. Click it.
The detail pane shows the tag's triggers, each marked with a checkmark (matched) or X (failed).
For each failed trigger, GTM shows the condition that failed and the actual value found at fire time.
Example: trigger is "Form ID equals contact-form-7" but the actual Form ID at fire time was "wpcf7-f123-p456-o1." You see the mismatch immediately.
Fix: update the trigger condition (use 'Form ID contains contact-form' instead of equals) or use a different variable that matches.
Step 4
Click any event → Variables tab → see every variable's current value. Hover values to see source.
Click an event in Summary. Click Variables tab on the right pane.
Every Variable (Built-in and User-Defined) is listed with its value at that moment.
Data Layer Variables show their resolved path and value. If a DLV resolves to "undefined," you have one of three issues:
1. The Variable Name path is wrong (e.g., "ecommerce.value" but dataLayer has "ecom.value")
2. The dataLayer entry hasn't fired yet at this event point (the push happens later)
3. The push has a typo (camelCase vs snake_case mismatch is the most common)
Cross-reference with the Data Layer tab to see what actually exists in dataLayer at that moment.
Step 5
Data Layer tab shows every push in chronological order with full payload. Use this to verify your custom pushes are firing with the values you expect.
Click any event → Data Layer tab.
You see the full dataLayer state at that moment, top-to-bottom in push order.
Each entry is one push. Click to expand and see nested objects.
Cross-reference what you SEE in dataLayer against what you EXPECT. Differences are usually:
- A push you thought would happen but didn't (check the site code — is the push actually there?)
- A push with different key names (check casing, check nesting)
- A push that fires but values are empty (check the source data, e.g., a Liquid template variable that's null)
Step 6
Errors tab shows JavaScript errors from your container — tag compilation failures, Custom HTML errors, malformed templates.
Tag Assistant sidebar → Errors tab.
Each entry is one error caught by GTM. Click to see the stack trace and which tag triggered it.
Common errors: 'fbq is not defined' (Meta Pixel base tag didn't load before event tag — fix with Tag Sequencing); 'Cannot read property X of undefined' (DLV resolved to undefined and code didn't handle it); 'CSP violation' (Content Security Policy blocking inline script).
If Errors panel is empty but tags still misbehave, the issue is logical (trigger condition, variable value) not technical (broken code). Re-read steps 3-5.
Step 7
After fixing issues in Preview mode and Publishing, test the SAME flow on the live site without Preview. This catches Publish-vs-Preview discrepancies.
GTM → Submit → Publish.
CLOSE Tag Assistant (sometimes Preview mode masks production issues).
Open the live site in incognito. Open DevTools → Network tab.
Trigger the event flow you tested.
In Network tab, filter by "google-analytics" or "facebook" — confirm POST requests fire to the expected endpoints with the expected payloads.
If something works in Preview but not in production, the issue is usually: (a) you didn't publish, (b) a tag is configured to fire only in Preview mode (rare but possible), or (c) the published version doesn't match what you tested.
Common mistakes
Debugging in Preview mode and assuming production works
What goes wrong: Tag fires perfectly in Tag Assistant. You publish, walk away, and discover 3 days later that production never received the change because you never clicked Submit → Publish.
How to avoid: After every Preview-mode confirm, click Submit → Publish. Then re-test on the live site in incognito. Preview ≠ Live.
Reading 'Tags Fired' but not 'Tags Not Fired'
What goes wrong: Your tag is in the Not Fired list with a failed trigger condition you missed. You spend hours wondering why it's not in Fired — the answer was one tab over.
How to avoid: Always check Tags Not Fired alongside Tags Fired. The bug is usually in Not Fired.
Trusting the connected tab's URL when Tag Assistant shows a different URL
What goes wrong: Tag Assistant is connected to a stale URL (e.g., /old-page). You navigate to /new-page in the connected tab but Tag Assistant still shows /old-page data. You debug the wrong page.
How to avoid: After navigating in the connected tab, check the Summary tab refreshes with the new URL. If not, click Refresh in Tag Assistant or restart Preview mode.
Ignoring the Errors panel
What goes wrong: Custom HTML tag has a syntax error. It silently fails. No tag fires. You debug for hours in Variables and Data Layer before noticing the Errors panel had the answer in 30 seconds.
How to avoid: First thing to check on any tag misbehavior: Errors panel. If it has entries, fix those before debugging anything else.
Using Preview mode with cached pages
What goes wrong: Your site has aggressive caching (Cloudflare, browser cache). Preview mode connects to a cached version that doesn't have your latest GTM snippet. Tags don't fire because GTM isn't installed in the cached page.
How to avoid: Open the connected tab in incognito (no cache). Or use DevTools → Network → "Disable cache" while the panel is open. Cache is the silent killer of GTM debugging.
Recap
Done — what's next
How to fire GA4 through Google Tag Manager — without double-counting
Read the next tutorial
Hand it off
Debugging GTM is part skill, part pattern recognition. A specialist who has shipped 50+ containers will diagnose most issues in under an hour — issues that can take a DIYer a full day. If you're stuck, hiring is the faster path. Typically $80-200 for a one-off diagnosis at $14-16/hr.
See specialist rates
Three usual causes: (1) The GA4 Measurement ID in the tag is wrong or for a different property; (2) Your test browser is in a region with Consent Mode blocking — check that consent is granted; (3) DebugView only shows events from sessions with the GA4 debug parameter — Preview mode normally adds this, but if you opened the site directly (not via Tag Assistant's connected tab) the parameter is missing.
Usually one of: (a) you didn't actually click Submit → Publish (Preview doesn't auto-publish); (b) you're testing the live site without the GTM snippet correctly installed (re-check theme.liquid / header.php); (c) caching is serving an older version of the page without GTM.
Yes — Tag Assistant generates a shareable URL when you click 'Share' in the top-right. Send it to a teammate, they can see the same fire history (read-only) without joining your GTM account. Useful for handing off debugging.
Two common causes: (1) The trigger condition matches two events in the dataLayer (e.g., both 'gtm.dom' and 'gtm.load' satisfy 'All Pages'); (2) You have two tags configured similarly that both fire on the same trigger. Check Tags Fired for duplicate names — that's the giveaway.
Check: (1) GTM snippet is installed on the page you're trying to connect; (2) Popup blocker isn't blocking the connected tab; (3) Browser cache isn't serving an old page; (4) Network access from your browser to tagassistant.google.com isn't restricted (corporate firewalls sometimes block). Try incognito + different browser as a test.
Google Tag Manager
Firing GA4 through GTM is the foundation of every modern analytics stack. Done right, it's one tag and a clean event map. Done wrong, you double-count every event and pollute six months of reports. This is the right way.
Google Tag Manager
Meta doesn't ship a native GTM tag template, so the install is a Custom HTML tag. Done right, this is cleaner than the official Meta pixel-injection method — done wrong, you double-fire every event and the Events Manager fills with junk.
Google Tag Manager
Every GTM tutorial assumes you know what dataLayer is. Most don't actually explain it. This one does — in plain English, with examples you can copy. No JavaScript prerequisites.
Google Tag Manager
The default Form Submission trigger handles 70% of forms. The other 30% (AJAX forms, React forms, Webflow forms) need a custom pattern. This walks through both, and which one you need.
Google Tag Manager
DIY GTM works fine for simple stacks. It starts breaking down when you need GA4 + Meta + TikTok + Google Ads all firing accurately with deduplication. Here's the honest framework for when to hire.