Snapchat Ads Data Layer Setup | Blue Frog Docs

Snapchat Ads Data Layer Setup

Structure your data layer for consistent event tracking and seamless integration with Snap Pixel and GTM.

Data Layer Overview

A data layer is a JavaScript object that stores information about your webpage, products, user actions, and transactions in a structured format. It acts as a bridge between your website and tracking tools like Snap Pixel and Google Tag Manager.

Why Use a Data Layer?

Benefits

  • Consistency - Centralized data structure across all pages
  • Flexibility - Easy to update tracking without changing pixel code
  • Reliability - Reduces dependency on page HTML structure
  • GTM Integration - Seamless integration with tag management
  • Debugging - Easier to troubleshoot tracking issues
  • Scalability - Supports multiple marketing tools from one source

Without vs With Data Layer

Without Data Layer (Direct DOM access):

// Fragile - breaks if HTML changes
const productSku = document.querySelector('.product-sku')?.textContent;
const productPrice = parseFloat(document.querySelector('.price')?.textContent);

snaptr('track', 'VIEW_CONTENT', {
  'item_ids': [productSku],
  'price': productPrice,
  'currency': 'USD'
});

With Data Layer (Structured data):

// Robust - independent of HTML structure
const productData = window.dataLayer.find(item => item.event === 'productView');

snaptr('track', 'VIEW_CONTENT', {
  'item_ids': [productData.product.sku],
  'price': productData.product.price,
  'currency': productData.product.currency
});

Basic Data Layer Structure

Initialize Data Layer

Place at the top of your <head> tag, before any tracking scripts:

<!DOCTYPE html>
<html>
<head>
  <!-- Initialize dataLayer FIRST -->
  <script>
  window.dataLayer = window.dataLayer || [];
  </script>

  <!-- Then load Snap Pixel -->
  <script type='text/javascript'>
  // Snap Pixel code here
  </script>
</head>

Data Layer Object Format

window.dataLayer = window.dataLayer || [];
dataLayer.push({
  'event': 'eventName',      // Event identifier
  'eventCategory': 'category', // Optional categorization
  'eventAction': 'action',     // What happened
  'eventLabel': 'label',       // Additional context
  // Custom data
  'pageType': 'product',
  'product': {
    'sku': 'SKU_123',
    'name': 'Blue Widget',
    'price': 99.99,
    'currency': 'USD'
  }
});

E-Commerce Data Layer

Product Page

// When product page loads
dataLayer.push({
  'event': 'productView',
  'pageType': 'product',
  'product': {
    'sku': 'SKU_123',
    'name': 'Blue Widget Pro',
    'category': 'Electronics',
    'subcategory': 'Widgets',
    'brand': 'WidgetCo',
    'price': 99.99,
    'currency': 'USD',
    'availability': 'in_stock',
    'imageUrl': 'https://example.com/images/widget.jpg'
  },
  'user': {
    'customerId': 'USER_12345',  // If logged in
    'customerStatus': 'returning',
    'email': 'hashed_email_here'  // Hashed
  }
});

// Connect to Snap Pixel
if (typeof snaptr !== 'undefined') {
  const productData = dataLayer.find(item => item.event === 'productView');

  snaptr('track', 'VIEW_CONTENT', {
    'item_ids': [productData.product.sku],
    'price': productData.product.price,
    'currency': productData.product.currency,
    'item_category': productData.product.category,
    'description': productData.product.name
  });
}

Add to Cart

// When user adds item to cart
dataLayer.push({
  'event': 'addToCart',
  'product': {
    'sku': 'SKU_123',
    'name': 'Blue Widget Pro',
    'category': 'Electronics',
    'price': 99.99,
    'currency': 'USD',
    'quantity': 2
  },
  'cart': {
    'itemCount': 3,
    'totalValue': 249.97,
    'items': [
      {
        'sku': 'SKU_123',
        'name': 'Blue Widget Pro',
        'price': 99.99,
        'quantity': 2
      },
      {
        'sku': 'SKU_456',
        'name': 'Red Widget',
        'price': 49.99,
        'quantity': 1
      }
    ]
  }
});

// Connect to Snap Pixel
window.addEventListener('dataLayerEvent', function(e) {
  if (e.detail.event === 'addToCart') {
    const data = e.detail;

    snaptr('track', 'ADD_CART', {
      'item_ids': [data.product.sku],
      'price': data.product.price * data.product.quantity,
      'currency': data.product.currency,
      'number_items': data.product.quantity
    });
  }
});

Checkout Started

