Skip to content
EARNST.
DE
Tracking & Compliance

Event Deduplication: Why Your Meta Conversions Count Double and How to Fix It

Meta Pixel and Conversions API send the same event twice. Without event_id matching, Meta counts duplicate purchases. Here is how correct deduplication works.

EARNST · · 10 min read

Key Takeaways

  • Without deduplication, Meta counts 30 to 80% more conversions than actually occur
  • event_id is the only reliable deduplication mechanism between Pixel and CAPI
  • Meta deduplicates within a 48-hour window: identical event_id + event_name = one event
  • Google and Meta handle deduplication differently: Google uses transaction_id, Meta uses event_id

Since 2023, Meta has recommended using the Conversions API (CAPI) in parallel with the browser Pixel. The reasoning is sound: ad blockers block the Pixel for 15 to 30% of users, Safari ITP limits cookie lifetimes, and the server-side CAPI delivers data regardless of browser restrictions. The combination of Pixel and CAPI maximizes data coverage.

But "maximizes data coverage" also means: every event is potentially sent twice. Once from the Pixel in the browser, once from the CAPI via the server. If Meta counts both events as separate conversions, your reports show 30 to 80% more purchases than actually occurred. Your ROAS looks fantastic, your budget planning is based on phantom numbers.

The solution is event deduplication. And it only works when browser and server send the same event with the same ID.

How double-counting occurs

Three scenarios that appear in almost every setup:

Scenario 1: Pixel + CAPI without event_id. A user makes a purchase. The Pixel sends a Purchase event to Meta. The GTM Server Container sends the same Purchase event via CAPI to Meta. Meta receives two events but has no way to recognize that they represent the same purchase. Result: 2 conversions instead of 1.

Scenario 2: Pixel + CAPI with different event_id. The Pixel generates a random event_id. The server generates a different random event_id. Meta receives two events with different IDs and counts them as separate conversions. Result: identical to Scenario 1.

Scenario 3: Pixel blocked, CAPI active. An ad blocker blocks the Meta Pixel. Only the CAPI sends the Purchase event. Meta receives one event. Result: correct, 1 conversion. Deduplication is not needed in this case, but the event_id does no harm.

The problem only affects Scenarios 1 and 2. And these scenarios are the norm for users without ad blockers, which is 70 to 85% of your traffic.

Meta's deduplication mechanism

Meta deduplicates events based on two fields:

  1. event_name: The name of the event (e.g. Purchase, AddToCart, ViewContent)
  2. event_id: A unique ID that identifies the specific event instance

The rule: if Meta receives two events with identical event_name and identical event_id within 48 hours, the second event is recognized as a duplicate and discarded. Only the first one counts.

Requirements for event_id

The event_id must:

  • Be unique per event instance. Every purchase needs its own ID. Two different purchases must not share the same ID.
  • Be identical between Pixel and CAPI. Browser and server must send exactly the same ID for the same purchase.
  • Be stable. No regeneration on page reload. If the user loads the thank-you page twice, the ID must remain the same.

What works as event_id

Source Example Suitable?
Shopify Order ID #1042 > purchase_1042 Yes, stable and unique
Transaction ID 5312847 Yes, identical between browser and server
Random UUID (generated per client) a3f7c2d-... Only if the exact same UUID goes to Pixel AND server
Random UUID (generated per request) b8e1f4a-... (Pixel) vs c9d2e5b-... (Server) No, different IDs = no deduplication
Timestamp 1711382400 No, Pixel and server have slightly different timestamps

The safest option: the Shopify Order ID or Transaction ID as a basis. This exists in both contexts (browser DataLayer and server request) and is by definition unique per purchase.

Implementation in Shopify

Step 1: event_id in the DataLayer

The purchase event in the DataLayer already contains the transaction_id. This is used as the basis for the event_id:

dataLayer.push({
  event: 'purchase',
  event_id: 'purchase_' + transactionId,
  ecommerce: {
    transaction_id: transactionId,
    value: orderValue,
    currency: 'EUR',
    items: [...]
  }
});

The purchase_ prefix prevents collisions in case you use the same transaction ID for other events (e.g. refund_1042).

Step 2: event_id in the Pixel

The Meta Pixel in GTM reads the event_id from the DataLayer:

fbq('track', 'Purchase', {
  value: NaN,
  currency: NaN,
  content_ids: NaN,
  content_type: 'product'
}, {
  eventID: NaN
});

The fourth parameter of fbq('track', ...) accepts an options object with eventID. Note the casing: eventID (camelCase) in the Pixel, event_id (snake_case) in CAPI.

Step 3: event_id in CAPI

