Webflow Tracking Issues | Blue Frog Docs

Webflow Tracking Issues

Troubleshoot and resolve analytics tracking issues on Webflow websites.

Webflow Tracking Issues

Platform-specific guides for diagnosing and fixing analytics and tracking issues on Webflow.

Common Issues

Events Not Firing

Debug why analytics events aren't being captured on Webflow.

Webflow-Specific Tracking Challenges

Webflow's visual development platform and publishing system create unique tracking scenarios, especially with its Designer vs published site differences and CMS dynamic content.

Platform Code Injection Points

Webflow provides multiple locations for custom code:

Site-Wide Custom Code (Project Settings → Custom Code):

  • Head Code - Loads in <head> on all pages
  • Footer Code - Loads before </body> on all pages
  • Applies to entire published site
  • Separate for staging vs production

Page-Level Custom Code:

  • Page Settings → Custom Code → Inside <head> tag
  • Page Settings → Custom Code → Before </body> tag
  • Overrides or supplements site-wide code
  • Useful for page-specific tracking

Embed Elements:

  • Custom Code embed element
  • HTML Embed element
  • Inline within page content
  • Limited scope to that element

CMS Item Custom Code:

  • Available in CMS collection templates
  • Can access dynamic CMS fields
  • Useful for product/blog tracking

Code Injection Hierarchy:

Site-wide Head Code
↓
Page-level Head Code
↓
Embed Elements (in DOM order)
↓
Page-level Footer Code
↓
Site-wide Footer Code

Designer vs Published Site

Critical Difference:

  • Code in Custom Code sections does not run in the Designer
  • Only runs on published site (staging or production)
  • Must publish to test tracking implementation

Testing Workflow:

  1. Add tracking code to Custom Code
  2. Publish to staging domain
  3. Test on staging.webflow.io subdomain
  4. Verify tracking works
  5. Publish to custom domain

Common Mistake:

// This will NOT work in Webflow Designer
console.log('Testing tracking'); // Won't see this in Designer console

// Must publish and view published site to see output

CMS and Dynamic Content

Webflow CMS adds complexity to tracking:

Accessing CMS Fields in Code: Webflow doesn't expose CMS data to JavaScript directly. Must use embed code in CMS template:

<!-- In CMS Collection Template Page Settings → Before </body> -->
<script>
window.cmsData = {
  name: '<span class="w-dyn-bind-empty"></span>',
  slug: '<span class="w-dyn-bind-empty"></span>',
  category: '<span class="w-dyn-bind-empty"></span>',
  price: '<span class="w-dyn-bind-empty"></span>'
};

// Track CMS item view
dataLayer.push({
  'event': 'itemView',
  'itemName': window.cmsData.name,
  'itemCategory': window.cmsData.category
});
</script>

Alternative - Scrape from DOM:

// More reliable - get CMS data from rendered HTML
const itemTitle = document.querySelector('.item-title')?.textContent;
const itemPrice = document.querySelector('.item-price')?.textContent;
const itemCategory = document.querySelector('.category-badge')?.textContent;

dataLayer.push({
  'event': 'itemView',
  'itemName': itemTitle,
  'itemPrice': itemPrice,
  'itemCategory': itemCategory
});

E-commerce Tracking (Webflow Ecommerce)

Webflow Ecommerce has limited JavaScript access to cart/order data:

Challenges:

  • No native data layer
  • Order data not exposed as JavaScript object
  • Limited checkout customization
  • Must scrape from DOM or use Webflow's Limited API

Add to Cart Tracking:

// Monitor add to cart buttons
document.addEventListener('click', function(e) {
  const addToCartBtn = e.target.closest('.w-commerce-commerceaddtocartbutton');

  if (addToCartBtn && !addToCartBtn.disabled) {
    console.log('Add to cart clicked');

    // Get product info from page
    const productName = document.querySelector('.w-commerce-commerceitemname')?.textContent;
    const productPrice = document.querySelector('.w-commerce-commercepricevalue')?.textContent;

    // Small delay to let cart update
    setTimeout(function() {
      dataLayer.push({
        'event': 'addToCart',
        'productName': productName?.trim(),
        'productPrice': parseFloat(productPrice?.replace(/[^0-9.]/g, ''))
      });
    }, 100);
  }
}, true);

Order Confirmation Tracking:

// On Order Confirmation page template
window.addEventListener('DOMContentLoaded', function() {
  // Check if we're on order confirmation
  const isOrderConfirmation = window.location.pathname.includes('/order-confirmation');

  if (isOrderConfirmation) {
    // Scrape order details from page
    const orderNumber = document.querySelector('.w-commerce-commerceorderconfirmationorderid')?.textContent;
    const orderTotal = document.querySelector('.w-commerce-commerceorderconfirmationtotal')?.textContent;

    if (orderNumber && orderTotal) {
      const transactionValue = parseFloat(orderTotal.replace(/[^0-9.]/g, ''));

      dataLayer.push({
        'event': 'purchase',
        'transactionId': orderNumber.trim(),
        'transactionTotal': transactionValue,
        'currency': 'USD' // Adjust based on your store
      });

      console.log('Purchase tracked:', orderNumber, transactionValue);
    }
  }
});

Webflow Interactions and Tracking

Webflow's visual interaction system can affect tracking:

IX2 (Interactions 2.0):

  • Animations and interactions run before your tracking code may be ready
  • Events triggered by interactions need special handling
  • Modal opens, tab clicks, etc. need event listeners

Tracking Interaction-Based Events:

// Track tab clicks (Webflow tabs)
document.addEventListener('click', function(e) {
  const tabLink = e.target.closest('.w-tab-link');
  if (tabLink) {
    const tabName = tabLink.textContent.trim();
    dataLayer.push({
      'event': 'tabClick',
      'tabName': tabName
    });
  }
});

// Track modal/lightbox opens
const observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    mutation.addedNodes.forEach(function(node) {
      if (node.classList && node.classList.contains('w-lightbox')) {
        dataLayer.push({
          'event': 'lightboxOpen'
        });
      }
    });
  });
});

observer.observe(document.body, {
  childList: true,
  subtree: true
});

Form Submission Tracking

Webflow forms submit to Webflow's servers, making tracking tricky:

Form Submit Event:

// Track Webflow form submissions
document.addEventListener('submit', function(e) {
  const webflowForm = e.target.closest('.w-form');

  if (webflowForm) {
    const formName = webflowForm.getAttribute('data-name') || webflowForm.getAttribute('name');

    dataLayer.push({
      'event': 'formSubmit',
      'formName': formName
    });

    console.log('Form submitted:', formName);
  }
});

// Also monitor for success/error states
const formObserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    const target = mutation.target;

    // Check for success message
    if (target.classList && target.classList.contains('w-form-done') &&
        target.style.display !== 'none') {
      dataLayer.push({
        'event': 'formSuccess',
        'formName': target.closest('.w-form')?.getAttribute('data-name')
      });
    }

    // Check for error message
    if (target.classList && target.classList.contains('w-form-fail') &&
        target.style.display !== 'none') {
      dataLayer.push({
        'event': 'formError',
        'formName': target.closest('.w-form')?.getAttribute('data-name')
      });
    }
  });
});

// Observe all forms
document.querySelectorAll('.w-form').forEach(form => {
  formObserver.observe(form, {
    attributes: true,
    attributeFilter: ['style'],
    subtree: true
  });
});

Comprehensive Diagnostic Checklist

1. Verify Code is Published

Critical First Step:

  • Code in Custom Code sections only runs on published site
  • Check staging site: yoursite.webflow.io
  • Then check custom domain if configured

Verify Code is Present:

# View source of published page
# Look for your tracking code in <head> or before </body>
# Search for your GA/GTM ID

2. Check Code Injection Location

Site Settings → Publishing → Custom Code:

  • Verify code is in Head Code (for most tracking)
  • Check for typos, unclosed tags
  • Ensure code is complete

Validation Script:

<!-- Add to Site-wide Head Code -->
<script>
console.log('=== Webflow Tracking Diagnostic ===');
console.log('URL:', window.location.href);
console.log('Path:', window.location.pathname);
console.log('Webflow object:', window.Webflow);
console.log('Published:', !window.location.hostname.includes('.webflow.io'));
console.log('Loaded at:', new Date().toISOString());
</script>

3. Test on Published Site

// Add to Footer Code to verify execution
console.log('Footer code executed');
console.log('dataLayer:', window.dataLayer);
console.log('GTM loaded:', !!window.google_tag_manager);
console.log('GA loaded:', typeof window.gtag);

4. Inspect Webflow Objects

// Check Webflow-specific objects
console.log('Webflow:', window.Webflow);
console.log('jQuery (Webflow includes it):', typeof window.$);

