Event Deduplication on Shopify: How event_id Prevents Double-Counting

Event Deduplication on Shopify: How event_id Prevents Double-Counting

TL;DR

Event deduplication stops the same conversion from being counted twice when more than one integration reports it. The shared event_id is the key: platforms collapse events that carry the same identifier. WeltPixel Conversion Tracking fires purchases server-side only and reuses Shopify's native event.id, so its purchase deduplicates against any other Meta or TikTok integration the store runs. Non-purchase events fire both browser and server with a shared id and deduplicate against each other.


Key Takeaways

  • Meta's Conversions API deduplicates on event_id plus event_name. If two integrations send a purchase with different values, Meta counts both as separate purchase events [1].
  • TikTok's Events API deduplicates on event_id within a 48-hour window. Mismatched IDs inflate reported conversions [2].
  • WCT fires its purchase event server-side only for Meta, TikTok, GA4, and Google Ads, so it never double-counts its own purchase. The shared event_id exists to dedup the WCT server purchase against other integrations the store runs that report the same Shopify event.id.
  • GA4 deduplicates purchase events on transaction_id. WCT sends purchase server-side only, so no browser event competes with the CAPI event [3].
  • Shopify's Web Pixels API assigns a unique event.id to every checkout_completed event. That value is the natural deduplication anchor for purchase events [4].
  • If the metafield bridge fails during a network outage, WCT falls back to a deterministic ID pattern so the CAPI payload still carries a consistent identifier.

What event_id Actually Is

A unique string. That is the whole definition.

When a customer completes checkout, two different sources can fire a purchase event for the same order. That might be a browser pixel and a server-side Conversion API call, or two separate integrations that both report the purchase. The ad platform receives two signals claiming the same conversion. Without a way to match them, it counts both.

The event_id field is the match key. Both events include it, carrying the identical string. The platform sees the duplicate, merges the two events into one, and keeps a single conversion while still benefiting from the combined data for match quality.

Each platform names the field slightly differently:

Platform Field name Where it lives
Meta event_id Browser pixel parameter + CAPI payload [1]
TikTok event_id Browser pixel parameter + Events API payload [2]
GA4 transaction_id purchase event parameter [3]
Google Ads order_id Conversion tag + enhanced conversions payload

The value format does not matter as long as it is consistent between the two events and unique per conversion. Order ID strings work. Shopify's native event.id UUIDs work. What does not work is generating the browser value at pixel-fire time and the server value independently, because they will never match.


How Each Platform Handles Deduplication

Meta matches on event_id plus event_name. Both must match for deduplication to occur [1]. If your browser pixel fires a Purchase event with event_id: abc123 and your CAPI payload fires a Purchase event with event_id: xyz789, Meta counts two purchases. Meta Events Manager will flag this under "Potential duplicate events" when it detects high overlap without matching IDs.

TikTok deduplicates within a 48-hour window using event_id [2]. Events arriving outside that window are not deduplicated regardless of the ID. TikTok Events Manager Diagnostics has an explicit deduplication status indicator that shows whether matched events are being collapsed correctly.

GA4 deduplicates purchase events on transaction_id transparently [3]. You do not get a visual "deduplicated" indicator in the GA4 UI the way you do in Meta Events Manager. The deduplication happens silently. If two purchase events arrive for the same transaction_id within a session window, GA4 keeps one. This matters if you are running both gtag.js and a Measurement Protocol payload for the same purchase.

Google Ads deduplicates on order_id in the enhanced conversions flow. Same logic: browser conversion tag plus server-side conversion upload both carry the order ID, and Google matches them.


How WCT Implements Deduplication

The architecture has three stages: capture, bridge, attach.

Stage 1: Capture. Shopify's Web Pixels API fires a checkout_completed event when a customer completes payment [4]. This event carries a native event.id property, a UUID Shopify generates for that specific checkout completion. WCT's web pixel reads this value at the moment it fires.

Stage 2: Bridge. The web pixel cannot directly communicate with your server-side webhook. It runs in a sandboxed browser context. WCT routes the captured event.id through an event-bridge proxy that writes it to an order metafield before the orders/create webhook fires on the server.

Stage 3: Attach. When the orders/create webhook fires, WCT reads that metafield and uses the captured event.id as the event_id on its purchase payload. Here is the part that surprises people: for the purchase event, WCT does not fire a browser-side Purchase at all. Across Meta, TikTok, GA4, and Google Ads, the purchase fires server-side only, from the orders/create webhook. There is no WCT browser Purchase racing the WCT server Purchase, so WCT never double-counts its own purchase.

So why carry the shared event.id onto the server payload at all? Because most stores run more than one integration. Shopify's native Facebook & Instagram channel, or a base pixel hardcoded into the theme, can emit its own purchase tagged with the same Shopify event.id. By stamping its server-side purchase with that same identifier, WCT lets Meta and TikTok recognize the WCT purchase and the other integration's purchase as one event and collapse them. The dedup is not WCT-versus-itself. It is WCT-versus-whatever-else-the-store-is-running.

Non-purchase events work differently. For events like page_view and add_to_cart, WCT does fire both a browser event and a server event, and it stamps both with a shared event_id so the platform deduplicates the pair against each other. That browser-plus-server pattern is exactly the classic dedup case described above. Purchase is the deliberate exception: server-side only.

This architecture is covered in more depth in the CAPI vs pixel article if you want to understand why server-only purchase firing is the right call.


What Happens When Deduplication Fails

Two scenarios cause dedup failure.

Scenario 1: The metafield bridge does not write in time. If there is a network failure between the web pixel and the event-bridge proxy, the metafield never gets written. When the webhook fires, there is no captured Shopify event.id to read. WCT falls back to a deterministic, order-derived identifier so the CAPI payload always carries a consistent ID.

