TikTok Events API

TikTok Events API without ttq.js. Better match rates. Zero browser overhead.

TikTok ad spend is growing faster than any other platform. Their Events API delivers better match rates than the client-side pixel, but requires server infrastructure. Datafly Signal handles this automatically — self-generated _ttp, captured ttclid, and direct server-to-server delivery with zero TikTok JavaScript in the browser.

45KB

ttq.js payload

TikTok's pixel JavaScript competes with your content for bandwidth on every page load.

20-40%

Blocked by ad blockers

Desktop users with ad blockers never trigger TikTok pixel events. Your attribution data has a permanent gap.

7 days

ITP cookie limit

Safari caps client-side _ttp cookies to 7 days, breaking attribution for returning visitors.

Zero

TikTok JS with Signal

Datafly Signal delivers events server-to-server. No ttq.js, no pixel, no browser overhead.

Problems with the TikTok Pixel

The TikTok Pixel has the same architectural limitations as every other client-side tracking tag. These are not configuration problems — they are fundamental constraints of browser-based JavaScript.

45KB JavaScript Payload

ttq.js loads 45KB of JavaScript that competes with your content for bandwidth. On mobile connections this directly impacts page load times, Core Web Vitals, and conversion rates.

Ad Blockers Block It

20-40% of desktop users run ad blockers that block TikTok's tracking domains by default. These users never register a single event, creating a permanent blind spot in your attribution data.

ITP-Limited Cookies

Safari's Intelligent Tracking Prevention caps client-side JavaScript cookies at 7 days. Your _ttp cookie expires weekly, breaking attribution windows and fragmenting user identity.

Consent Timing Issues

The TikTok pixel fires before consent banners resolve, or consent is revoked after events are already in flight. Server-side delivery gives you full control over when events are sent.

How Signal delivers TikTok events

Datafly Signal replaces the TikTok Pixel with server-to-server delivery via the TikTok Events API. Better identity matching, zero browser overhead.

Self-generated _ttp

Generated server-side using the same algorithm as ttq.js and set as a server-set first-party cookie with 400-day expiry. Fully exempt from Safari ITP restrictions.

Captured ttclid from URL

When a user arrives from a TikTok ad, the ttclid query parameter is automatically captured and stored as a 400-day server-set cookie for attribution.

Server-to-server delivery

Events are delivered directly to business-api.tiktok.com via the Events API. Purpose-built delivery worker with exponential backoff retry on failure.

SHA-256 enhanced matching

Email and phone are normalised and SHA-256 hashed before transmission. Enhanced matching improves match rates without sending raw PII to TikTok.

ITP-exempt 400-day cookies

All identity signals — _ttp, ttclid, external_id — are set via Set-Cookie headers from your first-party subdomain. Safari ITP does not restrict server-set cookies.

Zero TikTok JavaScript

No ttq.js, no TikTok Pixel, no third-party scripts. The only JavaScript in the browser is your 5.2KB Datafly.js collector.

Identity signals sent on every event

Datafly Signal sends the complete set of identity parameters to the TikTok Events API on every event. More signals means higher match rates and better ad optimisation.

_ttp
Source: Self-generated
Expiry: 400 days
Description: TikTok browser identifier. Generated server-side using the same algorithm as ttq.js. Set as a server-set first-party cookie.
ttclid
Source: URL capture
Expiry: 400 days
Description: TikTok click identifier. Automatically captured from the ttclid query parameter when a user arrives from a TikTok ad.
external_id
Source: Your user ID
Expiry: Session
Description: Your internal user identifier, passed directly. Enables cross-device matching for logged-in users.
em
Source: traits.email
Expiry: SHA-256
Description: Email address, normalised (lowercase, trimmed) and SHA-256 hashed before transmission.
ph
Source: traits.phone
Expiry: SHA-256
Description: Phone number, normalised to E.164 format and SHA-256 hashed before transmission.

All PII is automatically SHA-256 hashed as required by TikTok. Email and phone data are normalised and hashed before leaving your server. Raw PII never reaches the TikTok API.

Pipeline as Code

Purpose-built TikTok event transformation

