Webflow GTM Integration | Blue Frog Docs

Webflow GTM Integration

Integrate Google Tag Manager with Webflow for centralized tag management.

Webflow GTM Integration

Complete guide to setting up Google Tag Manager (GTM) on your Webflow site for centralized tracking and tag management.

Overview

Google Tag Manager integrates seamlessly with Webflow, providing a powerful solution for managing all your marketing and analytics tags. Webflow's custom code areas make GTM implementation straightforward while maintaining design flexibility.

Why Use GTM with Webflow?

GTM provides powerful tag management benefits:

  • Centralized Management: Control all tracking from one interface
  • No Code Deploys: Add/modify tags without republishing
  • Version Control: Track changes and roll back if needed
  • Preview Mode: Test tags before publishing
  • Advanced Triggers: Fire tags based on complex conditions
  • Ecommerce Support: Full tracking for Webflow Ecommerce
  • CMS Integration: Track dynamic CMS content

Prerequisites

Before implementing GTM on Webflow:

  1. GTM Account: Create a free account at tagmanager.google.com
  2. Container: Create a Web container for your site
  3. Webflow Site Plan: Site plan required (not just Account plan)
  4. Custom Code Access: Available on all site plans

Installation Methods

Install GTM across your entire Webflow site.

Step 1: Get GTM Container Code

  1. Log in to Google Tag Manager
  2. Click on your container ID (e.g., GTM-XXXXXX)
  3. Copy both code snippets provided

Step 2: Add to Webflow Project Settings

  1. In Webflow Designer, open Project Settings (gear icon)
  2. Go to the Custom Code tab
  3. Paste the first GTM snippet in the Head Code section:
<!-- 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 -->
  1. Paste the second GTM snippet in the Footer Code section:
<!-- 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) -->
  1. Replace GTM-XXXXXX with your actual container ID
  2. Click Save Changes
  3. Publish your site

Method 2: Page-level Implementation

For specific pages only:

  1. Select the page in the Pages panel
  2. Click the gear icon for Page Settings
  3. Go to Custom Code tab
  4. Add GTM snippets to page-level Head/Footer Code
  5. Note: Less efficient for multi-page tracking

Method 3: Embed Component

Alternative using Webflow's HTML Embed:

  1. Add an HTML Embed component to your page
  2. Paste GTM noscript code
  3. Place at top of page body
  4. Combine with Head Code for full implementation

Data Layer Implementation

Basic Data Layer Setup

Add before the GTM container code in Head Code:

<script>
window.dataLayer = window.dataLayer || [];

// Initialize with page data
dataLayer.push({
  'pageType': 'standard',
  'pageTitle': document.title,
  'pageUrl': window.location.href,
  'pagePath': window.location.pathname
});
</script>

CMS Collection Page Data Layer

For dynamic CMS content pages:

<script>
dataLayer.push({
  'pageType': 'cms-item',
  'collectionName': 'blog', // or your collection name
  'itemName': document.querySelector('h1').textContent,
  'publishDate': document.querySelector('[data-publish-date]')?.textContent
});
</script>

Ecommerce Product Page Data Layer

For Webflow Ecommerce product pages, add to page-level Head Code:

<script>
// Wait for Webflow commerce data
Webflow.push(function() {
  var product = window.Webflow?.commerce?.productData;

  if (product) {
    dataLayer.push({
      'event': 'productView',
      'ecommerce': {
        'detail': {
          'products': [{
            'id': product.id,
            'name': product.name,
            'price': product.price / 100, // Convert cents to dollars
            'category': product.category || '',
            'variant': product.defaultSku
          }]
        }
      }
    });
  }
});
</script>

Add to Cart Event

Track when products are added to cart:

