How to Set Up E-commerce Tracking in Google Analytics 4
If you run an online store, pageviews alone won't tell you much about the health of your business. You need to know which products people view, which ones they add to their cart, where they abandon checkout, and which ones actually convert into revenue. That's exactly what GA4's e-commerce tracking is built for, but unlike Universal Analytics, it isn't something you get for free — you have to explicitly send the right events with the right parameters.
This guide covers the full e-commerce event set, how to implement it with gtag.js and Google Tag Manager, and how to verify it's actually working.
The GA4 E-commerce Event Set
GA4 recognizes a specific list of e-commerce events, each with an expected items array and event-specific parameters:
view_item_list— a list of products was shown (category or search results page)select_item— a user clicked a product from a listview_item— a product detail page was viewedadd_to_cart— a product was added to the cartremove_from_cart— a product was removed from the cartview_cart— the cart page was viewedbegin_checkout— checkout was startedadd_shipping_info— shipping details were enteredadd_payment_info— payment details were enteredpurchase— an order was completedrefund— an order was refunded
You don't have to implement all of them on day one, but view_item, add_to_cart, and purchase are the minimum set that gives you a usable funnel.
Enabling E-commerce Data Collection
E-commerce reporting in GA4 is automatically available once you start sending e-commerce events — there's no separate toggle to flip like there was in Universal Analytics. The prerequisite is simply that your items arrays and event names match Google's schema exactly, since GA4 uses those to populate the standard e-commerce reports.
Implementing with gtag.js
Here's what a product detail page view looks like:
gtag("event", "view_item", {
currency: "USD",
value: 49.99,
items: [
{
item_id: "SKU_12345",
item_name: "Wireless Mouse",
item_category: "Electronics",
price: 49.99,
quantity: 1,
},
],
});
And an add-to-cart event, fired on the button's click handler:
function handleAddToCart(product) {
gtag("event", "add_to_cart", {
currency: "USD",
value: product.price * product.quantity,
items: [
{
item_id: product.sku,
item_name: product.name,
item_category: product.category,
price: product.price,
quantity: product.quantity,
},
],
});
}
The purchase event is the most important one, since it's what populates revenue reporting. It requires a transaction_id to prevent duplicate counting:
gtag("event", "purchase", {
transaction_id: order.id,
value: order.total,
tax: order.tax,
shipping: order.shipping,
currency: "USD",
items: order.lineItems.map((item) => ({
item_id: item.sku,
item_name: item.name,
price: item.price,
quantity: item.quantity,
})),
});
Fire this once, on the order confirmation page, after the order has actually been created server-side — never on the checkout form submit, or you'll record purchases that fail.
Implementing with Google Tag Manager
If you're using GTM instead of hardcoded gtag calls, push e-commerce data to the dataLayer before your GA4 event tag fires:
window.dataLayer = window.dataLayer || [];
dataLayer.push({ ecommerce: null }); // clear the previous ecommerce object
dataLayer.push({
event: "add_to_cart",
ecommerce: {
currency: "USD",
value: 49.99,
items: [
{
item_id: "SKU_12345",
item_name: "Wireless Mouse",
item_category: "Electronics",
price: 49.99,
quantity: 1,
},
],
},
});
Then in GTM:
- Create a Custom Event trigger that fires on the event name
add_to_cart. - Create a GA4 Event tag, set the event name to
add_to_cart, and configure it to send the e-commerce data. - Under Event Parameters, add
itemswith the value{{DLV - ecommerce.items}}(a Data Layer Variable pointing atecommerce.items). - Repeat for each e-commerce event you plan to track.
Clearing the ecommerce object before each push (dataLayer.push({ ecommerce: null })) matters — without it, GTM can merge stale data from a previous event into the new one.
Verifying Your Implementation
Before trusting the data, verify it two ways:
- GTM Preview mode — confirm the right
dataLayerevents fire in the right order, with the expecteditemsarray attached. - GA4 DebugView — go to Admin → DebugView in your GA4 property. With debug mode enabled (either via the GA4 DebugView Chrome extension or a
debug_mode: trueparameter), you can watch events arrive in real time and inspect every parameter GA4 actually received.
Once verified, check the Monetization reports under Reports in GA4 — specifically Ecommerce purchases — to confirm revenue and item data is populating correctly.
Handling Refunds
Refunds are easy to overlook until finance asks why GA4's revenue doesn't match your order management system. Fire a refund event when an order is fully or partially refunded:
gtag("event", "refund", {
transaction_id: order.id,
currency: "USD",
value: refundAmount,
items: refundedItems.map((item) => ({
item_id: item.sku,
item_name: item.name,
price: item.price,
quantity: item.quantity,
})),
});
For a partial refund, only include the specific items and quantities being refunded, along with the partial value — not the full original order total. This keeps GA4's net revenue figure accurate rather than zeroing out an order that was only partly returned.
Server-Side Purchase Tracking
Client-side purchase events break whenever a customer closes the tab right after paying, before the confirmation page fully loads — which, for a high-value event like a purchase, is exactly the kind of data loss you can't afford. A more reliable pattern is to fire the purchase event server-side via the Measurement Protocol, triggered by your payment webhook rather than a page load:
curl -X POST "https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXX&api_secret=YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"client_id": "'"$CLIENT_ID"'",
"events": [{
"name": "purchase",
"params": {
"transaction_id": "'"$ORDER_ID"'",
"value": '"$ORDER_TOTAL"',
"currency": "USD",
"items": [{"item_id": "SKU_12345", "item_name": "Wireless Mouse", "price": 49.99, "quantity": 1}]
}
}]
}'
You'll need the client_id GA4 assigned the browser session (read it from the _ga cookie, or capture it client-side and pass it to your backend at checkout) so the server-side event is correctly attributed to the same user who started the session.
Common Mistakes to Avoid
- Missing
transaction_idon thepurchaseevent, which causes GA4 to treat every reload of the confirmation page as a new order. - Sending price as a string instead of a number — GA4 expects numeric values for
price,value, andquantity. - Firing
purchaseon page load without checking whether the order was already recorded, leading to duplicate revenue on refresh. - Inconsistent
item_idvalues betweenview_itemandpurchasefor the same product, which breaks funnel and product-performance reports.
FAQ about How to Set Up E-commerce Tracking in Google Analytics 4

