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
- In GTM, go to Variables > New
- Choose Data Layer Variable
- Data Layer Variable Name: Enter the exact variable name (e.g.,
pageType) - Name your variable (e.g., "DLV - Page Type")
- Save
2. Common Variables to Create
pageType- Type of pageproductId- Product ID on product pagesproductName- Product nameproductPrice- Product pricememberStatus- Member login statussquarespaceVersion- 7.0 or 7.1transactionId- Order ID on confirmation pagetransactionTotal- 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\}\}
- Parameter Name:
Using Data Layer for Triggers
Create triggers based on data layer values:
Example: Fire Tag Only on Product Pages
- Trigger Type: Custom Event
- Event name:
product_detail_view - This trigger fires on: All Custom Events
Example: Fire Tag Only for Members
- Trigger Type: Page View
- This trigger fires on: Some Page Views
- Condition:
memberStatusequalsmember
Testing the Data Layer
1. Browser Console
- Open your Squarespace site
- Open DevTools (F12)
- In Console, type:
dataLayer - Inspect the array to see all pushed data
2. GTM Preview Mode
- Click Preview in GTM
- Enter your site URL
- In the debug panel, click Variables
- 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
DOMContentLoadedorwindow.onloadevents - Check that
window.Static.SQUARESPACE_CONTEXT.productexists - 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:
- Create a GA4 Configuration tag
- Add User Properties:
- Property Name:
squarespace_version - Value:
\{\{DLV - Squarespace Version\}\}
- Property Name:
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
Consistent Naming:
- Use camelCase for variable names
- Be descriptive (e.g.,
productPricenotpp) - Document your data layer schema
Event-Driven:
- Push custom events for important interactions
- Use event names that describe the action (e.g.,
addToCart, notevent1)
Data Validation:
- Add null checks before pushing data
- Validate data types (strings, numbers, booleans)
- Handle edge cases (missing products, empty carts)
Performance:
- Don't push excessive data
- Use throttling for frequent events (scroll, mousemove)
- Clear old data if needed
Privacy:
Next Steps
- Implement GA4 Event Tracking using your data layer
- Set up Ecommerce Tracking with enhanced data layer
- Create Meta Pixel events using data layer values
- Troubleshoot tracking issues if data isn't flowing correctly