Skip to main content
Ask your AI

TikTok Events API

Server Source code Package

Server-side event delivery to TikTok's Events API for enhanced conversion tracking, bypassing browser limitations and improving match quality for ad optimization.

Where this fits

TikTok Events API is a server destination in the walkerOS flow:

Sends events server-side to TikTok's Events API using raw HTTP (no SDK). Identity fields (email, phone_number, external_id) are SHA-256 hashed before sending. Events include a stable `event_id` for deduplication with the browser pixel.

Installation​

npm install @walkeros/server-destination-tiktok
import { startFlow } from '@walkeros/collector';
import { destinationTikTok } from '@walkeros/server-destination-tiktok';

await startFlow({
  destinations: {
    tiktok: {
      code: destinationTikTok,
      config: {
        settings: {
          accessToken: 'YOUR_ACCESS_TOKEN',
          pixelCode: 'YOUR_PIXEL_CODE',
        },
      },
    },
  },
});

Configuration​

This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.

Settings​

PropertyTypeDescriptionMore
pixelCode*stringTikTok Pixel Code from Events Manager
accessToken*stringEvents API access token from TikTok Events Manager
urlstringCustom Events API endpoint URL
test_event_codestringTest event code for debugging in TikTok Events Manager
doNotHashArray<string>User data fields to skip hashing
user_dataRecord<string, string>Mapping for user data fields
partner_namestringPartner name for TikTok attribution
ipany | booleanClient IP, sent as context.ip. Resolves against { ingest, event }. Default: ["ingest.ip", "event.user.ip"]. false switches it off.
userAgentany | booleanClient user agent, sent as context.user_agent. Resolves against { ingest, event }. Default: ["ingest.userAgent", "event.user.userAgent"]. false switches it off.
* Required fields

Mapping​

This package does not define custom rule-level settings. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

Examples

Add to cart

A product add is sent to TikTok as an AddToCart event with value, currency, and product contents.

Event
{
  "name": "product add",
  "data": {
    "id": "SKU-B2",
    "name": "Running Shoes",
    "price": 89.99,
    "color": "blue"
  },
  "context": {
    "shopping": [
      "intent",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "SKU-B2",
        "name": "Running Shoes",
        "price": 89.99,
        "quantity": 1
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "d1e2f3a4b5c60002",
  "trigger": "click",
  "entity": "product",
  "action": "add",
  "timestamp": 1700000901000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://shop.example.com/products/running-shoes"
  }
}
Mapping
{
  "name": "AddToCart",
  "data": {
    "map": {
      "content_type": {
        "value": "product"
      },
      "value": "data.price",
      "currency": {
        "value": "EUR"
      },
      "contents": {
        "loop": [
          "nested",
          {
            "condition": {
              "$code": "e=>k(e)&&\"product\"===e.entity"
            },
            "map": {
              "content_id": "data.id",
              "content_name": "data.name",
              "quantity": {
                "key": "data.quantity",
                "value": 1
              },
              "price": "data.price"
            }
          }
        ]
      }
    }
  }
}
Out
sendServer("https://business-api.tiktok.com/open_api/v1.3/event/track/", "{\"pixel_code\":\"PIXEL_CODE\",\"partner_name\":\"walkerOS\",\"data\":[{\"event\":\"AddToCart\",\"event_id\":\"d1e2f3a4b5c60002\",\"timestamp\":\"2023-11-14T22:28:21.000Z\",\"context\":{\"page\":{\"url\":\"https://shop.example.com/products/running-shoes\"}},\"properties\":{\"content_type\":\"product\",\"value\":89.99,\"currency\":\"EUR\",\"contents\":[{\"content_id\":\"SKU-B2\",\"content_name\":\"Running Shoes\",\"quantity\":1,\"price\":89.99}]}}]}", {
  "headers": {
    "Access-Token": "s3cr3t",
    "Content-Type": "application/json"
  }
})

Submit form

A newsletter form submission is sent to TikTok as a SubmitForm event with the hashed email in user context.

Event
{
  "name": "form submit",
  "data": {
    "type": "newsletter"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "lang": "elb"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "email": "user@example.com"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "d1e2f3a4b5c60004",
  "trigger": "test",
  "entity": "form",
  "action": "submit",
  "timestamp": 1700000903000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://example.com/contact"
  }
}
Mapping
{
  "name": "SubmitForm",
  "data": {
    "map": {
      "user_data": {
        "map": {
          "email": "user.email"
        }
      }
    }
  }
}
Out
sendServer("https://business-api.tiktok.com/open_api/v1.3/event/track/", "{\"pixel_code\":\"PIXEL_CODE\",\"partner_name\":\"walkerOS\",\"data\":[{\"event\":\"SubmitForm\",\"event_id\":\"d1e2f3a4b5c60004\",\"timestamp\":\"2023-11-14T22:28:23.000Z\",\"context\":{\"user\":{\"email\":\"b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514\"},\"page\":{\"url\":\"https://example.com/contact\"}},\"properties\":{}}]}", {
  "headers": {
    "Access-Token": "s3cr3t",
    "Content-Type": "application/json"
  }
})

Page view

A page view is forwarded to TikTok as a page view event with the source URL in the page context.

Event
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "d1e2f3a4b5c60003",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000902000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://example.com/docs/"
  }
}
Out
sendServer("https://business-api.tiktok.com/open_api/v1.3/event/track/", "{\"pixel_code\":\"PIXEL_CODE\",\"partner_name\":\"walkerOS\",\"data\":[{\"event\":\"page view\",\"event_id\":\"d1e2f3a4b5c60003\",\"timestamp\":\"2023-11-14T22:28:22.000Z\",\"context\":{\"page\":{\"url\":\"https://example.com/docs/\"}},\"properties\":{}}]}", {
  "headers": {
    "Access-Token": "s3cr3t",
    "Content-Type": "application/json"
  }
})

