Data Layer Approach for Ecommerce
The most maintainable approach to ecommerce tracking is to have your development team push events to the GTM data layer, and then forward these to GA4 via GTM tags. This separates the data generation (developer's responsibility) from the analytics configuration (analyst's responsibility).
The Items Array: Shared Across All Events
Every ecommerce event uses the same items array structure. Each product object:
{
"item_id": "SKU-001", // Required — your product ID
"item_name": "Blue Running Shoe", // Required — product name
"affiliation": "Google Store",
"coupon": "SUMMER10",
"discount": 9.90, // Discount amount applied to this item
"index": 0, // Position in list (0-based)
"item_brand": "Nike",
"item_category": "Footwear",
"item_category2": "Running",
"item_category3": "Women",
"item_list_id": "category_running",
"item_list_name": "Running Shoes",
"item_variant": "Blue/Size 8",
"location_id": "ChIJIQBpAG2ahYAR_6128GcTUEo",
"price": 89.00, // Unit price AFTER discount
"quantity": 1
}
view_item_list
dataLayer.push({ ecommerce: null }); // Clear previous ecommerce data
dataLayer.push({
event: "view_item_list",
ecommerce: {
item_list_id: "category_running",
item_list_name: "Running Shoes",
items: [
{ item_id: "SKU-001", item_name: "Blue Running Shoe", price: 89.00, index: 0 },
{ item_id: "SKU-002", item_name: "Red Running Shoe", price: 79.00, index: 1 }
]
}
});
select_item
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "select_item",
ecommerce: {
item_list_id: "category_running",
item_list_name: "Running Shoes",
items: [{ item_id: "SKU-001", item_name: "Blue Running Shoe", price: 89.00, index: 0 }]
}
});
view_item
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "view_item",
ecommerce: {
currency: "GBP",
value: 89.00,
items: [{ item_id: "SKU-001", item_name: "Blue Running Shoe", price: 89.00, quantity: 1 }]
}
});
add_to_cart / remove_from_cart
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "add_to_cart",
ecommerce: {
currency: "GBP",
value: 89.00,
items: [{ item_id: "SKU-001", item_name: "Blue Running Shoe", price: 89.00, quantity: 1 }]
}
});
begin_checkout
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "begin_checkout",
ecommerce: {
currency: "GBP",
value: 89.00,
coupon: "SUMMER10",
items: [{ item_id: "SKU-001", item_name: "Blue Running Shoe", price: 89.00, quantity: 1 }]
}
});
purchase (Most Critical)
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "purchase",
ecommerce: {
transaction_id: "T-12345", // Required — unique order ID
value: 89.00, // Required — revenue (excl. tax/shipping or incl. — be consistent)
tax: 14.83,
shipping: 4.99,
currency: "GBP", // Required
coupon: "SUMMER10",
items: [{
item_id: "SKU-001",
item_name: "Blue Running Shoe",
price: 89.00,
quantity: 1,
coupon: "SUMMER10",
discount: 9.90
}]
}
});
Critical Notes
- Always push
{ ecommerce: null }before every ecommerce event to clear the previous data layer state transaction_idmust be unique per order — use your order ID from the databasevaluemust be consistent — either always include tax and shipping or always exclude them- Currency must be ISO 4217 three-letter code (GBP, USD, EUR)
- Prices should be decimal numbers, not formatted strings ("89.00" not "£89.00")
Summary
The data layer specification above covers all standard GA4 ecommerce events. Implement with your development team using this spec as the reference. The most common errors are missing the ecommerce: null clear, using formatted price strings instead of numbers, and missing the transaction_id on purchase events.
See our Enhanced Ecommerce Tracking service for implementation.
Need the data layer implemented correctly? Contact Adslytics.
Need expert tracking setup?
Our Google Tag Manager experts have delivered 500+ tracking setups with a 98% success rate.
Get a Free Consultation →