The GA4 ecommerce items array: required vs optional fields

8 minutes read

The GA4 ecommerce data layer has one parameter that quietly decides whether your reports work: the items array. Get it right and you get item-level revenue, product performance, and conversion-path detail. Get it wrong, even slightly, and the items disappear from your reports while the purchase event still fires. The header number looks fine. The breakdown is empty.

Here’s what you actually need to send, what’s optional, and the formatting mistakes we see most.

Where the items array sits

Every GA4 ecommerce event, view_item, add_to_cart, begin_checkout, purchase, refund, carries an items array as part of the event parameters. It’s a list of product objects, one per line item:

window.dataLayer.push({
  event: 'purchase',
  ecommerce: {
    transaction_id: 'ORD-12345',
    value: 89.95,
    currency: 'EUR',
    items: [
      { item_id: 'SKU-RED-M', item_name: 'Red T-shirt', price: 29.95, quantity: 1 },
      { item_id: 'SKU-BLU-L', item_name: 'Blue Jeans',  price: 60.00, quantity: 1 }
    ]
  }
});

Each object in the array represents one line item. Multiple items sold means multiple objects.

Required fields

Officially, GA4 requires one of:

item_id, your SKU or product identifier. ✅ item_name, the human-readable product name.

In practice you should always send both. The reason: GA4’s reports use item_id as the canonical key for joining and aggregation, but item_name is what shows up in reports and dashboards. Sending only item_id gives you reports full of unreadable SKUs. Sending only item_name means two products with the same name (different sizes, different colours) collapse into one row.

⚠️ Missing both is the failure case. If neither is present on an item object, GA4 silently drops that item from the items table, and on some events, drops the entire array. The purchase event still records, the revenue still shows, but the items breakdown is empty.

Recommended fields (send these too)

These aren’t required, but every serious ecommerce setup sends them. Skipping them limits your reports for no real benefit.

price, the unit price of one item, as a number (not a string). GA4 calculates item_revenue as price × quantity.

quantity, how many of this item the customer bought. Defaults to 1 if missing, which is wrong for any cart with multi-item line entries.

currency, the ISO 4217 currency code (EUR, USD, GBP). Set on the event level (not the item level) for purchases in a single currency. Required if your store transacts in multiple currencies.

A note on tax: Google’s spec says value and price should exclude tax and shipping. Almost every real-world implementation sends incl-tax values because CMS data layers don’t expose clean ex-tax per-item values. As long as you’re consistent across events and across the items array, this isn’t worth fighting. Compare GA4 against your CMS’s grand-total revenue (incl-tax) and you’ll get a clean match.

Optional fields worth using

The next tier of fields is what enables segmentation, product reporting, and advanced attribution. Send the ones that match your reporting needs.

item_brand, for multi-brand catalogues. Lets you slice reports by brand.

item_category, item_category2 through item_category5, taxonomy levels. Match your CMS’s category structure: item_category = "Apparel", item_category2 = "T-shirts".

item_variant, size, colour, or SKU variant. Keep this consistent with how the CMS stores variants.

item_list_id and item_list_name, which list (collection page, search results, recommendation widget) the item came from. Required for “promotion attribution” reports.

affiliation, useful for multi-brand or multi-store setups: identify which storefront the order came from.

coupon, discount code applied at item level.

discount, discount amount per unit, as a number.

location_id, physical store ID for omnichannel setups.

The mistakes we see most

Sending price and quantity as strings. GA4 will accept "19.95" as a price, but it won’t aggregate correctly in reports. Always send numbers: price: 19.95, quantity: 1. The data-layer object should have unquoted numeric values.

Wrong currency. Set this once on the event, not per item, unless you genuinely have mixed-currency carts. Setting per-item currency is allowed but it complicates downstream reporting for no reason.

Mismatched item_id between events. The same product needs the same item_id in every event in its journey. If your view_item sends item_id: "12345" but your purchase sends item_id: "SKU-12345", GA4 treats them as different products. Conversion-rate reports break, product performance gets fragmented.

Missing items array on purchase. We see this on Shopify themes that fire a custom purchase push without the items array. The transaction records, the revenue records, but the items breakdown for that order is blank. Open DevTools on the thank-you page and check that window.dataLayer contains an items array on the purchase push.

Items array structured as an object instead of an array. A common templating bug. The items field must be a JSON array (items: [{...}, {...}]), not an object with numeric keys (items: {"0": {...}, "1": {...}}). The latter looks similar in the data layer preview but GA4 ignores it.

How to verify

The fastest verification is GA4 DebugView on a real test order:

  1. Enable debug mode (the GA Debugger Chrome extension is the easiest).
  2. Open GA4 → DebugView in another tab.
  3. Place a test order on your site.
  4. Click into the purchase event in DebugView and inspect parameters.
  5. Confirm items shows a list of objects, each with item_id, item_name, price, quantity.

If items is missing or empty, your data layer push isn’t including it. If items is present but a field is missing on each object, you’ve found a templating gap.

The takeaway

Required: item_id and item_name. Always send both, even though only one is technically mandatory.

Recommended: price, quantity, currency, without these, item-level revenue reports go blank.

Optional: pick from item_brand, item_category, item_variant, item_list_* based on what segmentation you actually report on. Don’t send fields you won’t use; they just add noise.

The single biggest mistake we see is missing the items array on purchase events. The transaction records, the revenue records, the items table stays empty. A 30-second check in DebugView catches it.

If you’d like an automated check that flags items-array gaps and a few dozen other GA4 issues, you can run our free GA4 audit.

Profielfoto Freek Kampen

By Freek Kampen

Data & Analytics consultant and co-owner of New North Digital. With a background in online advertising, I solve tracking and data issues for entrepreneurs and agencies.

Looking for growth? ▸ Set your New North ▸