-
Notifications
You must be signed in to change notification settings - Fork 229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update TikTok Pixel Destination #1937
Changes from 4 commits
9376af1
285cee3
cb531d1
fd5ed26
a26ffe2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import { InputField } from '@segment/actions-core' | ||
|
||
export const commonFields: Record<string, InputField> = { | ||
event: { | ||
label: 'Event Name', | ||
type: 'string', | ||
required: true, | ||
description: | ||
'Conversion event name. Please refer to the "Supported Web Events" section on in TikTok’s [Pixel SDK documentation](https://business-api.tiktok.com/portal/docs?id=1739585696931842) for accepted event names.' | ||
}, | ||
event_id: { | ||
label: 'Event ID', | ||
type: 'string', | ||
description: 'Any hashed ID that can identify a unique user/session.', | ||
default: { | ||
'@path': '$.messageId' | ||
} | ||
}, | ||
phone_number: { | ||
label: 'Phone Number', | ||
description: | ||
'A single phone number in E.164 standard format. TikTok Pixel will hash this value before sending to TikTok. e.g. +14150000000. Segment will hash this value before sending to TikTok.', | ||
type: 'string', | ||
multiple: true, | ||
default: { | ||
'@if': { | ||
exists: { '@path': '$.properties.phone' }, | ||
then: { '@path': '$.properties.phone' }, | ||
else: { '@path': '$.context.traits.phone' } | ||
} | ||
} | ||
}, | ||
email: { | ||
label: 'Email', | ||
description: 'A single email address. TikTok Pixel will be hash this value before sending to TikTok.', | ||
type: 'string', | ||
multiple: true, | ||
default: { | ||
'@if': { | ||
exists: { '@path': '$.properties.email' }, | ||
then: { '@path': '$.properties.email' }, | ||
else: { '@path': '$.context.traits.email' } | ||
} | ||
} | ||
}, | ||
order_id: { | ||
label: 'Order ID', | ||
type: 'string', | ||
description: 'Order ID of the transaction.', | ||
default: { | ||
'@path': '$.properties.order_id' | ||
} | ||
}, | ||
shop_id: { | ||
label: 'Shop ID', | ||
type: 'string', | ||
description: 'Shop ID of the transaction.', | ||
default: { | ||
'@path': '$.properties.shop_id' | ||
} | ||
}, | ||
external_id: { | ||
label: 'External ID', | ||
description: | ||
'Uniquely identifies the user who triggered the conversion event. TikTok Pixel will hash this value before sending to TikTok.', | ||
type: 'string', | ||
multiple: true, | ||
default: { | ||
'@if': { | ||
exists: { '@path': '$.userId' }, | ||
then: { '@path': '$.userId' }, | ||
else: { '@path': '$.anonymousId' } | ||
} | ||
} | ||
}, | ||
contents: { | ||
label: 'Contents', | ||
type: 'object', | ||
multiple: true, | ||
description: 'Related item details for the event.', | ||
properties: { | ||
price: { | ||
label: 'Price', | ||
description: 'Price of the item.', | ||
type: 'number' | ||
}, | ||
quantity: { | ||
label: 'Quantity', | ||
description: 'Number of items.', | ||
type: 'number' | ||
}, | ||
content_category: { | ||
label: 'Content Category', | ||
description: 'Category of the product item.', | ||
type: 'string' | ||
}, | ||
content_id: { | ||
label: 'Content ID', | ||
description: 'ID of the product item.', | ||
type: 'string' | ||
}, | ||
content_name: { | ||
label: 'Content Name', | ||
description: 'Name of the product item.', | ||
type: 'string' | ||
}, | ||
brand: { | ||
label: 'Brand', | ||
description: 'Brand name of the product item.', | ||
type: 'string' | ||
} | ||
} | ||
}, | ||
content_type: { | ||
label: 'Content Type', | ||
description: | ||
'Type of the product item. When the `content_id` in the `Contents` field is specified as a `sku_id`, set this field to `product`. When the `content_id` in the `Contents` field is specified as an `item_group_id`, set this field to `product_group`.', | ||
type: 'string', | ||
choices: [ | ||
{ label: 'product', value: 'product' }, | ||
{ label: 'product_group', value: 'product_group' } | ||
], | ||
default: 'product' | ||
}, | ||
currency: { | ||
label: 'Currency', | ||
type: 'string', | ||
description: 'Currency for the value specified as ISO 4217 code.', | ||
default: { | ||
'@path': '$.properties.currency' | ||
} | ||
}, | ||
value: { | ||
label: 'Value', | ||
type: 'number', | ||
description: 'Value of the order or items sold.', | ||
default: { | ||
'@if': { | ||
exists: { '@path': '$.properties.value' }, | ||
then: { '@path': '$.properties.value' }, | ||
else: { '@path': '$.properties.revenue' } | ||
} | ||
} | ||
}, | ||
description: { | ||
label: 'Description', | ||
type: 'string', | ||
description: 'A string description of the web event.' | ||
}, | ||
query: { | ||
label: 'Query', | ||
type: 'string', | ||
description: 'The text string that was searched for.', | ||
default: { | ||
'@path': '$.properties.query' | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -19,11 +19,17 @@ const productProperties = { | |||||
quantity: { | ||||||
'@path': '$.quantity' | ||||||
}, | ||||||
content_type: { | ||||||
content_category: { | ||||||
'@path': '$.category' | ||||||
}, | ||||||
content_id: { | ||||||
'@path': '$.product_id' | ||||||
}, | ||||||
content_name: { | ||||||
'@path': '$.name' | ||||||
}, | ||||||
brand: { | ||||||
'@path': '$.brand' | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -57,16 +63,66 @@ export const destination: BrowserDestinationDefinition<Settings, TikTokPixel> = | |||||
slug: 'actions-tiktok-pixel', | ||||||
mode: 'device', | ||||||
presets: [ | ||||||
{ | ||||||
name: 'Complete Payment', | ||||||
subscribe: 'event = "Order Completed"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...multiProductContents, | ||||||
event: 'CompletePayment' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'Contact', | ||||||
subscribe: 'event = "Callback Started"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...defaultValues(reportWebEvent.fields), | ||||||
event: 'Contact' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'Subscribe', | ||||||
subscribe: 'event = "Subscription Created"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...defaultValues(reportWebEvent.fields), | ||||||
event: 'Subscribe' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'Submit Form', | ||||||
subscribe: 'event = "Form Submitted"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...defaultValues(reportWebEvent.fields), | ||||||
event: 'SubmitForm' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'View Content', | ||||||
subscribe: 'type="page"', | ||||||
subscribe: 'event = "Product Viewed"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...singleProductContents, | ||||||
event: 'ViewContent' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'Click Button', | ||||||
subscribe: 'event = "Product Clicked"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...singleProductContents, | ||||||
event: 'ClickButton' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'Search', | ||||||
subscribe: 'event = "Products Searched"', | ||||||
|
@@ -119,13 +175,33 @@ export const destination: BrowserDestinationDefinition<Settings, TikTokPixel> = | |||||
}, | ||||||
{ | ||||||
name: 'Place an Order', | ||||||
subscribe: 'event = "Order Completed"', | ||||||
subscribe: 'event = "Order Placed"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...multiProductContents, | ||||||
event: 'PlaceAnOrder' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'Download', | ||||||
subscribe: 'event = "Download Link Clicked"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...defaultValues(reportWebEvent.fields), | ||||||
event: 'Download' | ||||||
}, | ||||||
type: 'automatic' | ||||||
}, | ||||||
{ | ||||||
name: 'Complete Registration', | ||||||
subscribe: 'event = "Signed Up"', | ||||||
partnerAction: 'reportWebEvent', | ||||||
mapping: { | ||||||
...defaultValues(reportWebEvent.fields), | ||||||
event: 'CompleteRegistration' | ||||||
}, | ||||||
type: 'automatic' | ||||||
} | ||||||
], | ||||||
settings: { | ||||||
|
@@ -136,16 +212,24 @@ export const destination: BrowserDestinationDefinition<Settings, TikTokPixel> = | |||||
"Your TikTok Pixel ID. Please see TikTok's [Pixel documentation](https://ads.tiktok.com/marketing_api/docs?id=1739583652957185) for information on how to find this value.", | ||||||
required: true | ||||||
}, | ||||||
useExistingPixel: { | ||||||
label: 'Use Existing Pixel', | ||||||
ldu: { | ||||||
label: 'Limited Data Use', | ||||||
type: 'boolean', | ||||||
description: | ||||||
'Important! Changing this setting may block data collection to Segment if not done correctly. Select "true" to use an existing TikTok Pixel which is already installed on your website. The Pixel MUST be installed on your website when this is set to "true" or all data collection to Segment may fail.' | ||||||
'In order to help facilitate advertiser\'s compliance with the right to opt-out of sale and sharing of personal data under certain U.S. state privacy laws, TikTok offers a Limited Data Use ("LDU") feature. For more information, please refer to TikTok\'s [documentation page](https://business-api.tiktok.com/portal/docs?id=1770092377990145).' | ||||||
}, | ||||||
useExistingPixel: { | ||||||
// TODO: HOW TO DELETE (reusing will not include Segment Partner name) | ||||||
label: '[Deprecated]Use Existing Pixel', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
type: 'boolean', | ||||||
default: false, | ||||||
required: false, | ||||||
description: 'Deprecated. Please do not provide any value.' | ||||||
} | ||||||
jae-rhee-tiktok marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
}, | ||||||
initialize: async ({ settings }, deps) => { | ||||||
if (!settings.useExistingPixel) { | ||||||
initScript(settings.pixelCode) | ||||||
initScript(settings) | ||||||
} | ||||||
await deps.resolveWhen(() => window.ttq != null, 100) | ||||||
return window.ttq | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,3 +16,8 @@ export function formatPhone(phone: string | undefined): string | undefined { | |
formattedPhone = formattedPhone.substring(0, 15) | ||
return formattedPhone | ||
} | ||
|
||
export function handleArrayInput(array: string[] | undefined): string { | ||
if (!array) return '' | ||
return array[0] | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we also handle the case where 'array' is empty? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you are changing this from a string to be a string array. It should be fine, but is this deliberate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to be a string array to match the s2s destination mappings, so that clients can re-use the same mappings for both Pixel & S2S destinations.