Duplicate Purchase Events: Causes and How Deduplication Works

You check Events Manager and it shows 140 purchases. Your store shows 100 orders. The first reaction is often to celebrate the higher number, or to blame the ad platform. Both are wrong. Most of the time the same order was reported more than once, and the platform is optimising on a picture that is not real.
This article lists the usual causes, shows how to find yours, and explains how deduplication is meant to work.
Why duplicates matter
A duplicated purchase does two kinds of damage. It inflates reported revenue, which makes campaigns look better than they are. And it trains the ad platform on events that did not happen as counted. Bad input leads to bad optimisation, however good the budget.
The common causes
Pixel installed twice
Once by the theme or app, once by Tag Manager or custom code.
Thank-you page reloads
The customer refreshes, or comes back from a link, and the purchase fires again.
Browser and server without a shared ID
Both paths report the purchase and nothing tells the platform they are the same.
Several tools sending the same event
A plugin and a custom integration both send server events.
One order, several pages
The purchase fires on more than one step of the checkout.
Test orders
Internal or test purchases are counted with real ones.
How deduplication is supposed to work
When two reports describe the same action, the platform needs a shared key to merge them.
- Meta uses the event name together with the event ID. If the browser event and the server event have the same name and the same ID, Meta keeps one.
- GA4 uses the transaction ID on the purchase event. Two purchases with the same transaction ID are meant to be treated as one.
- TikTok follows a similar idea with an event ID shared between the browser and server events.
The rule is simple to state and easy to break: the same real-world action must always carry the same ID, whichever path reports it.
Browser purchase, order 1042
ID: 1042
Result: Matched
Server purchase, order 1042
ID: 1042
Result: Counted once
Browser purchase, order 1042
ID: a81f (random)
Result: Counted separately
Server purchase, order 1042
ID: c3b2 (random)
Result: Counted again
With a stable ID such as the order number, both reports collapse into one. With random IDs on each path, one order becomes two.
Find your cause in four steps
- Compare counts. For a short period, compare purchases in the ad platform and in GA4 against orders in your store. A large gap in one direction is the first clue.
- Look at what fires. Use the platform's test tool and a browser inspector on a real test order. Count how many purchase events fire, and from where.
- Check for duplicates in the setup. List every place a pixel or tag can be installed: the theme, store apps, Tag Manager, custom code. If the same event can come from two of them, that is your cause.
- Check IDs. Open the browser event and the server event and compare their IDs. They must be identical for the same order.
Fix it once
- Keep one source for each event on the browser. Remove the extra installs.
- Send purchase only when the order is confirmed, and guard against a second send on reload, for example by marking the order as already reported.
- Use a stable ID, usually the order number, as the event ID and as the GA4 transaction ID.
- Exclude test orders from the real data, or mark them so they never reach production events.
- Retest with a real order after every change.
What to expect afterwards
After the fix, the platform's purchase count will usually drop. That can feel like things got worse. They did not. You now have a number you can compare to your store, and a break-even calculation that rests on real orders. If the count still does not match, remember that attribution windows and different definitions can legitimately create gaps. The article Why Your Store Sales Don't Match Meta and Google Ads covers those.
For the server path itself, read Meta Conversions API Explained: What It Adds to the Pixel. If you would rather have the whole chain tested for you, the tracking setup service includes deduplication and testing, and the audit shows where duplicates come from in an account you already run.