Fix guide · Any website · advanced · about 60 min
TikTok Events API deduplication: match the pixel's event_id
For the findings “TikTok server events have no event ID” and “TikTok server events carry a different event ID”.
What this means
Your site sends its TikTok events twice, on purpose: once from the browser through the TikTok Pixel, and once more to your own server, which forwards them to TikTok through the Events API. TikTok recommends the Events API as a second channel together with the pixel, as long as both copies of an event can be recognized as one.
The server copy we saw does not carry the browser event’s ID:
- No event ID: the request to your server has the event name but no ID.
- A different event ID: the request carries an ID, but not the one the browser event had.
TikTok deduplicates on the pixel code (event_source_id), the event name and the event_id. It keeps the first copy and discards later ones within 48 hours. If the server event carries a different ID, both copies count. If it carries no ID at all, TikTok can fall back to the _ttp cookie, but only within 5 minutes, only if first-party cookies are on and your server sends ttp; otherwise both count too.
We report this as possible: we can see the request from the browser to your server, but never the request from your server to TikTok, so check the server side yourself.
Why it costs you money:
- Purchases and leads count twice in TikTok, so results and return on ad spend look better than they are.
- Campaigns learn from inflated numbers and may spend on the wrong people.
- When someone later “fixes” the double counting by switching one side off, you lose the reason you added the server copy.
How to confirm it yourself
- Open your page in a private (incognito) window, open developer tools (F12) and go to the Network tab. Accept cookies and trigger the conversion (for example, submit a test lead).
- Filter by
analytics.tiktok.com/api/v2/pixel, open the request for that event and noteeventandevent_idin the payload. An emptyevent_idmeans the browser event has no ID at all (see “TikTok events have no event ID”). - Clear the filter and find the request your site sends to its own server at the same moment: a form submission, an
/api/...call, or a request to your server-side tag manager address. Open its payload. - Compare: does it contain the same ID? If there is no ID, or a different one, the copies cannot be matched.
- In TikTok Events Manager, the pixel’s detail page shows “Browser”, “Server” and “Server & Browser” figures. TikTok says that if the “Server & Browser” numbers are too low, you should check your deduplication.
How to fix
The rule: one action, one ID, created in one place and used by both copies.
-
Pick where the ID is created.
- For purchases, the order number is ideal: the confirmation page can use it in the browser, and your backend already has it. TikTok suggests order numbers or transaction IDs.
- For leads, page views and clicks, create a random ID in the browser when the action happens (for example
crypto.randomUUID()), or create it on your server when it renders the page or handles the form, and hand it to the browser.
-
Pass it to the pixel in the third argument of
ttq.track:const eventId = crypto.randomUUID(); ttq.track('Lead', {}, { event_id: eventId }); -
Send the same value to your server with the request it already receives: a hidden form field, a property in your
/api/...call, or an event parameter in your server-side tag manager feed. -
Use it as
event_idin the Events API event, with the same event name and your pixel code asevent_source_id:{ "event_source": "web", "event_source_id": "<PIXEL CODE>", "data": [{ "event": "Lead", "event_time": 1792771200, "event_id": "4b1f0c6e-2f7d-4f6b-9a51-2d3c8e7f9a10", "user": { "ttclid": "<from the ttclid cookie>", "ttp": "<from the _ttp cookie>", "ip": "203.0.113.7", "user_agent": "Mozilla/5.0 ..." }, "page": { "url": "https://example.com/contact" } }] } -
Do not create a second ID on the server. A server that makes its own random ID, prefixes it, or sends a different value (a database row ID while the browser used the order number) produces a mismatch even though both copies “have an ID”.
-
Keep the names identical. Event names are case-sensitive. TikTok renamed
CompletePaymenttoPurchaseandSubmitFormtoLeadin 2025 and converts the old names automatically, but use the same name on both sides to be safe. -
With server-side Google Tag Manager: use one variable for the ID in the web TikTok Pixel tag and pass it to the server container, where TikTok’s TikTok Events API (Official) tag sends it as
event_id. If you set GTM up through TikTok’s interactive flow in Events Manager, TikTok configures anevent_idvariable for you. Check both containers in Preview mode: they must show the same value for the same event. -
With a partner integration or the Events API Gateway: these handle IDs for events they collect themselves. A separate, older pixel that sends its own browser events will not match; remove it.
-
Publish and run a test conversion.
Common causes
- The browser events have an empty
event_id, so there is nothing for the server to copy. - The server-side code was added later and never received the ID from the browser.
- Browser and server each generate their own random ID.
- The server sends a different identifier or a different event name.
- In server-side GTM, the web tag and the server tag read different variables.
How to verify the fix
- For one test conversion, the pixel’s
event_id, the ID in the request to your server and theevent_idyour server sends to TikTok are identical, and so are the event names. - Send a server test event with the
test_event_codefrom the Test Events tab (Test Server Events) and check that browser and server copies arrive; remove the code afterwards. - Over the following days, the “Server & Browser” figures for the event grow.
- Re-run the check on IsPixelWorking. The finding should be gone.
Sources
- TikTok API for Business, Event Deduplication (keys, 48 hours, merge within 5 minutes,
_ttpfallback, unique IDs, Server & Browser metrics): https://business-api.tiktok.com/portal/docs?id=1771100965992450 - TikTok API for Business, Events API 2.0 setup guide for Web (payload,
event_idrequired when sending from pixel and Events API): https://business-api.tiktok.com/portal/docs?id=1771100865818625 - TikTok API for Business, Events API and Pixel setup with Google Tag Manager (interactive flow configures an
event_idvariable): https://business-api.tiktok.com/portal/docs?id=1799004052020225 - TikTok API for Business, Verify Events API setup: https://business-api.tiktok.com/portal/docs?id=1771100984456193
- TikTok Business Help Center, How to adopt TikTok’s updated standard events (CompletePayment to Purchase, SubmitForm to Lead): https://ads.tiktok.com/resources/help/article/how-to-adopt-tiktoks-updated-standard-events?lang=en
- TikTok Business Help Center, Getting started with the Events API (second channel with the pixel): https://ads.tiktok.com/resources/help/article/getting-started-events-api?lang=en
More TikTok guides
- TikTok Pixel fires before cookie consent: how to fix it
- TikTok Pixel not firing after cookie consent: how to fix it
- Repeated TikTok event IDs drop real conversions: how to fix
- Duplicate TikTok Pixel events: how to find and remove them
- TikTok Pixel event_id missing: how to add it for deduplication
- TikTok click ID (ttclid) lost after an ad click: how to fix it
- TikTok Pixel tracks a button on desktop but not on mobile
- Two TikTok Pixels on one site: when it's fine, how to fix
- How to set up the TikTok Events API (with deduplication)