Skip to main content
Scripts

TikTok Pixel

TikTok Pixel reports browser events to TikTok Ads for conversion measurement and audiences.

Use useScriptTikTokPixel() to load the pixel and access its ttq API.

TikTok Pixel

View source

Nuxt Config Setup

Add this to your nuxt.config.ts to load TikTok Pixel globally. Alternatively you can use the useScriptTikTokPixel composable for more control.

export default defineNuxtConfig({
  scripts: {
    registry: {
      tiktokPixel: {
        id: 'CXXXXXXXXXXXXXX',
        trigger: 'onNuxtReady',
      }
    }
  }
})

This config automatically enables first-party mode (bundle + proxy). See below to customise.

useScriptTikTokPixel()

The useScriptTikTokPixel composable lets you have fine-grain control over when and how TikTok Pixel is loaded on your site.

const { proxy } = useScriptTikTokPixel()

proxy.ttq.track('CompletePayment', { value: 1, currency: 'USD' })

Please follow the Registry Scripts guide to learn more about advanced usage.

First-Party Mode: Privacy Focused Proxy

No extra config needed. The script is bundled from your domain (faster loads, no extra DNS lookup) and runtime requests are reverse-proxied through your server with automatic anonymisation (user IPs stay hidden from TikTok Pixel, works with ad blockers). Learn more.

Mode
Bundle Proxy Partytown
Privacy
All identifying data is stripped: IP, user agent, language, screen size, timezone, and hardware fingerprints.
export default defineNuxtConfig({
  scripts: {
    // ✅ First-party mode: bundled + proxied
    registry: {
      tiktokPixel: {
        id: 'CXXXXXXXXXXXXXX',
        trigger: 'onNuxtReady',
      },
    },
  },
})

Example

Using TikTok Pixel in a component with the proxy to send events .

<script setup lang="ts">
const { proxy } = useScriptTikTokPixel()

// noop in development, ssr
// just works in production, client
function handleAction() {
  proxy.ttq.track('CompletePayment', { value: 1, currency: 'USD' })
}
</script>

<template>
  <div>
    <button @click="handleAction">
      Send Event
    </button>
  </div>
</template>

Disabling automatic page views

By default, TikTok Pixel tracks a page view during initialization. Disable it in the composable call:

useScriptTikTokPixel({
  id: 'YOUR_PIXEL_ID',
  trackPageView: false,
})

TikTok Pixel exposes a three-state consent API: grant, revoke, or hold (defer the decision). Set the initial state with defaultConsent and call consent.grant() / consent.revoke() / consent.hold() at runtime:

<script setup lang="ts">
const { consent } = useScriptTikTokPixel({
  id: 'YOUR_PIXEL_ID',
  defaultConsent: 'hold', // 'granted' | 'denied' | 'hold'
})

function acceptAds() {
  consent.grant()
}
function rejectAds() {
  consent.revoke()
}
</script>

See the TikTok cookie consent docs for the full behavior.

The initial consent command is queued before pixel initialization, but it does not delay the SDK request. If your policy requires no request to TikTok before opt-in, use a consent trigger for the script itself.

Data-residency endpoint

Set region: 'us' to load the Pixel SDK from analytics.us.tiktok.com instead of the global host:

useScriptTikTokPixel({
  id: 'YOUR_PIXEL_ID',
  region: 'us',
})

This option selects the SDK host only. It does not by itself establish that the rest of your tracking setup meets a data-residency or privacy requirement.

Server-side event deduplication

For the Pixel + Events API (CAPI) pattern, pass the same event_id on both the browser and server sides so TikTok deduplicates the pair:

<script setup lang="ts">
const { proxy } = useScriptTikTokPixel({ id: 'YOUR_PIXEL_ID' })

async function checkout(order: { id: string, total: number }) {
  const eventId = crypto.randomUUID()

  proxy.ttq('track', 'Purchase', { value: order.total, currency: 'USD', order_id: order.id }, { event_id: eventId })

  await $fetch('/api/tiktok/event', {
    method: 'POST',
    body: { event: 'Purchase', event_id: eventId, order_id: order.id, value: order.total },
  })
}
</script>

See TikTok's event-deduplication guide for full rules.

Testing browser events

TikTok's browser Pixel testing guide uses the Test Events tab in Events Manager: enter the site URL, open it through the generated test flow, then perform the action you want to inspect.

The current Nuxt Scripts type also accepts test_event_code in a fourth track argument and forwards it to the SDK. TikTok documents that field for the server-side Events API, not for the browser ttq.track signature, so do not rely on it for browser testing.

Advanced matching

Nuxt Scripts expects each identify field (email, phone_number, external_id, first_name, last_name, city, state, country, zip_code) as a 64-character SHA-256 hex digest. TikTok's Advanced Matching guide covers normalization and hashing. In development, the composable warns when a value does not look hashed.

async function sha256(value: string) {
  const input = new TextEncoder().encode(value)
  const digest = await crypto.subtle.digest('SHA-256', input)
  return Array.from(new Uint8Array(digest), byte => byte.toString(16).padStart(2, '0')).join('')
}

const { proxy } = useScriptTikTokPixel({ id: 'YOUR_PIXEL_ID' })
proxy.ttq('identify', {
  email: await sha256('[email protected]'.trim().toLowerCase()),
  phone_number: await sha256('+15551234567'),
})

crypto.subtle.digest() is available only in a secure context in browsers. Localhost is treated as secure for development; deploy this example over HTTPS.

idstring required

Your TikTok Pixel ID.

trackPageViewboolean = true

Whether to automatically track a page view on initialization.

defaultConsent'granted' | 'denied' | 'hold'

Default consent state, applied before `ttq('init', id)`. - `'granted'` fires `ttq.grantConsent()` - `'denied'` fires `ttq.revokeConsent()` - `'hold'` fires `ttq.holdConsent()` to defer until an explicit update

region'global' | 'us'

Data residency region for the Pixel SDK. - `'global'` (default) -> `analytics.tiktok.com` - `'us'` -> `analytics.us.tiktok.com` (US enterprise data residency)