Skip to content

GA4 + Meta CAPI deduplication: what breaks and how to fix it

The Pixel + CAPI run in parallel, and deduplication is supposed to happen via event_id. In practice, 30% of deployments have a bug somewhere. Here are the 5 most common ones and how to fix them.

T
Tým DataNostro 9. 5. 2026 · 6 min · Středně pokročilý

Server-side CAPI is a great thing, but when deduplication with the pixel breaks, you have 40–80% more conversions in Ads Manager than actually flowed to the account. Five of the most common bugs we see in a Care audit.

1. event_id isn't passed from the web to the server

A classic bug: the GTM web container generates event_id = uuid() in the dataLayer, but the server-side request doesn't include it (it didn't get into the payload). Meta only deduplicates if both events have the same event_id — a missing event_id = every conversion counted 2×.

Fix: in GTM web → Meta Pixel tag → Advanced → Event ID → insert {{Event - Event ID}}. In GTM server → Meta CAPI tag → Event ID → the same variable from the incoming request.

2. event_time differs by more than 5 minutes

Meta only deduplicates if the client-side and server-side event_time are within a 5-minute window. If server-side runs in a cron job (a Stripe webhook with a delay), a delay of up to 30 minutes can occur.

Fix: the server-side event_time = the original client-side timestamp from the dataLayer, not time.time() in the server-side handler.

3. A Test Event Code in production

In the Meta Test Events tab you create a test code (TEST12345), forget to remove it from the server-side config, and deploy to production. All production conversions end up in Test Events instead of Live — they never reach Ads attribution.

Fix: the Test Event Code should be an env variable, not hardcoded. Leave it empty in production. The DataNostro dashboard has a separate "Test Event Code" field that is separate from the production setting.

4. Hashing email/phone incorrectly

Meta CAPI wants em = sha256(lowercase(trim(email))). Common mistakes:

  • Hashing with preserved punctuation or whitespace (e.g. "[email protected]" → a different hash than "[email protected]")
  • Phone without the E.164 format (it must be +420..., not 123456789)
  • An external ID in plain text (Meta hashes it itself, but the server-side sends it hashed — double hashing breaks the match)

Fix: normalize before anything is sent. DataNostro does this automatically per the Meta CAPI specification.

5. The Pixel sends, the server-side doesn't (and vice versa)

The server-side request fails (timeout, network error), the pixel goes through — Meta gets only 1 hit instead of 2. Meta can't recognize this as a problem, it just has less data.

Fix: in the DataNostro debug console you see the status of every server-side hit. If you have a higher than 2% error rate on Meta CAPI, something's off (typically an expired Access Token or an IP blocked by Meta).

How to debug it

Meta Events Manager → Test Events → send the pixel + CAPI. If you see a green "Deduplicated" badge, it's OK. If you see two separate events of the same type, the event_id doesn't match.

DataNostro Debug Events shows the payload of both paths with a diff highlight.

Share

A new article once a month

In-depth server-side tracking guides + case studies from the CZ market. No spam, just 1 email a month. Unsubscribe anytime.

Back to Tracking