<script>
document.addEventListener('DOMContentLoaded', function() {
  // Listen for Webflow commerce events
  document.querySelectorAll('[data-commerce-add-to-cart-button]').forEach(function(button) {
    button.addEventListener('click', function(e) {
      var form = e.target.closest('form');
      var productName = form.querySelector('[data-wf-product-name]')?.textContent;
      var productPrice = form.querySelector('[data-wf-product-price]')?.textContent;

      dataLayer.push({
        'event': 'addToCart',
        'ecommerce': {
          'add': {
            'products': [{
              'name': productName,
              'price': parseFloat(productPrice.replace(/[^0-9.]/g, '')),
              'quantity': parseInt(form.querySelector('[data-wf-quantity]')?.value || 1)
            }]
          }
        }
      });
    });
  });
});
</script>

Ecommerce Purchase Tracking

Add to Order Confirmation page in Page Settings > Custom Code:

<script>
Webflow.push(function() {
  var order = window.Webflow?.commerce?.orderData;

  if (order && !sessionStorage.getItem('orderTracked_' + order.orderId)) {
    dataLayer.push({
      'event': 'purchase',
      'ecommerce': {
        'purchase': {
          'actionField': {
            'id': order.orderId,
            'revenue': order.total / 100,
            'tax': order.tax / 100,
            'shipping': order.shippingCost / 100
          },
          'products': order.lineItems.map(function(item) {
            return {
              'id': item.productId,
              'name': item.name,
              'price': item.price / 100,
              'quantity': item.quantity
            };
          })
        }
      }
    });

    // Prevent duplicate tracking on page refresh
    sessionStorage.setItem('orderTracked_' + order.orderId, 'true');
  }
});
</script>

Common GTM Tags for Webflow

Google Analytics 4 Configuration

  1. In GTM, create GA4 Configuration tag
  2. Enter Measurement ID (G-XXXXXXXXXX)
  3. Trigger: All Pages
  4. Configure ecommerce events separately

GA4 Ecommerce Events

Create separate Event tags for each:

Event Name Trigger Purpose
view_item Custom Event: productView Product page views
add_to_cart Custom Event: addToCart Cart additions
begin_checkout Page View: /checkout Checkout starts
purchase Custom Event: purchase Completed orders

Meta Pixel Base Code

  1. Create Custom HTML tag
  2. Paste Meta Pixel code
  3. Trigger: All Pages
  4. Add conversion events as separate tags

LinkedIn Insight Tag

  1. Create Custom HTML tag
  2. Add LinkedIn Partner ID
  3. Trigger: All Pages
  4. Track conversions on form submissions

Common Triggers

Page View Triggers

Trigger Name Type Conditions
All Pages Page View All pages
Homepage Page View Page Path equals /
Product Pages Page View Page URL contains /products/
Blog Posts Page View Page URL contains /blog/
Cart Page Page View Page Path equals /cart
Checkout Pages Page View Page URL contains /checkout
Thank You Page Page View Page URL contains /order-confirmation

Event Triggers

Trigger Name Type Conditions
Add to Cart Custom Event Event equals addToCart
Product View Custom Event Event equals productView
Purchase Custom Event Event equals purchase
Form Submit Form Submission All forms or specific

Click Triggers

Create for specific interactions:

// CTA button clicks
Trigger: Click - All Elements
Conditions: Click Classes contains 'cta-button'

// Outbound link clicks
Trigger: Click - Just Links
Conditions: Click URL does NOT contain hostname

Built-in Variables

Enable these variables in GTM:

Page Variables:

  • Page URL
  • Page Hostname
  • Page Path
  • Referrer

Click Variables:

  • Click Element
  • Click Classes
  • Click ID
  • Click URL
  • Click Text

Form Variables:

  • Form Element
  • Form Classes
  • Form ID
  • Form Target

Utility Variables:

  • Random Number
  • Container ID
  • Container Version

Custom Variables

Page Type Variable

Type: JavaScript Variable

function() {
  var path = window.location.pathname;

  if (path === '/') return 'homepage';
  if (path.startsWith('/products/')) return 'product';
  if (path.startsWith('/blog/')) return 'blog-post';
  if (path === '/cart') return 'cart';
  if (path.includes('/checkout')) return 'checkout';
  if (path.includes('/order-confirmation')) return 'confirmation';

  return 'other';
}

