Troubleshoot Events Not Firing on HubSpot
When analytics events don't fire correctly on your HubSpot site, it impacts your ability to measure performance and optimize campaigns. This guide covers HubSpot-specific troubleshooting for GA4, GTM, Meta Pixel, and other tracking tools.
Common Symptoms
- GA4 events not appearing in Realtime reports
- GTM tags not firing in Preview mode
- Meta Pixel events missing in Events Manager
- Form submissions not tracked
- HubSpot analytics showing data but external tools don't
Diagnosis Checklist
Work through this checklist systematically:
1. Verify Base Installation
For GA4:
// Check in browser console
console.log(typeof gtag); // Should return 'function'
console.log(window.dataLayer); // Should return array
For GTM:
console.log(typeof google_tag_manager); // Should return 'object'
console.log(google_tag_manager); // Should show container ID
For Meta Pixel:
console.log(typeof fbq); // Should return 'function'
console.log(window._fbq); // Should return pixel object
2. Check for JavaScript Errors
- Open DevTools (F12)
- Go to Console tab
- Reload page
- Look for red error messages
Common errors:
gtag is not defineddataLayer is not definedfbq is not defined- HubL syntax errors
3. Verify Tracking IDs
GA4 Measurement ID:
- Format:
G-XXXXXXXXXX(starts with G-) - Find in GA4 → Admin → Data Streams
GTM Container ID:
- Format:
GTM-XXXXXX(starts with GTM-) - Find in GTM → Admin → Container ID
Meta Pixel ID:
- Format: Numeric (e.g.,
1234567890) - Find in Meta Events Manager
4. Check Ad Blockers
Temporarily disable:
- Browser ad blockers
- Privacy extensions (uBlock Origin, Privacy Badger)
- VPN/proxy that blocks tracking
Note: 20-40% of users may have ad blockers; account for this in analytics.
GA4 Events Not Firing
Issue: PageView Not Tracking
Check:
Verify GA4 code in Site Header:
Check Network Requests:
- DevTools → Network tab
- Filter by "collect"
- Reload page
- Should see requests to
google-analytics.com/g/collect
Use GA4 DebugView:
- GA4 → Admin → DebugView
- Visit your site
- Should see events appear in real-time
Common fixes:
<!-- Ensure code is properly formatted -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
Issue: Custom Events Not Tracking
Problem: PageView works but custom events (forms, clicks) don't fire
Check:
Event listener code placement:
- Must be AFTER GA4 base code
- Should be in Site Header HTML (not footer)
- Ensure no JavaScript syntax errors
Test event manually:
// In browser console
gtag('event', 'test_event', {
'test_parameter': 'test_value'
});
// Check DebugView - should appear immediately
- Verify event name format:
- Use lowercase and underscores (e.g.,
form_submission) - Max 40 characters
- No spaces or special characters
- Use lowercase and underscores (e.g.,
Common issue: Form events
<!-- Check form event listener is correct -->
<script>
window.addEventListener('message', function(event) {
// Add debug logging
console.log('Message received:', event.data);
if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
console.log('Form submitted:', event.data.id);
gtag('event', 'generate_lead', {
'form_id': event.data.id
});
}
});
</script>
Issue: Events Firing Multiple Times
Problem: Same event tracked 2-3 times
Causes:
- GA4 code in multiple locations (Site Header + GTM + Template)
- Event listener fires multiple times
- Duplicate GTM tags
Fix:
Check all locations:
1. Site Header HTML
2. Site Footer HTML
3. Page-specific code
4. GTM tags
5. HubSpot apps
Remove duplicates, keep only one instance.
Prevent duplicate form events:
var formSubmitted = {};
window.addEventListener('message', function(event) {
if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
var formId = event.data.id;
// Only track once per form
if (!formSubmitted[formId]) {
formSubmitted[formId] = true;
gtag('event', 'generate_lead', {
'form_id': formId
});
}
}
});
GTM Issues
Issue: GTM Container Not Loading
Check:
- Container code in Site Header:
// Should see this in page source
<script>(function(w,d,s,l,i){w[l]=w[l]||[];...})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
Container is published:
- In GTM, check top-right corner
- Should say "Latest Workspace Changes Published"
- If not, click Submit → Publish
Test in browser console:
console.log(google_tag_manager['GTM-XXXXXX']); // Your container ID
Issue: Tags Not Firing in Preview Mode
Problem: Preview mode can't connect or tags don't fire
Solutions:
Disable browser extensions:
- Ad blockers
- Privacy tools
- Try incognito mode
Check trigger conditions:
- In Preview, click tag
- View "Why didn't this tag fire?"
- Adjust trigger conditions
Verify data layer variables:
// In console during Preview
console.log(dataLayer);
// Check if expected values are present
Issue: Data Layer Variables Undefined
Problem: Variables show "undefined" in GTM
Causes:
- Data layer pushed AFTER GTM loads
- Variable name mismatch
- HubL variable empty
Fix:
Ensure data layer comes first:
<!-- Data layer FIRST -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'pageType': '{{ content.type }}',
'contactId': '{{ contact.vid }}'
});
</script>
<!-- GTM container SECOND -->
<script>(function(w,d,s,l,i){...})</script>
Check variable names match exactly:
// Data layer push
dataLayer.push({ 'formId': '12345' });
// GTM variable configuration
Data Layer Variable Name: formId // Must match exactly
Handle empty HubL variables:
{% if contact %}
'contactId': '{{ contact.vid }}',
{% else %}
'contactId': 'anonymous',
{% endif %}
Meta Pixel Issues
Issue: Pixel Not Loading
Check:
- Pixel code in Site Header:
// Should see in page source
!function(f,b,e,v,n,t,s){...}
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
- Test in console:
console.log(typeof fbq); // Should be 'function'
console.log(window._fbq); // Should be object with pixel info
Use Meta Pixel Helper:
- Install browser extension
- Visit your site
- Extension should show pixel ID and PageView event
Check Network tab:
- Filter by "facebook"
- Should see requests to
facebook.com/tr
Issue: Custom Events Not Firing
Problem: PageView works but Lead/Contact events don't fire
Debug:
<script>
window.addEventListener('message', function(event) {
// Add logging
console.log('Event data:', event.data);
if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
console.log('Firing Meta Pixel Lead event');
fbq('track', 'Lead', {
'content_name': 'Form Submission'
});
console.log('Meta Pixel event fired');
}
});
</script>
Check Events Manager:
- Meta Events Manager → Test Events
- Enter your URL
- Submit form
- Event should appear within seconds
HubSpot-Specific Issues
Issue: Form Callback Not Triggering
Problem: HubSpot form event listener doesn't fire
Possible causes:
- Form is non-HubSpot form (custom HTML form)
- Event listener added after form loads
- Form is in iframe (different message format)
Solutions:
Test form callback:
// Add to console to see ALL messages
window.addEventListener('message', function(event) {
console.log('Message:', event.data);
});
// Submit form and check console
Ensure listener is in Site Header:
- Site Header HTML loads on all pages
- Loads before forms
- Always available
Check form type:
<!-- HubSpot form will have this -->
<div class="hbspt-form">
<form id="hsForm_..." ...>
</form>
</div>
Issue: CTA Clicks Not Tracked
Problem: Click event listeners don't catch CTA clicks
Debug:
// Test click detection
document.addEventListener('click', function(event) {
console.log('Clicked:', event.target);
console.log('Classes:', event.target.className);
var ctaElement = event.target.closest('.cta_button, [class*="hs-cta"]');
console.log('CTA element:', ctaElement);
});
Common fixes:
// Ensure selector matches your CTA classes
document.addEventListener('click', function(event) {
// Try multiple selectors
var ctaElement = event.target.closest(
'.cta_button, ' +
'[class*="hs-cta"], ' +
'a[data-hs-cta-id], ' +
'.hs-cta-wrapper a'
);
if (ctaElement) {
// Track event
}
});
Issue: HubL Variables Not Working
Problem: Variables like \{\{ contact.email \}\} return empty
Causes:
- Visitor not identified (anonymous)
- Contact property doesn't exist
- HubL syntax error
Debug:
{# Test variable output #}
<script>
console.log('Contact email:', '{{ contact.email }}');
console.log('Contact ID:', '{{ contact.vid }}');
console.log('Page type:', '{{ content.type }}');
</script>
Fix with conditionals:
{% if contact %}
{# Contact exists - use variables #}
dataLayer.push({
'contactId': '{{ contact.vid }}'
});
{% else %}
{# Anonymous visitor #}
dataLayer.push({
'contactId': 'anonymous'
});
{% endif %}
Advanced Debugging
Enable Debug Mode
GA4:
gtag('config', 'G-XXXXXXXXXX', {
'debug_mode': true
});
GTM:
- Use Preview mode (built-in debugging)
Meta Pixel:
- Use Test Events feature in Events Manager
Monitor Network Requests
DevTools → Network tab:
For GA4: Filter "collect"
For GTM: Filter "gtm"
For Meta Pixel: Filter "tr?id"
Check:
- Request URL
- Request payload (contains event data)
- Response status (200 = success)
Use Debugging Extensions
- Google Tag Assistant - GTM debugging
- Meta Pixel Helper - Facebook pixel verification
- GA Debugger - Google Analytics debugging
- Omnibug - Multi-platform tag debugging
Common Fixes Summary
Quick Checks
- ✅ Clear browser cache (hard refresh: Ctrl+Shift+R)
- ✅ Disable ad blockers (for testing)
- ✅ Check console for errors
- ✅ Verify tracking IDs are correct
- ✅ Ensure code is in Site Header (not footer)
Code Order
<!-- Correct order in Site Header HTML -->
<!-- 1. Data Layer (if using GTM) -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({...});
</script>
<!-- 2. GTM Container (if using) -->
<script>(function(w,d,s,l,i){...})</script>
<!-- 3. GA4 (if not using GTM) -->
<script async src="...gtag/js..."></script>
<script>gtag(...);</script>
<!-- 4. Meta Pixel -->
<script>fbq(...);</script>
<!-- 5. Event Listeners -->
<script>
window.addEventListener('message', ...);
</script>
Prevention Best Practices
- Test before publishing - Use preview/debug modes
- Document all tracking - Keep list of what's installed where
- Use version control - Save old versions before changes
- Monitor regularly - Check analytics weekly
- Use GTM - Centralized management reduces errors
Next Steps
- Performance Troubleshooting - Optimize site speed
- GTM Data Layer - Implement data layer correctly
- Event Tracking Guide - Set up events properly
For general debugging concepts, see Analytics Debugging Guide.