This fallback ID is consistent and unique per order, so the WCT purchase is still well-formed. The narrow risk is cross-integration: if another integration on the store reported its own purchase tagged with the original Shopify event.id, the WCT server purchase now carries a different fallback ID, and Meta or TikTok sees two purchases that no longer match. Both get counted. That only happens when (a) the metafield write fails AND (b) a second integration already emitted a purchase stamped with the Shopify UUID for that order.

Scenario 2: Two integrations both fire a purchase, but at least one carries no event_id at all. This is the "forgot to implement dedup" scenario common in manual setups. Meta and TikTok have no way to match events without the field. Every event gets counted independently.

The practical consequence: a store running dual tracking without deduplication can see a meaningful fraction of conversions double-counted, inflating reported numbers and ROAS, and pushing Smart Bidding to optimize toward volume that is not real. The campaign looks profitable. The underlying economics have not changed.

For more context on why server-side signal quality matters beyond just deduplication, the Meta EMQ guide walks through how platform scoring works when both browser and server events arrive.


Verify Deduplication Is Working on Your Own Store

This walkthrough covers Meta verification, TikTok verification, and GA4 verification separately.

Meta Events Manager

  1. Go to business.facebook.com/events_manager.
  2. Select your pixel from the data sources list.
  3. Click Overview, then scroll to the Events table.
  4. Find the Purchase row. Look at the Connection method column. It should read Browser + Server, not just Browser or just Server.
  5. Click into the Purchase event row.
  6. Look for the Deduplication section. It shows the percentage of events that were successfully deduplicated.
  7. If you see Potential duplicate events, Meta detected Purchase events with overlapping timing but non-matching event_id values. That is the signal that dedup is failing.

TikTok Events Manager

  1. Go to ads.tiktok.com and open Assets → Events.
  2. Select your pixel.
  3. Click Diagnostics.
  4. Look for the Deduplication check under the Events API section.
  5. TikTok shows a pass/fail status and a sample of recent events. If it shows events marked as potential duplicates without a matching event_id, the browser and server IDs are not aligned.

GA4

  1. Go to your GA4 property and open Reports → Realtime.
  2. Trigger a test purchase on your store (use a real or test transaction).
  3. In Realtime, look for the purchase event. If it appears twice within a short window (once from the browser, once from the server), and both have the same transaction_id, GA4 will silently collapse them. If they appear with different transaction_id values, both will be counted.
  4. For historical verification, go to Explore → Free form, set the dimension to Event name, the metric to Event count, and filter to purchase. Compare against your Shopify Orders count for the same date range. As a rule of thumb, a ratio meaningfully above 1.0 suggests duplicate events are getting through.

Shopify Admin (WCT-specific)

  1. Go to Shopify Admin → Orders.
  2. Open any recent order.
  3. Scroll to the Metafields section (you may need to click Show all or use the Metafields app to see custom fields).
  4. Look for a metafield in the WCT namespace. If the metafield is present and contains a UUID string, the event-bridge write succeeded for that order. If the metafield is absent, that order used the fallback ID pattern.

FAQ

What is event deduplication in Shopify tracking?

Event deduplication is the process of preventing a single conversion from being counted twice when both a browser pixel and a server-side Conversion API fire the same event. It works by including a shared event_id string in both payloads so the ad platform can recognize they represent one conversion [1].

What happens if I run Meta CAPI and the Meta pixel without event_id?

Meta receives two separate Purchase events for every transaction. Without a matching event_id to link them, Meta counts both [1]. Reported conversions inflate, ROAS looks artificially high, and Smart Bidding optimizes toward the wrong volume signals.

Does GA4 automatically deduplicate purchase events from Measurement Protocol?

Yes, GA4 deduplicates on transaction_id [3]. If a browser-side purchase event and a Measurement Protocol purchase event arrive with the same transaction_id, GA4 keeps one. WCT avoids this entirely by disabling the browser-side purchase event for GA4, so there is nothing to deduplicate.

How does Shopify's Web Pixels API generate the event_id?

Shopify assigns a unique UUID to each checkout_completed event through the Web Pixels API [4]. This UUID is available as event.id in the web pixel sandbox at the moment the event fires. WCT captures this value and uses it as the deduplication anchor for Meta and TikTok CAPI payloads.

Can I verify event deduplication without a paid analytics tool?

Yes. Meta Events Manager shows deduplication status for free under Assets → Data Sources → your pixel → Events [1]. TikTok Events Manager Diagnostics is also free. For GA4, the Realtime report and a simple Explore query comparing purchase event count to Shopify order count is enough to detect the problem.


WeltPixel Conversion Tracking Handles This Automatically

WCT captures Shopify's native event.id at checkout through the Web Pixels API, routes it through the event-bridge proxy to an order metafield, and fires the purchase server-side only across Meta, TikTok, GA4, and Google Ads. That means WCT never double-counts its own purchase, and the shared event.id lets Meta and TikTok collapse the WCT purchase against any other integration the store runs that reports the same identifier. For non-purchase events like add-to-cart, WCT fires both browser and server with a shared event_id so those dedup against each other too.

No configuration. No event_id field mapping. No manual wiring between your pixel and your webhook.

Install WeltPixel Conversion Tracking on the Shopify App Store


Sources

  1. Meta Developers: Deduplicate Pixel and Conversions API Events
  2. TikTok Business API: Event Deduplication
  3. Google Analytics Measurement Protocol for GA4
  4. Shopify Web Pixels API Reference

Ready to upgrade your tracking?

Server-side tracking for Magento and Shopify — accurate data, better attribution, full privacy compliance.