Product Price Variable

Type: Data Layer Variable Data Layer Variable Name: ecommerce.detail.products.0.price

Order Revenue Variable

Type: Data Layer Variable Data Layer Variable Name: ecommerce.purchase.actionField.revenue

CMS Collection Name Variable

Type: JavaScript Variable

function() {
  // Extract from URL or data attributes
  var collection = document.querySelector('[data-wf-collection]');
  return collection ? collection.getAttribute('data-wf-collection') : '';
}

Form Tracking

Built-in Form Tracking

  1. Enable Form variables in GTM
  2. Create Form Submission trigger
  3. Add conditions for specific forms
  4. Create GA4 Event tag with event name form_submit

Custom Form Tracking

For Webflow forms with specific tracking:

<script>
document.addEventListener('DOMContentLoaded', function() {
  var forms = document.querySelectorAll('form[data-name]');

  forms.forEach(function(form) {
    form.addEventListener('submit', function(e) {
      dataLayer.push({
        'event': 'formSubmit',
        'formName': form.getAttribute('data-name'),
        'formLocation': window.location.pathname
      });
    });
  });
});
</script>

Newsletter Signup Tracking

<script>
document.querySelectorAll('form[data-name="Newsletter"]').forEach(function(form) {
  form.addEventListener('submit', function() {
    dataLayer.push({
      'event': 'newsletter_signup',
      'location': 'footer' // or wherever it appears
    });
  });
});
</script>

Webflow Interactions Tracking

Track Webflow IX2 interactions:

<script>
// Track specific interactions
document.querySelectorAll('[data-w-id]').forEach(function(element) {
  element.addEventListener('click', function() {
    dataLayer.push({
      'event': 'interaction_click',
      'elementId': element.getAttribute('data-w-id'),
      'elementText': element.textContent.trim()
    });
  });
});
</script>

Preview and Debug Mode

Using GTM Preview

  1. In GTM, click Preview button
  2. Enter your Webflow site URL (use published URL)
  3. Click Connect
  4. Tag Assistant opens in new window
  5. Navigate through your site

Debugging Tips

View data layer in browser console:

// Show all data layer pushes
console.log(window.dataLayer);

// Monitor new events
var originalPush = dataLayer.push;
dataLayer.push = function() {
  console.log('GTM Event:', arguments);
  originalPush.apply(dataLayer, arguments);
};

Common Issues to Check

  • GTM loads on all pages after publishing
  • Data layer initializes before GTM container
  • Ecommerce events fire with correct data
  • Form submissions tracked properly
  • No JavaScript console errors
  • Tags don't fire multiple times
  • Revenue values formatted correctly

Publishing Workflow

Pre-publish Checklist

  • Test all tags in Preview mode
  • Verify data in GA4 DebugView
  • Test form submissions
  • Complete test purchase (if ecommerce)
  • Check mobile responsiveness
  • Verify page load performance
  • Test across browsers

Publishing Steps

  1. In GTM, click Submit
  2. Add descriptive version name
  3. Document changes in description
  4. Click Publish
  5. Verify live on published Webflow site
  6. Monitor for 24-48 hours

Webflow Publishing Requirements

Remember to:

  • Publish your Webflow site after adding GTM code
  • GTM only works on published site, not in Designer preview
  • Re-publish if you update custom code
  • Use staging domain for testing before production

Ecommerce Tracking Setup

Required Ecommerce Events

Event Trigger Implementation
Product Impressions Collection pages Auto or custom code
Product Views Product page load Data layer push
Add to Cart Button click Event listener
Remove from Cart Cart page Event listener
Checkout Checkout page load Page view
Purchase Confirmation page Data layer on load

Revenue Attribution

Ensure accurate tracking:

  • Convert Webflow prices from cents to dollars (divide by 100)
  • Remove currency symbols and formatting
  • Include tax and shipping separately
  • Track discounts if applicable
  • Prevent duplicate purchase events

Troubleshooting