Complete payment

A completed order is sent to the TikTok Events API as a CompletePayment with value, currency, and contents.

Event
{
  "name": "order complete",
  "data": {
    "id": "ORD-300",
    "total": 249.99,
    "currency": "EUR"
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "user-123",
    "device": "device-456"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "SKU-A1",
        "name": "Widget Pro",
        "price": 124.99,
        "quantity": 2
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "d1e2f3a4b5c60001",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000900000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://shop.example.com/checkout/complete"
  }
}
Mapping
{
  "name": "CompletePayment",
  "data": {
    "map": {
      "value": "data.total",
      "currency": {
        "key": "data.currency",
        "value": "EUR"
      },
      "order_id": "data.id",
      "content_type": {
        "value": "product"
      },
      "contents": {
        "loop": [
          "nested",
          {
            "condition": {
              "$code": "e=>k(e)&&\"product\"===e.entity"
            },
            "map": {
              "content_id": "data.id",
              "content_name": "data.name",
              "quantity": {
                "key": "data.quantity",
                "value": 1
              },
              "price": "data.price"
            }
          }
        ]
      },
      "user_data": {
        "map": {
          "external_id": "user.id"
        }
      }
    }
  }
}
Out
sendServer("https://business-api.tiktok.com/open_api/v1.3/event/track/", "{\"pixel_code\":\"PIXEL_CODE\",\"partner_name\":\"walkerOS\",\"data\":[{\"event\":\"CompletePayment\",\"event_id\":\"d1e2f3a4b5c60001\",\"timestamp\":\"2023-11-14T22:28:20.000Z\",\"context\":{\"user\":{\"external_id\":\"fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8\"},\"page\":{\"url\":\"https://shop.example.com/checkout/complete\"}},\"properties\":{\"value\":249.99,\"currency\":\"EUR\",\"order_id\":\"ORD-300\",\"content_type\":\"product\",\"contents\":[{\"content_id\":\"SKU-A1\",\"content_name\":\"Widget Pro\",\"quantity\":2,\"price\":124.99}]}}]}", {
  "headers": {
    "Access-Token": "s3cr3t",
    "Content-Type": "application/json"
  }
})

Client IP and user agent​

The destination sends the client IP as context.ip and the user agent as context.user_agent by default. The ip and userAgent settings resolve against { ingest, event } and default to ["ingest.ip", "event.user.ip"] and ["ingest.userAgent", "event.user.userAgent"], so they fill in whenever the source provides them (see the config.ingest recipe on the Express source). A value that resolves to nothing is not sent. Set either setting to false to turn it off, or to another mapping value to read it elsewhere.

Hashing​

The destination automatically SHA-256 hashes email, phone_number, and external_id before sending to TikTok. Pass raw values and the hashing is handled for you. If your data is already hashed or you want to skip hashing for specific fields, use the doNotHash setting:

"settings": {
  "accessToken": "YOUR_ACCESS_TOKEN",
  "pixelCode": "YOUR_PIXEL_CODE",
  "doNotHash": ["email"]
}

Deduplication​

Each event is sent with event_id set to the walkerOS event id. If you also run the TikTok browser pixel, TikTok deduplicates server and browser events that share the same event_id, so conversions are not double-counted.

💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)