---
title: Advanced GA4 Ecommerce Tracking | RGM®
url: https://realgrowthmatters.com/learn/ga4/ecommerce-tracking/
updated: 2026-06-10
source_html: https://realgrowthmatters.com/learn/ga4/ecommerce-tracking/
---

# Advanced GA4 Ecommerce Tracking

GA4 ecommerce tracking from first event to refund handling. The standard schema, item-array parameters, currency requirements, multi-step funnels, and the subscription-renewal patterns most setups miss.

By **David Schaefer** · [LinkedIn](https://www.linkedin.com/in/daschaefer/) · Updated May 2026

## The GA4 ecommerce schema in one place

GA4 ecommerce expects a specific event taxonomy and a specific item-array structure. Setups that match the schema get reporting for free. Setups that don't get partial reporting, missing revenue, and item-level data that never surfaces in standard reports. Follow the schema. Customize on top of it, not against it.

## The seven core events

GA4 ecommerce events

| Event | When it fires | Required params |
| --- | --- | --- |
| view\_item\_list | Category, collection, or search results page loads | item\_list\_id, item\_list\_name, items[] |
| select\_item | User clicks an item from a list | item\_list\_id, items[] |
| view\_item | Product detail page loads | currency, value, items[] |
| add\_to\_cart | User adds item to cart | currency, value, items[] |
| begin\_checkout | User initiates checkout | currency, value, items[] |
| add\_shipping\_info / add\_payment\_info | User fills shipping or payment | currency, value, items[], shipping\_tier or payment\_type |
| purchase | Order completes | transaction\_id, currency, value, items[], optionally tax, shipping |

Plus `refund` for refunded orders (pass the same transaction\_id with negative value or the refunded subset of items).

## The items array

Every ecommerce event accepts an items array. Each item is an object with these keys (use as many as apply):

- **item\_id** — your SKU or variant ID. Stable identifier.
- **item\_name** — display name of the product.
- **item\_brand** — brand if multi-brand store.
- **item\_category, item\_category2, item\_category3, item\_category4, item\_category5** — hierarchical categories.
- **item\_variant** — size, color, configuration.
- **price** — unit price.
- **quantity** — number of units.
- **discount** — per-item discount.
- **coupon** — coupon code applied to the item.
- **affiliation** — store or sub-brand for multi-source orders.
- **item\_list\_id, item\_list\_name** — for tracking which list the item came from.
- **index** — position in the list.
- **location\_id** — physical store ID for omnichannel.

## Currency: the parameter most setups skip

GA4 requires `currency` on every ecommerce event in ISO 4217 format (USD, EUR, GBP, JPY). Without it, GA4 logs the event but does not include revenue in reports. For multi-currency stores, pass the order's actual currency; GA4 handles conversion to your property's reporting currency automatically.

## Implementation through GTM

1. **Push to dataLayer on every ecommerce event.** Use the standard schema. `window.dataLayer.push({ event: 'view_item', ecommerce: { currency: 'USD', value: 49.99, items: [{ item_id: 'SKU-123', ... }] } });`
2. **Set up a GTM dataLayer variable** for the ecommerce object.
3. **Create a GA4 Event tag** for each event type. Event name matches the dataLayer event. Parameters reference the dataLayer variable.
4. **Trigger on Custom Event matching the event name.**
5. **Test in GTM Preview and GA4 DebugView.** Confirm the event arrives in GA4 with all parameters and the items array intact.

## Refund handling

Two approaches.

- **Full refund:** fire `refund` with the same transaction\_id and value as the original purchase. Optionally include items[] for clarity.
- **Partial refund:** fire `refund` with the subset of items being refunded, plus the partial value.

Refunds fire from the server when the refund is processed in your subscription processor, payment processor, or CRM. Send via Measurement Protocol (server-side) since they do not happen in a browser.

## Subscription renewal handling

Renewals happen server-side and never fire a client event. The pattern:

1. Subscription processor (Recharge, Bold, Skio, Loop, Stripe Billing) fires a webhook on successful renewal.
2. Your server forwards the renewal to GA4 via Measurement Protocol with event\_name "purchase," the renewal transaction\_id, the renewal value, items, and the original customer's client\_id (passed through from the initial signup).
3. GA4 attributes the renewal correctly.

## Common ecommerce tracking failure modes

Currency missing

Most common cause of "GA4 shows the event but no revenue." Add currency to every ecommerce event in the dataLayer.

Items array as an object, not an array

GA4 requires items to be an array, even for single-item events. Single item: items: [{...}], not items: {...}. The latter silently fails.

item\_id and item\_name inconsistent across events

If view\_item reports item\_id "SKU-123" but add\_to\_cart reports item\_id "PROD-123" for the same SKU, GA4 cannot join the funnel. Use the same item\_id everywhere.

transaction\_id not unique

GA4 deduplicates purchases by transaction\_id. If the same order ID fires twice, GA4 counts it once but logs an error. Use unique order IDs.

Subscription renewals not tracked

The most-missed pattern. Without webhook-driven server-side firing, GA4 reports look like every customer made one purchase and never bought again. LTV reporting becomes useless.

## What to read next

Sister pages: [GA4 best practices](/learn/ga4/best-practices/), [GA4 enhanced conversions](/learn/ga4/enhanced-conversions/), [GA4 BigQuery export](/learn/ga4/bigquery-export/). For implementation infrastructure, read [advanced GTM setup](/learn/gtm/advanced-setup/). For Shopify-specific patterns, read [Shopify GA4 + GTM tracking](/learn/shopify/ga4-gtm-tracking/).

### In this section

- [GA4](/learn/ga4/)
- [All learn topics](/learn/)
- [Concepts](/learn/concepts/)
- [Measurement](/learn/measurement/)

### Foundational reading

- [What is growth marketing?](/learn/concepts/what-is-growth-marketing/)
- [What is performance marketing?](/learn/concepts/what-is-performance-marketing/)
- [Server-side vs client-side](/learn/measurement/server-side-vs-client-side-tracking/)
- [Vickrey auction](/learn/concepts/vickrey-auction-google-ads/)

### Hubs

- [Services](/services/)
- [Platforms](/platforms/)
- [Areas served](/areas-served/)
- [Performance marketing](/services/performance-marketing/)