This pipeline config transforms an Order Completed track event into a TikTok Events API CompletePayment event. User identity is enriched from cookies, PII is automatically hashed, and product data is mapped to TikTok's content format.

  • content_type, content_id, value, and currency from product data
  • User identity with _ttp, ttclid, and external_id from cookies
  • SHA-256 normalisation for email and phone fields
  • IP address and user agent forwarded for enhanced matching
  • Output validation against TikTok's API schema before delivery
tiktok-purchase.yamlYAML
# tiktok-purchase.yaml — Purchase event to TikTok Events API
name: tiktok_purchase
integration: tiktok-events-api
trigger:
  event: track
  conditions:
    - field: event
      operator: equals
      value: Order Completed

transform:
  static:
    - target: event
      value: CompletePayment

  mapping:
    - source: timestamp
      target: timestamp
      transform: iso8601

  # User context
  context:
    - source: context.ip
      target: user.ip
    - source: context.userAgent
      target: user.user_agent

  # User identity — auto-hashed PII
  user_data:
    - source: traits.email
      target: user.email
      transform: sha256_normalise
    - source: traits.phone
      target: user.phone
      transform: sha256_normalise

  enrichments:
    - type: vendor_id
      vendor: tiktok
      cookies: [_ttp]
    - type: click_id
      param: ttclid
      target: user.ttclid
    - type: identity
      source: user_id
      target: user.external_id

  # Properties — purchase details
  properties:
    - source: properties.products
      target: content_id
      transform: pluck
      field: product_id
    - source: properties.products
      target: content_type
      value: product
    - source: properties.revenue
      target: value
    - source: properties.currency
      target: currency
      default: USD

output:
  format: tiktok_events_api
  endpoint: https://business-api.tiktok.com/open_api/v1.3/event/track/
  auth: access_token
  validate: true

Supported TikTok events

All standard TikTok Events API event types are supported out of the box. Each event is delivered server-to-server with full identity enrichment.

PageView

When a user views any page on your site

ViewContent

When a user views a product or content page

AddToCart

When a user adds an item to their shopping cart

InitiateCheckout

When a user begins the checkout process

CompletePayment

When a user completes a purchase transaction

PlaceAnOrder

When a user places an order before payment

Subscribe

When a user subscribes to a plan or newsletter

Contact

When a user submits a contact or enquiry form

SubmitForm

When a user submits any form on your site

Frequently asked questions

How does Datafly Signal capture ttclid for TikTok attribution?
When a user lands from a TikTok ad, the URL contains ttclid. Datafly.js extracts it on landing and the gateway stores it in the same 400-day server-set first-party cookie as the _ttp identifier. Conversions days, weeks, or months later are matched against the original ttclid for full-cycle attribution, regardless of Safari ITP's 7-day cap on browser-set cookies.
What is _ttp and how is it generated server-side?
The _ttp cookie is TikTok's anonymous browser-side identifier, normally set by ttq.js on first visit. Datafly's gateway generates a value matching TikTok's expected format and persists it in your own subdomain's first-party cookies. From TikTok's identity graph perspective the value is identical to a ttq-set _ttp, so server-side events match against the same identity record as any prior client-side ones.
Do I need to keep ttq.js on the page?
No. ttq.js exists to generate _ttp, capture ttclid, and fire events. All three are handled server-side by Datafly Signal. Removing ttq.js eliminates ~50KB of JavaScript per page, removes a category of ad blocker target, and gives you cleaner attribution because cookies persist for 400 days instead of 7.
How does this affect TikTok Smart Performance Campaigns?
Smart Performance Campaigns optimise on the events TikTok sees. Server-side delivery via the Events API recovers events that ad blockers and Safari ITP would otherwise have hidden, giving Smart Performance a fuller picture. Match rates also improve because every event ships with the complete identifier set (_ttp, ttclid, hashed email, hashed phone) instead of just whatever ttq.js was able to send before it was blocked.
Can I deduplicate against an existing ttq.js setup during migration?
Yes. Datafly Signal generates a deterministic event_id for every event and emits it via the Events API. If ttq.js is still on the page during migration, both client-side and server-side events arrive at TikTok with the same event_id and TikTok deduplicates. You can run both in parallel for as long as needed before fully removing ttq.js.

Maximise TikTok ROAS with server-side events

See how Datafly Signal delivers TikTok Events API events with full identity matching, zero browser overhead, and ITP-exempt 400-day cookies. Better data, better optimisation.