The GTM Server Container sends the CAPI request. The Meta CAPI tag in the server container must use the same event_id. In the server-side configuration:

  1. The GA4 client in the server container receives the request from the browser
  2. The event_id is forwarded as an event parameter
  3. The Meta CAPI tag reads the event_id and includes it in the CAPI request
{
  "data": [{
    "event_name": "Purchase",
    "event_id": "purchase_1042",
    "event_time": 1711382400,
    "user_data": {
      "em": ["hashed_email"],
      "ph": ["hashed_phone"]
    },
    "custom_data": {
      "value": 149.90,
      "currency": "EUR"
    }
  }]
}

Step 4: Web Pixel for checkout events

In the Shopify Checkout, tracking runs via Web Pixels. The Web Pixel has no access to the storefront DataLayer, but it can access Shopify's standard events (checkout_completed). For the event_id, the Web Pixel uses the Order ID from the event payload:

analytics.subscribe('checkout_completed', (event) => {
  const orderId = event.data.checkout.order.id;
  const eventId = 'purchase_' + orderId;

  // Pixel event with event_id
  // CAPI receives the same event_id via the server
});

All events that need deduplication

Deduplication does not only apply to Purchase. Every event sent by both Pixel and CAPI needs an event_id.

Event event_id source Example
Purchase Transaction ID / Order ID purchase_1042
AddToCart Product ID + timestamp bucket (minute precision) atc_7829384_202603251430
InitiateCheckout Checkout Token ic_abc123def456
ViewContent Product ID + Session ID vc_7829384_sess_a3f7c2d
AddPaymentInfo Checkout Token api_abc123def456
Lead Form ID + submission timestamp lead_contact_202603251430

For events without a natural unique ID (like ViewContent), the combination of object ID and session ID is the best compromise: unique enough for deduplication, but stable across page reloads within the same session.

Google vs. Meta: Different approaches

Google and Meta handle deduplication differently. If you use both platforms, you need to implement both approaches.

Google: transaction_id

Google Ads and GA4 deduplicate purchase events based on the transaction_id in the ecommerce object. Deduplication happens automatically: GA4 recognizes when the same transaction_id value is sent multiple times and counts the purchase only once.

Specificity: Google only deduplicates purchase events. Other events (like add_to_cart or begin_checkout) are not deduplicated. This is usually not a problem, because Google does not count these events as conversions by default (unless you have explicitly marked them as conversions).

Meta: event_id for all events

Meta deduplicates every event for which an event_id is sent. This covers all standard events and custom events. Without event_id, no deduplication occurs. Meta's approach is more explicit: you must actively implement deduplication, but in return you get full control over all event types.

Comparison

Aspect Google Meta
Deduplication key transaction_id event_id
Automatic? Yes, for purchases No, must be explicitly sent
Affected events Purchase only All events with event_id
Time window Not documented (hours to days) 48 hours
Without deduplication Duplicate purchases in GA4 Duplicate conversions in Meta Ads

Debugging and validation

Meta Events Manager

The Events Manager shows the deduplication status per event:

  1. Events Manager > Pixel > Test Events
  2. Select event (e.g. Purchase)
  3. Check: "Event received from" shows "Browser" and "Server"
  4. Check: "Event ID" shows the same value for both sources
  5. Status: "Deduplicated" or "Not deduplicated"

Common errors

event_id missing in one of the two channels. The Pixel sends eventID, but the CAPI request contains no event_id. Meta cannot deduplicate.

Incorrect casing. Pixel: eventID (camelCase in the options object). CAPI: event_id (snake_case in the JSON body). Confusion causes the field to be ignored.

event_id generated per request instead of per event instance. When Pixel and server each generate a new UUID, the IDs differ. The ID must come from the event (e.g. Order ID), not from the sending mechanism.

Time offset exceeds 48 hours. If the CAPI request is sent 3 days after the Pixel event, it falls outside the deduplication window. In Shopify setups with server-side GTM, the time offset is normally under one second.

Monitoring: measuring deduplication rate

To ensure deduplication works consistently, track these metrics:

Meta Events Manager > Diagnostics: Shows warnings for missing or faulty deduplication. Check this page weekly.

Conversion comparison: Compare the number of Purchase events in Meta with actual orders in Shopify. The ratio should be between 0.95 and 1.05 (slight deviations from consent gaps and timing). A ratio above 1.2 indicates deduplication problems.

GA4 custom dimension: Send the event_id as a custom dimension in GA4. This allows you to check in BigQuery whether the same event_id appears multiple times.

Conclusion

Event deduplication is not an optional optimization. Without it, Meta overstates your conversions by 30 to 80%, your ROAS looks better than it is, and your budget planning is based on false data. Smart Bidding on Meta optimizes toward inflated conversion numbers and misallocates budget.

The implementation is not complex, but it requires care: a stable event_id from the DataLayer, correct forwarding to Pixel and CAPI, and regular validation in the Events Manager.

Want to make sure your Meta conversions count correctly? In our tracking setup, event deduplication for all platforms is standard.

Our service

Tracking & Data Architecture

20–40% of your conversion data is missing. Server-side tracking, Consent Mode v2, 18+ events, and engagement scoring bring it back.

Learn more