Do I need a separate e-commerce toggle in GA4 settings?
No. Unlike Universal Analytics, GA4 doesn't have a manual e-commerce on/off switch — reports populate automatically once you send correctly formatted e-commerce events.
What happens if I only implement the purchase event?
You'll get revenue reporting, but you'll miss the rest of the funnel — product views, add-to-carts, and checkout starts — which is what lets you diagnose where customers drop off before buying.
Can I track e-commerce on a site without a custom checkout, like Shopify?
Yes — most e-commerce platforms (Shopify, WooCommerce, BigCommerce) have official or well-supported GA4 integrations that handle this event set for you, though it's worth verifying the events in DebugView regardless.
Why don't my purchases show up in the Monetization report?
The most common causes are a missing or malformed items array, a missing transaction_id, or the event firing before the GA4 configuration tag has loaded.
How do I avoid double-counting purchases on page refresh?
Store a flag (in sessionStorage or a URL parameter) once the purchase event fires for a given transaction_id, and check it before firing again.
Can I track e-commerce events in a mobile app?
Yes, using the same event names and parameters through the Firebase SDK for GA4, which shares the same underlying event schema as the web implementation.
Conclusion
E-commerce tracking is where Google Analytics stops being a traffic dashboard and starts being a revenue tool. Implement the core event set, verify every event in DebugView before trusting the numbers, and keep your item_id values consistent across the funnel. Once it's wired up correctly, GA4's Monetization reports become one of the most useful dashboards on your entire website.


