Events Not Firing on Salesforce Commerce Cloud | Blue Frog Docs

Events Not Firing on Salesforce Commerce Cloud

Troubleshooting tracking events on SFCC

Events Not Firing on Salesforce Commerce Cloud

General Guide: See Global Events Not Firing Guide for universal concepts and fixes.

SFCC-Specific Causes

1. Page Caching Conflicts

SFCC's aggressive caching can prevent dynamic data layer values:

<!-- Problem: Cached page has stale customer data -->
<iscache type="relative" hour="24"/>
<script>
    dataLayer.push({
        'userLoggedIn': ${customer.authenticated} // Cached value!
    });
</script>

2. AJAX-Based Cart Updates

SFRA cart operations use AJAX, requiring client-side event handling:

// Problem: Cart events handled without tracking
$('.add-to-cart').on('click', function() {
    $.post('/Cart-AddProduct', data); // No tracking!
});

3. Controller Response Format

Non-JSON responses don't include tracking data:

// Problem: Render response without tracking data
server.get('AddProduct', function (req, res, next) {
    res.render('cart/miniCart', viewData); // No event data
    return next();
});

4. Content Security Policy Blocking

Strict CSP can block GTM or analytics scripts:

Content-Security-Policy: script-src 'self'; // Blocks GTM!

Third-party consent tools blocking tracking:

// OneTrust or similar blocking analytics
if (typeof OptanonActiveGroups === 'undefined') {
    // Scripts blocked by consent
}

SFCC-Specific Fixes

Fix 1: Disable Caching for Dynamic Data

Use cache bypass for user-specific data:

<!-- Exclude from page cache -->
<iscache status="off"/>

<!-- Or use remote include for dynamic parts -->
<isinclude url="${URLUtils.url('DataLayer-Get')}" />

Better approach - use client-side API:

// Fetch dynamic data client-side
$(document).ready(function() {
    $.get('/DataLayer-GetUserData', function(data) {
        dataLayer.push(data);
    });
});

Fix 2: Hook into SFRA Events

Use SFRA's built-in event system:

// Listen for SFRA cart events
$(document).on('cart:update', function(e, data) {
    if (data.action === 'add') {
        gtag('event', 'add_to_cart', {
            currency: data.currency,
            value: data.totalPrice,
            items: data.items
        });
    }
});

// Product added successfully
$(document).on('product:afterAddToCart', function(e, data) {
    gtag('event', 'add_to_cart', {
        items: [{
            item_id: data.pid,
            item_name: data.pname,
            price: data.price,
            quantity: data.quantity
        }]
    });
});

Fix 3: Include Tracking Data in Controller Responses

Add event data to JSON responses:

// cartridges/app_custom/cartridge/controllers/Cart.js
server.extend(Cart);

server.append('AddProduct', function (req, res, next) {
    var viewData = res.getViewData();

    if (!viewData.error) {
        var addedProduct = viewData.cart.items[viewData.cart.items.length - 1];

        viewData.trackingEvent = {
            event: 'add_to_cart',
            items: [{
                item_id: addedProduct.id,
                item_name: addedProduct.productName,
                price: addedProduct.price.sales.value,
                quantity: addedProduct.quantity
            }],
            value: addedProduct.price.sales.value * addedProduct.quantity,
            currency: viewData.cart.totals.currencyCode
        };
    }

    res.setViewData(viewData);
    return next();
});

module.exports = server.exports();

Client-side handler:

// Handle tracking from AJAX response
$(document).ajaxComplete(function(event, xhr, settings) {
    if (settings.url.includes('Cart-AddProduct')) {
        try {
            var response = JSON.parse(xhr.responseText);
            if (response.trackingEvent) {
                gtag('event', response.trackingEvent.event, {
                    items: response.trackingEvent.items,
                    value: response.trackingEvent.value,
                    currency: response.trackingEvent.currency
                });
            }
        } catch (e) {
            console.error('Tracking parse error:', e);
        }
    }
});

Fix 4: Configure CSP for Analytics

Update CSP in Business Manager or controller:

// In controller or custom CSP cartridge
response.setHttpHeader('Content-Security-Policy',
    "script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com; " +
    "connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://region1.google-analytics.com; " +
    "img-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;"
);

Implement Google Consent Mode:

// Before GTM loads
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}

// Default to denied
gtag('consent', 'default', {
    'ad_storage': 'denied',
    'analytics_storage': 'denied',
    'wait_for_update': 500
});

// Update on consent
function updateConsent(granted) {
    gtag('consent', 'update', {
        'ad_storage': granted ? 'granted' : 'denied',
        'analytics_storage': granted ? 'granted' : 'denied'
    });
}

// Hook into your consent tool
OneTrust.OnConsentChanged(function() {
    var analyticsConsent = OnetrustActiveGroups.includes('C0002');
    updateConsent(analyticsConsent);
});

Debugging Checklist

Step 1: Verify Script Loading

// Check GTM loaded
console.log('GTM:', typeof google_tag_manager);

// Check GA loaded
console.log('gtag:', typeof gtag);

// Check dataLayer
console.log('dataLayer:', dataLayer);

Step 2: Check Network Requests

In browser DevTools Network tab:

  • Filter by google or analytics
  • Look for failed requests (red)
  • Check request payloads

Step 3: Use GTM Preview

  1. Open GTM and click Preview
  2. Enter your SFCC URL
  3. Check which tags fire
  4. Review trigger conditions

Step 4: Check SFCC Logs

Business Manager > Administration > Operations > Custom Object Editor

Look for JavaScript errors in custom logging.

Common Error Patterns

Symptom Likely Cause Solution
No events at all Script blocked or not loaded Check CSP and network
Events on some pages Inconsistent implementation Review all controllers
Duplicate events Multiple listeners Deduplicate event handlers
Missing parameters Data layer not populated Check ISML rendering
Wrong values Caching issues Use client-side API calls

Next Steps

// SYS.FOOTER