Squarespace Data Layer for GTM | Blue Frog Docs

Squarespace Data Layer for GTM

Comprehensive guide to implementing and utilizing the Squarespace data layer with Google Tag Manager, including Y.Squarespace API and Commerce events.

Squarespace Data Layer for GTM

The data layer is the communication channel between your Squarespace site and Google Tag Manager. This guide covers how to leverage Squarespace-specific data, including the Y.Squarespace API and Commerce events.


What is the Data Layer?

The data layer is a JavaScript object that stores information about your page and user interactions. GTM reads this data to:

  • Determine when to fire tags
  • Pass dynamic values to tags
  • Create audience segments
  • Track user behavior

Basic Structure:

window.dataLayer = window.dataLayer || [];
dataLayer.push({
  'variable_name': 'value',
  'another_variable': 'another_value'
});

Setting Up the Base Data Layer

Add this code to Settings > Advanced > Code Injection > Header (BEFORE your GTM container code):

<script>
  // Initialize data layer
  window.dataLayer = window.dataLayer || [];

  // Push initial page data
  dataLayer.push({
    'event': 'page_data_ready',
    'pageType': getPageType(),
    'squarespaceVersion': getSquarespaceVersion(),
    'templateName': getTemplateName(),
    'hasCommerce': hasCommerce(),
    'hasMemberAreas': hasMemberAreas()
  });

  // Helper functions
  function getPageType() {
    var path = window.location.pathname;

    if (path === '/') return 'homepage';
    if (path.includes('/blog/') && path.split('/').length > 3) return 'blog_post';
    if (path.includes('/blog')) return 'blog_index';
    if (document.querySelector('.sqs-commerce-product-detail')) return 'product';
    if (path.includes('/checkout')) return 'checkout';
    if (path.includes('/cart')) return 'cart';
    if (document.querySelector('.sqs-block-form')) return 'form_page';

    return 'standard_page';
  }

  function getSquarespaceVersion() {
    return document.body.classList.contains('squarespace-7.1') ? '7.1' : '7.0';
  }

  function getTemplateName() {
    var bodyClasses = document.body.className;
    var match = bodyClasses.match(/template-([^\s]+)/);
    return match ? match[1] : 'unknown';
  }

  function hasCommerce() {
    return document.body.classList.contains('sqs-site-has-commerce') ||
           document.querySelector('.sqs-commerce-product-item') !== null;
  }

  function hasMemberAreas() {
    return document.body.classList.contains('has-member-areas') ||
           window.Squarespace && window.Squarespace.user !== undefined;
  }
</script>

Product Page Data Layer

For product pages, capture detailed product information:

<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Check if this is a product page
    var productBlock = document.querySelector('.sqs-commerce-product-detail');

    if (productBlock) {
      // Wait for Squarespace product data to load
      if (window.Static && window.Static.SQUARESPACE_CONTEXT && window.Static.SQUARESPACE_CONTEXT.product) {
        var product = window.Static.SQUARESPACE_CONTEXT.product;
        var variant = product.variants && product.variants[0];

        dataLayer.push({
          'event': 'product_detail_view',
          'ecommerce': {
            'currencyCode': variant.priceMoney.currency,
            'detail': {
              'products': [{
                'id': product.id,
                'name': product.title,
                'price': variant.priceMoney.value / 100, // Convert cents to dollars
                'brand': product.vendor || '',
                'category': product.categories && product.categories[0] ? product.categories[0] : '',
                'variant': variant.attributes ? Object.values(variant.attributes).join(' / ') : '',
                'inventory': variant.stock ? variant.stock.quantity : 'unknown'
              }]
            }
          },
          'productId': product.id,
          'productName': product.title,
          'productPrice': variant.priceMoney.value / 100,
          'productCategory': product.categories && product.categories[0] ? product.categories[0] : '',
          'productType': product.isDigital ? 'digital' : 'physical',
          'onSale': variant.onSale || false
        });
      }
    }
  });
</script>

Commerce Events via Y.Squarespace

