Revenue that doesn't match the backend: mistakes in the GA4 purchase event
value as text, no currency and an empty transaction_id: three mistakes in the purchase event that make GA4 lose or duplicate revenue.
- This is the purchase event the site pushes to the dataLayer when an order is confirmed.
- Three fields are wrong: an empty transaction_id, value as text with a decimal comma and no currency.
- The result: revenue GA4 cannot add up, and purchases that can't be deduplicated or matched to the backend.
- The fix: a unique identifier, a numeric value and the currency in ISO 4217 format.
- Before every push, clear the ecommerce object and validate the schema. Then compare with the backend.
It is normal for GA4 revenue not to match the order system to the cent: some users decline measurement, ad blockers exist and some orders are cancelled later. But that gap is usually stable and moderate. When it is large, erratic or changes after a release, the most frequent cause is the purchase event itself.
What happens when GA4 revenue doesn’t match the backend
The site sends a purchase for every confirmed order, but GA4 can’t make good use of its data. The typical symptoms:
- Revenue lower than expected, or purchases that show up with zero revenue.
- Duplicate purchases when the user reloads the confirmation page.
- No way to match GA4 orders with the backend.
Why the purchase event loses or duplicates revenue
The event arrives with a wrong schema. The three most common faults:
valueas text."49,90"is a string with a decimal comma. GA4 expects a number with a decimal point (49.90); a string with a comma isn’t read as the right amount.- No
currency. Without an ISO 4217 currency code (EUR,USD…), GA4 can’t calculate revenue metrics fromvalue. - Empty or repeated
transaction_id. The order ID lets GA4 deduplicate purchases and lets you match them with the backend. If it is empty, every reload of the confirmation page can be logged as a new purchase.
There is a fourth, dataLayer-specific problem: if the ecommerce object isn’t cleared between events, products from a previous event can mix with the next one.
How to audit the purchase event in DebugView
- In DebugView, place a test order and open the
purchaseevent. Check the type and format ofvalue, thatcurrencyis there and the value oftransaction_id. - In the browser console, type
dataLayeron the confirmation page and inspect the object being sent. - In an exploration, build a table with Transaction ID, purchases and revenue. Empty IDs,
(not set)or IDs with more than one purchase reveal the problem.
How to fix value, currency and transaction_id
dataLayer.push({ ecommerce: null }); // clear the previous object
dataLayer.push({
event: "purchase",
ecommerce: {
transaction_id: "T-10482", // unique per order
value: 49.90, // a number, with a decimal point
currency: "EUR", // ISO 4217
items: [ /* … */ ],
},
});
- Build
valuefrom the order’s numeric amount, not from the formatted text shown on screen. - Always send
currency, even if the shop sells in a single currency. - Use the same order ID as the backend, so both systems can be matched.
Google’s documentation: Measure ecommerce.
How to check GA4 revenue against the backend
- Repeat the test order and check the three fields in DebugView.
- Reload the confirmation page: no second purchase with the same
transaction_idshould appear in the reports. - For a few days, compare GA4 orders and revenue with the backend by date. The gap should settle at a small, explainable percentage.