// Check for Webflow Ecommerce
const isEcommerce = document.querySelector('.w-commerce-commercecartcontainerwrapper');
console.log('Ecommerce site:', !!isEcommerce);

// Check for CMS
const isCMS = document.querySelector('[data-wf-page]');
console.log('CMS template:', !!isCMS);

5. Monitor DOM Ready State

// Webflow may use document ready differently
document.addEventListener('DOMContentLoaded', function() {
  console.log('DOM Content Loaded');
});

window.addEventListener('load', function() {
  console.log('Window loaded');
});

// Webflow's ready event
if (window.Webflow) {
  window.Webflow.push(function() {
    console.log('Webflow ready');
  });
}

Browser DevTools Debugging Steps

Network Tab Analysis

Filter for Tracking Requests:

Filter: /collect|/analytics|/gtm|/pixel|/track

Expected Requests:

google-analytics.com/g/collect - GA4
googletagmanager.com/gtm.js - GTM
facebook.com/tr - Facebook Pixel
webflow.com/api - Webflow's own analytics

Common Issues:

  • 404 on tracking script: Wrong URL or blocked
  • CORS errors: Cross-domain tracking misconfigured
  • Blocked by client: Ad blocker or privacy extension

Console Debugging

// Comprehensive tracking check
console.log('=== Tracking Status ===');
console.log('dataLayer:', window.dataLayer?.length, 'items');
console.log('GTM containers:', Object.keys(window.google_tag_manager || {}));
console.log('GA function:', typeof window.gtag);
console.log('Facebook Pixel:', typeof window.fbq);
console.log('jQuery:', typeof window.$);
console.log('Webflow ready:', typeof window.Webflow?.ready);

// List all global tracking objects
const trackingObjects = ['dataLayer', 'gtag', 'ga', 'fbq', 'analytics', '_kmq'];
trackingObjects.forEach(obj => {
  console.log(`${obj}:`, typeof window[obj]);
});

// Check for errors
window.addEventListener('error', function(e) {
  console.error('JavaScript error:', e.message, e.filename, e.lineno);
});

Application Tab Storage

// Check cookies
const cookies = document.cookie.split(';').map(c => c.trim());
const trackingCookies = cookies.filter(c =>
  c.startsWith('_ga') || c.startsWith('_gid') || c.startsWith('_fb')
);
console.log('Tracking cookies:', trackingCookies);

// Check localStorage
console.log('localStorage keys:', Object.keys(localStorage));

// Check sessionStorage
console.log('sessionStorage keys:', Object.keys(sessionStorage));

Common Symptoms and Causes

Symptom Likely Cause Solution
Code not running at all Not published / testing in Designer Publish and test on live site
Tracking works on staging not production Different custom code for domains Check custom domain settings
Events fire multiple times Code in multiple locations Audit all Custom Code locations
CMS data not available No JavaScript access to CMS Scrape from DOM or use embed in template
Form tracking missing Form submits before tracking fires Use submit event with small delay
Cart events not captured No Webflow ecommerce API Use click handlers and DOM scraping
Code works then breaks Webflow updated/broke something Check Webflow changelog, update code
jQuery conflicts Webflow includes jQuery Use noConflict or Webflow's jQuery
Interactions interfere with tracking IX2 timing issues Use delayed tracking or interaction events
Preview mode tracking fires Code runs on all published versions Add conditional logic to exclude staging

Tag Manager Troubleshooting

Google Tag Manager Setup

Site Settings → Publishing → Custom Code → Head Code:

<!-- Google Tag Manager -->
<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-XXXXXX');</script>
<!-- End Google Tag Manager -->

Site Settings → Publishing → Custom Code → Footer Code:

<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

Data Layer Implementation:

<script>
// Initialize dataLayer before GTM
window.dataLayer = window.dataLayer || [];

// Push page data
dataLayer.push({
  'pageType': document.body.className.match(/[\w-]+page/)?.[0] || 'unknown',
  'pagePath': window.location.pathname
});

// Webflow ready hook
if (window.Webflow) {
  Webflow.push(function() {
    dataLayer.push({
      'event': 'webflowReady'
    });
  });
}
</script>

GTM Preview Mode:

  • Works on published sites
  • May need to clear cache
  • Test on staging first

E-commerce Tracking

Product Page Tracking

