hello@newnorth.nl+31 (0) 85 401 31 62
/Journal

The GA4 ecommerce items array: required against optional fields

GuideE-commerce2026.05.25
Freek Kampen
Freek KampenCo-founder, New North Digital

One parameter quietly decides whether your ecommerce reports work. What you have to send, what is worth sending, and the formatting mistakes we see most.

Where the items array sits

Every GA4 ecommerce event, from view_item through add_to_cart and begin_checkout to purchase and refund, carries an items array in its parameters. It is 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 }
    ]
  }
});

Get it right and you get item-level revenue, product performance and conversion-path detail. Get it slightly wrong and the items disappear from your reports while the transaction still records, which is why it goes unnoticed.

Required fields

Officially GA4 requires one of item_id, your SKU or product identifier, or item_name, the human-readable name.

In practice send both. GA4 uses item_id as the key for joining and aggregation, while item_name is what appears in reports. Only item_id gives you reports full of unreadable SKUs; only item_name breaks the joins.

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

Fields worth sending anyway

Not required, but every serious setup sends them. Skipping them limits your reports for no gain.

  • price, the unit price as a number, not a string. GA4 calculates item_revenue as price times quantity.
  • quantity, how many of this item was bought. Defaults to 1 when missing, which is wrong for any cart with multi-item lines.
  • currency, the ISO 4217 code. Set it at event level, not per item, unless you genuinely transact in several currencies.

On tax: Google's spec says value and price should exclude tax and shipping. Almost every real implementation sends amounts including tax, because CMS data layers rarely expose clean per-item ex-tax values. Consistency across events matters more than matching the spec.

Optional fields that earn their place

The next tier is what enables segmentation and product reporting. Send what matches your actual reporting, not everything.

  • item_brand for multi-brand catalogues, so you can slice by brand
  • item_category through item_category5, taxonomy levels matching your CMS structure
  • item_variant for size, colour or SKU variant, kept consistent with how the CMS stores them
  • item_list_id and item_list_name, which collection page, search result or recommendation widget the item came from
  • affiliation to identify which storefront an order came from
  • coupon and discount, the code applied and the amount per unit as a number
  • location_id, the physical store for omnichannel setups

The mistakes we see most

Price and quantity as strings. GA4 accepts "19.95" but will not aggregate it correctly. Send unquoted numbers.

Currency per item. Allowed, but it complicates everything downstream for no reason. Set it once on the event.

Mismatched item_id between events. The same product needs the same id throughout its journey. If view_item sends 12345 and purchase sends SKU-12345, GA4 treats them as two products and your conversion-rate reports break.

No items array on purchase. Common on Shopify themes that fire a custom purchase push without it. The transaction and revenue record, the items table stays blank.

Items as an object instead of an array. A templating bug. It has to be a JSON array, not an object with numeric keys. The two look almost identical in the data layer preview and GA4 ignores the second.

How to verify

The fastest check is DebugView on a real test order:

  1. Enable debug mode, easiest with the GA Debugger extension.
  2. Open GA4 DebugView in another tab.
  3. Place a test order.
  4. Click into the purchase event and inspect its parameters.
  5. Confirm items holds a list of objects, each with item_id, item_name, price and quantity.

Missing or empty items means your push does not include it. Present but with a field missing on every object means a templating gap.

The takeaway

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

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

Optional: pick from item_brand, item_category, item_variant and item_list_* based on what you actually report on. Fields you never use are noise.

The single biggest mistake remains a missing items array on purchase. Thirty seconds in DebugView catches it.

Want to talk about this?

Let's talk data.

Tell us about your stack, your goals, the data you wish you had.

Takes 1 minute