Transaction ID deduplication
Ecommerce purchases are deduplicated on transaction_id. If a confirmation page reloads or a user refreshes, the same purchase event can fire twice; GA4 collapses repeated transaction_ids so revenue is not double-counted. The flip side: a missing transaction_id, or one reused across different orders, breaks dedup and corrupts revenue. This page explains the mechanism and its failure modes.
How dedup works
GA4's recommended purchase event carries a transaction_id. When two purchase events share the same transaction_id, GA4 treats them as the same transaction and does not double-count revenue or items for that id within the dataset. This protects against the most common cause of inflated ecommerce numbers: confirmation-page reloads and back-button revisits.
When dedup fails
Dedup only works if the id is present and unique per order. Two failure modes dominate. First, a missing or empty transaction_id means GA4 cannot match duplicates, so every refresh adds revenue. Second, a reused id — e.g. a hard-coded test value, or an id scoped per-day rather than per-order — makes genuinely different orders collapse into one, undercounting.
Server-side purchase tracking reduces refresh duplication because the event fires from the backend on order completion rather than on a reloadable page.
- transaction_id must be present on every purchase event
- It must be globally unique per order, never reused
- Missing id → refreshes inflate revenue
- Reused id → distinct orders merge and undercount
How it appears in analytics and logs
Duplicate purchase rows that still sum to one order mean dedup worked on transaction_id; inflated revenue from refreshes means the id was absent or not stable per order.
Diagnostic use case
Explain why a refreshed order-confirmation page did not double your revenue (dedup worked), or why revenue looks inflated (transaction_id missing or non-unique).
What WebmasterID can help detect
WebmasterID records purchase/conversion events first-party with your order reference, so you can verify each order id appears once and spot duplicates before they inflate revenue.
Common mistakes
- Sending purchase events without a transaction_id.
- Hard-coding or reusing a transaction_id across orders.
- Relying on a reloadable confirmation page as the only purchase trigger.
Privacy and accuracy notes
transaction_id should be an order reference, never an email or customer identifier. Keep personal data out of the parameter. This page is educational, not legal advice.
Related pages
- Duplicate transactions in ecommerce data
Duplicate transactions occur when one purchase is counted more than once — usually because the order-confirmation page is reloaded, bookmarked, or shared, or because a retry resends the same event. GA4 deduplicates ecommerce purchases on `transaction_id`, so an absent or unstable ID is the root cause. This page covers detection and the deduplication key.
- Server-side deduplication
Server-side tagging and the Measurement Protocol let the server emit events alongside the browser. If a conversion fires from both the client tag and the server without coordination, it is counted twice. Deduplication on a shared event identifier prevents this, mirroring how ad platforms dedupe browser and server signals. This page explains the dual-send problem and the id-based dedup that solves it.
- Missing currency or value on events
GA4 monetary events such as `purchase` need both a `value` and a `currency` field, and currency must be a valid ISO 4217 code. If currency is missing or invalid, GA4 may not credit the revenue; if value is missing, the event records but contributes nothing to monetary metrics. This page explains the requirement and the silent failure modes.
- Event Explorer
Inspect purchase events and their transaction ids.
Sources and verification notes
- Google — [GA4] Measure ecommerce (purchase event)
- Google — [GA4] Recommended events (purchase, transaction_id)
Last reviewed 2026-06-24. Facts are checked against primary/official sources where available; uncertain specifics are marked “Data not yet verified” rather than guessed.