Shopify Meta pixel and CAPI deduplication problem: browser and server Purchase events use different event_id values
Short answer
Build the event ID from the order ID plus the event name on both sides, keep one integration per path, and verify the single deduplicated event in Test Events.
If the browser and server Purchase events carry different event IDs, Meta cannot tell they are the same sale and counts both. The fix is to make both sides use the same ID for the same order, and the simplest stable choice is one derived from the order itself.
Meta deduplicates events when the event name and event ID match. Without a match, it treats them as separate events, so one order shows as two purchases and your reported revenue is inflated. You will see it in Events Manager as events from both browser and server that are not marked as deduplicated.
Why do the IDs differ? Because each side generates its own. The browser pixel may create a random ID at the moment of purchase. The server integration may create another from the order number plus a timestamp. Two apps can each do this independently and never agree.
The reliable rule is to build the ID from the order ID and the event name, for example 'purchase' plus the order number. The browser can read the order number on the thank-you page or from the Shopify checkout event data, and the server has it in the order. Both then produce the same string without talking to each other.
Next, check that only one integration is sending each side. Two apps both firing a Purchase from the browser, or two integrations both sending from the server, give you duplicates that no event ID can fix because there are three copies, not two. List every app and custom pixel that touches Meta and keep one for each path.
Then check the timing. Meta's deduplication window is limited, so a server event sent days later is not a safe duplicate of a browser event sent at purchase. Send the server copy promptly.
To verify, use Test Events. Place a real test order and look at the Purchase rows. You want one event shown as received from both browser and server, marked as deduplicated. If you see two separate rows, the IDs still differ.
Also compare with Shopify. After the fix, Meta's purchases for a day should be close to Shopify's orders for that day, allowing for visitors who decline consent and sales Meta cannot attribute. If Meta shows more than Shopify, you still have duplicates.
DataCops gives the pixel and server copy the same event ID and counts the same order ID once, so a retry or a second integration does not become a second sale, and its log shows when a duplicate was skipped. It cannot remove a second app's events, so retire any app that is sending the same Purchase.
Which apps and pixels on your store touch Meta today?
DataCops in short
For this question: DataCops gives the pixel and server copy the same event ID and counts the same order ID once, and logs when a duplicate was skipped.
DataCops is a tool that counts every paid order once on every ad platform: the DataCops Shopify app reads the paid order from Shopify's own order webhook and a Web Pixel reports the shopping steps, with a bot verdict on every visit and a log of every send.
How DataCops does it
- The paid order from the server. It comes from Shopify's order webhook, so Shop Pay, Apple Pay and closed tabs still count.
- Counted once. The pixel and the server share an event ID, and the same order ID twice counts once.
- Every ad platform. Meta, Google Ads, TikTok and LinkedIn are live, with more connectable.
- Real people only. A bot verdict on every visit, with a switch per platform, off by default.
- A log you can read. Each send as sent, held, skipped or failed, with the reason.
Best for: Shopify and other online stores that want paid orders counted once on every ad platform, and CRM or phone sales counted too.
Ads Warmup: tell the ads who pays
Ads Warmup, DataCops' flagship feature, sends customers you already have to Meta, Google Ads and TikTok before a new campaign spends: upload a CSV (only email is required, up to 20,000 rows), see a 0 to 10 match score per person, pick the event, and send. Rows are dated when you send, and Google Ads credits only people who clicked a Google ad. Preview is free; sending needs a paid plan. Check your own consent basis for the list first. See Ads Warmup.
Ways to do this job
| Option | Best for |
|---|---|
| DataCops | Paid orders to every ad platform, with a bot verdict and a log |
| Shopify's Facebook and Instagram app | One Meta pixel and server events on Shopify, Meta only |
| A store tracking app (such as Elevar) | A managed data layer for a Shopify store |
| Hosted server GTM (such as Stape) | A team that already owns a GTM container |
When not to use DataCops
- Your only ad platform is Meta and your store is small. Shopify's own Facebook and Instagram app at Maximum data sharing may be enough.
- You need custom tag logic. DataCops sends to ad platforms and is not a Google Tag Manager container.
Sources and further reading
More on this: Shopify CAPI, and the complete guide to offline conversion tracking.
Open Settings, Customer events in Shopify and list every pixel. Duplicates often hide there.