// Enhanced product view tracking
window.addEventListener('DOMContentLoaded', function() {
  const isProductPage = document.querySelector('.w-commerce-commerceproductdetails');

  if (isProductPage) {
    const productName = document.querySelector('.w-commerce-commerceitemname')?.textContent;
    const productPrice = document.querySelector('.w-commerce-commercepricevalue')?.textContent;
    const productSKU = document.querySelector('[data-commerce-sku-id]')?.getAttribute('data-commerce-sku-id');

    dataLayer.push({
      'event': 'productView',
      'ecommerce': {
        'detail': {
          'products': [{
            'name': productName?.trim(),
            'id': productSKU,
            'price': parseFloat(productPrice?.replace(/[^0-9.]/g, ''))
          }]
        }
      }
    });
  }
});

Cart Interaction Tracking

// Track cart opens
let cartObserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.attributeName === 'style') {
      const cartWrapper = mutation.target.closest('.w-commerce-commercecartcontainerwrapper');
      if (cartWrapper && cartWrapper.style.display !== 'none') {
        dataLayer.push({
          'event': 'cartOpen'
        });
      }
    }
  });
});

document.querySelectorAll('.w-commerce-commercecartcontainerwrapper').forEach(cart => {
  cartObserver.observe(cart, {
    attributes: true,
    attributeFilter: ['style']
  });
});

// Track checkout button click
document.addEventListener('click', function(e) {
  const checkoutBtn = e.target.closest('.w-commerce-commercecartemptystate, .w-commerce-commercecheckoutbutton');
  if (checkoutBtn) {
    dataLayer.push({
      'event': 'beginCheckout'
    });
  }
});
// Simple consent banner implementation
function showConsentBanner() {
  const hasConsent = localStorage.getItem('cookieConsent');

  if (!hasConsent) {
    // Show banner (assumes you have a .cookie-banner element in Webflow)
    const banner = document.querySelector('.cookie-banner');
    if (banner) {
      banner.style.display = 'block';
    }
  } else if (hasConsent === 'accepted') {
    loadTrackingScripts();
  }
}

function acceptCookies() {
  localStorage.setItem('cookieConsent', 'accepted');
  document.querySelector('.cookie-banner').style.display = 'none';
  loadTrackingScripts();
}

function loadTrackingScripts() {
  // Load Google Analytics
  const gaScript = document.createElement('script');
  gaScript.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX';
  gaScript.async = true;
  document.head.appendChild(gaScript);

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

// Add click handler to accept button
document.addEventListener('click', function(e) {
  if (e.target.matches('.accept-cookies')) {
    acceptCookies();
  }
});

// Run on page load
showConsentBanner();

Google Consent Mode:

<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}

// Set default consent
gtag('consent', 'default', {
  'ad_storage': 'denied',
  'analytics_storage': 'denied',
  'ad_user_data': 'denied',
  'ad_personalization': 'denied',
  'wait_for_update': 500
});

// Update consent when user accepts
function updateConsent(accepted) {
  if (accepted) {
    gtag('consent', 'update', {
      'ad_storage': 'granted',
      'analytics_storage': 'granted',
      'ad_user_data': 'granted',
      'ad_personalization': 'granted'
    });
  }
}
</script>

When to Contact Support

Contact Webflow Support When:

Platform-Level Issues:

  • Custom Code not saving in project settings
  • Published site not reflecting code changes
  • Form submissions not working
  • Ecommerce checkout bugs
  • CMS collection issues

Provide to Webflow:

  1. Project share link or site URL
  2. Screenshots of Custom Code settings
  3. Browser console errors
  4. Specific pages affected
  5. Steps to reproduce issue

Contact Analytics Vendor When:

  • Events firing correctly but not appearing in reports
  • Data discrepancies between platforms
  • Tag configuration issues
  • API integration problems

Provide to Vendor:

  1. Network tab showing successful requests
  2. Console logs with tracking data
  3. Property/measurement IDs
  4. Example URLs where tracking fires

Contact Developer/Agency When:

  • Complex CMS tracking requirements
  • Custom ecommerce tracking beyond standard
  • Advanced interaction tracking
  • Multi-site tracking coordination
  • Custom API integrations

Provide to Developer:

  1. Webflow project access or site export
  2. Current tracking implementation code
  3. Desired tracking specification
  4. Console errors and network logs
  5. Test account credentials if needed

General Fixes

For universal tracking concepts, see the Global Tracking Issues Hub.

// SYS.FOOTER