GTM Troubleshooting
Common Google Tag Manager issues and how to resolve them.
Tags Not Firing
Symptom: Tag Shows "Not Fired"
Diagnosis Steps:
- Check trigger conditions in Preview mode
- Verify event is pushing to data layer
- Confirm variable values match trigger
Common Causes:
| Cause | Solution | |-------|----------| | Trigger event mismatch | Verify exact event name match | | Variable undefined | Check variable configuration | | Condition not met | Review trigger conditions | | Consent blocking | Check consent mode status |
Trigger Not Matching
// Problem: Custom event trigger not firing
// Trigger expects: 'formSubmit'
// Data layer has: 'form_submit'
// Fix: Match case exactly
dataLayer.push({
event: 'formSubmit' // Must match trigger exactly
});
Variable Issues
// Problem: Data Layer Variable returns undefined
// Variable Name: transaction.value
// Data layer: { 'transaction_value': 100 }
// Fix: Correct the variable path
// Either fix variable name to: transaction_value
// Or fix data layer to: { transaction: { value: 100 } }
Duplicate Tags
Symptom: Event Fires Multiple Times
Diagnosis:
// Check data layer for duplicates
dataLayer.filter(e => e.event === 'purchase')
// Returns multiple entries = duplicate pushes
Common Causes:
| Cause | Solution | |-------|----------| | Multiple GTM containers | Remove duplicate containers | | Tag fires on multiple triggers | Consolidate triggers | | Data layer pushed multiple times | Add deduplication logic | | SPA re-initialization | Track page state |
Deduplication Strategy
// Prevent duplicate purchase tracking
(function() {
var trackedTransactions = JSON.parse(
sessionStorage.getItem('tracked_transactions') || '[]'
);
var transactionId = '{{transaction_id}}';
if (trackedTransactions.includes(transactionId)) {
// Already tracked, don't fire again
return;
}
trackedTransactions.push(transactionId);
sessionStorage.setItem('tracked_transactions', JSON.stringify(trackedTransactions));
// Proceed with tracking
dataLayer.push({
event: 'purchase',
transaction_id: transactionId
// ... rest of data
});
})();
Container Not Loading
Symptom: GTM Not Appearing on Page
Checklist:
- [ ] GTM snippet present in HTML
- [ ] Correct container ID (GTM-XXXXX)
- [ ] Snippet in correct location (head/body)
- [ ] No JavaScript errors blocking load
- [ ] No Content Security Policy blocking
CSP Issues
<!-- If CSP is blocking GTM, add to your policy: -->
<meta http-equiv="Content-Security-Policy" content="
script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;
img-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;
connect-src 'self' https://www.google-analytics.com https://region1.google-analytics.com;
">
Verify Installation
// Check if GTM loaded
if (typeof google_tag_manager !== 'undefined') {
console.log('GTM loaded:', google_tag_manager);
} else {
console.log('GTM NOT loaded');
}
// Check container ID
console.log('Container:', Object.keys(google_tag_manager));
Preview Mode Issues
Preview Not Connecting
Troubleshooting Steps:
- Clear browser cache and cookies
- Disable browser extensions (especially ad blockers)
- Try incognito/private mode
- Check popup blockers
- Verify same domain as workspace
Debug URL Issues
// If preview panel doesn't appear:
// 1. Check URL for gtm_debug parameter
// 2. Manually add: ?gtm_debug=x
// Clear preview state:
localStorage.removeItem('GTM_DEBUG_STATE');
Multiple Containers
When previewing with multiple containers:
- Preview one container at a time
- Or use separate browser profiles
- Check for container conflicts
Data Layer Problems
Data Layer Not Defined
// Problem: dataLayer is not defined error
// Solution: Initialize before GTM loads
<script>
window.dataLayer = window.dataLayer || [];
</script>
<!-- GTM snippet here -->
Wrong Data Layer Structure
// Problem: Nested data not accessible
dataLayer.push({
ecommerce: {
items: [...]
},
event: 'purchase' // Event should trigger
});
// But variable for 'items' returns undefined
// Check variable configuration:
// Data Layer Variable Name: ecommerce.items
// Data Layer Version: Version 2 (required for nested objects)
Race Conditions
// Problem: Data pushed after tag fires
// This happens when data layer push is async
// Solution: Push data before event
dataLayer.push({
transaction_id: 'T123',
value: 99.99,
event: 'purchase' // Event LAST
});
// NOT:
dataLayer.push({ event: 'purchase' });
dataLayer.push({ transaction_id: 'T123' }); // Too late!
Variable Resolution
Built-in Variables
| Variable | Common Issues | |----------|---------------| | Click Element | Returns null outside click events | | Page URL | Returns full URL, not path | | Form Element | Only works with Form triggers |
Custom Variable Not Resolving
Debug Steps:
- In Preview, click the event
- Go to Variables tab
- Check resolved value
- Compare expected vs. actual
JavaScript Variable Errors
// Problem: JS Variable returns undefined
// Custom JavaScript Variable:
function() {
return window.userData.email; // userData might not exist yet
}
// Solution: Add safety checks
function() {
if (window.userData && window.userData.email) {
return window.userData.email;
}
return undefined;
}
Consent Mode Issues
Tags Blocked by Consent
Symptom: Tags never fire even after consent
Diagnosis:
- Check consent state in Preview → Consent tab
- Verify consent update is triggering
- Check tag's required consent settings
Consent Not Updating
// Debug consent state
dataLayer.filter(function(item) {
return item[0] === 'consent';
});
// Should show 'default' then 'update' events
Fix:
// Ensure consent update fires after default
gtag('consent', 'update', {
'ad_storage': 'granted',
'analytics_storage': 'granted'
});
// Verify GTM receives the update
// Check for 'consent_update' in GTM preview
Performance Issues
Slow Page Load
Causes:
| Issue | Impact | Solution | |-------|--------|----------| | Too many tags | +2-5s load time | Audit and remove unused | | Synchronous tags | Blocks rendering | Use async loading | | Heavy scripts | Large payloads | Lazy load or defer | | Third-party latency | External dependencies | Server-side where possible |
Tag Timing
// Check tag timing in Preview mode
// Look for tags taking >500ms
// Optimize slow tags:
// 1. Move to server-side
// 2. Lazy load after page ready
// 3. Use pageview trigger instead of container loaded
Publishing Issues
Changes Not Live
Checklist:
- [ ] Published the workspace (not just saved)
- [ ] Correct workspace selected
- [ ] Browser cache cleared
- [ ] CDN cache propagated (wait 5-10 min)
- [ ] No version conflicts
Rollback
If publishing causes issues:
- Admin → Versions
- Find last working version
- Click Publish on that version
- Confirm rollback
Error Messages
Common Errors
| Error | Meaning | Fix | |-------|---------|-----| | "Tag not found" | Tag ID incorrect | Verify tag configuration | | "Invalid JSON" | Malformed data | Check data structure | | "Network error" | Endpoint unreachable | Check destination URL | | "Permission denied" | GTM permissions | Update user access |
JavaScript Errors
// Check console for JS errors
// Common culprits:
// - Undefined variables
// - Missing DOM elements
// - Timing issues
// Wrap custom JS in try-catch
(function() {
try {
// Your code here
} catch(e) {
console.error('GTM Tag Error:', e);
}
})();
Next: GA4 Data Discrepancies