Skip to content
🚀 Find us on Product Hunt
GTM Preview Data Layer tab showing the purchase ecommerce object expanded

By Humayun Kabir Naim — 7 November 2026

Quick answer

A missing, (not set) or $0-revenue GA4 purchase is almost always one break in the same chain: the dataLayer push never happens, it fires at the wrong moment, the ecommerce object is malformed, or the report is misleading you. Prove the push exists first, then audit the object field by field — the 10 fixes below follow that order.

A broken GA4 purchase event shows up in one of three ways: the purchase never reaches GA4 at all, it arrives but the items say (not set), or it arrives with items and still reports $0 revenue. They look like three problems, but they are almost always one workflow with a break at a different point: the push never happens, happens at the wrong moment, carries a dirty or malformed ecommerce object, or is fine and the report is lying to you. Work through the checks in that order — prove the push exists, prove the tag reads it, audit the object field by field, and only at the end question the reports.

If every event is missing, start with our guide to tags that fire in Preview but not in GA4. This post assumes your other events arrive and the purchase specifically is wrong.

Quick diagnostic: which of the three symptoms do you have?

What you see Most likely cause Go to
No purchase anywhere, not even DebugView Push never happens, wrong event name, bad timing Checks 1, 2, 3
Purchase missing only for some orders or visitors Offsite gateway return, or consent denied at checkout Checks 1, 4
Purchase arrives, items show (not set) Tag not sending ecommerce data, stale object, broken items Checks 5, 6, 7
Items look right, revenue is $0 value sent as a formatted string Check 8
DebugView shows a value, reports show no revenue currency or transaction_id missing Check 9
DebugView is perfect, the report is wrong $0 test order, processing delay, thresholds Check 10

Before the checks: what a healthy purchase push looks like

Every check below is a comparison against this push. If yours differs, the difference is usually the bug:

dataLayer.push({ ecommerce: null }); // clear the previous object first
dataLayer.push({
  event: "purchase",
  ecommerce: {
    transaction_id: "1042",
    value: 129.99,
    tax: 10.00,
    shipping: 5.00,
    currency: "USD",
    items: [{
      item_id: "SKU-123",
      item_name: "Trail Running Shoes",
      item_category: "Footwear",
      price: 119.99,
      quantity: 1
    }]
  }
});

Note the details people skip: a clearing push first, value and price as numbers with no symbol or quotes, a currency code, a transaction_id, and items with an ID and a name. The full setup is in our WooCommerce GA4 tracking guide.

GTM Preview Data Layer tab showing the purchase ecommerce object expanded

Check 1: The purchase push never happens on the thank-you page

Symptom: view_item, add_to_cart, and begin_checkout all appear in DebugView, but purchase never does — for any order.

Verify: In GTM Preview, complete a test order and watch the left-hand timeline on the confirmation page. If no purchase entry appears, nothing pushed it, and no tag or trigger can fix that. The usual reason is the payment flow: offsite gateways (PayPal and similar) return customers to a confirmation page where the plugin’s push is missing, fires on a different URL than you are watching, or never runs.

Fix: Make the push happen on the confirmation page, after payment is confirmed, built from the actual order data. In WooCommerce, GTM4WP’s enhanced ecommerce does this for standard flows; offsite gateways often need their return/confirmation hook wired to fire the push. Never push purchase on the Place Order click — clicks happen before payment succeeds, and failed payments will inflate revenue.

GTM Preview timeline on a thank-you page with no purchase event

Check 2: The event is not named exactly purchase

Symptom: DebugView shows an event after checkout, but the Monetization reports stay empty and no revenue attaches to it.

Verify: In Preview’s timeline, read the event name character by character. GA4 reserves its ecommerce behaviour — Monetization reports, revenue, item reporting — for the exact name purchase, all lowercase. Names like Purchase or purchaseComplete arrive as ordinary custom events GA4 does not treat as a sale.

Fix: Correct the name at the source so the dataLayer event is exactly purchase (and refund for refunds). If the push comes from a plugin you cannot change yet, a GTM trigger on the wrong name feeding a GA4 tag with the name overridden to purchase works as a bridge — but every other platform still sees the wrong name, so fix the push itself soon.

Check 3: The push fires before GTM and the Google tag are ready

Symptom: Purchase tracking is intermittent — works in some tests, vanishes in others, or arrives with empty values.

