Product Data Layer Errors | Blue Frog Docs

Product Data Layer Errors

Diagnosing and fixing product data layer issues that affect e-commerce tracking accuracy.

Product Data Layer Errors

What This Means

Product data layer errors occur when e-commerce product information is missing, malformed, or inconsistent in your data layer. This causes inaccurate tracking, broken remarketing, and unreliable analytics.

Common Issues:

  • Missing required fields (item_id, item_name, price)
  • Incorrect data types (price as string instead of number)
  • Currency format mismatches
  • Empty or null product arrays
  • Duplicate events

Impact Assessment

Business Impact

  • Revenue Tracking: Incorrect purchase values in analytics
  • Remarketing: Dynamic ads show wrong products
  • Attribution: Conversion attribution fails
  • Reporting: Inaccurate product performance data

Technical Impact

  • GA4 Rejections: Events rejected for invalid format
  • Meta Pixel: Product catalog sync failures
  • Google Ads: Conversion value errors

How to Diagnose

Browser Console Check

// Check for e-commerce events
dataLayer.filter(event => event.ecommerce).forEach((e, i) => {
  console.log(`E-commerce Event ${i}:`, e);

  // Validate required fields
  const items = e.ecommerce?.items || [];
  items.forEach((item, j) => {
    const issues = [];
    if (!item.item_id) issues.push('Missing item_id');
    if (!item.item_name) issues.push('Missing item_name');
    if (typeof item.price !== 'number') issues.push('Price not a number');
    if (issues.length) console.warn(`Item ${j} issues:`, issues);
  });
});

GA4 DebugView

  1. Enable GA4 DebugView
  2. Trigger e-commerce events
  3. Look for red warning icons
  4. Check parameter validation errors

GTM Preview Mode

  1. Open GTM Preview
  2. Navigate through product pages
  3. Check Variables tab for product data
  4. Verify event tags fire correctly

General Fixes

1. Implement Correct Data Structure

GA4 Format:

dataLayer.push({
  event: 'view_item',
  ecommerce: {
    currency: 'USD',
    value: 29.99,
    items: [{
      item_id: 'SKU_12345',           // Required: string
      item_name: 'Product Name',       // Required: string
      affiliation: 'Store Name',       // Optional
      coupon: 'SUMMER_SALE',          // Optional
      discount: 5.00,                  // Optional: number
      index: 0,                        // Optional: position
      item_brand: 'Brand Name',        // Recommended
      item_category: 'Category',       // Recommended
      item_category2: 'Subcategory',   // Optional
      item_list_id: 'related_products',// Optional
      item_list_name: 'Related Products', // Optional
      item_variant: 'Blue / Large',    // Optional
      location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', // Optional
      price: 29.99,                    // Required: number
      quantity: 1                      // Required for cart events
    }]
  }
});

2. Fix Common Data Type Issues

// WRONG: Price as string
{ price: '29.99' }

// CORRECT: Price as number
{ price: 29.99 }

// WRONG: Quantity as string
{ quantity: '1' }

// CORRECT: Quantity as number
{ quantity: 1 }

// WRONG: Missing currency
{ value: 29.99 }

// CORRECT: With currency
{ currency: 'USD', value: 29.99 }

3. Handle Product Variants

// Include variant information
dataLayer.push({
  event: 'add_to_cart',
  ecommerce: {
    currency: 'USD',
    value: 34.99,
    items: [{
      item_id: 'SKU_12345_BLUE_L',     // Unique variant SKU
      item_name: 'T-Shirt',
      item_variant: 'Blue / Large',    // Human-readable variant
      price: 34.99,
      quantity: 1
    }]
  }
});

4. Clear Previous E-commerce Data

// Clear before pushing new e-commerce event
dataLayer.push({ ecommerce: null });

// Then push new event
dataLayer.push({
  event: 'view_item',
  ecommerce: {
    // ... new data
  }
});

5. Validate Before Pushing

function pushEcommerceEvent(event, data) {
  // Validate required fields
  const items = data.ecommerce?.items || [];

  const validItems = items.filter(item => {
    if (!item.item_id || !item.item_name) {
      console.error('Missing required fields:', item);
      return false;
    }
    if (typeof item.price !== 'number') {
      console.error('Invalid price type:', item);
      return false;
    }
    return true;
  });

  if (validItems.length !== items.length) {
    console.warn('Some items filtered due to validation errors');
  }

  data.ecommerce.items = validItems;
  dataLayer.push({ ecommerce: null });
  dataLayer.push(data);
}

Platform-Specific Fixes

Shopify

<script>
dataLayer.push({
  event: 'view_item',
  ecommerce: {
    currency: '{{ shop.currency }}',
    value: {{ product.price | money_without_currency | remove: ',' }},
    items: [{
      item_id: '{{ product.selected_or_first_available_variant.sku | default: product.id }}',
      item_name: '{{ product.title | escape }}',
      item_brand: '{{ product.vendor | escape }}',
      item_category: '{{ product.type | escape }}',
      price: {{ product.price | money_without_currency | remove: ',' }},
      quantity: 1
    }]
  }
});
</script>

WooCommerce

// In functions.php or custom plugin
add_action('wp_footer', function() {
    if (is_product()) {
        global $product;
        ?>
        <script>
        dataLayer.push({
            event: 'view_item',
            ecommerce: {
                currency: '<?php echo get_woocommerce_currency(); ?>',
                value: <?php echo $product->get_price(); ?>,
                items: [{
                    item_id: '<?php echo $product->get_sku() ?: $product->get_id(); ?>',
                    item_name: '<?php echo esc_js($product->get_name()); ?>',
                    price: <?php echo $product->get_price(); ?>,
                    quantity: 1
                }]
            }
        });
        </script>
        <?php
    }
});

Testing Your Implementation

Automated Validation

// Add to page for development testing
(function validateEcommerce() {
  const requiredFields = ['item_id', 'item_name', 'price'];
  const recommendedFields = ['item_brand', 'item_category'];

  window.addEventListener('load', () => {
    const observer = new MutationObserver(() => {
      const ecomEvents = dataLayer.filter(e => e.ecommerce?.items);
      ecomEvents.forEach(validateEvent);
    });

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

  function validateEvent(event) {
    const items = event.ecommerce.items;
    items.forEach((item, i) => {
      const missing = requiredFields.filter(f => !item[f]);
      const recommended = recommendedFields.filter(f => !item[f]);

      if (missing.length) {
        console.error(`Item ${i} missing required:`, missing);
      }
      if (recommended.length) {
        console.warn(`Item ${i} missing recommended:`, recommended);
      }
    });
  }
})();

Further Reading

// SYS.FOOTER