GA4 ecommerce tracking tells you exactly how customers interact with your products—what they view, what they add to cart, where they abandon, and what they purchase. Setting it up correctly is critical for understanding your funnel and optimizing for revenue.
This guide walks through the complete GA4 ecommerce implementation, from initial data layer setup to verified purchase tracking.
GA4 Ecommerce Events: The Full Funnel
GA4’s recommended ecommerce events follow the customer journey:
| Event | Description | When to Fire |
|---|---|---|
view_item_list | User views a product list | Category page, search results |
select_item | User clicks a product | Click on product in list |
view_item | User views product details | Product detail page load |
add_to_cart | User adds to cart | Add to cart button click |
remove_from_cart | User removes from cart | Remove from cart action |
view_cart | User views cart | Cart page load |
begin_checkout | User starts checkout | Checkout page load |
add_shipping_info | User enters shipping | Shipping step complete |
add_payment_info | User enters payment | Payment step complete |
purchase | Transaction complete | Order confirmation page |
You don’t need all events—at minimum, implement view_item, add_to_cart, and purchase.
Step 1: Set Up the Data Layer
The data layer is a JavaScript array that holds your ecommerce data. GA4 reads from this layer to track events.
Add this code before your GTM container (or GA4 tag):
<script>
window.dataLayer = window.dataLayer || [];
</script>
Then push ecommerce data when events occur:
dataLayer.push({ ecommerce: null }); // Clear previous ecommerce data
dataLayer.push({
event: 'view_item',
ecommerce: {
currency: 'USD',
value: 29.99,
items: [{
item_id: 'SKU123',
item_name: 'Blue Widget',
item_brand: 'WidgetCo',
item_category: 'Widgets',
item_variant: 'Blue',
price: 29.99,
quantity: 1
}]
}
});
Important: Always clear the ecommerce object with { ecommerce: null } before pushing new ecommerce data. This prevents data from previous events bleeding into new events.
Step 2: Product Data Structure
Every ecommerce event uses the same items array structure:
items: [{
item_id: 'SKU123', // Required: Your product ID/SKU
item_name: 'Blue Widget', // Required: Product name
affiliation: 'Online Store', // Optional: Store or channel
coupon: 'SUMMER20', // Optional: Applied coupon
discount: 5.00, // Optional: Discount amount
index: 0, // Optional: Position in list
item_brand: 'WidgetCo', // Optional: Brand name
item_category: 'Widgets', // Optional: Category
item_category2: 'Home', // Optional: Sub-category
item_category3: 'Decor', // Optional: Sub-sub-category
item_list_id: 'featured', // Optional: List identifier
item_list_name: 'Featured Products', // Optional: List name
item_variant: 'Blue', // Optional: Variant (color, size)
location_id: 'US-NYC', // Optional: Store location
price: 29.99, // Required: Unit price
quantity: 1 // Required: Quantity
}]
Required vs Optional Parameters
Always include:
item_idoritem_name(at least one)pricequantity
Highly recommended:
item_branditem_category- Both
item_idANDitem_name
For purchase events, also include:
currencyat the event levelvalue(total) at the event leveltransaction_idfor the purchase
Step 3: Implementing Key Events
View Item (Product Detail Page)
Fire when a user views a product detail page:
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item',
ecommerce: {
currency: 'USD',
value: 29.99,
items: [{
item_id: 'SKU123',
item_name: 'Blue Widget',
item_brand: 'WidgetCo',
item_category: 'Widgets',
price: 29.99,
quantity: 1
}]
}
});
Add to Cart
Fire when a user clicks “Add to Cart”:
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: 'USD',
value: 29.99, // Value of items added
items: [{
item_id: 'SKU123',
item_name: 'Blue Widget',
item_brand: 'WidgetCo',
item_category: 'Widgets',
price: 29.99,
quantity: 1 // Quantity added this action
}]
}
});
Begin Checkout
Fire when checkout process starts:
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'begin_checkout',
ecommerce: {
currency: 'USD',
value: 59.98, // Cart total
coupon: 'SUMMER20', // If coupon applied
items: [
{
item_id: 'SKU123',
item_name: 'Blue Widget',
price: 29.99,
quantity: 1
},
{
item_id: 'SKU456',
item_name: 'Red Widget',
price: 29.99,
quantity: 1
}
]
}
});
Purchase (Most Important)
Fire on the order confirmation page:
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'ORD-12345', // Required: Unique order ID
value: 59.98, // Required: Total revenue
tax: 4.80, // Optional: Tax amount
shipping: 5.99, // Optional: Shipping cost
currency: 'USD', // Required: Currency code
coupon: 'SUMMER20', // Optional: Order coupon
items: [
{
item_id: 'SKU123',
item_name: 'Blue Widget',
item_brand: 'WidgetCo',
item_category: 'Widgets',
price: 29.99,
quantity: 1
},
{
item_id: 'SKU456',
item_name: 'Red Widget',
item_brand: 'WidgetCo',
item_category: 'Widgets',
price: 29.99,
quantity: 1
}
]
}
});
Critical: transaction_id must be unique per order. GA4 uses this for deduplication. Reusing IDs causes data loss.
Step 4: GTM Configuration
With data layer events firing, configure GTM to send them to GA4.
Create Ecommerce Variables
- In GTM, go to Variables → New
- Create a Data Layer Variable
- Name: “DLV - Ecommerce Items”
- Data Layer Variable Name:
ecommerce.items
Repeat for:
ecommerce.currencyecommerce.valueecommerce.transaction_id
Create Triggers
For each ecommerce event, create a Custom Event trigger:
- Triggers → New → Custom Event
- Event name:
view_item(exact match) - Save
Repeat for add_to_cart, begin_checkout, purchase, etc.
Create GA4 Event Tags
For each ecommerce event:
- Tags → New → GA4 Event
- Configuration Tag: Your GA4 Config tag
- Event Name: Same as trigger (e.g.,
view_item) - Event Parameters:
currency: {{DLV - Ecommerce Currency}}value: {{DLV - Ecommerce Value}}items: {{DLV - Ecommerce Items}}
For purchase, add:
transaction_id: {{DLV - Ecommerce Transaction ID}}
- Trigger: Your corresponding trigger
Enable Ecommerce in Tags
In the GA4 event tag:
- Scroll to “Ecommerce”
- Check “Send Ecommerce data”
- Data source: “Data Layer”
This automatically captures the ecommerce.items array.
Step 5: Verify Implementation
Use GTM Preview Mode
- Click Preview in GTM
- Navigate through your purchase flow
- Check each event fires with correct data:
- Click on the event in Tag Assistant
- Verify items array contains product data
- Verify currency and value are correct
Use GA4 DebugView
- GA4 → Admin → DebugView
- Add
?gtm_debug=1to your URL - Walk through the purchase flow
- Each event should appear with parameters
Check:
- Event names are exact (
purchasenotPurchase) - Items array is populated
- Values are numbers, not strings
Check GA4 Reports
After 24-48 hours:
- GA4 → Reports → Monetization → Ecommerce purchases
- You should see revenue and transaction data
- Check product performance data populates
Common Implementation Mistakes
Mistake 1: String Values Instead of Numbers
// Wrong
price: '29.99',
quantity: '1',
value: '59.98'
// Right
price: 29.99,
quantity: 1,
value: 59.98
GA4 expects numbers for price, quantity, and value.
Mistake 2: Missing ecommerce: null Clear
// Wrong - previous data may persist
dataLayer.push({
event: 'purchase',
ecommerce: { ... }
});
// Right
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'purchase',
ecommerce: { ... }
});
Mistake 3: Duplicate Transaction IDs
If your confirmation page reloads or user refreshes, you’ll send duplicate purchases unless you have logic to prevent it:
// Simple approach: check sessionStorage
if (!sessionStorage.getItem('order_' + orderId)) {
dataLayer.push({ ecommerce: null });
dataLayer.push({ event: 'purchase', ecommerce: { ... } });
sessionStorage.setItem('order_' + orderId, 'true');
}
Mistake 4: Items Not in Array
// Wrong - items must be an array
items: {
item_id: 'SKU123',
item_name: 'Widget'
}
// Right - even for single items
items: [{
item_id: 'SKU123',
item_name: 'Widget'
}]
Mistake 5: Wrong Event Names
GA4 is case-sensitive. Use exact names:
// Wrong
event: 'Purchase'
event: 'add-to-cart'
event: 'AddToCart'
// Right
event: 'purchase'
event: 'add_to_cart'
Platform-Specific Notes
Shopify
Shopify requires additional setup because their checkout is hosted:
- Use Shopify’s native GA4 integration for checkout events
- Add custom data layer code for product pages and add to cart
- Consider server-side tracking for reliable purchase data
WooCommerce
Many GA4 plugins are available:
- Google Site Kit (official, basic)
- GA4 for WooCommerce (more features)
- GTM4WP (most flexible)
If using a plugin, verify it implements the standard data layer format.
Custom Platforms
For custom builds:
- Implement data layer pushes in your application code
- Fire events from server-side if necessary (for purchase reliability)
- Consider GA4 Measurement Protocol for server-side events
Validating Your Ecommerce Data
After implementation, validate in GA4:
Check Monetization Reports
- GA4 → Reports → Monetization
- Verify:
- Revenue matches actual orders
- Transaction count is accurate
- Average order value is reasonable
Check Item Performance
- GA4 → Reports → Monetization → Ecommerce purchases → View item details
- Verify:
- Product names display correctly
- Item revenue adds up
- Quantity data is present
Check Funnel Visualization
- GA4 → Explore → New exploration
- Choose Funnel exploration
- Add steps: view_item → add_to_cart → begin_checkout → purchase
- Verify funnel shows reasonable conversion rates
Need Help With Implementation?
GA4 ecommerce tracking has many moving parts. Issues with data layer implementation, GTM configuration, or event parameters can cause:
- Missing revenue data
- Incorrect product attribution
- Broken funnel analysis
- Bad data feeding your ads
If your ecommerce tracking isn’t showing complete data, or you’re not sure if your implementation is correct, we can help.
Get a free scan and we’ll audit your GA4 ecommerce implementation to identify exactly what’s missing or misconfigured.