Issue Possible Cause Solution
GTM not loading Code not published Publish Webflow site
Tags not firing Wrong trigger setup Check trigger conditions
Duplicate events Multiple implementations Remove redundant code
Ecommerce data missing Commerce API not loaded Wait for Webflow.push callback
Forms not tracked Wrong form selector Update form trigger
Purchase tracking twice No deduplication Add sessionStorage check
Wrong revenue values Cents not converted Divide by 100
CMS data missing Wrong selector Check CMS element attributes
Preview mode not working Using Designer URL Use published site URL
Interactions not tracked No event listener Add custom tracking code

Advanced Configuration

Cross-Domain Tracking

If tracking across multiple domains:

// In GA4 Configuration tag
{
  'linker': {
    'domains': ['yourdomain.com', 'app.yourdomain.com'],
    'accept_incoming': true
  }
}

User ID Tracking

For member areas or logged-in users:

<script>
// After user authentication
if (window.Webflow?.memberships?.currentMember) {
  dataLayer.push({
    'userId': window.Webflow.memberships.currentMember.id,
    'userEmail': window.Webflow.memberships.currentMember.email
  });
}
</script>

Scroll Depth Tracking

Track how far users scroll:

function() {
  var scrollDepth = Math.round((window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100);

  [25, 50, 75, 90].forEach(function(threshold) {
    if (scrollDepth >= threshold && !window['scrollTracked_' + threshold]) {
      dataLayer.push({
        'event': 'scroll_depth',
        'scrollPercentage': threshold
      });
      window['scrollTracked_' + threshold] = true;
    }
  });
}

Video Tracking

For embedded videos (Vimeo, YouTube):

<script>
// YouTube video tracking
var players = [];
function onYouTubeIframeAPIReady() {
  document.querySelectorAll('iframe[src*="youtube.com"]').forEach(function(iframe, i) {
    players[i] = new YT.Player(iframe, {
      events: {
        'onStateChange': function(event) {
          if (event.data === YT.PlayerState.PLAYING) {
            dataLayer.push({
              'event': 'video_start',
              'videoTitle': event.target.getVideoData().title
            });
          }
        }
      }
    });
  });
}
</script>

Performance Optimization

Best Practices

  • Limit total tags to under 20
  • Use async loading for third-party scripts
  • Minimize Custom HTML tags
  • Remove unused triggers and variables
  • Test page load impact regularly
  • Use tag sequencing when needed

Performance Monitoring

// Measure GTM load time
window.addEventListener('load', function() {
  var perfData = window.performance.timing;
  var pageLoadTime = perfData.loadEventEnd - perfData.navigationStart;

  dataLayer.push({
    'event': 'performance_timing',
    'pageLoadTime': pageLoadTime
  });
});

Webflow-specific Considerations

Designer vs. Published Site

  • GTM only functions on published sites
  • Test using your published staging domain
  • Designer preview won't load external scripts
  • Always publish after custom code changes

CMS Limitations

  • Limited access to CMS data in custom code
  • Use data attributes for dynamic content
  • Test across different CMS items
  • Collection lists need special handling

Ecommerce Considerations

  • Webflow stores prices in cents (convert for tracking)
  • Limited checkout customization
  • Order data available via Webflow.commerce API
  • Test with real transactions in staging

Privacy and Compliance

Implement consent before loading GTM:

<script>
// Wait for consent
window.addEventListener('cookieConsent', function(e) {
  if (e.detail.analytics) {
    // Load GTM container
    (function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXXXXX');
  }
});
</script>

Use Google's Consent Mode:

// Default consent state
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}

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

Testing Checklist

  • GTM container loads on published site
  • Data layer initializes correctly
  • All page types tracked properly
  • Product views fire on product pages
  • Add to cart events work
  • Purchase tracking on confirmation page
  • Forms submit tracking works
  • No JavaScript console errors
  • Mobile experience tested
  • Cross-browser compatibility verified
  • Page performance acceptable

Additional Resources

// SYS.FOOTER