Verify: In Preview, look at the timeline order. If purchase sits above the Initialization and Container Loaded entries, or the GA4 tag shows under Tags Not Fired for that event, the push raced ahead of the setup meant to read it. Common with hand-coded pushes placed high in the page, and confirmation pages that render the push before the order values exist.

Fix: Fire the Google tag on Initialization – All Pages, and push purchase only when the order data exists — when the confirmation renders, not in a script that runs before it. Move custom pushes after the data they need and after the GTM snippet.

GTM Preview timeline showing a purchase push before the Google tag initialization

Check 4: Consent Mode is blocking the purchase hit

Symptom: Your own tests track perfectly — you accepted the banner long ago — but a slice of real orders never appears in GA4, worst from European traffic.

Verify: In Preview, open the Consent tab and complete a checkout without accepting the banner, or after rejecting it. If analytics_storage is “Denied” at the moment of the purchase push, the hit is blocked or reduced to a limited ping that will not show as a normal purchase in DebugView.

Fix: Wire your consent platform so the state is set before checkout completes and updates on choice; test both paths. Our Consent Mode Checker shows what your banner actually sends. Do not force consent to granted to make purchases appear — that fixes a report by breaking the consent the visitor gave.

Consent tab in GTM Preview showing analytics_storage denied during checkout

Check 5: The GA4 tag is not sending the ecommerce object

Symptom: The purchase reaches DebugView as an empty shell — no items, no value, no currency — even though the dataLayer contains all of them.

Verify: In Preview, click the purchase event and compare two panels. The Data Layer tab shows the full ecommerce object. Now open the fired GA4 tag: under More Settings → Ecommerce, if “Send Ecommerce Data” is unticked, or the source is Custom with nothing mapped, the tag fires the event name and drops the object. This one setting explains a large share of both (not set) items and $0 revenue.

Fix: Tick Send Ecommerce Data and set Data Source: Data Layer, as in Step 2 of our WooCommerce GA4 guide. Do not compensate by hand-mapping value and items as event parameters — that patches one tag and leaves the dataLayer broken for everything else.

GA4 event tag in GTM with Send Ecommerce Data ticked and Data Layer as the source

Check 6: The ecommerce object was never cleared

Symptom: The purchase arrives with items the customer did not buy — products viewed or added then removed — or with quantities merged from several steps.

Verify: In Preview’s timeline, examine the pushes around the purchase. A healthy flow shows a push setting ecommerce to null immediately before the purchase push. Without it, GTM merges dataLayer objects across events on the same page, so a stale items array from an earlier add_to_cart survives into the purchase.

Fix: Add dataLayer.push({ ecommerce: null }); immediately before the purchase push — and before every ecommerce event push, not just purchase. GTM4WP does this automatically; hand-written pushes are where it gets skipped.

GTM Preview showing the ecommerce null clearing push immediately before the purchase push

Check 7: The items array is empty, or missing item_id and item_name

Symptom: The purchase arrives with a correct value, but the item name shows (not set), and item-level reports are empty.

Verify: In Preview’s Data Layer tab for the purchase event, expand items and read what is actually there. Common findings: an empty array, items carrying only price and quantity, or items in the old Universal Analytics shape — nested under a products array — which a GA4 tag cannot read as items at all. GA4 labels items (not set) when the event arrived without usable item data; it describes what it received, it is not a separate bug.

Fix: Push items in GA4 format, each with at least item_id or item_name (send both), plus price and quantity as numbers. If your plugin sends the Universal Analytics format, switch its output to GA4 format — GTM4WP has this setting.

GA4 ecommerce report showing (not set) as the item name

Check 8: value and price are formatted strings, not numbers

Symptom: The event and the items look right everywhere, but revenue totals $0 in every GA4 report.

Verify: In the Data Layer tab, look at the quotes. value: "$129.99" is text formatted for a human — currency symbol, quotation marks. GA4 sums numbers; a formatted string is not summed. The purchase counts, the money does not:

// Broken — formatted for humans, invisible to GA4's totals
ecommerce: {
  value: "$129.99",
  items: [{ item_id: "SKU-123", item_name: "Trail Running Shoes", price: "$119.99", quantity: 1 }]
}

// Fixed — raw numbers, same order
ecommerce: {
  value: 129.99,
  items: [{ item_id: "SKU-123", item_name: "Trail Running Shoes", price: 119.99, quantity: 1 }]
}