// When checkout begins
dataLayer.push({
  'event': 'checkoutStarted',
  'pageType': 'checkout',
  'checkout': {
    'step': 1,
    'stepName': 'Information',
    'cart': {
      'itemCount': 3,
      'subtotal': 249.97,
      'tax': 20.00,
      'shipping': 10.00,
      'total': 279.97,
      'currency': 'USD',
      'items': [
        {
          'sku': 'SKU_123',
          'name': 'Blue Widget Pro',
          'price': 99.99,
          'quantity': 2,
          'category': 'Electronics'
        },
        {
          'sku': 'SKU_456',
          'name': 'Red Widget',
          'price': 49.99,
          'quantity': 1,
          'category': 'Electronics'
        }
      ]
    }
  }
});

// Connect to Snap Pixel
const checkoutData = dataLayer.find(item => item.event === 'checkoutStarted');

snaptr('track', 'START_CHECKOUT', {
  'item_ids': checkoutData.checkout.cart.items.map(item => item.sku),
  'price': checkoutData.checkout.cart.total,
  'currency': checkoutData.checkout.cart.currency,
  'number_items': checkoutData.checkout.cart.itemCount
});

Purchase Completed

// On order confirmation page
dataLayer.push({
  'event': 'purchase',
  'pageType': 'confirmation',
  'transaction': {
    'orderId': 'ORDER_12345',
    'orderNumber': '12345',
    'revenue': 279.97,
    'subtotal': 249.97,
    'tax': 20.00,
    'shipping': 10.00,
    'currency': 'USD',
    'paymentMethod': 'credit_card',
    'shippingMethod': 'standard',
    'items': [
      {
        'sku': 'SKU_123',
        'name': 'Blue Widget Pro',
        'category': 'Electronics',
        'price': 99.99,
        'quantity': 2
      },
      {
        'sku': 'SKU_456',
        'name': 'Red Widget',
        'category': 'Electronics',
        'price': 49.99,
        'quantity': 1
      }
    ]
  },
  'customer': {
    'customerId': 'USER_12345',
    'email': 'hashed_email',  // Hashed
    'phone': 'hashed_phone',  // Hashed
    'type': 'returning'
  }
});

// Connect to Snap Pixel
const purchaseData = dataLayer.find(item => item.event === 'purchase');

snaptr('track', 'PURCHASE', {
  'price': purchaseData.transaction.revenue,
  'currency': purchaseData.transaction.currency,
  'transaction_id': purchaseData.transaction.orderId,
  'item_ids': purchaseData.transaction.items.map(item => item.sku),
  'number_items': purchaseData.transaction.items.reduce((sum, item) => sum + item.quantity, 0)
});

Lead Generation Data Layer

Form Submission

// When form is submitted
dataLayer.push({
  'event': 'formSubmitted',
  'form': {
    'formId': 'contact-form',
    'formName': 'Contact Us',
    'formType': 'contact',
    'formLocation': 'homepage',
    'fields': {
      'name': true,        // Boolean: was field filled?
      'email': true,
      'phone': true,
      'message': true
    }
  },
  'lead': {
    'value': 500,  // Estimated lead value
    'source': 'website',
    'campaign': 'spring-2025'
  }
});

// Connect to Snap Pixel
const formData = dataLayer.find(item => item.event === 'formSubmitted');

snaptr('track', 'CUSTOM_EVENT_1', {
  'event_name': 'Lead_Form_Submitted',
  'value': formData.lead.value,
  'currency': 'USD',
  'form_type': formData.form.formType
});

Sign Up

// When user signs up
dataLayer.push({
  'event': 'signUp',
  'user': {
    'customerId': 'USER_12345',
    'signUpMethod': 'email',  // 'email', 'google', 'facebook'
    'accountType': 'free',     // 'free', 'premium'
    'email': hashSHA256('user@example.com'),  // Hashed
    'phone': hashSHA256('+15551234567')       // Hashed
  },
  'signUp': {
    'source': 'homepage',
    'campaign': 'spring-2025'
  }
});

// Connect to Snap Pixel
const signUpData = dataLayer.find(item => item.event === 'signUp');

snaptr('track', 'SIGN_UP', {
  'sign_up_method': signUpData.user.signUpMethod,
  'user_email': signUpData.user.email,
  'user_phone_number': signUpData.user.phone
});

Page-Specific Data Layers

Home Page