Squarespace's YUI framework provides event hooks for commerce interactions.

Add to Cart

<script>
  (function() {
    if (window.Y && window.Y.Squarespace) {
      window.Y.use(function(Y) {
        // Add to Cart Event
        Y.on('cart:item:added', function(e) {
          var item = e.item;

          dataLayer.push({
            'event': 'addToCart',
            'ecommerce': {
              'currencyCode': 'USD', // Update to your currency
              'add': {
                'products': [{
                  'id': item.sku || item.id,
                  'name': item.title,
                  'price': item.price / 100,
                  'quantity': item.quantity,
                  'variant': item.chosenVariant ? JSON.stringify(item.chosenVariant.attributes) : ''
                }]
              }
            }
          });
        });

        // Remove from Cart Event
        Y.on('cart:item:removed', function(e) {
          var item = e.item;

          dataLayer.push({
            'event': 'removeFromCart',
            'ecommerce': {
              'remove': {
                'products': [{
                  'id': item.sku || item.id,
                  'name': item.title,
                  'price': item.price / 100,
                  'quantity': item.quantity
                }]
              }
            }
          });
        });

        // Cart Quantity Updated
        Y.on('cart:item:updated', function(e) {
          var item = e.item;

          dataLayer.push({
            'event': 'cartUpdate',
            'itemId': item.id,
            'itemName': item.title,
            'newQuantity': item.quantity,
            'itemPrice': item.price / 100
          });
        });
      });
    }
  })();
</script>

Checkout Data Layer

For the checkout page:

<script>
  document.addEventListener('DOMContentLoaded', function() {
    if (window.location.pathname.includes('/checkout')) {
      if (window.Y && window.Y.Squarespace) {
        window.Y.use(function(Y) {
          var cart = Y.Squarespace.Commerce.getCart();

          if (cart && cart.entries) {
            var products = cart.entries.map(function(entry) {
              return {
                'id': entry.sku || entry.id,
                'name': entry.title,
                'price': entry.price / 100,
                'quantity': entry.quantity,
                'variant': entry.chosenVariant ? JSON.stringify(entry.chosenVariant.attributes) : ''
              };
            });

            dataLayer.push({
              'event': 'checkout',
              'ecommerce': {
                'currencyCode': 'USD',
                'checkout': {
                  'actionField': {'step': 1},
                  'products': products
                }
              },
              'cartValue': cart.subtotal / 100,
              'cartItemCount': cart.entries.length
            });
          }
        });
      }
    }
  });
</script>

Purchase Data Layer (Order Confirmation)

Add to Settings > Advanced > Code Injection > ORDER CONFIRMATION PAGE:

<script>
  (function() {
    // Get order data from Squarespace
    var orderData = {orderInformation};

    if (orderData) {
      var products = orderData.lineItems.map(function(item) {
        return {
          'id': item.sku || item.productId,
          'name': item.productName,
          'price': item.unitPricePaid.value,
          'quantity': item.quantity,
          'variant': item.variantOptions ? item.variantOptions.join(' / ') : ''
        };
      });

      dataLayer.push({
        'event': 'purchase',
        'ecommerce': {
          'currencyCode': orderData.grandTotal.currency,
          'purchase': {
            'actionField': {
              'id': orderData.id,
              'affiliation': 'Squarespace Store',
              'revenue': orderData.grandTotal.value,
              'tax': orderData.salesTax ? orderData.salesTax.value : 0,
              'shipping': orderData.shippingTotal.value
            },
            'products': products
          }
        },
        'transactionId': orderData.id,
        'transactionTotal': orderData.grandTotal.value,
        'transactionTax': orderData.salesTax ? orderData.salesTax.value : 0,
        'transactionShipping': orderData.shippingTotal.value,
        'transactionProducts': products.length
      });
    }
  })();
</script>

Member Area Data Layer

Track member status and interactions:

<script>
  (function() {
    if (window.Squarespace && window.Squarespace.user) {
      window.Squarespace.onInitialize(Y, function() {
        var isLoggedIn = Y.Squarespace.User.isLoggedIn();

        dataLayer.push({
          'event': 'member_status_detected',
          'memberStatus': isLoggedIn ? 'member' : 'guest',
          'isLoggedIn': isLoggedIn
        });

        // Track member login
        if (isLoggedIn) {
          var wasLoggedIn = sessionStorage.getItem('member_logged_in');

          if (!wasLoggedIn) {
            dataLayer.push({
              'event': 'member_login'
            });
            sessionStorage.setItem('member_logged_in', 'true');
          }
        } else {
          sessionStorage.removeItem('member_logged_in');
        }
      });
    }
  })();
</script>

Form Submission Data Layer

Track form submissions with form details:

<script>
  document.addEventListener('DOMContentLoaded', function() {
    var forms = document.querySelectorAll('.sqs-block-form form');

    forms.forEach(function(form) {
      form.addEventListener('submit', function(e) {
        // Get form name from nearest heading
        var block = form.closest('.sqs-block');
        var heading = block ? block.querySelector('h1, h2, h3, h4') : null;
        var formName = heading ? heading.textContent.trim() : 'Unknown Form';

        // Get form fields
        var formFields = [];
        var inputs = form.querySelectorAll('input, textarea, select');
        inputs.forEach(function(input) {
          if (input.name && input.name !== '') {
            formFields.push(input.name);
          }
        });

        dataLayer.push({
          'event': 'form_submission',
          'formName': formName,
          'formLocation': window.location.pathname,
          'formFields': formFields.join(', ')
        });
      });
    });
  });
</script>

Newsletter Signup Data Layer

For Squarespace Newsletter blocks:

<script>
  document.addEventListener('DOMContentLoaded', function() {
    var newsletterForms = document.querySelectorAll('.sqs-block-newsletter form');

    newsletterForms.forEach(function(form) {
      form.addEventListener('submit', function(e) {
        dataLayer.push({
          'event': 'newsletter_signup',
          'newsletterLocation': window.location.pathname
        });
      });
    });
  });
</script>

Scroll Depth Tracking

Track how far users scroll on pages:

<script>
  (function() {
    var scrollMarks = [25, 50, 75, 90, 100];
    var scrollCache = {};

    window.addEventListener('scroll', throttle(function() {
      var scrollPercent = Math.round((window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100);

      scrollMarks.forEach(function(mark) {
        if (scrollPercent >= mark && !scrollCache[mark]) {
          scrollCache[mark] = true;

          dataLayer.push({
            'event': 'scroll_depth',
            'scrollDepth': mark,
            'pageType': getPageType()
          });
        }
      });
    }, 500));

    function throttle(func, wait) {
      var timeout;
      return function() {
        var context = this, args = arguments;
        if (!timeout) {
          timeout = setTimeout(function() {
            timeout = null;
            func.apply(context, args);
          }, wait);
        }
      };
    }

    function getPageType() {
      if (window.location.pathname === '/') return 'homepage';
      if (window.location.pathname.includes('/blog/')) return 'blog';
      if (document.querySelector('.sqs-commerce-product-detail')) return 'product';
      return 'page';
    }
  })();
</script>

Creating GTM Variables from Data Layer

Once data is in the data layer, create GTM variables to use in tags and triggers.

1. Data Layer Variable

  1. In GTM, go to Variables > New
  2. Choose Data Layer Variable
  3. Data Layer Variable Name: Enter the exact variable name (e.g., pageType)
  4. Name your variable (e.g., "DLV - Page Type")
  5. Save

2. Common Variables to Create

  • pageType - Type of page
  • productId - Product ID on product pages
  • productName - Product name
  • productPrice - Product price
  • memberStatus - Member login status
  • squarespaceVersion - 7.0 or 7.1
  • transactionId - Order ID on confirmation page
  • transactionTotal - Order total

3. Using Variables in Tags

Example: Send product name to GA4 event

Tag Configuration:

  • Tag Type: GA4 Event
  • Event Name: view_product
  • Event Parameters:
    • Parameter Name: product_name
    • Value: \{\{DLV - Product Name\}\}

Using Data Layer for Triggers

Create triggers based on data layer values:

Example: Fire Tag Only on Product Pages

  1. Trigger Type: Custom Event
  2. Event name: product_detail_view
  3. This trigger fires on: All Custom Events

Example: Fire Tag Only for Members

  1. Trigger Type: Page View
  2. This trigger fires on: Some Page Views
  3. Condition: memberStatus equals member

Testing the Data Layer

1. Browser Console

  1. Open your Squarespace site
  2. Open DevTools (F12)
  3. In Console, type: dataLayer
  4. Inspect the array to see all pushed data

2. GTM Preview Mode

  1. Click Preview in GTM
  2. Enter your site URL
  3. In the debug panel, click Variables
  4. Verify your data layer variables have correct values

3. DataLayer Inspector

Install the DataLayer Inspector Chrome extension for easier debugging.


Common Issues & Solutions

Issue: Data Layer Variable is Undefined

Cause: Variable not pushed before GTM tries to read it

Solution:

  • Ensure data layer code is BEFORE GTM container code
  • Use dataLayer.push() instead of direct assignment
  • Check variable names match exactly (case-sensitive)

Issue: Commerce Events Not Firing

Cause: Y.Squarespace not loaded or events not properly bound

Solution:

  • Wrap code in window.Y.use() callback
  • Verify Squarespace Commerce is enabled on the site
  • Check browser console for JavaScript errors

Issue: Product Data Not Available

Cause: Product data loads after page load

Solution:

  • Use DOMContentLoaded or window.onload events
  • Check that window.Static.SQUARESPACE_CONTEXT.product exists
  • Add null checks before accessing product properties

Advanced Data Layer Patterns

Custom Dimensions for GA4

Send Squarespace-specific data to GA4:

// In your data layer
dataLayer.push({
  'user_properties': {
    'squarespace_version': '7.1',
    'template_name': 'aviator',
    'member_status': 'guest'
  }
});

Then in GTM:

  1. Create a GA4 Configuration tag
  2. Add User Properties:
    • Property Name: squarespace_version
    • Value: \{\{DLV - Squarespace Version\}\}

Enhanced Ecommerce Impressions

Track product impressions on collection pages:

document.addEventListener('DOMContentLoaded', function() {
  var products = document.querySelectorAll('.sqs-commerce-product-item');

  if (products.length > 0) {
    var impressions = [];

    products.forEach(function(product, index) {
      var title = product.querySelector('.product-title');
      var price = product.querySelector('.product-price');
      var link = product.querySelector('a[href*="/products/"]');

      if (title && price && link) {
        impressions.push({
          'id': link.getAttribute('href').split('/').pop(),
          'name': title.textContent.trim(),
          'price': parseFloat(price.textContent.replace(/[^0-9.]/g, '')),
          'position': index + 1
        });
      }
    });

    if (impressions.length > 0) {
      dataLayer.push({
        'event': 'productImpressions',
        'ecommerce': {
          'currencyCode': 'USD',
          'impressions': impressions
        }
      });
    }
  }
});

Best Practices

  1. Consistent Naming:

    • Use camelCase for variable names
    • Be descriptive (e.g., productPrice not pp)
    • Document your data layer schema
  2. Event-Driven:

    • Push custom events for important interactions
    • Use event names that describe the action (e.g., addToCart, not event1)
  3. Data Validation:

    • Add null checks before pushing data
    • Validate data types (strings, numbers, booleans)
    • Handle edge cases (missing products, empty carts)
  4. Performance:

    • Don't push excessive data
    • Use throttling for frequent events (scroll, mousemove)
    • Clear old data if needed
  5. Privacy:

    • Don't push personally identifiable information (PII)
    • Be careful with customer emails and names
    • Comply with GDPR and other regulations

Next Steps


Additional Resources

// SYS.FOOTER