TikTok Events API: server-side conversions from a Telegram funnel
A TikTok pixel in the browser sees the click and nothing after it. The bot start, the channel join, the deposit all happen inside Telegram, where no pixel runs, so TikTok's optimizer buys lookalikes of people who tapped, not of people who paid. Leadgram closes the loop server-side through the Events API 2.0: every conversion goes straight from our backend to your pixel, with the TikTok click ID attached.
How the model works
Leadgram posts one event per conversion to https://business-api.tiktok.com/open_api/v1.3/event/track/ and authorizes it with your account's access token in the Access-Token header. The pixel is addressed by its Pixel Code; there is no advertiser field in the request at all.
One detail decides how you should read every report on this page: at TikTok, HTTP 200 does not mean the event was accepted. The verdict lives in the response body, in the code field, and TikTok's own appendix says the return code takes precedence over the HTTP status - a 200 carrying code: 40002 is a failed call. Leadgram parses the body, so a rejected conversion is recorded as failed, never as sent. Rejections that a retry cannot fix - a revoked token, a pixel that isn't yours, a payload TikTok refuses - stop after the first attempt instead of burning all five.
Prepare TikTok
- Open the pixel in Events Manager (Assets → Events → Web Events). Use an existing pixel or create one, and set its connection method to Events API.
- Copy the Pixel Code. That is the identifier Leadgram sends as
event_source_id- not the advertiser ID and not the campaign ID. - Generate an access token with permission for that pixel. Follow TikTok's Events API 2.0 authentication flow; the token belongs to the pixel, so each pixel gets its own.
- Check your attribution window. TikTok ties how long a
ttclidstays valid to the CTA window you set in Attribution Manager. Leadgram never expires a click on its own, so the window in your ad account is the only one that applies.
Add the account in Leadgram
- On TikTok under Ad Platforms, click Add account.
- Account name - an internal label you'll recognize.
- Pixel ID - the Pixel Code from step 2 above.
- Advertiser ID - optional, and purely for your own bookkeeping. The Events API addresses the pixel by Pixel Code, so this value is never sent in a request.
- Access token - stored encrypted; the UI only ever shows the last 4 characters.
That is the whole form: four fields, no more. There is no test-event code and no one-click test conversion for TikTok - that pair exists for Meta only. Your first proof that the wiring works is a real conversion on Delivery Health, so send one through yourself before you turn the traffic on.
Bind it to a campaign
On Campaigns, pick TikTok as the ad platform and paste the same Pixel Code into the campaign's TikTok field. The match must be exact - that value is the join Leadgram uses at dispatch time to find the right credentials. A live indicator under the field confirms the match while you type, and the banner after saving repeats the verdict, so a typo doesn't fail silently.
What gets sent
- Event name - mapped from the internal type:
registration→ CompleteRegistration,deposit/ftd/purchase→ Purchase,bot_start/lead→ Lead,channel_join→ Subscribe,join_request→ SubmitApplication,first_dm→ Contact,land/miniapp_launch→ ViewContent,click→ ClickButton. The request and the join carry different names on purpose: one person who applies and is then approved moves two funnel steps instead of doubling one. Anything missing from that list never reaches TikTok at all:subscription_renewed,subscription_cancelledandcustom_*. Such an event creates no delivery and raises no error - it lands in the "Event not mapped" counter on TikTok's card. - ClickButton is a custom event. It is not in TikTok's Web Standard Events table, so raw clicks show up in Events Manager for reporting and audiences, but TikTok cannot optimize a campaign on them. Every other name above is a standard event.
- ttclid - the TikTok click ID your tracking link captured, sent unhashed. It is the only identifier TikTok can match us on, so a click without one is skipped rather than sent blind; the skip shows up on the platform card, not as an error.
- external_id - a SHA-256 hash of Leadgram's internal click ID, which TikTok requires to be hashed. It cannot match a user on its own; it groups events from the same visitor.
- Value and currency - only on Purchase, and only in a currency TikTok's list supports. An unrecognized currency would make TikTok reject the whole event, so Leadgram sends the conversion without the amount instead of losing it.
- A deterministic event ID deduplicates on TikTok's side: identical
event_source_id, event name and event ID within 48 hours keep the first copy and discard the rest. Every retry Leadgram makes falls inside that window, so a repeat cannot double-count a conversion. - Not sent: email, phone and IP. Leadgram doesn't collect the first two, and TikTok wants a raw public IP where we store only a hash. Sending a hash into a field that expects an address would degrade matching and misreport what we have.
Verify
Delivery Health shows the TikTok delivery within seconds of the event. On TikTok's side, open the pixel's Overview tab in Events Manager: once your first server event lands, Connection Method reads "Server".
If the delivery count looks low, read the platform card's "Skipped (not sent)" block before assuming something broke. It splits skips by reason - no click ID, event not mapped, platform not connected - so you can tell a real gap from a click that was never going to carry a ttclid.
Common pitfalls
- Pasting the advertiser ID as the Pixel ID. The request is addressed by Pixel Code; an advertiser ID in that field matches no account and no campaign.
- Token revoked or expired. TikTok answers with an authorization code and Leadgram marks the delivery failed on the first attempt instead of retrying for minutes. The reason is on the delivery row - regenerate the token and re-fire.
- Running Meta and TikTok on one campaign. A click that only carries
fbclidskips on the TikTok side by design. That is not an error, just a click TikTok was never going to match, and it appears in the same skip breakdown. - Overriding the event name on the campaign. The TikTok event name field in the campaign dialog sends whatever you type, verbatim, as the event name - and not for one event type but for every event of that campaign at once,
clickandlandincluded, so the whole funnel collapses into one row in Events Manager. A name outside TikTok's standard list is accepted as a custom event, which reports and builds audiences but cannot be optimized on. It is the only place to name thecustom_*types, and it is worth reaching for only when the campaign reports one kind of conversion anyway. - Conversions rejected with a parameter error. TikTok's parameter table marks the
pageobject as required for web events, while three of its four official web payload examples omit it. Leadgram sends nopage: the conversion happens in Telegram, and there is no page URL to report. If your pixel turns out to enforce it, the rejection is visible on the delivery row rather than silent - send us the error text.