Skip to main content

Reset pattern (mandatory)

The ruleโ€‹

Before every ecommerce event, push { ecommerce: null } to clear state.

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ ecommerce: null }); // โ† reset
window.dataLayer.push({
event: 'view_item',
ecommerce: { /* ... */ }
});

Whyโ€‹

GTM does a recursive merge of dataLayer data. If you push add_to_cart with one item, then view_item with a different item, GTM sees both items in view_item unless you reset.

This corrupts:

  • Revenue attribution per event.
  • Google Ads conversions (potential double-counting).
  • Meta Catalog matching.
function pushEcommerce(eventName, ecommerce, userData) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({
event: eventName,
ecommerce,
...(userData && { user_data: userData })
});
}

// Usage
pushEcommerce('add_to_cart', {
currency: 'EUR',
value: 84.00,
items: [{ item_id: 'BIO-CRM-001', item_name: 'Day Cream', price: 42.00, quantity: 2 }]
});

Anti-patternโ€‹

// โŒ BAD: no reset, previous items leak
window.dataLayer.push({ event: 'view_item', ecommerce: { items: [a] } });
window.dataLayer.push({ event: 'add_to_cart', ecommerce: { items: [b] } });
// GTM sees items = [a, b] in add_to_cart ๐Ÿ”ฅ
// โœ… GOOD
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({ event: 'view_item', ecommerce: { items: [a] } });
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({ event: 'add_to_cart', ecommerce: { items: [b] } });