dataLayer.push({
  'event': 'pageView',
  'pageType': 'home',
  'page': {
    'title': 'Homepage - WidgetCo',
    'url': window.location.href,
    'path': window.location.pathname,
    'referrer': document.referrer
  },
  'site': {
    'name': 'WidgetCo',
    'language': 'en-US',
    'country': 'US',
    'currency': 'USD'
  }
});

Category Page

dataLayer.push({
  'event': 'categoryView',
  'pageType': 'category',
  'category': {
    'name': 'Electronics',
    'id': 'CAT_123',
    'path': 'Electronics > Widgets',
    'productCount': 24
  },
  'page': {
    'title': 'Electronics - WidgetCo',
    'url': window.location.href
  }
});

Search Results Page

dataLayer.push({
  'event': 'searchResults',
  'pageType': 'search',
  'search': {
    'query': 'blue widgets',
    'resultsCount': 12,
    'filters': {
      'category': 'Electronics',
      'priceRange': '50-100',
      'brand': 'WidgetCo'
    }
  }
});

// Connect to Snap Pixel
const searchData = dataLayer.find(item => item.event === 'searchResults');

snaptr('track', 'SEARCH', {
  'search_string': searchData.search.query,
  'item_category': searchData.search.filters.category
});

GTM Integration

Reading Data Layer in GTM

1. Create Data Layer Variables

In GTM:

  • Variables > New > Data Layer Variable
  • Name: "DL - Product SKU"
  • Data Layer Variable Name: product.sku
  • Save

Create variables for:

  • product.sku
  • product.price
  • product.currency
  • transaction.orderId
  • transaction.revenue

2. Use in Tags

<!-- GTM Tag for Snap Pixel VIEW_CONTENT -->
<script>
snaptr('track', 'VIEW_CONTENT', {
  'item_ids': ['{{DL - Product SKU}}'],
  'price': {{DL - Product Price}},
  'currency': '{{DL - Product Currency}}',
  'item_category': '{{DL - Product Category}}'
});
</script>

3. Create Custom Event Triggers

  • Triggers > New > Custom Event
  • Event name: productView (matches dataLayer event)
  • Fire on: All Custom Events (or specific event)

Advanced Data Layer Patterns

Data Layer Helper Function

// Utility to safely push to dataLayer
window.pushDataLayer = function(data) {
  try {
    // Validate data structure
    if (!data.event) {
      console.error('Data layer push missing event name');
      return;
    }

    // Log for debugging (remove in production)
    if (window.location.hostname === 'localhost') {
      console.log('DataLayer Push:', data);
    }

    // Push to dataLayer
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push(data);

    // Dispatch custom event for listeners
    window.dispatchEvent(new CustomEvent('dataLayerEvent', {
      detail: data
    }));

    return true;
  } catch (error) {
    console.error('Data layer push failed:', error);
    return false;
  }
};

// Usage
pushDataLayer({
  'event': 'productView',
  'product': {
    'sku': 'SKU_123',
    'price': 99.99
  }
});

Data Layer Listener

// Listen for data layer events
window.addEventListener('dataLayerEvent', function(e) {
  const data = e.detail;

  // Route to appropriate Snap Pixel event
  switch(data.event) {
    case 'productView':
      snaptr('track', 'VIEW_CONTENT', {
        'item_ids': [data.product.sku],
        'price': data.product.price,
        'currency': data.product.currency
      });
      break;

    case 'addToCart':
      snaptr('track', 'ADD_CART', {
        'item_ids': [data.product.sku],
        'price': data.product.price,
        'currency': data.product.currency
      });
      break;

    case 'purchase':
      snaptr('track', 'PURCHASE', {
        'price': data.transaction.revenue,
        'currency': data.transaction.currency,
        'transaction_id': data.transaction.orderId,
        'item_ids': data.transaction.items.map(item => item.sku)
      });
      break;
  }
});

Data Layer Validation

// Validate data layer structure before pushing
function validateProductData(product) {
  const required = ['sku', 'price', 'currency'];
  const missing = required.filter(field => !product[field]);

  if (missing.length > 0) {
    console.error('Missing required product fields:', missing);
    return false;
  }

  if (typeof product.price !== 'number' || product.price <= 0) {
    console.error('Invalid product price:', product.price);
    return false;
  }

  return true;
}

// Usage
const productData = {
  'sku': 'SKU_123',
  'price': 99.99,
  'currency': 'USD'
};

if (validateProductData(productData)) {
  dataLayer.push({
    'event': 'productView',
    'product': productData
  });
}

Platform-Specific Implementations

Shopify Data Layer

