Deduplicating Pixel and Server-Side Purchase Events
How to stop Google and Meta from double-counting the same Shopify order when you run both browser pixels and server-side APIs.
Written by Mantas Jurgutis — Founder, Adsify — builds the Google & Meta automation merchants use daily
Editorially reviewed by Adsify Editorial on May 16, 2026 — Reviewed against Shopify, Google Ads and Meta official documentation.
Why deduplication is necessary at all
Running both a browser-based Web Pixel and a server-side integration like Meta's Conversions API or Google's Enhanced Conversions is the recommended setup for reliability, but it creates a real risk: the same Shopify order can generate two separate purchase events, one from the browser and one from the server, unless the platform is explicitly told they represent the same transaction. Without deduplication, reported revenue and conversion counts can be inflated by roughly double for every order where both events successfully arrive.
How Meta's deduplication works
Meta deduplicates Purchase events using an event_id parameter that must be identical on both the browser pixel event and the server-side Conversions API event for the same order, combined with a matching event_name and the events arriving within Meta's deduplication window. Meta's documentation recommends deriving the event_id from a stable, unique value like the Shopify order ID rather than a randomly generated one per request, since the same order might trigger the browser event and server event through separate code paths.
How Google's deduplication differs
Google Ads doesn't use a single universal deduplication key across every integration in the same way; instead, when using Enhanced Conversions alongside standard gtag or Global Site Tag conversion tracking, the same conversion action and transaction ID are used to prevent double counting, with Google's systems matching on the order/transaction identifier passed with the conversion. Getting the transaction ID consistent between your browser conversion tag and Enhanced Conversions upload is what prevents duplication here.
A worked example of the risk
Assume a store processes 500 orders in a month. Its Meta app fires a browser Purchase event for 420 of them (80 were blocked by ad blockers or ITP) and a server-side Conversions API event for all 500 using Shopify webhook data. If event_ids don't match between the two paths, Meta's Events Manager would show up to 920 Purchase events for 500 real orders, inflating both conversion volume and, if event values are included, reported revenue by up to 84% in the worst case where none of the 420 browser events deduplicate.
Where the order ID should come from
For Shopify stores, the natural deduplication key is the Shopify order ID (or the checkout token, which is also stable per completed checkout) available in the checkout_completed event payload delivered to the Web Pixel and in the order webhook payload used for server-side delivery. Using this same identifier to construct the event_id on both the browser and server events, typically formatted as a string like order_<id> or the raw numeric order ID, is what lets Meta's matching succeed.
Checking your current setup
In Meta Events Manager, open the Purchase event details for a recent real order and check whether it shows as a single deduplicated event with both a Browser and Server source tag, or as two separate un-merged entries. If you see two entries for one order, inspect the event_id values sent by each path; a mismatch (or a missing event_id on one side entirely) is almost always the cause.
What happens with three or more sources
Stores running a legacy manually-pasted pixel, an app-installed pixel, and a separate server-side integration simultaneously can end up with three sources for one order. Deduplication only works pairwise when event_ids match across all sources sending the same event_name; if the legacy script generates no event_id at all (common in old pixel code predating deduplication support), it cannot be deduplicated against the others regardless of configuration, and the old script needs to be removed rather than reconciled.
Value and currency consistency
Beyond just counting, mismatched event values between the browser and server event for the same order, for example if one path includes a discount and the other doesn't, or one uses store currency and the other uses presentment currency, can cause inconsistent reported revenue depending on which duplicate the ad platform's deduplication logic happens to retain as the canonical event. Both paths should source the order total and currency from the same underlying order object.
Testing methodology
Place a single test order, then check, within an hour, both Meta Events Manager's Test Events tool and Google Ads' conversion diagnostics for that transaction. Confirm exactly one Purchase/conversion is attributed per platform per order, with the correct value. Repeat after any change to either the browser pixel or the server-side integration, since a code change on one side can silently break the matching key without any visible error.
Why app-based setups tend to get this right
Because deduplication requires the browser and server event to originate from code that shares the same order identifier logic, app vendors that control both the Web Pixel and the server-side API integration, as Adsify does by installing its own pixel while also sending Meta Conversions API and Google Enhanced Conversions events from the same Shopify order data, are structurally better positioned to keep event_ids in sync than a merchant stitching together separate tools that don't know about each other.
A checklist to prevent double counting
Confirm every active tracking source is visible in Settings > Customer events (rules out orphaned legacy scripts). Confirm any server-side integration uses the Shopify order ID or checkout token as its deduplication key. Confirm the browser pixel event for checkout_completed uses the identical key format. Test with a real order and verify a single deduplicated event appears per platform before trusting reported ROAS for budget decisions.
