Server-Side GTM + TikTok Ads Setup Guide

Most TikTok Ads tracking setups I audit are leaking 20-30% of conversions, and it’s always the same culprit: relying entirely on TikTok’s pixel firing from the browser. Ad blockers, iOS tracking restrictions, and slow page loads kill your conversion data before it ever reaches TikTok’s servers. Server-side tracking fixes this by sending conversion data directly from your server to TikTok’s API, bypassing all the browser-based tracking limitations.

I’ve set up server-side TikTok tracking for over 60 accounts in the last two years, and the data quality improvement is consistently dramatic — usually 15-25% more conversions showing up in TikTok Ads Manager within the first week.

What You’ll Have Working By The End

Prerequisites

Step 1: Get Your TikTok API Credentials

You need two pieces from TikTok Events Manager before you can send server-side events.

In TikTok Ads Manager, go to Assets → Events → Manage. Find your pixel and click “Set up Events API”:

  1. Generate an Access Token (this authenticates your server requests)
  2. Copy your Pixel ID (this tells TikTok which pixel to attribute events to)
  3. Note your Test Event Code (you’ll need this for testing)

The access token expires every 365 days, so set a calendar reminder to regenerate it. I’ve seen accounts lose 3-4 weeks of data because someone forgot to update an expired token.

Store these credentials securely. I typically add them as environment variables in Cloud Run or as GTM server container variables.

Step 2: Configure the TikTok Server-Side Tag

In your server-side GTM container, create a new TikTok tag:

Tag Type: TikTok (if available) or HTTP Client for custom implementation

Basic Configuration:

Event Data Mapping:

{
  "event_name": "{{Event Name}}", // CompletePayment, ViewContent, etc.
  "event_time": "{{Event Timestamp}}", // Unix timestamp
  "event_id": "{{Event ID}}", // For deduplication
  "event_source_url": "{{Page URL}}",
  "user_data": {
    "email": "{{User Email Hashed}}", // SHA256 hash
    "phone": "{{User Phone Hashed}}", // SHA256 hash, E.164 format
    "external_id": "{{User ID}}"
  },
  "custom_data": {
    "value": "{{Purchase Value}}",
    "currency": "{{Currency}}",
    "content_id": "{{Product ID}}",
    "content_type": "product"
  }
}

Critical: TikTok requires email and phone to be SHA256 hashed before sending. If you’re sending unhashed PII, TikTok will reject the events. Use GTM’s built-in SHA256 variables or hash them client-side before sending to your server.

Step 3: Set Up Event Deduplication

This is where 40% of setups break. You’re now sending the same conversion from both browser (TikTok pixel) and server (Events API). Without proper deduplication, TikTok counts each conversion twice.

Generate Consistent Event IDs:

Client-side (send with your dataLayer event):

// Generate unique ID for each conversion
const eventId = 'txn_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);

// Send to both client GTM and your server
dataLayer.push({
  event: 'purchase',
  event_id: eventId,
  transaction_id: 'order_12345',
  value: 99.99,
  currency: 'USD'
});

In both your client-side pixel and server-side tag, use the same event_id:

Client-side TikTok pixel configuration:

ttq.track('CompletePayment', {
  content_id: 'product_123',
  content_type: 'product',
  value: 99.99,
  currency: 'USD'
}, {
  event_id: '{{Event ID}}'
});

Server-side tag configuration includes the same event_id field in your JSON payload.

TikTok automatically deduplicates events with the same event_id within a 48-hour window, keeping the first event received (usually the browser event for speed, server event for accuracy).

Step 4: Configure Transport URL (If Using Custom Implementation)

If you’re not using the built-in TikTok tag in server GTM, you’ll send events via HTTP Client tag:

Transport URL: https://business-api.tiktok.com/open_api/v1.3/pixel/track/

Headers:

Content-Type: application/json
Access-Token: {{TikTok Access Token}}

Request Body:

{
  "pixel_code": "{{Pixel ID}}",
  "event": "{{Event Name}}",
  "event_id": "{{Event ID}}",
  "timestamp": "{{Event Timestamp}}",
  "context": {
    "user_agent": "{{User Agent}}",
    "ip": "{{User IP}}",
    "page": {
      "url": "{{Page URL}}",
      "referrer": "{{Referrer}}"
    }
  },
  "properties": {
    "email": "{{Hashed Email}}",
    "phone": "{{Hashed Phone}}",
    "external_id": "{{User ID}}",
    "value": "{{Purchase Value}}",
    "currency": "{{Currency}}",
    "content_id": "{{Product ID}}"
  }
}

Event Name Mapping:

Step 5: Enhanced Data Quality Setup

Server-side tracking lets you send much richer user data than browser-based pixels. This improves TikTok’s ability to match conversions back to users and optimize your campaigns.

Required Fields:

Recommended Fields for Better Match Quality:

"user_data": {
  "email": "hash_of_user_email", // SHA256
  "phone": "hash_of_phone_e164", // SHA256, E.164 format (+1234567890)
  "external_id": "your_user_id",
  "ip_address": "user_ip", // Don't hash this one
  "user_agent": "full_user_agent_string"
}

Purchase Event Custom Data:

"custom_data": {
  "value": 99.99, // Required for purchase events
  "currency": "USD", // Required for purchase events
  "content_id": ["product_123", "product_456"], // Product IDs
  "content_type": "product",
  "content_name": "Product Name",
  "content_category": "Electronics",
  "quantity": 2
}

The more accurate user identifiers you send, the better TikTok can optimize your campaigns. I typically see a 10-15% improvement in ROAS when accounts start sending hashed email and phone numbers server-side.

Testing & Verification

1. Server Container Debug Mode: Enable debug mode in your server-side GTM container and trigger a test conversion. Check that your TikTok tag fires and the request payload looks correct.

2. TikTok Events Manager Testing: In TikTok Events Manager, use your Test Event Code to send test events:

curl -X POST "https://business-api.tiktok.com/open_api/v1.3/pixel/track/" \
  -H "Access-Token: YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "pixel_code": "YOUR_PIXEL_ID",
    "test_event_code": "YOUR_TEST_EVENT_CODE",
    "event": "CompletePayment",
    "timestamp": "'$(date +%s)'",
    "context": {"ip": "127.0.0.1"},
    "properties": {"value": 99.99, "currency": "USD"}
  }'

Events should appear in the Test Events tab within 5 minutes.

3. Live Event Verification: After removing the test event code, trigger real conversions and check:

4. Campaign Performance Check: Within 24-48 hours, check that your TikTok campaigns are receiving conversion data. The “Events Received” column in campaign reporting should show your server-side events.

Acceptable Variance: 5-15% difference between your internal conversion count and TikTok’s received events is normal due to user consent, bot filtering, and attribution windows.

Troubleshooting

Problem: Events showing in test mode but not in live mode Solution: Remove the test_event_code from your production requests. TikTok ignores events sent with test codes in live campaigns.

Problem: Getting 401 “Invalid Access Token” errors Solution: Your access token expired or is incorrect. Generate a new one in TikTok Events Manager. Access tokens expire every 365 days.

Problem: Events received but showing “Poor Match Quality” Solution: Your email/phone hashing is broken. Verify you’re SHA256 hashing emails in lowercase and phone numbers in E.164 format (+1234567890) before hashing.

Problem: Seeing 2x conversion counts in TikTok campaigns Solution: Event deduplication isn’t working. Check that your client-side pixel and server-side tag are sending identical event_id values for the same conversion.

Problem: Server requests timing out or failing Solution: TikTok’s API can be slow (2-5 second response times). Increase your HTTP Client tag timeout to 10 seconds and consider implementing retry logic for failed requests.

Problem: Purchase events missing value/currency data Solution: TikTok requires value and currency for CompletePayment events. These must be numbers (not strings) and currency must be a valid 3-letter ISO code.

What To Do Next

Server-side TikTok tracking is just one piece of a complete tracking infrastructure. For maximum data quality, you should also set up:

Ready to audit your current TikTok tracking setup? Get a free tracking audit — I’ll identify exactly what conversion data you’re missing and how much it’s costing your campaigns.

This guide is part of the Server-Side GTM Hub — complete guides for implementing server-side tracking across all major ad platforms.