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.
Recommended helperโ
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] } });