If your Meta Ads Manager shows more purchases than your store does, you probably have a deduplication problem. It is one of the most common tracking faults we find in audits, and it quietly damages bidding, reporting and every scaling decision built on top of them.
Two ways Meta hears about a purchase
The Meta Pixel runs in the visitor's browser. When someone completes a purchase, the pixel sends a Purchase event to Meta. Browsers and privacy tools block a share of these events, so Meta may never hear about some purchases.
The Conversions API (CAPI) sends events from your server directly to Meta. It is not affected by browser blocking. It can also include extra customer data such as hashed email and phone, which helps Meta match the event to a person.
Best practice is to run both. The pixel catches what it can. CAPI catches what the pixel misses. The risk is that Meta now hears about the same purchase twice.
What deduplication does
Meta can merge two events into one when it can tell they describe the same action. It does this by comparing two fields on each event:
event_name, such as Purchaseevent_id, a unique identifier for that specific action
If the browser event and the server event share the same event_name and event_id, and arrive within 48 hours of each other, Meta keeps one and discards the other. If the event_id is missing on either side, or does not match, both are counted.
What double counting looks like
| Symptom | Likely cause |
|---|---|
| Meta purchases 20 to 100% above your store orders | No event_id on one or both events |
| Some purchases counted once, others twice | event_id only present sometimes |
| Deduplication shows 0% in Events Manager | event_id mismatch or event_name casing differs |
| ROAS looks excellent but cash does not move | Inflated purchases feeding reporting |
It also hurts optimisation. Meta's delivery learns from the events you send. If half of them are duplicates, the learning is skewed toward whichever audience looks best on inflated data.
How to fix it
Step 1: Generate one ID per action
When a purchase happens, create a unique ID once. The order number works well, for example order_10482. Use the same ID for the browser event and the server event for that purchase.
Step 2: Send the ID on both sides
In the pixel call, pass the ID as the eventID option. In the server payload, pass it as event_id. Keep the event name identical, including capitalisation: Purchase is not the same as purchase.
Step 3: Use the platform integration where it exists
Shopify, WooCommerce and BigCommerce each have native Meta integrations that handle deduplication when configured correctly. Check the settings for maximum data sharing and confirm only one integration is active. Running a native integration and a manual one together is a common cause of duplicates.
Step 4: Test in Events Manager
- Open Events Manager and use the Test Events tab.
- Place a test order and confirm you see one browser event and one server event.
- Check that each shows the same event_id.
- Look at the Diagnostics tab for deduplication warnings.
How to check the result
Do a plain reconciliation for the last 14 days. Compare Meta purchases with backend orders. Meta will rarely match exactly because of attribution windows and view-through credit, but a gap larger than 10 to 15% after fixing should trigger another look.
- Deduplication rate in Events Manager is healthy and stable
- Event Match Quality is 8 or higher for Purchase
- Meta purchases within 10 to 15% of backend orders
- Only one integration sending server events
- Refunds and cancelled orders are not sent as new purchases
Common mistakes
- Different event names. A server event named purchase will not merge with a browser event named Purchase.
- Different IDs. Generating a random ID in the browser and another on the server defeats the purpose.
- Sending server events only. Without the pixel, you lose browser context such as the click ID and cookies that help matching.
- Ignoring test traffic. Test orders can pollute your data. Filter them out.
A worked example of the double count
A store takes 400 orders in a week. The pixel catches 300 of them because browsers block the rest. CAPI sends all 400 from the server. With no shared event_id, Meta counts 700 purchases. Reported ROAS looks 75% higher than reality. With a shared event_id, Meta merges the 300 that appear in both, and counts 400. The pixel still adds browser context for the events it sees. CAPI still covers the 100 it would have missed.
Special cases worth knowing
- Lead generation. Use the lead ID or a form submission ID as the event_id, and send CRM stages such as qualified or won as offline events so Meta can optimise on lead quality.
- Subscriptions. Send the first purchase as Purchase and renewals under a separate custom event, or Meta may optimise toward renewals that were never driven by ads.
- Server-side tagging. If you use server-side GTM, make sure the browser tag passes the event_id into the data layer so the server container reuses it.
- Refunds. Do not send a refund as a negative purchase. Handle it in your reporting layer.
What to do after the fix
Expect your reported purchases and ROAS to fall. That is correct. Reset your nCAC and ROAS targets against the cleaned data and let the campaigns relearn for one to two weeks. For a wider look at the stack, including GA4 and UTMs, see our Tracking and Analytics service or ask for a free tracking audit.