All integrations

Integration · TikTok Events API

Complete purchase signals for an algorithm that rewards them

RoasProof captures the ttclid the moment a TikTok click lands, resolves it to the eventual order, and delivers CompletePayment server-side. Every event is deduplicated against your TikTok pixel and matched with hashed identifiers.

The TikTok Events API is TikTok's server-to-server channel for conversion events. RoasProof captures the ttclid the moment a TikTok click lands, stores it first-party, and sends CompletePayment and other funnel events from the server, deduplicated against your TikTok pixel by a shared event_id and matched with hashed identifiers.

ttclid captureevent_id deduphashed identifierspixel coexistence

What a RoasProof server event looks like

A CompletePayment event as it leaves our servers for the Events API: click ID restored, identifiers hashed, event ID shared with your pixel.

tiktok events api · CompletePayment
POST https://business-api.tiktok.com/open_api/v1.3/event/track/

{
  "event_source":    "web",
  "event_source_id": "{pixel_code}",
  "data": [{
    "event":      "CompletePayment",
    "event_time": 1781430082,
    "event_id":   "ord_84213",
    "user": {
      "email":       "9f3d0c52ab…",
      "phone":       "1b6e21c84f…",
      "external_id": "7ac8044190…",
      "ttclid":      "E.C.P.CrKzqUv…",
      "ttp":         "9cf2laqOaU…",
      "ip":          "203.0.113.24",
      "user_agent":  "Mozilla/5.0 (iPhone; …)"
    },
    "properties": {
      "currency": "EUR",
      "value":    184.50,
      "order_id": "84213",
      "contents": [
        { "content_id": "SKU-2481", "quantity": 1, "price": 129.00 },
        { "content_id": "SKU-1177", "quantity": 1, "price": 55.50 }
      ]
    },
    "page": {
      "url": "https://store.example/checkout/thank-you"
    }
  }]
}
  • event_id matches your pixel

    Both the pixel's CompletePayment and this server event carry ord_84213, so TikTok pairs them and counts the purchase once, no matter which copy arrives first.

  • ttclid restored at conversion time

    The click ID was captured from the landing URL and stored first-party. When the purchase happens (even weeks later), it's re-attached, so the conversion maps back to the exact ad and campaign.

  • Hashed to TikTok's spec

    email, phone (E.164), and external_id are SHA-256 hashed server-side before transmission. Raw PII never reaches TikTok.

  • Context that lifts match rate

    The buyer's IP, user agent, and the _ttp cookie value (when the pixel set one) ride along, giving TikTok additional keys to match against logged-in users.

ttclid: easy to receive, easy to lose unless you store it

TikTok appends ttclid to your landing URL, and most sessions start inside TikTok's in-app browser, where cookies are short-lived and journeys frequently hop to the real browser. Persistence is the whole game.

  • Captured on the first pageview

    The script reads ttclid from the landing URL before any redirect or navigation can strip it, and stores it first-party against a persistent visitor ID.

  • Built for in-app browser journeys

    When the visitor returns later in Safari, on desktop, or from an email, identity resolution reconnects them to the stored click, so the eventual purchase still carries the ttclid.

  • The _ttp cookie comes too

    Where the TikTok pixel has set its _ttp identifier, we store and forward that as well. That adds one more matching key to every event.

stored click record
ttclid
E.C.P.CrKzqUv…
ttp
9cf2laqOaU…
utm_campaign
spark-ads-summer
landing
/products/trail-jacket
referrer
tiktok.com
captured
2026-06-14 09:41:22 UTC
attached_to
order #84213

Pixel and Events API, coexisting by design

TikTok recommends running the pixel and the Events API together and deduplicating by event_id. That's exactly the setup we create.

TikTok pixel · browser
CompletePayment·event_id: ord_84213
RoasProof · server
CompletePayment·event_id: ord_84213
counted once
1 × CompletePayment

Same event + event_id: TikTok keeps a single copy, and reported ROAS stops drifting from reality.

  • Shared IDs, coordinated at fire time

    Our on-page script hands the pixel a deterministic event ID derived from the order, and the server event reuses it. The pair is unambiguous.

  • Keep the pixel for the upper funnel

    ViewContent, AddToCart, and InitiateCheckout can stay browser-side where they're cheap and plentiful, while revenue events get the guaranteed server-side path.

  • No inflated numbers during migration

    Because dedup is deterministic from day one, you can turn on server events next to an existing pixel without a week of double-counted purchases polluting optimization.

The identifiers TikTok matches on, and where each comes from

TikTok matches server events to users with hashed contact details, click IDs, and browser context. We populate every field your data allows.

fieldwhat it iswhere we get it
emailSHA-256 of the normalized email addressOrder or signup email, trimmed and lowercased before hashing
phoneSHA-256 of the phone number in E.164 formatCheckout or lead-form phone, country-normalized
external_idSHA-256 of a stable first-party visitor IDSet on the first visit and reused across sessions
ttclidTikTok click IDCaptured from the landing URL, stored first-party, restored at conversion
ttpTikTok pixel cookie identifierRead from the _ttp cookie when the pixel has set one
ip / user_agentThe buyer's browsing contextRecorded with the session that produced the conversion, not our server's

Per-field coverage is visible in the dashboard, so if phone numbers stop arriving from a changed checkout, you find out from a chart instead of a slow bleed in matched conversions. Curious about the click ID itself? See the ttclid glossary entry.

Queued delivery with per-event receipts

Events API requests hit rate limits and transient errors like any API. The queue absorbs them; the dashboard shows you everything.

Store-and-forward

Every event is persisted before delivery and retried with exponential backoff on errors and rate limits. A TikTok outage delays events, but it never deletes them.

Test events before go-live

During setup, events run through TikTok's test mode so you can watch them arrive and dedupe in Events Manager before a single production event is sent.

Per-event delivery status

Each event stores the payload sent and TikTok's response code and message. Failures are diagnosable and replayable, individually or in bulk.

Give TikTok the purchase data it's been missing.

Connect a pixel code and an access token, fire a test event, and confirm the dedup in TikTok Events Manager before going live.