Fix: Send raw numbers at the source and let GA4 handle display formatting via the currency field. In WooCommerce this usually means a custom push used a formatted price helper instead of the raw amount. Change the helper, not the report.

Data Layer tab showing value sent as a formatted string instead of a number

Check 9: currency or transaction_id is missing from the push

Symptom: DebugView shows the purchase with a value, yet Monetization revenue is missing — or the same order counts twice after a thank-you page refresh.

Verify: In the Data Layer tab, audit the object field by field against the healthy push at the top. Without currency, GA4 cannot place the value into the property’s reporting currency, and the revenue is dropped from the money reports. Without transaction_id, GA4 cannot recognise a repeat hit for the same order as a duplicate — and neither can Meta, whose Pixel/CAPI deduplication keys on exactly this value, as our WooCommerce Meta guide explains.

Fix: Send both fields on every purchase push: currency as the ISO code (for example "USD") and transaction_id as the store’s unique order ID. Judge duplication by unique transaction IDs in GA4, not raw event counts in Preview.

Check 10: The false alarm — a $0 test order, or a report that has not caught up

Symptom: DebugView shows a textbook purchase, the Monetization report shows $0 or nothing, and you are about to rebuild the whole setup.

Verify: Ask two questions before touching anything. First, what was the test order actually worth? A 100% coupon or a test gateway makes value: 0.00 the correct data — GA4 is reporting your test faithfully. Second, where are you looking? DebugView is near real time, the ground truth for collection. Standard reports can take 24 to 48 hours to process, and thresholds can hide low-volume rows.

Fix: Test with a real amount, or a partial coupon that leaves a nonzero value, confirm the purchase in DebugView, and check the standard report the next day. If you would rather not wire this by hand, our free GTM container builder generates this setup with tag, trigger, and ecommerce setting connected.

GA4 DebugView showing the purchase event with value, currency, and transaction ID parameters
Chrome DevTools Network tab showing a g/collect request for the purchase event

Summary checklist

# Check Pass means
1 Push happens A purchase entry appears in Preview’s timeline
2 Event name The dataLayer event is exactly purchase
3 Timing Push lands after Initialization, values present
4 Consent analytics_storage at checkout matches the visitor’s choice
5 Tag setting Send Ecommerce Data is on, Data Source is Data Layer
6 Clearing ecommerce: null is pushed immediately before the purchase push
7 Items Every item carries item_id and item_name, in GA4 format
8 Value format value and price are raw numbers, no symbols or quotes
9 Required fields currency and transaction_id are on every purchase
10 Evidence You judged the setup in DebugView, with a nonzero test order

Frequently asked questions

Why is my purchase event not showing in GA4 at all?

Start in GTM Preview, not GA4. If no purchase entry appears in the timeline on the confirmation page, the push never happens — most often an offsite gateway return or a plugin setting. If it appears under a different name, GA4 treats it as a custom event, not a sale. Consent denial at checkout is the third common cause.

What does (not set) mean next to items in GA4?

It means the purchase arrived without usable item data when it fired: an empty items array, items missing item_id and item_name, items in the old Universal Analytics format, or a tag not sending ecommerce data from the data layer. Read the actual array in Preview’s Data Layer tab.

Why does GA4 show $0 revenue for orders that really had value?

Usually the push sent value as a formatted string such as “$129.99” instead of the number 129.99, and GA4 does not sum text. The other honest cause: a test order paid with a 100% coupon genuinely has a value of 0. Inspect the raw push before changing anything.

The purchase is in DebugView but not in the Monetization report — is it broken?

Almost certainly not. DebugView proves GA4 collected the event. Standard reports take 24 to 48 hours, thresholds can hide low-volume rows, and a missing currency can keep value out of the money reports. Check again tomorrow; audit currency meanwhile.

Does a missing transaction_id really matter if the event fires?

Yes. Without it, GA4 cannot deduplicate the same order when the thank-you page is refreshed, so one order can count as several purchases. It is also the value Meta uses as the event_id to deduplicate Pixel and Conversions API copies of the same purchase.

My purchase fires twice. Is that covered here?

That is the mirror problem: two senders — a plugin, a theme snippet, or a hardcoded tag — or the same push repeating on refresh. Look for two senders first, and judge it by unique transaction IDs. Our WooCommerce GA4 guide covers the duplicate cases in its troubleshooting.

Share with