<!-- In theme.liquid or product.liquid -->
<script>
window.dataLayer = window.dataLayer || [];

{% if template contains 'product' %}
dataLayer.push({
  'event': 'productView',
  'product': {
    'sku': '{{ product.selected_or_first_available_variant.sku }}',
    'name': '{{ product.title | escape }}',
    'price': {{ product.selected_or_first_available_variant.price | money_without_currency }},
    'currency': '{{ shop.currency }}',
    'category': '{{ product.type }}',
    'brand': '{{ product.vendor }}',
    'variant': '{{ product.selected_or_first_available_variant.title }}',
    'availability': '{% if product.available %}in_stock{% else %}out_of_stock{% endif %}'
  }
});
{% endif %}

{% if template contains 'collection' %}
dataLayer.push({
  'event': 'categoryView',
  'category': {
    'name': '{{ collection.title }}',
    'productCount': {{ collection.products_count }}
  }
});
{% endif %}
</script>

WooCommerce Data Layer

// In functions.php

// Product page data layer
add_action('woocommerce_after_single_product', 'add_product_datalayer');
function add_product_datalayer() {
  global $product;
  ?>
  <script>
  window.dataLayer = window.dataLayer || [];
  dataLayer.push({
    'event': 'productView',
    'product': {
      'sku': '<?php echo esc_js($product->get_sku()); ?>',
      'name': '<?php echo esc_js($product->get_name()); ?>',
      'price': <?php echo $product->get_price(); ?>,
      'currency': '<?php echo get_woocommerce_currency(); ?>',
      'category': '<?php echo esc_js(strip_tags(wc_get_product_category_list($product->get_id()))); ?>'
    }
  });
  </script>
  <?php
}

// Purchase data layer
add_action('woocommerce_thankyou', 'add_purchase_datalayer', 10, 1);
function add_purchase_datalayer($order_id) {
  $order = wc_get_order($order_id);
  $items = array();

  foreach ($order->get_items() as $item) {
    $product = $item->get_product();
    $items[] = array(
      'sku' => $product->get_sku(),
      'name' => $product->get_name(),
      'price' => $product->get_price(),
      'quantity' => $item->get_quantity()
    );
  }
  ?>
  <script>
  window.dataLayer = window.dataLayer || [];
  dataLayer.push({
    'event': 'purchase',
    'transaction': {
      'orderId': '<?php echo $order_id; ?>',
      'revenue': <?php echo $order->get_total(); ?>,
      'tax': <?php echo $order->get_total_tax(); ?>,
      'shipping': <?php echo $order->get_shipping_total(); ?>,
      'currency': '<?php echo $order->get_currency(); ?>',
      'items': <?php echo json_encode($items); ?>
    }
  });
  </script>
  <?php
}

Best Practices

1. Initialize Early

Place dataLayer initialization at the top of <head>, before any tracking scripts.

2. Use Consistent Naming

// Good: Consistent camelCase
dataLayer.push({
  'productSku': 'SKU_123',
  'productPrice': 99.99
});

// Avoid: Mixed naming conventions
dataLayer.push({
  'product_sku': 'SKU_123',
  'ProductPrice': 99.99
});

3. Hash PII

// Always hash personally identifiable information
dataLayer.push({
  'user': {
    'email': hashSHA256('user@example.com'),  // Hashed
    'phone': hashSHA256('+15551234567')       // Hashed
  }
});

4. Validate Data

Validate data before pushing to ensure quality:

function pushValidatedData(eventData) {
  // Check required fields
  if (!eventData.event || !eventData.product) {
    console.error('Invalid data structure');
    return;
  }

  // Push to dataLayer
  dataLayer.push(eventData);
}

5. Document Your Schema

Maintain documentation of your data layer structure:

## Data Layer Schema

### productView Event
- event: 'productView'
- product.sku: String (required)
- product.price: Number (required)
- product.currency: String (required)
- product.category: String (optional)

Debugging Data Layer

Console Inspection

// View entire dataLayer
console.table(dataLayer);

// Find specific event
const purchaseEvent = dataLayer.find(item => item.event === 'purchase');
console.log('Purchase data:', purchaseEvent);

// Monitor dataLayer pushes
const originalPush = dataLayer.push;
dataLayer.push = function() {
  console.log('DataLayer push:', arguments[0]);
  return originalPush.apply(this, arguments);
};

GTM Preview Mode

  1. Enable GTM Preview mode
  2. Browse your site
  3. Check "Data Layer" tab
  4. Verify data structure matches expectations

Resources

// SYS.FOOTER