How to Fix Grav CMS Tracking Events Not Firing | OpsBlu Docs

How to Fix Grav CMS Tracking Events Not Firing

Fix GA4, GTM, and pixel events not firing on Grav — Twig base template head block editing, flat-file cache clearing, and asset pipeline debugging

Diagnose and fix tracking issues specific to Grav's flat-file architecture, Twig templating system, and caching mechanisms.

Quick Diagnostics

1. Check Browser Console

// Open browser console (F12)

// Check if GA4 loaded
console.log(typeof gtag);  // Should be 'function'
console.log(window.dataLayer);  // Should be array

// Check if GTM loaded
console.log(typeof google_tag_manager);  // Should be 'object'

// Check if Meta Pixel loaded
console.log(typeof fbq);  // Should be 'function'

2. Check Page Source

# View source and search for tracking codes
# Right-click → View Page Source → Ctrl+F

# Search for:
- "gtag" (for GA4)
- "GTM-" (for GTM)
- "fbq" (for Meta Pixel)

3. Check Grav Cache

# Clear Grav cache
bin/grav clear-cache

# Or via Admin Panel
Admin → Configuration → Clear Cache

Grav-Specific Issues

1. Cache Preventing Code Updates

Symptom: Tracking code doesn't appear even after adding to templates.

Cause: Grav's caching system serving old HTML.

Solution:

# Clear all Grav caches
bin/grav clear-cache

# Clear specific caches
bin/grav clear-cache --all
bin/grav clear-cache --assets-only
bin/grav clear-cache --images-only
bin/grav clear-cache --cache-only
# Temporarily disable cache during development
# user/config/system.yaml
cache:
  enabled: false  # Re-enable for production

twig:
  cache: false
  auto_reload: true

2. Twig Syntax Errors

Symptom: Tracking code not rendering in HTML.

Cause: Twig template errors preventing code output.

Diagnosis:

# Enable Twig debugging
# user/config/system.yaml
debugger:
  enabled: true
  provider: debugbar
  censored: false

twig:
  debug: true

Common Issues:

{# Bad - Unescaped quotes #}
gtag('config', 'G-XXXXXXXXXX', {
    'page_title': '{{ page.title }}'  {# This can break if title has quotes #}
});

{# Good - Properly escaped #}
gtag('config', 'G-XXXXXXXXXX', {
    'page_title': '{{ page.title|e("js") }}'
});
{# Bad - Wrong variable reference #}
{% if grav.config.plugins.analytics.enabled %}

{# Good - Correct path #}
{% if grav.config.plugins['google-analytics'].enabled %}

3. Plugin Conflicts

Symptom: Tracking works on some pages but not others.

Cause: Plugin interference or disabled on certain pages.

Solution:

# List all enabled plugins
bin/gpm list

# Disable suspected plugin
bin/gpm uninstall plugin-name

# Or via config
# user/config/plugins/problematic-plugin.yaml
enabled: false

Check if tracking plugin disabled in frontmatter:

# pages/example.md
---
title: Example Page
google_analytics: false  # This might disable tracking
---

4. Admin Panel Exclusion

Symptom: Tracking works on frontend but not in admin.

Cause: Most tracking should be excluded from admin (this is normal).

Verify:

// In your plugin or template
if ($this->isAdmin()) {
    return;  // Don't load tracking in admin
}
{# Exclude admin routes #}
{% if not grav.uri.path starts with '/admin' %}
    {# Tracking code here #}
{% endif %}

5. Asset Pipeline Issues

Symptom: JavaScript tracking code not loading.

Cause: Grav's asset pipeline breaking inline scripts.

Solution:

# user/config/system.yaml
assets:
  js_pipeline: false  # Temporarily disable to test
  js_minify: false

Or exclude tracking scripts from pipeline:

{{ assets.addInlineJs('
    gtag("config", "G-XXXXXXXXXX");
', {'group': 'bottom', 'pipeline': false})|raw }}

GA4-Specific Issues

GA4 Not Loading

Check Installation:

{# Verify GA4 code in templates/partials/head.html.twig #}

{% set ga_id = grav.config.site.google_analytics_id %}
{% if ga_id %}
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id={{ ga_id }}"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', '{{ ga_id }}');
</script>
{% endif %}

Check Configuration:

# user/config/site.yaml
google_analytics_id: 'G-XXXXXXXXXX'  # Verify ID is correct

Events Not Tracking

Test Event Manually:

// In browser console
gtag('event', 'test_event', {
    'event_category': 'Test',
    'event_label': 'Manual Test'
});

// Then check GA4 Realtime reports

Enable Debug Mode:

<script>
gtag('config', '{{ ga_id }}', {
    'debug_mode': true
});
</script>

GTM-Specific Issues

GTM Not Loading

Check Container ID:

{# Verify GTM ID format: GTM-XXXXXXX #}

{% set gtm_id = grav.config.site.gtm_id %}
{% if gtm_id %}
    <!-- Google Tag Manager -->
    <script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','{{ gtm_id }}');</script>
{% endif %}

Check Both Parts Installed:

<!-- Head section - Script -->
<script>(function(w,d,s,l,i){...})</script>

<!-- Body section - Noscript -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"...></iframe></noscript>

Data Layer Not Populating

Check Initialization Order:

<!-- WRONG ORDER - GTM loads before data -->
<script>(function(w,d,s,l,i){...})</script>  <!-- GTM -->
<script>
window.dataLayer.push({...});  <!-- Data layer -->
</script>

<!-- CORRECT ORDER - Data before GTM -->
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({...});  <!-- Data layer first -->
</script>
<script>(function(w,d,s,l,i){...})</script>  <!-- Then GTM -->

Debug Data Layer:

// View data layer
console.table(window.dataLayer);

// Monitor pushes
var originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
    console.log('DataLayer push:', arguments[0]);
    return originalPush.apply(window.dataLayer, arguments);
};

GTM Preview Mode Not Connecting

Disable Cache:

# user/config/system.yaml
cache:
  enabled: false

Check Environment:

{# Only load GTM in production #}
{% if grav.config.system.environment == 'production' %}
    {# GTM code #}
{% endif %}

{# Change to test #}
{% if grav.config.system.environment != 'development' %}
    {# GTM code #}
{% endif %}

Meta Pixel-Specific Issues

Pixel Not Loading

Check Installation:

{# Verify pixel code in template #}

{% set pixel_id = grav.config.site.meta_pixel_id %}
{% if pixel_id %}
<!-- Meta Pixel Code -->
<script>
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '{{ pixel_id }}');
fbq('track', 'PageView');
</script>
{% endif %}

Check Configuration:

# user/config/site.yaml
meta_pixel_id: '1234567890123456'  # Verify 16-digit ID

Events Not Firing

Test Event Manually:

// In browser console
fbq('track', 'ViewContent', {
    content_name: 'Test Event'
});

// Check Meta Events Manager → Test Events

Enable Debug Mode:

Install Meta Pixel Helper Chrome extension.

Browser & Extension Issues

Ad Blockers

Test:

  1. Open site in incognito/private mode
  2. Disable ad blocker extensions
  3. Check if tracking works

Solutions:

  • Cannot bypass ad blockers (by design)
  • Consider server-side tracking for critical data
  • Educate users on privacy settings

Content Security Policy

Symptom: Console shows CSP errors.

Fix:

# user/config/system.yaml
security:
  content_security_policy:
    enabled: true
    directives:
      script-src:
        - 'self'
        - 'unsafe-inline'
        - 'https://www.googletagmanager.com'
        - 'https://www.google-analytics.com'
        - 'https://connect.facebook.net'

Environment-Specific Issues

Development vs Production

Problem: Tracking disabled in development.

Check Environment:

# Check current environment
bin/grav config system.environment

# Output: development, staging, or production

Conditional Loading:

{# Load tracking only in production #}
{% if grav.config.system.environment == 'production' %}
    {# Tracking codes #}
{% endif %}

{# Or load everywhere except development #}
{% if grav.config.system.environment != 'development' %}
    {# Tracking codes #}
{% endif %}

Testing Checklist

  1. Clear Cache

    bin/grav clear-cache
    
  2. Check Browser Console

    • No JavaScript errors
    • Tracking functions defined
    • Data layer exists
  3. Check Page Source

    • Tracking code present
    • IDs correct
    • Scripts loading
  4. Test in Incognito

    • Eliminates extension conflicts
    • Fresh cache
  5. Use Tracking Tools

  6. Check Grav Config

    # Verify in user/config/site.yaml
    google_analytics_id: 'G-XXXXXXXXXX'
    gtm_id: 'GTM-XXXXXXX'
    meta_pixel_id: '1234567890123456'
    
  7. Check Template Paths

    {# Verify tracking code in correct template #}
    # user/themes/your-theme/templates/partials/base.html.twig
    # or
    # user/themes/your-theme/templates/partials/head.html.twig
    

Still Not Working?

Enable Full Debugging

# user/config/system.yaml
debugger:
  enabled: true
  provider: debugbar
  censored: false
  twig: true

twig:
  debug: true
  auto_reload: true

errors:
  display: 1
  log: true

Check Grav Logs

# View error logs
tail -f logs/grav.log

# Check for template errors
grep "twig" logs/grav.log

Get Help

  1. Grav Community

  2. Check Documentation

Next Steps

For general tracking troubleshooting, see Events Not Firing Guide.