Duplicate purchase events inflate revenue and reduce trust in conversion reporting. The common causes are two tracking integrations, a tag firing on both page view and data-layer event, thank-you page refreshes, or uncoordinated browser and server measurement.
Do not delete real WooCommerce orders to correct Analytics. Fix collection, annotate the affected period and keep financial reporting sourced from the store and provider.
Prove the duplication
Use one controlled order and inspect GA4 DebugView, Tag Assistant and browser Network requests. Record transaction ID, event timestamps, values and origins.
Distinguish:
two requests from one page load
one request on each page refresh
browser plus server request
two different transaction IDs for one order
reporting duplication only
Never send customer email, address or payment data as event parameters.
Inventory every measurement source
List WooCommerce analytics plugins, theme snippets, Google tag, Tag Manager containers, consent platform integrations and server-side endpoints.
Inspect page source and loaded scripts for multiple GA measurement IDs or containers. One integration may inject Google tag directly while another sends through Tag Manager.
Choose one ownership path for the purchase event. Other tools can consume a shared data layer without independently inventing the transaction.
Inspect Tag Manager triggers
A purchase tag may fire on a custom purchase data-layer event and again on a page-view trigger matching /order-received/. Preview the container and note which triggers activate each tag.
Use an explicit ecommerce event with required fields rather than URL alone. The confirmation URL can be refreshed, bookmarked or reached without a newly completed payment.
Remove or constrain the duplicate trigger, then publish a documented container version.
Check thank-you refresh behaviour
Reload the controlled order-received page. If a new purchase request appears, the implementation lacks client-side protection.
GA4 can deduplicate purchases with the same transaction_id in relevant processing, but collection should still send one intentional event. Plugins may mark an order as tracked, yet cache or multiple browsers can bypass a local flag.
Do not expose the order key in analytics or use it as the transaction identifier.
Coordinate browser and server events
Server-side tracking can improve reliability when the customer does not return from a gateway. If browser tracking remains active, both paths need a shared transaction ID and explicit deduplication design.
Record the event origin in safe debug logs, not as personal data. Decide which path is authoritative under each consent state.
Do not use a random event ID on every retry; that defeats deduplication.
Review consent transitions
A consent update can cause queued tags to fire after the purchase event already sent, or both the consent platform and Tag Manager may initialise measurement.
Test Accept, Reject and undecided states in new profiles. Optional analytics must remain off after rejection, and a later grant should not replay historical purchases without an approved design.
Keep checkout functionality independent of the analytics callback.
Deploy the smallest correction
Disable one duplicate source or trigger rather than rewriting the entire ecommerce data layer. Preserve product-view and add-to-cart tracking if they are correctly owned.
Publish version notes containing the controlled transaction ID and observed before/after request count. Clear relevant generated assets and verify the public container version.
Avoid testing repeatedly against the main revenue reports without identifying test transactions.
Verify order and measurement integrity
Test a normal purchase, thank-you refresh, gateway return revisit and any server retry. Each real order should produce one logical purchase with stable transaction ID, currency and value.
Check refunds separately; they are not negative duplicate purchases. Recurring care should compare unique GA4 transaction IDs with WooCommerce paid orders and alert when event count exceeds order count unexpectedly.