How to Fix Shopware 6 Tracking Events Not Firing | OpsBlu Docs

How to Fix Shopware 6 Tracking Events Not Firing

Fix GA4, GTM, and pixel events not firing on Shopware 6 — Twig storefront template editing, HTTP cache clearing, and plugin event subscriber debugging

When analytics events don't fire in Shopware 6, it impacts your ability to measure performance, optimize ads, and understand customer behavior. This guide helps you diagnose and fix tracking issues.

General Guide: See global tracking troubleshooting for universal concepts.

Shopware-Specific Tracking Issues

1. Cache Preventing Updated Code

The most common Shopware tracking issue is cache preventing updated tracking code from loading.

Problem: You've added or updated tracking code, but it doesn't appear on the storefront.

Diagnosis:

# Check if cache is enabled
grep APP_ENV .env

# If APP_ENV=prod, cache is enabled

Solutions:

A. Clear All Caches

# Clear Symfony cache
bin/console cache:clear

# Clear HTTP cache
bin/console http:cache:clear

# Warm cache
bin/console cache:warmup

# Recompile theme
bin/console theme:compile

# Complete cache clear (recommended)
bin/console cache:clear && bin/console theme:compile && bin/console cache:warmup

B. Clear Cache via Admin

Admin Panel:

  1. SettingsSystemCaches & indexes
  2. Click Clear cache
  3. Click Rebuild index

C. Bypass Cache for Testing

# In .env (ONLY for testing, NOT production)
APP_ENV=dev
APP_DEBUG=1

# Remember to switch back:
APP_ENV=prod
APP_DEBUG=0

Important: Always clear cache after making changes to:

  • Theme templates (.twig files)
  • Plugin code
  • Configuration files
  • JavaScript files

2. JavaScript Errors Blocking Execution

Problem: JavaScript error prevents tracking scripts from running.

Diagnosis:

Browser Console:

  1. Open DevTools (F12)
  2. Go to Console tab
  3. Look for red error messages
  4. Refresh page and watch for errors

Common Errors:

  • gtag is not defined
  • fbq is not defined
  • dataLayer is not defined
  • Uncaught ReferenceError
  • Syntax error

Solutions:

A. Fix Syntax Errors

Check your tracking code for:

  • Missing closing tags
  • Unescaped quotes
  • Missing commas in objects
  • Incorrect Twig syntax

Example Fix:

{# Bad - syntax error #}
<script>
    gtag('event', 'purchase', {
        'value': {{ order.amountTotal }}  {# Missing comma #}
        'currency': 'EUR'
    });
</script>

{# Good - fixed #}
<script>
    gtag('event', 'purchase', {
        'value': {{ order.amountTotal }},
        'currency': 'EUR'
    });
</script>

B. Escape JavaScript Strings Properly

{# Bad - special characters break JavaScript #}
'product_name': '{{ product.translated.name }}'

{# Good - escaped for JavaScript #}
'product_name': '{{ product.translated.name|e('js') }}'

C. Check Script Load Order

Ensure scripts load in correct order:

{% block base_script_tracking %}
    {{ parent() }}

    {# 1. Load gtag/fbq first #}
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>

    {# 2. Initialize second #}
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'G-XXXXXXXXXX');
    </script>

    {# 3. Events last #}
    <script>
        // Event tracking code
    </script>
{% endblock %}

D. Check for Plugin Conflicts

# Disable plugins one by one to find conflict
bin/console plugin:deactivate SuspectPlugin
bin/console cache:clear

# Test if tracking works
# Then reactivate if not the issue
bin/console plugin:activate SuspectPlugin

Problem: GDPR/cookie consent is blocking tracking scripts.

Diagnosis:

Check Cookie Consent:

// In browser console
document.cookie.split(';').forEach(c => console.log(c.trim()));

// Look for cookie-preference or similar

Solutions:

<script>
    // Check cookie consent
    function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(';').shift();
    }

    const cookieConsent = getCookie('cookie-preference');

    if (cookieConsent === 'all' || cookieConsent === '1') {
        // Load tracking scripts
        (function() {
            var script = document.createElement('script');
            script.async = true;
            script.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX';
            document.head.appendChild(script);
        })();

        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'G-XXXXXXXXXX');
    }
</script>

B. Test Without Ad Blocker

For Testing Only:

  • Disable browser ad blockers
  • Use incognito/private mode
  • Test in different browser
  • Accept all cookies

Common Ad Blockers Blocking Tracking:

  • uBlock Origin
  • AdBlock Plus
  • Privacy Badger
  • Brave Browser (built-in)

If using Shopware's Cookie Consent or a plugin:

{# Listen for consent events #}
<script>
    document.addEventListener('cookie-preference-updated', function(event) {
        const consent = event.detail;

        if (consent.all || consent.analytics) {
            // Initialize analytics
            gtag('consent', 'update', {
                'analytics_storage': 'granted'
            });
        }

        if (consent.all || consent.marketing) {
            // Initialize marketing pixels
            fbq('consent', 'grant');
        }
    });
</script>

4. Data Layer Not Populating

Problem: GTM data layer is empty or has incorrect values.

Diagnosis:

Check Data Layer:

// In browser console
console.table(window.dataLayer);

// Check if specific value exists
window.dataLayer.filter(item => item.event === 'purchase');

Solutions:

A. Initialize Data Layer Early

{% block base_script_tracking %}
    <script>
        // Initialize BEFORE GTM loads
        window.dataLayer = window.dataLayer || [];
    </script>

    {{ parent() }}
    {# GTM code #}
{% endblock %}

B. Verify Twig Variables Exist

{# Check if variable exists before using #}
{% if product is defined and product.productNumber %}
    <script>
        window.dataLayer.push({
            'productNumber': '{{ product.productNumber }}'
        });
    </script>
{% endif %}

C. Add Fallback Values

<script>
    window.dataLayer.push({
        'productName': '{{ product.translated.name|default('Unknown')|e('js') }}',
        'productPrice': {{ product.calculatedPrice.unitPrice|default(0) }},
        'currency': '{{ context.currency.isoCode|default('EUR') }}'
    });
</script>

D. Clear Cache After Data Layer Changes

bin/console cache:clear && bin/console theme:compile

5. GTM Container Not Loading

Problem: Google Tag Manager container doesn't load.

Diagnosis:

Check Network Tab:

  1. Open DevTools → Network tab
  2. Filter by "gtm"
  3. Refresh page
  4. Look for request to googletagmanager.com/gtm.js?id=GTM-XXXXXXX

Check GTM Code:

// In console
console.log(window.google_tag_manager);

Solutions:

A. Verify Container ID

{# Correct format: GTM-XXXXXXX (7 characters after GTM-) #}
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>

B. Check Both GTM Snippets Present

Head snippet (in <head>):

{% block base_script_tracking %}
    <!-- Google Tag Manager -->
    <script>(function(w,d,s,l,i)...
{% endblock %}

Body snippet (after <body>):

{% block base_body_script %}
    <!-- Google Tag Manager (noscript) -->
    <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"...
{% endblock %}

C. Verify GTM Container is Published

In GTM:

  1. Check that container is published (not just saved)
  2. Version should be live
  3. Use Preview mode to test before publishing

6. Events Firing in Preview but Not Production

Problem: Events work in GTM Preview mode but not in production.

Causes:

  • GTM container not published
  • Different environment (staging vs. production)
  • Cache serving old version
  • Trigger conditions not met in production

Solutions:

A. Publish GTM Container

  1. In GTM, click Submit
  2. Add version name and description
  3. Click Publish
  4. Verify version number increments

B. Check Trigger Conditions

In GTM Preview:

  • Click on tag that didn't fire
  • Check Why didn't this tag fire?
  • Verify trigger conditions
  • Check data layer values

C. Test with Different Users

  • Test as logged-out user
  • Test as logged-in customer
  • Test from different geographic location
  • Test on different devices

7. Purchase Events Firing Multiple Times

Problem: Purchase event fires multiple times, inflating conversion data.

Causes:

  • User refreshing order confirmation page
  • Multiple tracking implementations (plugin + manual)
  • Event not deduplicated

Solutions:

A. Track Purchase Only Once

{% block page_checkout_finish %}
    {{ parent() }}

    <script>
        // Check if already tracked using sessionStorage
        const orderNumber = '{{ order.orderNumber }}';
        const trackedKey = 'order_' + orderNumber + '_tracked';

        if (!sessionStorage.getItem(trackedKey)) {
            // Track purchase
            if (typeof gtag !== 'undefined') {
                gtag('event', 'purchase', {
                    'transaction_id': orderNumber,
                    'value': {{ order.amountTotal }},
                    'currency': '{{ order.currency.isoCode }}'
                });
            }

            // Mark as tracked
            sessionStorage.setItem(trackedKey, 'true');
        }
    </script>
{% endblock %}

B. Remove Duplicate Implementations

Check for duplicates:

# Search theme for tracking code
grep -r "gtag" custom/plugins/YourTheme/
grep -r "fbq" custom/plugins/YourTheme/
grep -r "GTM-" custom/plugins/YourTheme/

# Check for tracking plugins
bin/console plugin:list | grep -i "analytic\|pixel\|tag\|track"

Remove duplicates:

  • Keep ONE implementation (preferably GTM)
  • Remove manual code if using plugin
  • Remove plugin if using manual code

C. Use Event Deduplication

For Meta Pixel + Conversions API:

// Generate unique event ID
const eventID = 'event_' + Date.now() + '_' + Math.random();

// Browser Pixel
fbq('track', 'Purchase', {
    value: 99.99,
    currency: 'EUR'
}, {
    eventID: eventID  // Deduplication ID
});

// Server-side CAPI also sends same eventID

8. Product Data Missing in Events

Problem: Events fire but product data is empty or incorrect.

Diagnosis:

// Check event in GA4 DebugView or browser console
// Look for missing or empty parameters

Solutions:

A. Verify Product Context Available

{% block page_product_detail %}
    {% if page.product is defined %}
        <script>
            console.log('Product:', {
                id: '{{ page.product.id }}',
                number: '{{ page.product.productNumber }}',
                name: '{{ page.product.translated.name }}'
            });
        </script>
    {% else %}
        {# Product context not available! #}
    {% endif %}

    {{ parent() }}
{% endblock %}

B. Use Correct Product Variables

{# Product detail page #}
{% set product = page.product %}

{# Product listing #}
{% for product in page.listing.elements %}
    {# ... #}
{% endfor %}

{# Cart #}
{% for lineItem in page.cart.lineItems %}
    {% set productId = lineItem.referencedId %}
{% endfor %}

C. Handle Missing Data Gracefully

<script>
    window.dataLayer.push({
        'product_id': '{{ product.productNumber|default('') }}',
        'product_name': '{{ product.translated.name|default('Unknown')|e('js') }}',
        'product_price': {{ product.calculatedPrice.unitPrice|default(0) }},
        'product_brand': '{{ product.manufacturer.translated.name|default('')|e('js') }}'
    });
</script>

9. Shopware Storefront Events Not Firing

Problem: Native Shopware storefront JavaScript events not triggering tracking.

Diagnosis:

// Check if Shopware event system works
document.$emitter.subscribe('test', (event) => {
    console.log('Event system working', event);
});

document.$emitter.publish('test', { data: 'test' });

Solutions:

A. Use Correct Event Names

Shopware 6 events:

// Off-canvas cart opened
document.$emitter.subscribe('offcanvas-cart-opened', function(event) {
    console.log('Cart opened', event.detail);
});

// Product added to cart (custom event)
document.$emitter.subscribe('addToCart', function(event) {
    const product = event.detail;
    // Track add to cart
});

B. Wait for DOM Ready

document.addEventListener('DOMContentLoaded', function() {
    // Subscribe to events after DOM is ready
    document.$emitter.subscribe('eventName', handler);
});

C. Create Custom Events

{# In buy form template #}
{% block page_product_detail_buy_form %}
    {{ parent() }}

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const form = document.querySelector('.product-detail-buy');

            form?.addEventListener('submit', function(e) {
                // Publish custom event
                if (document.$emitter) {
                    document.$emitter.publish('addToCart', {
                        productId: '{{ product.id }}',
                        productNumber: '{{ product.productNumber }}',
                        quantity: parseInt(this.querySelector('[name="quantity"]')?.value || 1)
                    });
                }
            });
        });
    </script>
{% endblock %}

Debugging Tools & Techniques

1. Browser Console Monitoring

// Monitor all gtag calls
const originalGtag = window.gtag;
window.gtag = function() {
    console.log('gtag called:', arguments);
    if (originalGtag) {
        return originalGtag.apply(window, arguments);
    }
};

// Monitor all dataLayer pushes
const originalPush = Array.prototype.push;
window.dataLayer = window.dataLayer || [];
window.dataLayer.push = function() {
    console.log('dataLayer.push:', arguments[0]);
    return originalPush.apply(this, arguments);
};

2. GTM Preview Mode

  1. Open GTM
  2. Click Preview
  3. Enter your Shopware store URL
  4. Navigate and trigger events
  5. Check Tags Fired vs. Tags Not Fired
  6. Review Data Layer tab for values

3. GA4 DebugView

Enable Debug Mode:

gtag('config', 'G-XXXXXXXXXX', {
    'debug_mode': true
});

View Events:

  1. GA4AdminDebugView
  2. Navigate your store
  3. See events in real-time
  4. Check all parameters

4. Meta Pixel Helper

  1. Install Meta Pixel Helper
  2. Visit your store
  3. Click extension icon
  4. Check for errors or warnings
  5. Verify events fire

5. Network Tab Inspection

Chrome DevTools → Network:

  1. Filter by "google-analytics" or "facebook"
  2. Check tracking requests sent
  3. Click request to see payload
  4. Verify parameters correct

6. Shopware Profiler

Enable profiler:

APP_ENV=dev

Check:

  • JavaScript errors in console
  • Twig template rendering
  • Variables available in context

Common Shopware Configuration Issues

1. Sales Channel Configuration

Check Sales Channel:

  1. AdminSales ChannelsStorefront
  2. Verify:
    • Domain is correct
    • HTTPS is enabled
    • Language is set
    • Currency is set

2. Plugin Installation Issues

Verify Plugin State:

# Check plugin status
bin/console plugin:list

# Should show "installed" and "active"
# If not, install and activate
bin/console plugin:install --activate PluginName
bin/console cache:clear

3. Theme Not Compiled

# Check if theme needs compilation
bin/console theme:dump

# Compile theme
bin/console theme:compile

# Verify compilation succeeded
ls -la public/theme/

Testing Checklist

Before considering tracking "fixed," test:

  • Page views fire on all page types
  • Product views fire on product pages
  • Add to cart fires (check console, GA4, Meta)
  • Cart view fires on cart page
  • Checkout events fire
  • Purchase fires on order confirmation (ONCE)
  • Events appear in GA4 Realtime
  • Events appear in GA4 DebugView
  • Meta Pixel Helper shows events
  • GTM Preview shows tags firing
  • No JavaScript errors in console
  • Data layer has correct values
  • Test as logged-out user
  • Test as logged-in customer
  • Test on mobile device
  • Test with ad blocker disabled

When to Seek Help

Consider hiring a developer if:

  • Multiple persistent tracking issues
  • Complex custom implementation needed
  • Plugin development required
  • Server-side tracking (CAPI) needed
  • Advanced debugging required

Find Shopware Partners: store.shopware.com/en/partners

Next Steps

For general tracking troubleshooting, see Events Not Firing Guide.