Skip to content

Commit

Permalink
ZRZ-1346 update to tiktok events api v2
Browse files Browse the repository at this point in the history
  • Loading branch information
ad-astra-via committed Jun 25, 2024
1 parent 8741278 commit 67a4482
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 36 deletions.
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

Find out more about Managed Components [here](https://blog.cloudflare.com/zaraz-open-source-managed-components-and-webcm/) for inspiration and motivation details.


[![Released under the Apache license.](https://img.shields.io/badge/license-apache-blue.svg)](./LICENSE)
[![PRs welcome!](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
Expand All @@ -21,7 +20,7 @@ Find out more about Managed Components [here](https://blog.cloudflare.com/zaraz-

`pixelCode` is a long number that identifies your Facebook Ads account.

### API Access Token _required_
### API Access Token _required_

`accessToken` is a string used to authenticate when sending server side events in your name. You can obtain it [following the information here](https://ads.tiktok.com/marketing_api/docs?id=1727537566862337n).

Expand All @@ -33,19 +32,30 @@ Find out more about Managed Components [here](https://blog.cloudflare.com/zaraz-

> Fields are properties that can/must be sent with certain events
### Tiktok Event Name `string` _required_
### Tiktok Standard Event Name `string` _required_

`ev` can be \"ContentView\", \"PlaceAnOrder\", \"Add to Cart\" one of [the standard Tiktok events](https://ads.tiktok.com/marketing_api/docs?id=1727541103358977).

### Custom Event Name `string` _required_

`cev` can be any custom event name. Do not use sensitive words in the name of Custom Events. [Learn more](https://business-api.tiktok.com/portal/docs?id=1771101303285761).

### Email `string`

`email` user email. Automatically hashed.

### Phone Number `string`
### Phone `string`

`phone_number` remove symbols, letters, and any leading zeros. Phone numbers must include a country code to be used for matching (e.g., the number 1 must precede a phone number in the United States). Always include the country code as part of your customers' phone numbers, even if all of your data is from the same country. Automatically hashed.
`phone` remove symbols, letters, and any leading zeros. Phone numbers must include a country code to be used for matching (e.g., the number 1 must precede a phone number in the United States). Always include the country code as part of your customers' phone numbers, even if all of your data is from the same country. Automatically hashed.

### External ID `string`

`external_id` can be `true` or `false`. If set to 'true', TikTok will recognize this parameter as a request for limited data processing, and will limit its processing activities accordingly if the event shared occurred in an eligible location. [Learn more](https://business-api.tiktok.com/portal/docs?id=1771101204435970).

### Limited Data Use `string`

`external_id` IDs that represent any unique identifier on the advertiser's side, such as loyalty membership IDs, user IDs, and external cookie IDs. Automatically hashed.

### TikTok Pixel Cookie ID `string`

`ttp` can be `_ttp` Cookie value. If you also use Pixel SDK and have enabled cookies, Pixel SDK automatically saves a unique identifier in the \_ttp cookie. The value of \_ttp is used to match website visitor events with TikTok ads. You can extract the value of \_ttp and attach the value here. [Learn more](https://business-api.tiktok.com/portal/docs?id=1771101303285761).
11 changes: 8 additions & 3 deletions src/ecommerce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ const getContents = (payload: any) => {

return products.map((p: any) => {

Check warning on line 20 in src/ecommerce.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Unexpected any. Specify a different type

Check warning on line 20 in src/ecommerce.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Unexpected any. Specify a different type
return {
content_type: 'product',
price: p.price || payload.price,
quantity: p.quantity || 1,
content_id: p.sku || p.product_id || payload.sku || payload.product_id,
content_category: p.category || payload.category,
content_name: p.name || payload.name,
brand: p.brand || payload.brand,
}
})
}

const getValue = (payload: any) =>

Check warning on line 32 in src/ecommerce.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Unexpected any. Specify a different type

Check warning on line 32 in src/ecommerce.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Unexpected any. Specify a different type
payload.value || payload.price || payload.total || payload.revenue
payload.revenue || payload.total || payload.value || payload.price

const mapEcommerceData = (event: MCEvent) => {
const { payload } = event
Expand All @@ -40,10 +42,13 @@ const mapEcommerceData = (event: MCEvent) => {
properties.currency = data.currency

properties.contents = getContents(data)

if (properties.contents?.content_id) {
properties.content_type = 'product'
}
if (event.name === 'Products Searched') {
properties.query = data.query
}
properties.order_id = payload.order_id

return properties
}
Expand Down
20 changes: 14 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ const sendEvent = async (
settings: ComponentSettings
) => {
const tiktokEndpoint =
'https://business-api.tiktok.com/open_api/v1.3/pixel/track/'
'https://business-api.tiktok.com/open_api/v1.3/event/track/'

const requestBody = {
pixel_code: payload.properties.pixelCode || settings.pixelCode,
...payload,
...(settings.testKey && {
test_event_code: settings.testKey,
}),
event_source: payload.event_source || 'web',
event_source_id: payload.properties.pixelCode || settings.pixelCode,
data: {
...payload,
...(settings.testKey && {
test_event_code: settings.testKey,
}),
},
}

manager.fetch(tiktokEndpoint, {
Expand All @@ -34,6 +37,11 @@ export default async function (manager: Manager, settings: ComponentSettings) {
sendEvent(request, manager, settings)
})

manager.addEventListener('custom-event', async event => {
const request = await getRequestBody('event', event, settings)
sendEvent(request, manager, settings)
})

manager.addEventListener('pageview', async event => {
const request = await getRequestBody('pageview', event, settings)
sendEvent(request, manager, settings)
Expand Down
45 changes: 23 additions & 22 deletions src/track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { ComponentSettings, MCEvent } from '@managed-components/types'

const USER_DATA: Record<string, { hashed?: boolean }> = {
email: { hashed: true },
phone_number: { hashed: true },
phone: { hashed: true },
external_id: { hashed: true },
ttp: { hashed: false },
ttclid: { hashed: false },
locale: { hashed: false },
}

const getTtclid = (event: MCEvent) => {
Expand All @@ -29,23 +31,25 @@ const getBaseRequestBody = (

const body: { [k: string]: any } = {

Check warning on line 32 in src/track.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Unexpected any. Specify a different type

Check warning on line 32 in src/track.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Unexpected any. Specify a different type
event:
(eventType === 'pageview' ? 'Pageview' : payload.ev) ||
(eventType === 'pageview' ? 'ViewContent' : payload.ev) ||
payload.cev ||
event.name ||
event.type,
event_id: eventId,
timestamp: new Date(client.timestamp! * 1000).toISOString(),
context: {
page: {
url: client.url.href,
},
event_time: new Date(client.timestamp! * 1000).toISOString(),

Check warning on line 39 in src/track.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Forbidden non-null assertion

Check warning on line 39 in src/track.ts

View workflow job for this annotation

GitHub Actions / build-test (20.x)

Forbidden non-null assertion
user: {
...(!settings.hideClientIP && {
user_agent: client.userAgent,
ip: client.ip,
}),
user: {},
ad: {},
},
page: {
url: client.url.href,
referrer: client.referer || '',
},
ad: {},
properties: {},
limited_data_use: payload.ldu,
}
delete payload.ev

Expand All @@ -60,10 +64,12 @@ export const getRequestBody = async (
// an array containing built-in fields that must be kept up to date!
const builtInFields = [
'ev',
'cev',
'email',
'phone_number',
'phone',
'external_id',
'event_id',
'ldu',
]

let payload
Expand All @@ -81,6 +87,12 @@ export const getRequestBody = async (
const ttclid = getTtclid(event)
const body = getBaseRequestBody(eventType, event, settings)

if (ttclid) {
payload.ttclid = ttclid
body.ad = {
callback: ttclid,
}
}
// appending hashed user data
const encoder = new TextEncoder()
for (const [key, options] of Object.entries(USER_DATA)) {
Expand All @@ -92,7 +104,7 @@ export const getRequestBody = async (
const hashArray = Array.from(new Uint8Array(digest))
value = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
}
body.context.user[key] = value
body.user[key] = value
delete payload[key]
}
}
Expand All @@ -103,16 +115,5 @@ export const getRequestBody = async (
}
}

const ttpFromCookie = event.client.get('_ttp')
if (!body.context.user.ttp && ttpFromCookie) {
body.context.user.ttp = ttpFromCookie
}

if (ttclid) {
body.context.ad = {
callback: ttclid,
}
}

return body
}

0 comments on commit 67a4482

Please sign in to comment.