TikTok Pixel
Description
Section titled “Description”The TikTok Pixel is a JavaScript snippet that loads TikTok’s tracking library so you can measure web events, attribute conversions to TikTok campaigns, and improve optimization and measurement in TikTok Ads Manager.
App Coverage
Section titled “App Coverage”| App | Integrated |
|---|---|
| UK | ✅ |
| DE | ❌ |
Integration
Section titled “Integration”TikTok Pixel requires the pixel’s base code. An overview of the integration methods can be found via the links below:
- Set up and verify your TikTok Pixel
- Standard events and parameters
- Set up TikTok Pixel with Google Tag Manager
Debug Tools
Section titled “Debug Tools”An overview of the debugging tools can be found via the links below:
- TikTok Pixel Helper (Chrome extension)
- How to test TikTok Pixel events
Before integrating TikTok Pixel, note the following:
- Event names and parameters should match how conversions are defined in TikTok Events Manager.
- Validate conversion values and currency when sending revenue events.
- If Events API is used with the pixel, follow TikTok’s guidance on event deduplication (including consistent event_id where the same event is sent on both channels).
Plugin Usage Guide
Section titled “Plugin Usage Guide”The @releafuk/analytics package provides a custom TikTok Pixel plugin through the tikTokProvider() factory function.
Configuration
Section titled “Configuration”The tikTokProvider() factory accepts the config parameter that should satisfy the TikTokConfig type:
type TikTokConfig = { pixelId: string; enabled?: boolean; defaultCurrency: string; consentMode?: "basic" | "advanced";};| Option | Required | Default | Description |
|---|---|---|---|
pixelId | Yes | - | The TikTok Pixel ID. |
enabled | No | true | Controls whether the provider loads and initializes the pixel. Use false to keep the provider registered but disabled for an environment — every method becomes a no-op. |
defaultCurrency | Yes | - | Currency code (e.g. "GBP") used for value-based events when a call does not pass its own currency param. |
consentMode | No | basic | Controls whether the pixel loads immediately with consent held (advanced), or only loads once consent is granted (basic). See Consent mode. |
Consent mode
Section titled “Consent mode”consentMode: "basic" (the default) makes markup() a no-op ([]). The pixel script is only loaded from init(), which the analytics service calls once the required advertising consent is granted. No consent commands are pushed to ttq in this mode.
consentMode: "advanced" makes markup() emit the pixel bootstrap so it loads before the visitor makes a consent choice, with tracking held until consent is confirmed:
---import { analytics } from "@/libs/analytics";
const markup = analytics.markup?.() ?? [];---
{ markup.map((contribution) => contribution.kind === "inline-script" ? ( <script is:inline id={contribution.id} set:html={contribution.content} /> ) : contribution.kind === "script-src" ? ( <script is:inline async src={contribution.src} /> ) : null, )}The inline bootstrap script sets window.TiktokAnalyticsObject, pushes holdConsent, init and page onto the ttq queue, and a separate script-src contribution loads https://analytics.tiktok.com/i18n/pixel/events.js. Because tracking is held from the start, init() in advanced mode does not reload the script — it pushes grantConsent and marks the provider ready. updateConsent() pushes grantConsent or revokeConsent based on consent.advertising, and is a no-op in basic mode.
Define TikTok event parameters under the tiktok provider key, then register tikTokProvider() when creating the analytics service:
import { createAnalyticsService, createEvent, createEventDefinition, createEventRegistry, tikTokProvider,} from "@releafuk/analytics";
const purchaseCompleted = createEvent< { total: number; currency: string; orderId: string }, "purchaseCompleted">({ name: "purchaseCompleted",});
const events = createEventRegistry().register( createEventDefinition(purchaseCompleted, { providers: { tiktok: (data) => ({ event: "purchase", params: { value: data.total, currency: data.currency, }, meta: { eventId: data.orderId, standardEvent: "Purchase", }, }), }, }),);
export const analytics = createAnalyticsService({ app: "releaf", events, providers: [ tikTokProvider({ pixelId: import.meta.env.PUBLIC_TIKTOK_PIXEL_ID, defaultCurrency: "GBP", consentMode: "advanced", }), ], consent: { default: { advertising: "denied", }, },});
await analytics.init();Event mapping
Section titled “Event mapping”The provider builds the data sent to ttq.track() from a fixed subset of params — value (with currency falling back to defaultCurrency), content_ids, content_type, and contents. Any other fields passed in params are dropped, so map an event’s data to these fields explicitly rather than passing arbitrary parameters through.
meta.eventId is forwarded as the TikTok event_id option, which should match the event_id sent to the Events API for the same event when deduplication is required.
meta.standardEvent fires an additional track() call using a TikTok standard event name (for example Purchase), alongside the app-specific event name, using the same event data and event_id. This lets the app track its own event name for internal reporting while still feeding TikTok’s standard events for ads optimization. Omit standardEvent, or set it equal to event, to send only one event.
Page views
Section titled “Page views”page() sends a PageView event, deduplicated by window.location.pathname — repeated calls for the same pathname are ignored, so it is safe to call analytics.page() on every route change without producing duplicate PageView events.