From e2207d3e6112dd5b5439ff8841cdef0bf10e55bf Mon Sep 17 00:00:00 2001 From: Jaehyuk Rhee Date: Thu, 18 Sep 2025 15:47:08 -0400 Subject: [PATCH 1/3] tiktok pixel sdk crm update --- .../src/identify/generated-types.ts | 16 ++ .../tiktok-pixel/src/identify/index.ts | 2 +- .../src/reportWebEvent/constants.ts | 4 + .../fields}/common_fields.ts | 46 ++++ .../src/reportWebEvent/fields/crm_fields.ts | 48 ++++ .../reportWebEvent/fields/travel_fields.ts | 216 +++++++++++++++ .../reportWebEvent/fields/vehicle_fields.ts | 255 ++++++++++++++++++ .../src/reportWebEvent/generated-types.ts | 16 ++ .../tiktok-pixel/src/reportWebEvent/index.ts | 12 +- .../destinations/tiktok-pixel/src/types.ts | 118 +++++--- .../destinations/tiktok-pixel/src/utils.ts | 2 + 11 files changed, 701 insertions(+), 34 deletions(-) create mode 100644 packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts rename packages/browser-destinations/destinations/tiktok-pixel/src/{ => reportWebEvent/fields}/common_fields.ts (83%) create mode 100644 packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts create mode 100644 packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts create mode 100644 packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/vehicle_fields.ts create mode 100644 packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/generated-types.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/generated-types.ts index ac49bf05424..5cef7f60c71 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/generated-types.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/generated-types.ts @@ -1,6 +1,10 @@ // Generated file. DO NOT MODIFY IT BY HAND. export interface Payload { + /** + * Include fields for travel or vehicle events. + */ + event_spec_type?: string /** * 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. */ @@ -87,6 +91,14 @@ export interface Payload { */ brand?: string }[] + /** + * Product IDs associated with the event, such as SKUs. Do not populate this field if the 'Contents' field is populated. This field accepts a single string value or an array of string values. + */ + content_ids?: string[] + /** + * Number of items when checkout was initiated. Used with the InitiateCheckout event. + */ + num_items?: number /** * 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`. */ @@ -107,4 +119,8 @@ export interface Payload { * The text string that was searched for. */ query?: string + /** + * The text string entered by the user for the search. Optionally used with the Search event. + */ + search_string?: string } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts index e73bae13630..b0f81793358 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts @@ -3,7 +3,7 @@ import type { Settings } from '../generated-types' import type { Payload } from './generated-types' import { formatPhone, handleArrayInput, formatString, formatAddress } from '../formatter' import { TikTokPixel } from '../types' -import { commonFields } from '../common_fields' +import { commonFields } from '../reportWebEvent/fields/common_fields' // Change from unknown to the partner SDK types const action: BrowserActionDefinition = { diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts new file mode 100644 index 00000000000..e3986781f3e --- /dev/null +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts @@ -0,0 +1,4 @@ +export const VEHICLE_FIELDS = 'vehicle_fields' +export const TRAVEL_FIELDS = 'travel_fields' +export const WEB = 'web' +export const CRM = 'crm' diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/common_fields.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/common_fields.ts similarity index 83% rename from packages/browser-destinations/destinations/tiktok-pixel/src/common_fields.ts rename to packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/common_fields.ts index e4111ed6ef5..9b656325410 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/common_fields.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/common_fields.ts @@ -1,6 +1,17 @@ import { InputField } from '@segment/actions-core' +import { VEHICLE_FIELDS, TRAVEL_FIELDS, CRM } from '../constants' export const commonFields: Record = { + event_spec_type: { + label: 'Additional Fields', + type: 'string', + description: 'Include fields for travel or vehicle events.', + choices: [ + { value: CRM, label: 'CRM Fields' }, + { value: TRAVEL_FIELDS, label: 'Travel Fields' }, + { value: VEHICLE_FIELDS, label: 'Vehicle Fields' } + ] + }, event: { label: 'Event Name', type: 'string', @@ -195,6 +206,24 @@ export const commonFields: Record = { } } }, + content_ids: { + label: 'Content IDs', + description: + "Product IDs associated with the event, such as SKUs. Do not populate this field if the 'Contents' field is populated. This field accepts a single string value or an array of string values.", + type: 'string', + multiple: true, + default: { + '@path': '$.properties.content_ids' + } + }, + num_items: { + label: 'Number of Items', + type: 'number', + description: 'Number of items when checkout was initiated. Used with the InitiateCheckout event.', + default: { + '@path': '$.properties.num_items' + } + }, content_type: { label: 'Content Type', description: @@ -238,5 +267,22 @@ export const commonFields: Record = { default: { '@path': '$.properties.query' } + }, + search_string: { + label: 'Search String', + type: 'string', + description: 'The text string entered by the user for the search. Optionally used with the Search event.', + default: { + '@path': '$.properties.search_string' + }, + depends_on: { + conditions: [ + { + fieldKey: 'event', + operator: 'is', + value: 'Search' + } + ] + } } } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts new file mode 100644 index 00000000000..b9c1486cda1 --- /dev/null +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts @@ -0,0 +1,48 @@ +import { InputField } from '@segment/actions-core' +import { CRM } from '../constants' + +export const crm_fields: Record = { + lead_fields: { + label: 'CRM Fields', + type: 'object', + description: 'Fields related to CRM events.', + additionalProperties: false, + defaultObjectUI: 'keyvalue', + properties: { + lead_id: { + label: 'TikTok Lead ID', + description: + 'ID of TikTok leads. Every lead will have its own lead_id when exported from TikTok. This feature is in Beta. Please contact your TikTok representative to inquire regarding availability', + type: 'string' + }, + lead_event_source: { + label: 'TikTok Lead Event Source', + description: + 'Lead source of TikTok leads. Please set this field to the name of your CRM system, such as HubSpot or Salesforce.', + type: 'string' + } + }, + default: { + lead_id: { '@path': '$.properties.lead_id' }, + lead_event_source: { '@path': '$.properties.lead_event_source' } + }, + // required: { + // conditions: [ + // { + // fieldKey: 'event_source', + // operator: 'is', + // value: CRM + // } + // ] + // }, + depends_on: { + conditions: [ + { + fieldKey: 'event_spec_type', + operator: 'is', + value: CRM + } + ] + } + } +} diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts new file mode 100644 index 00000000000..ed67acd1280 --- /dev/null +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts @@ -0,0 +1,216 @@ +import { InputField } from '@segment/actions-core' +import { TRAVEL_FIELDS } from '../constants' + +export const travel_fields: InputField = { + label: 'Travel Fields', + type: 'object', + description: 'Fields related to travel events.', + additionalProperties: false, + defaultObjectUI: 'keyvalue', + properties: { + city: { + label: 'Hotel City Location', + type: 'string', + description: 'Hotel city location.' + }, + region: { + label: 'Hotel Region', + type: 'string', + description: 'Hotel region location.' + }, + country: { + label: 'Hotel Country', + type: 'string', + description: 'Hotel country location.' + }, + checkin_date: { + label: 'Hotel Check-in Date', + type: 'string', + description: 'Hotel check-in date.' + }, + checkout_date: { + label: 'Hotel Check-out Date', + type: 'string', + description: 'Hotel check-out date.' + }, + num_adults: { + label: 'Number of Adults', + type: 'number', + description: 'Number of adults.' + }, + num_children: { + label: 'Number of Children', + type: 'number', + description: 'Number of children.' + }, + num_infants: { + label: 'Number of Infants', + type: 'number', + description: 'Number of infants flying.' + }, + suggested_hotels: { + label: 'Suggested Hotels', + description: 'Suggested hotels. This can be a single string value or an array of string values.', + type: 'string', + multiple: true + }, + departing_departure_date: { + label: 'Departure Date', + type: 'string', + description: + 'Date of flight departure. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD' + }, + returning_departure_date: { + label: 'Arrival Date', + type: 'string', + description: + 'Date of return flight. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD' + }, + origin_airport: { + label: 'Origin Airport', + type: 'string', + description: 'Origin airport.' + }, + destination_airport: { + label: 'Destination Airport', + type: 'string', + description: 'Destination airport.' + }, + destination_ids: { + label: 'Destination IDs', + description: + 'If a client has a destination catalog, the client can associate one or more destinations in the catalog with a specific flight event. For instance, link a particular route to a nearby museum and a nearby beach, both of which are destinations in the catalog. This field accepts a single string value or an array of string values.', + type: 'string', + multiple: true + }, + departing_arrival_date: { + label: 'Departing Arrival Date', + type: 'string', + description: + 'The date and time for arrival at the destination of the outbound journey. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD' + }, + returning_arrival_date: { + label: 'Returning Arrival Date', + type: 'string', + description: + 'The date and time when the return journey is completed. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD' + }, + travel_class: { + label: 'Flight Ticket Class', + type: 'string', + description: 'Class of the flight ticket, must be: "eco", "prem", "bus", "first".', + choices: [ + { value: 'eco', label: 'Economy' }, + { value: 'prem', label: 'Premium' }, + { value: 'bus', label: 'Bus' }, + { value: 'first', label: 'First' } + ] + }, + user_score: { + label: 'User Score', + type: 'number', + description: 'Represents the relative value of this potential customer to advertiser.' + }, + preferred_num_stops: { + label: 'Preferred Number of Stops', + type: 'integer', + description: 'The preferred number of stops the user is looking for. 0 for direct flight.' + }, + travel_start: { + label: 'Start Date of the Trip', + type: 'string', + description: + "The start date of user's trip. Accept date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD." + }, + travel_end: { + label: 'End Date of the Trip', + type: 'string', + description: + "The end date of user's trip. Accept date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD." + }, + suggested_destinations: { + label: 'Suggested Destination IDs', + description: + 'A list of IDs representing destination suggestions for this user. This parameter is not applicable for the Search event. This field accepts a single string value or an array of string values.', + type: 'string', + multiple: true + } + }, + default: { + city: { + '@path': '$.properties.city' + }, + region: { + '@path': '$.properties.region' + }, + country: { + '@path': '$.properties.country' + }, + checkin_date: { + '@path': '$.properties.checkin_date' + }, + checkout_date: { + '@path': '$.properties.checkout_date' + }, + num_adults: { + '@path': '$.properties.num_adults' + }, + num_children: { + '@path': '$.properties.num_children' + }, + num_infants: { + '@path': '$.properties.num_infants' + }, + suggested_hotels: { + '@path': '$.properties.suggested_hotels' // Confirmed this can be a single string or an array of strings + }, + departing_departure_date: { + '@path': '$.properties.departing_departure_date' + }, + returning_departure_date: { + '@path': '$.properties.returning_departure_date' + }, + origin_airport: { + '@path': '$.properties.origin_airport' + }, + destination_airiport: { + '@path': '$.properties.destination_airiport' + }, + destination_ids: { + '@path': '$.properties.destination_ids' // Confirmed this can be a single string or an array of strings + }, + departing_arrival_date: { + '@path': '$.properties.departing_arrival_date' + }, + returning_arrival_date: { + '@path': '$.properties.returning_arrival_date' + }, + travel_class: { + '@path': '$.properties.travel_class' + }, + user_score: { + '@path': '$.properties.user_score' + }, + preferred_num_stops: { + '@path': '$.properties.preferred_num_stops' + }, + travel_start: { + '@path': '$.properties.travel_start' + }, + travel_end: { + '@path': '$.properties.travel_end' + }, + suggested_destinations: { + '@path': '$.properties.suggested_destinations' // Confirmed this can be a single string or an array of strings + } + }, + depends_on: { + conditions: [ + { + fieldKey: 'event_spec_type', + operator: 'is', + value: TRAVEL_FIELDS + } + ] + } +} diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/vehicle_fields.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/vehicle_fields.ts new file mode 100644 index 00000000000..7d916a84781 --- /dev/null +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/vehicle_fields.ts @@ -0,0 +1,255 @@ +import { InputField } from '@segment/actions-core' +import { VEHICLE_FIELDS } from '../constants' + +export const vehicle_fields: InputField = { + label: 'Vehicle Fields', + type: 'object', + description: 'Fields related to vehicle events.', + additionalProperties: false, + defaultObjectUI: 'keyvalue', + properties: { + postal_code: { + label: 'Postal Code', + type: 'string', + description: 'Postal code for the vehicle location.' + }, + make: { + label: 'Make of the Vehicle', + type: 'string', + description: 'Vehicle make/brand/manufacturer.' + }, + model: { + label: 'Model of the Vehicle', + type: 'string', + description: 'Vehicle model.' + }, + year: { + label: 'Year of the Vehicle', + type: 'number', + description: 'Year the vehicle was laucned in yyyy format.' + }, + state_of_vehicle: { + label: 'State of the Vehicle', + type: 'string', + description: 'Vehicle status.', + choices: [ + { value: 'New', label: 'New' }, + { value: 'Used', label: 'Used' }, + { value: 'CPO', label: 'CPO' } + ] + }, + mileage_value: { + label: 'Mileage Value', + type: 'number', + description: 'Vehicle mileage (in km or miles). Zero (0) for new vehicle.' + }, + mileage_unit: { + label: 'Mileage Unit', + type: 'string', + description: 'Mileage unites in miles (MI) or kilometers (KM).', + choices: [ + { value: 'MI', label: 'Miles' }, + { value: 'KM', label: 'Kilometers' } + ] + }, + exterior_color: { + label: 'Exterior Color of the Vehicle', + type: 'string', + description: 'Vehicle exterior color.' + }, + transmission: { + label: 'Transmission Type of the Vehicle', + type: 'string', + description: 'Vehicle transmission type.', + choices: [ + { value: 'Automatic', label: 'Automatic' }, + { value: 'Manual', label: 'Manual' }, + { value: 'Other', label: 'Other' } + ] + }, + body_style: { + label: 'Body Type of the Vehicle', + type: 'string', + description: 'Vehicle body type.', + choices: [ + { value: 'Convertible', label: 'Convertible' }, + { value: 'Coupe', label: 'Coupe' }, + { value: 'Hatchback', label: 'Hatchback' }, + { value: 'Minivan', label: 'Minivan' }, + { value: 'Truck', label: 'Truck' }, + { value: 'SUV', label: 'SUV' }, + { value: 'Sedan', label: 'Sedan' }, + { value: 'Van', label: 'Van' }, + { value: 'Wagon', label: 'Wagon' }, + { value: 'Crossover', label: 'Crossover' }, + { value: 'Other', label: 'Other' } + ] + }, + fuel_type: { + label: 'Fuel Type of the Vehicle', + type: 'string', + description: 'Vehicle fuel type.', + choices: [ + { value: 'Diesel', label: 'Diesel' }, + { value: 'Electric', label: 'Electric' }, + { value: 'Flex', label: 'Flex' }, + { value: 'Gasoline', label: 'Gasoline' }, + { value: 'Hybrid', label: 'Hybrid' }, + { value: 'Other', label: 'Other' } + ] + }, + drivetrain: { + label: 'Drivetrain of the Vehicle', + type: 'string', + description: 'Vehicle drivetrain.', + choices: [ + { value: 'AWD', label: 'AWD' }, + { value: 'FOUR_WD', label: 'Four WD' }, + { value: 'FWD', label: 'FWD' }, + { value: 'RWD', label: 'RWD' }, + { value: 'TWO_WD', label: 'Two WD' }, + { value: 'Other', label: 'Other' } + ] + }, + preferred_price_range_min: { + label: 'Minimum Preferred Price', + type: 'number', + description: 'Minimum preferred price of the vehicle.' + }, + preferred_price_range_max: { + label: 'Maximum Preferred Price', + type: 'number', + description: 'Maximum preferred price of the vehicle.' + }, + trim: { + label: 'Trim of the Vehicle', + type: 'string', + description: 'Vehicle trim.' + }, + vin: { + label: 'VIN of the Vehicle', + type: 'string', + description: 'Vehicle identification number. Maximum characters: 17.' + }, + interior_color: { + label: 'Interior Color of the Vehicle', + type: 'string', + description: 'Vehicle interior color.' + }, + condition_of_vehicle: { + label: 'Condition of the Vehicle', + type: 'string', + description: 'Vehicle drivetrain.', + choices: [ + { value: 'Excellent', label: 'Excellent' }, + { value: 'Good', label: 'Good' }, + { value: 'Fair', label: 'Fair' }, + { value: 'Poor', label: 'Poor' }, + { value: 'Other', label: 'Other' } + ] + }, + viewcontent_type: { + label: 'Soft Lead Landing Page', + type: 'string', + description: 'Optional for ViewContent. Use viewcontent_type to differentiate between soft lead landing pages.', + depends_on: { + match: 'any', + conditions: [{ fieldKey: 'event', operator: 'is', value: 'ViewContent' }] + } + }, + search_type: { + label: 'Other Search Page', + type: 'string', + description: + 'Optional for Search. Use search_type to differentiate other user searches (such as dealer lookup) from inventory search.', + depends_on: { + match: 'any', + conditions: [{ fieldKey: 'event', operator: 'is', value: 'Search' }] + } + }, + registration_type: { + label: 'Other Registration Page', + type: 'string', + description: + 'Optional for CompleteRegistration. Use registration_type to differentiate between different types of customer registration on websites.', + depends_on: { + match: 'any', + conditions: [{ fieldKey: 'event', operator: 'is', value: 'CompleteRegistration' }] + } + } + }, + default: { + postal_code: { + '@path': '$.properties.postal_code' + }, + make: { + '@path': '$.properties.make' + }, + model: { + '@path': '$.properties.model' + }, + year: { + '@path': '$.properties.year' + }, + state_of_vehicle: { + '@path': '$.properties.state_of_vehicle' + }, + mileage_value: { + '@path': '$.properties.mileage_value' + }, + mileage_unit: { + '@path': '$.properties.mileage_unit' + }, + exterior_color: { + '@path': '$.properties.exterior_color' + }, + transmission: { + '@path': '$.properties.transmission' + }, + body_style: { + '@path': '$.properties.body_style' + }, + fuel_type: { + '@path': '$.properties.fuel_type' + }, + drivetrain: { + '@path': '$.properties.drive_train' + }, + preferred_price_range_min: { + '@path': '$.properties.preferred_price_range_min' + }, + preferred_price_range_max: { + '@path': '$.properties.preferred_price_range_max' + }, + trim: { + '@path': '$.properties.trim' + }, + vin: { + '@path': '$.properties.vin' + }, + interior_color: { + '@path': '$.properties.interior_color' + }, + condition_of_vehicle: { + '@path': '$.properties.condition_of_vehicle' + }, + viewcontent_type: { + '@path': '$.properties.viewcontent_type' + }, + search_type: { + '@path': '$.properties.search_type' + }, + registration_type: { + '@path': '$.properties.registration_type' + } + }, + depends_on: { + conditions: [ + { + fieldKey: 'event_spec_type', + operator: 'is', + value: VEHICLE_FIELDS + } + ] + } +} diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts index ac49bf05424..5cef7f60c71 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts @@ -1,6 +1,10 @@ // Generated file. DO NOT MODIFY IT BY HAND. export interface Payload { + /** + * Include fields for travel or vehicle events. + */ + event_spec_type?: string /** * 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. */ @@ -87,6 +91,14 @@ export interface Payload { */ brand?: string }[] + /** + * Product IDs associated with the event, such as SKUs. Do not populate this field if the 'Contents' field is populated. This field accepts a single string value or an array of string values. + */ + content_ids?: string[] + /** + * Number of items when checkout was initiated. Used with the InitiateCheckout event. + */ + num_items?: number /** * 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`. */ @@ -107,4 +119,8 @@ export interface Payload { * The text string that was searched for. */ query?: string + /** + * The text string entered by the user for the search. Optionally used with the Search event. + */ + search_string?: string } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts index c5667254ceb..35bc0a0c25d 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts @@ -3,7 +3,10 @@ import type { Settings } from '../generated-types' import type { Payload } from './generated-types' import { formatPhone, handleArrayInput, formatString, formatAddress } from '../formatter' import { TikTokPixel } from '../types' -import { commonFields } from '../common_fields' +import { commonFields } from './fields/common_fields' +import { crm_fields } from './fields/crm_fields' +import { travel_fields } from './fields/travel_fields' +import { vehicle_fields } from './fields/vehicle_fields' const action: BrowserActionDefinition = { title: 'Report Web Event', @@ -12,11 +15,14 @@ const action: BrowserActionDefinition = { platform: 'web', defaultSubscription: 'type = "track"', fields: { - ...commonFields + ...commonFields, + ...crm_fields, + vehicle_fields, + travel_fields }, perform: (ttq, { payload, settings }) => { if (payload.email || payload.phone_number || payload.external_id) { - ttq.identify({ + ttq.instance(settings.pixelCode).identify({ email: handleArrayInput(payload.email), phone_number: formatPhone(handleArrayInput(payload.phone_number)), external_id: handleArrayInput(payload.external_id), diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts index 93042f663dd..1653a1e32d2 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts @@ -11,17 +11,7 @@ export interface TikTokPixel { state, country, zip_code - }: { - email: string | undefined - phone_number: string | undefined - external_id: string | undefined - first_name: string | undefined - last_name: string | undefined - city: string | undefined - state: string | undefined - country: string | undefined - zip_code: string | undefined - }) => void + }: TTUser) => void track: ( event: string, { @@ -33,25 +23,7 @@ export interface TikTokPixel { query, order_id, shop_id - }: { - contents: - | { - price?: number | undefined - quantity?: number | undefined - content_category?: string | undefined - content_id?: string | undefined - content_name?: string | undefined - brand?: string | undefined - }[] - | [] - content_type: string | undefined - currency: string | undefined - value: number | undefined - description: string | undefined - query: string | undefined - order_id: string | undefined - shop_id: string | undefined - }, + }: TTBaseProps & TTTravelProps & TTAutoProps, { event_id }: { @@ -59,3 +31,89 @@ export interface TikTokPixel { } ) => void } + +export interface TTUser { + external_id: string + phone_number: string | undefined + email: string + locale?: string + first_name?: string + last_name?: string + city?: string + state?: string + country?: string + zip_code?: string +} + +export interface TTBaseProps { + contents: TTContentItem[] + content_type?: string + currency?: string + value?: number + query?: string + description?: string + order_id?: string + shop_id?: string + content_ids?: string[] + num_items?: number + search_string?: string +} + +export interface TTTravelProps { + city?: string + region?: string + country?: string + checkin_date?: string + checkout_date?: string + num_adults?: number + num_children?: number + num_infants?: number + suggested_hotels?: string[] + departing_departure_date?: string + returning_departure_date?: string + origin_airport?: string + destination_airiport?: string + destination_ids?: string[] + departing_arrival_date?: string + returning_arrival_date?: string + travel_class?: string + user_score?: number + preferred_num_stops?: number + travel_start?: string + travel_end?: string + suggested_destinations?: string[] +} + +export interface TTAutoProps { + postal_code?: string + make?: string + model?: string + year?: number + state_of_vehicle?: string + mileage?: { + value?: number + unit?: string + } + exterior_color?: string + transmission?: string + body_style?: string + fuel_type?: string + drivetrain?: string + preferred_price_range?: number[] + trim?: string + vin?: string + interior_color?: string + condition_of_vehicle?: string + viewcontent_type?: string + search_type?: string + registration_type?: string +} + +interface TTContentItem { + price?: number + quantity?: number + content_category?: string + content_id?: string + content_name?: string + brand?: string +} diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts new file mode 100644 index 00000000000..7c60225d791 --- /dev/null +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts @@ -0,0 +1,2 @@ + +// function getUser(payload: Payload) \ No newline at end of file From d621d7ef15fd5ad490445221aceb70d09bfaa103 Mon Sep 17 00:00:00 2001 From: Jaehyuk Rhee Date: Thu, 25 Sep 2025 13:56:20 -0400 Subject: [PATCH 2/3] add new params for pixel sdk --- .../tiktok-pixel/src/identify/index.ts | 16 +- .../src/reportWebEvent/constants.ts | 2 - .../reportWebEvent/fields/common_fields.ts | 3 +- .../src/reportWebEvent/fields/crm_fields.ts | 48 ----- .../src/reportWebEvent/generated-types.ts | 182 ++++++++++++++++++ .../tiktok-pixel/src/reportWebEvent/index.ts | 36 +--- .../tiktok-pixel/src/reportWebEvent/utils.ts | 167 ++++++++++++++++ .../destinations/tiktok-pixel/src/types.ts | 48 ++++- .../destinations/tiktok-pixel/src/utils.ts | 21 +- 9 files changed, 425 insertions(+), 98 deletions(-) delete mode 100644 packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts create mode 100644 packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts index b0f81793358..525e1ff5ea0 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts @@ -1,7 +1,7 @@ import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' import type { Settings } from '../generated-types' import type { Payload } from './generated-types' -import { formatPhone, handleArrayInput, formatString, formatAddress } from '../formatter' +import { getUserObject } from '../utils' import { TikTokPixel } from '../types' import { commonFields } from '../reportWebEvent/fields/common_fields' @@ -40,19 +40,9 @@ const action: BrowserActionDefinition = { } } }, - perform: (ttq, { payload }) => { + perform: (ttq, { payload, settings }) => { if (payload.email || payload.phone_number || payload.external_id) { - ttq.identify({ - email: handleArrayInput(payload.email), - phone_number: formatPhone(handleArrayInput(payload.phone_number)), - external_id: handleArrayInput(payload.external_id), - first_name: formatString(payload.first_name), - last_name: formatString(payload.last_name), - city: formatAddress(payload.address?.city), - state: formatAddress(payload.address?.state), - country: formatAddress(payload.address?.country), - zip_code: formatString(payload.address?.zip_code) - }) + ttq.instance(settings.pixelCode).identify(getUserObject(payload)) } } } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts index e3986781f3e..9c10e826fa0 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/constants.ts @@ -1,4 +1,2 @@ export const VEHICLE_FIELDS = 'vehicle_fields' export const TRAVEL_FIELDS = 'travel_fields' -export const WEB = 'web' -export const CRM = 'crm' diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/common_fields.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/common_fields.ts index 9b656325410..772e9c37743 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/common_fields.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/common_fields.ts @@ -1,5 +1,5 @@ import { InputField } from '@segment/actions-core' -import { VEHICLE_FIELDS, TRAVEL_FIELDS, CRM } from '../constants' +import { VEHICLE_FIELDS, TRAVEL_FIELDS } from '../constants' export const commonFields: Record = { event_spec_type: { @@ -7,7 +7,6 @@ export const commonFields: Record = { type: 'string', description: 'Include fields for travel or vehicle events.', choices: [ - { value: CRM, label: 'CRM Fields' }, { value: TRAVEL_FIELDS, label: 'Travel Fields' }, { value: VEHICLE_FIELDS, label: 'Vehicle Fields' } ] diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts deleted file mode 100644 index b9c1486cda1..00000000000 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/crm_fields.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { InputField } from '@segment/actions-core' -import { CRM } from '../constants' - -export const crm_fields: Record = { - lead_fields: { - label: 'CRM Fields', - type: 'object', - description: 'Fields related to CRM events.', - additionalProperties: false, - defaultObjectUI: 'keyvalue', - properties: { - lead_id: { - label: 'TikTok Lead ID', - description: - 'ID of TikTok leads. Every lead will have its own lead_id when exported from TikTok. This feature is in Beta. Please contact your TikTok representative to inquire regarding availability', - type: 'string' - }, - lead_event_source: { - label: 'TikTok Lead Event Source', - description: - 'Lead source of TikTok leads. Please set this field to the name of your CRM system, such as HubSpot or Salesforce.', - type: 'string' - } - }, - default: { - lead_id: { '@path': '$.properties.lead_id' }, - lead_event_source: { '@path': '$.properties.lead_event_source' } - }, - // required: { - // conditions: [ - // { - // fieldKey: 'event_source', - // operator: 'is', - // value: CRM - // } - // ] - // }, - depends_on: { - conditions: [ - { - fieldKey: 'event_spec_type', - operator: 'is', - value: CRM - } - ] - } - } -} diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts index 5cef7f60c71..323cd7cdd92 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/generated-types.ts @@ -123,4 +123,186 @@ export interface Payload { * The text string entered by the user for the search. Optionally used with the Search event. */ search_string?: string + /** + * Fields related to vehicle events. + */ + vehicle_fields?: { + /** + * Postal code for the vehicle location. + */ + postal_code?: string + /** + * Vehicle make/brand/manufacturer. + */ + make?: string + /** + * Vehicle model. + */ + model?: string + /** + * Year the vehicle was laucned in yyyy format. + */ + year?: number + /** + * Vehicle status. + */ + state_of_vehicle?: string + /** + * Vehicle mileage (in km or miles). Zero (0) for new vehicle. + */ + mileage_value?: number + /** + * Mileage unites in miles (MI) or kilometers (KM). + */ + mileage_unit?: string + /** + * Vehicle exterior color. + */ + exterior_color?: string + /** + * Vehicle transmission type. + */ + transmission?: string + /** + * Vehicle body type. + */ + body_style?: string + /** + * Vehicle fuel type. + */ + fuel_type?: string + /** + * Vehicle drivetrain. + */ + drivetrain?: string + /** + * Minimum preferred price of the vehicle. + */ + preferred_price_range_min?: number + /** + * Maximum preferred price of the vehicle. + */ + preferred_price_range_max?: number + /** + * Vehicle trim. + */ + trim?: string + /** + * Vehicle identification number. Maximum characters: 17. + */ + vin?: string + /** + * Vehicle interior color. + */ + interior_color?: string + /** + * Vehicle drivetrain. + */ + condition_of_vehicle?: string + /** + * Optional for ViewContent. Use viewcontent_type to differentiate between soft lead landing pages. + */ + viewcontent_type?: string + /** + * Optional for Search. Use search_type to differentiate other user searches (such as dealer lookup) from inventory search. + */ + search_type?: string + /** + * Optional for CompleteRegistration. Use registration_type to differentiate between different types of customer registration on websites. + */ + registration_type?: string + } + /** + * Fields related to travel events. + */ + travel_fields?: { + /** + * Hotel city location. + */ + city?: string + /** + * Hotel region location. + */ + region?: string + /** + * Hotel country location. + */ + country?: string + /** + * Hotel check-in date. + */ + checkin_date?: string + /** + * Hotel check-out date. + */ + checkout_date?: string + /** + * Number of adults. + */ + num_adults?: number + /** + * Number of children. + */ + num_children?: number + /** + * Number of infants flying. + */ + num_infants?: number + /** + * Suggested hotels. This can be a single string value or an array of string values. + */ + suggested_hotels?: string[] + /** + * Date of flight departure. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD + */ + departing_departure_date?: string + /** + * Date of return flight. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD + */ + returning_departure_date?: string + /** + * Origin airport. + */ + origin_airport?: string + /** + * Destination airport. + */ + destination_airport?: string + /** + * If a client has a destination catalog, the client can associate one or more destinations in the catalog with a specific flight event. For instance, link a particular route to a nearby museum and a nearby beach, both of which are destinations in the catalog. This field accepts a single string value or an array of string values. + */ + destination_ids?: string[] + /** + * The date and time for arrival at the destination of the outbound journey. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD + */ + departing_arrival_date?: string + /** + * The date and time when the return journey is completed. Accepted date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD + */ + returning_arrival_date?: string + /** + * Class of the flight ticket, must be: "eco", "prem", "bus", "first". + */ + travel_class?: string + /** + * Represents the relative value of this potential customer to advertiser. + */ + user_score?: number + /** + * The preferred number of stops the user is looking for. 0 for direct flight. + */ + preferred_num_stops?: number + /** + * The start date of user's trip. Accept date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD. + */ + travel_start?: string + /** + * The end date of user's trip. Accept date formats: YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD. + */ + travel_end?: string + /** + * A list of IDs representing destination suggestions for this user. This parameter is not applicable for the Search event. This field accepts a single string value or an array of string values. + */ + suggested_destinations?: string[] + } } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts index 35bc0a0c25d..a785fd6d4a4 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts @@ -1,10 +1,10 @@ import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' import type { Settings } from '../generated-types' import type { Payload } from './generated-types' -import { formatPhone, handleArrayInput, formatString, formatAddress } from '../formatter' +import { getUserObject } from '../utils' +import { getProp } from './utils' import { TikTokPixel } from '../types' import { commonFields } from './fields/common_fields' -import { crm_fields } from './fields/crm_fields' import { travel_fields } from './fields/travel_fields' import { vehicle_fields } from './fields/vehicle_fields' @@ -16,41 +16,17 @@ const action: BrowserActionDefinition = { defaultSubscription: 'type = "track"', fields: { ...commonFields, - ...crm_fields, vehicle_fields, travel_fields }, perform: (ttq, { payload, settings }) => { if (payload.email || payload.phone_number || payload.external_id) { - ttq.instance(settings.pixelCode).identify({ - email: handleArrayInput(payload.email), - phone_number: formatPhone(handleArrayInput(payload.phone_number)), - external_id: handleArrayInput(payload.external_id), - first_name: formatString(payload.first_name), - last_name: formatString(payload.last_name), - city: formatAddress(payload.address?.city), - state: formatAddress(payload.address?.state), - country: formatAddress(payload.address?.country), - zip_code: formatString(payload.address?.zip_code) - }) + ttq.instance(settings.pixelCode).identify(getUserObject(payload)) } - ttq.instance(settings.pixelCode).track( - payload.event, - { - contents: payload.contents ? payload.contents : [], - content_type: payload.content_type ? payload.content_type : undefined, - currency: payload.currency ? payload.currency : 'USD', - value: payload.value || payload.value === 0 ? payload.value : undefined, - query: payload.query ? payload.query : undefined, - description: payload.description ? payload.description : undefined, - order_id: payload.order_id ? payload.order_id : undefined, - shop_id: payload.shop_id ? payload.shop_id : undefined - }, - { - event_id: payload.event_id ? payload.event_id : '' - } - ) + ttq.instance(settings.pixelCode).track(payload.event, getProp(payload), { + event_id: payload.event_id ? payload.event_id : '' + }) } } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts new file mode 100644 index 00000000000..c7d5ef9a9b9 --- /dev/null +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts @@ -0,0 +1,167 @@ +import { Payload } from './generated-types' +import { TTBaseProps, TTTravelProps, TTAutoProps } from '../types' +import { TRAVEL_FIELDS, VEHICLE_FIELDS } from './constants' + +export function getProp(payload: Payload): TTBaseProps & TTAutoProps & TTTravelProps { + const { event_spec_type } = payload + + return { + ...buildBaseProp(payload), + ...(event_spec_type === TRAVEL_FIELDS ? buildTravelProp(payload) : {}), + ...(event_spec_type === VEHICLE_FIELDS ? buildAutoProp(payload) : {}) + } +} + +function buildBaseProp(payload: Payload): TTBaseProps { + const { + content_type, + currency, + value, + query, + description, + order_id, + shop_id, + content_ids, + num_items, + search_string, + contents + } = payload + + const requestProperties: TTBaseProps = { + contents: contents + ? contents.map(({ price, quantity, content_category, content_id, content_name, brand }) => ({ + price: price ?? undefined, + quantity: quantity ?? undefined, + content_category: content_category ?? undefined, + content_id: content_id ?? undefined, + content_name: content_name ?? undefined, + brand: brand ?? undefined + })) + : [], + ...(content_type !== undefined && { content_type }), + ...(currency !== undefined && { currency }), + ...(value !== undefined && { value }), + ...(query !== undefined && { query }), + ...(description !== undefined && { description }), + ...(order_id !== undefined && { order_id }), + ...(shop_id !== undefined && { shop_id }), + ...(content_ids !== undefined && { content_ids }), + ...(num_items !== undefined && { num_items }), + ...(search_string !== undefined && { search_string }) + } + + return requestProperties +} + +function buildTravelProp(payload: Payload): TTTravelProps { + const { + city, + region, + country, + checkin_date, + checkout_date, + num_adults, + num_children, + num_infants, + suggested_hotels, + departing_departure_date, + returning_departure_date, + origin_airport, + destination_airport, + destination_ids, + departing_arrival_date, + returning_arrival_date, + travel_class, + user_score, + preferred_num_stops, + travel_start, + travel_end, + suggested_destinations + } = payload?.travel_fields ?? {} + + const requestProperties: TTTravelProps = { + ...(city !== undefined && { city }), + ...(region !== undefined && { region }), + ...(country !== undefined && { country }), + ...(checkin_date !== undefined && { checkin_date }), + ...(checkout_date !== undefined && { checkout_date }), + ...(num_adults !== undefined && { num_adults }), + ...(num_children !== undefined && { num_children }), + ...(num_infants !== undefined && { num_infants }), + ...(suggested_hotels !== undefined && { suggested_hotels }), + ...(departing_departure_date !== undefined && { departing_departure_date }), + ...(returning_departure_date !== undefined && { returning_departure_date }), + ...(origin_airport !== undefined && { origin_airport }), + ...(destination_airport !== undefined && { destination_airport }), + ...(destination_ids !== undefined && { destination_ids }), + ...(departing_arrival_date !== undefined && { departing_arrival_date }), + ...(returning_arrival_date !== undefined && { returning_arrival_date }), + ...(travel_class !== undefined && { travel_class }), + ...(user_score !== undefined && { user_score }), + ...(preferred_num_stops !== undefined && { preferred_num_stops }), + ...(travel_start !== undefined && { travel_start }), + ...(travel_end !== undefined && { travel_end }), + ...(suggested_destinations !== undefined && { suggested_destinations }) + } + + return requestProperties +} + +function buildAutoProp(payload: Payload): TTAutoProps { + const { + postal_code, + make, + model, + year, + state_of_vehicle, + mileage_unit, + mileage_value, + exterior_color, + transmission, + body_style, + fuel_type, + drivetrain, + preferred_price_range_min, + preferred_price_range_max, + trim, + vin, + interior_color, + condition_of_vehicle, + viewcontent_type, + search_type, + registration_type + } = payload?.vehicle_fields ?? {} + + const requestProperties: TTAutoProps = { + ...(postal_code !== undefined && { postal_code }), + ...(make !== undefined && { make }), + ...(model !== undefined && { model }), + ...(year !== undefined && { year }), + ...(state_of_vehicle !== undefined && { state_of_vehicle }), + ...(exterior_color !== undefined && { exterior_color }), + ...(transmission !== undefined && { transmission }), + ...(body_style !== undefined && { body_style }), + ...(fuel_type !== undefined && { fuel_type }), + ...(drivetrain !== undefined && { drivetrain }), + ...(trim !== undefined && { trim }), + ...(vin !== undefined && { vin }), + ...(interior_color !== undefined && { interior_color }), + ...(condition_of_vehicle !== undefined && { condition_of_vehicle }), + ...(viewcontent_type !== undefined && { viewcontent_type }), + ...(search_type !== undefined && { search_type }), + ...(registration_type !== undefined && { registration_type }), + ...(mileage_unit !== undefined && + typeof mileage_value === 'number' && { + mileage: { + unit: mileage_unit, + value: mileage_value + } + }), + ...(typeof preferred_price_range_min === 'number' && + typeof preferred_price_range_max === 'number' && { + preferred_price_range: [preferred_price_range_min, preferred_price_range_max] + }) + } + + return requestProperties +} diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts index 1653a1e32d2..7b3c5419dd1 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts @@ -19,10 +19,54 @@ export interface TikTokPixel { content_type, currency, value, - description, query, + description, order_id, - shop_id + shop_id, + content_ids, + num_items, + search_string, + city, + region, + country, + checkin_date, + checkout_date, + num_adults, + num_children, + num_infants, + suggested_hotels, + departing_departure_date, + returning_departure_date, + origin_airport, + destination_airiport, + destination_ids, + departing_arrival_date, + returning_arrival_date, + travel_class, + user_score, + preferred_num_stops, + travel_start, + travel_end, + suggested_destinations, + postal_code, + make, + model, + year, + state_of_vehicle, + mileage, + exterior_color, + transmission, + body_style, + fuel_type, + drivetrain, + preferred_price_range, + trim, + vin, + interior_color, + condition_of_vehicle, + viewcontent_type, + search_type, + registration_type }: TTBaseProps & TTTravelProps & TTAutoProps, { event_id diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts index 7c60225d791..7ce7a876f8b 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts @@ -1,2 +1,21 @@ +import { Payload } from './reportWebEvent/generated-types' +import { formatPhone, handleArrayInput, formatString, formatAddress } from './formatter' +import { TTUser } from './types' -// function getUser(payload: Payload) \ No newline at end of file +export function getUserObject(payload: Payload): TTUser { + return buildUserObject(payload) +} + +function buildUserObject(payload: Payload): TTUser { + return { + email: handleArrayInput(payload.email), + phone_number: formatPhone(handleArrayInput(payload.phone_number)), + external_id: handleArrayInput(payload.external_id), + first_name: formatString(payload.first_name), + last_name: formatString(payload.last_name), + city: formatAddress(payload.address?.city), + state: formatAddress(payload.address?.state), + country: formatAddress(payload.address?.country), + zip_code: formatString(payload.address?.zip_code) + } +} From 95e6736edeb27e5522aa18e93affd96d22c0fca6 Mon Sep 17 00:00:00 2001 From: Joe Ayoub Date: Thu, 2 Oct 2025 13:46:06 +0100 Subject: [PATCH 3/3] reviewer PR --- .../tiktok-pixel/src/identify/index.ts | 4 +- .../reportWebEvent/fields/travel_fields.ts | 4 +- .../tiktok-pixel/src/reportWebEvent/index.ts | 16 ++-- .../tiktok-pixel/src/reportWebEvent/utils.ts | 14 ++-- .../destinations/tiktok-pixel/src/types.ts | 73 +------------------ .../destinations/tiktok-pixel/src/utils.ts | 8 +- .../reportWebEvent/fields/travel_fields.ts | 4 +- 7 files changed, 28 insertions(+), 95 deletions(-) diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts index 525e1ff5ea0..2767a001a36 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/identify/index.ts @@ -1,7 +1,7 @@ import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' import type { Settings } from '../generated-types' import type { Payload } from './generated-types' -import { getUserObject } from '../utils' +import { getUser } from '../utils' import { TikTokPixel } from '../types' import { commonFields } from '../reportWebEvent/fields/common_fields' @@ -42,7 +42,7 @@ const action: BrowserActionDefinition = { }, perform: (ttq, { payload, settings }) => { if (payload.email || payload.phone_number || payload.external_id) { - ttq.instance(settings.pixelCode).identify(getUserObject(payload)) + ttq.instance(settings.pixelCode).identify(getUser(payload)) } } } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts index ed67acd1280..a0dbdd47489 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/fields/travel_fields.ts @@ -173,8 +173,8 @@ export const travel_fields: InputField = { origin_airport: { '@path': '$.properties.origin_airport' }, - destination_airiport: { - '@path': '$.properties.destination_airiport' + destination_airport: { + '@path': '$.properties.destination_airport' }, destination_ids: { '@path': '$.properties.destination_ids' // Confirmed this can be a single string or an array of strings diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts index a785fd6d4a4..f464877ccc4 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/index.ts @@ -1,8 +1,8 @@ import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' import type { Settings } from '../generated-types' import type { Payload } from './generated-types' -import { getUserObject } from '../utils' -import { getProp } from './utils' +import { getUser } from '../utils' +import { getAllProperties } from './utils' import { TikTokPixel } from '../types' import { commonFields } from './fields/common_fields' import { travel_fields } from './fields/travel_fields' @@ -21,12 +21,16 @@ const action: BrowserActionDefinition = { }, perform: (ttq, { payload, settings }) => { if (payload.email || payload.phone_number || payload.external_id) { - ttq.instance(settings.pixelCode).identify(getUserObject(payload)) + ttq.instance(settings.pixelCode).identify(getUser(payload)) } - ttq.instance(settings.pixelCode).track(payload.event, getProp(payload), { - event_id: payload.event_id ? payload.event_id : '' - }) + ttq.instance(settings.pixelCode).track( + payload.event, + getAllProperties(payload), + { + event_id: payload.event_id ? payload.event_id : '' + } + ) } } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts index c7d5ef9a9b9..df4a41530c1 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/reportWebEvent/utils.ts @@ -2,17 +2,17 @@ import { Payload } from './generated-types' import { TTBaseProps, TTTravelProps, TTAutoProps } from '../types' import { TRAVEL_FIELDS, VEHICLE_FIELDS } from './constants' -export function getProp(payload: Payload): TTBaseProps & TTAutoProps & TTTravelProps { +export function getAllProperties(payload: Payload): TTBaseProps & TTAutoProps & TTTravelProps { const { event_spec_type } = payload return { - ...buildBaseProp(payload), - ...(event_spec_type === TRAVEL_FIELDS ? buildTravelProp(payload) : {}), - ...(event_spec_type === VEHICLE_FIELDS ? buildAutoProp(payload) : {}) + ...getProps(payload), + ...(event_spec_type === TRAVEL_FIELDS ? getTravelProps(payload) : {}), + ...(event_spec_type === VEHICLE_FIELDS ? getAutoProp(payload) : {}) } } -function buildBaseProp(payload: Payload): TTBaseProps { +function getProps(payload: Payload): TTBaseProps { const { content_type, currency, @@ -53,7 +53,7 @@ function buildBaseProp(payload: Payload): TTBaseProps { return requestProperties } -function buildTravelProp(payload: Payload): TTTravelProps { +function getTravelProps(payload: Payload): TTTravelProps { const { city, region, @@ -107,7 +107,7 @@ function buildTravelProp(payload: Payload): TTTravelProps { return requestProperties } -function buildAutoProp(payload: Payload): TTAutoProps { +function getAutoProp(payload: Payload): TTAutoProps { const { postal_code, make, diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts index 7b3c5419dd1..6dc176ef900 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/types.ts @@ -1,78 +1,11 @@ export interface TikTokPixel { page: () => void instance: (pixel_code: string) => TikTokPixel - identify: ({ - email, - phone_number, - external_id, - first_name, - last_name, - city, - state, - country, - zip_code - }: TTUser) => void + identify: (user: TTUser) => void track: ( event: string, - { - contents, - content_type, - currency, - value, - query, - description, - order_id, - shop_id, - content_ids, - num_items, - search_string, - city, - region, - country, - checkin_date, - checkout_date, - num_adults, - num_children, - num_infants, - suggested_hotels, - departing_departure_date, - returning_departure_date, - origin_airport, - destination_airiport, - destination_ids, - departing_arrival_date, - returning_arrival_date, - travel_class, - user_score, - preferred_num_stops, - travel_start, - travel_end, - suggested_destinations, - postal_code, - make, - model, - year, - state_of_vehicle, - mileage, - exterior_color, - transmission, - body_style, - fuel_type, - drivetrain, - preferred_price_range, - trim, - vin, - interior_color, - condition_of_vehicle, - viewcontent_type, - search_type, - registration_type - }: TTBaseProps & TTTravelProps & TTAutoProps, - { - event_id - }: { - event_id: string | undefined - } + { ...props }: TTBaseProps & TTTravelProps & TTAutoProps, + { event_id }: { event_id?: string } ) => void } diff --git a/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts b/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts index 7ce7a876f8b..d2511946fce 100644 --- a/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts +++ b/packages/browser-destinations/destinations/tiktok-pixel/src/utils.ts @@ -2,11 +2,7 @@ import { Payload } from './reportWebEvent/generated-types' import { formatPhone, handleArrayInput, formatString, formatAddress } from './formatter' import { TTUser } from './types' -export function getUserObject(payload: Payload): TTUser { - return buildUserObject(payload) -} - -function buildUserObject(payload: Payload): TTUser { +export function getUser(payload: Payload): TTUser { return { email: handleArrayInput(payload.email), phone_number: formatPhone(handleArrayInput(payload.phone_number)), @@ -18,4 +14,4 @@ function buildUserObject(payload: Payload): TTUser { country: formatAddress(payload.address?.country), zip_code: formatString(payload.address?.zip_code) } -} +} \ No newline at end of file diff --git a/packages/destination-actions/src/destinations/tiktok-conversions/reportWebEvent/fields/travel_fields.ts b/packages/destination-actions/src/destinations/tiktok-conversions/reportWebEvent/fields/travel_fields.ts index a225c5428c9..d095571a64c 100644 --- a/packages/destination-actions/src/destinations/tiktok-conversions/reportWebEvent/fields/travel_fields.ts +++ b/packages/destination-actions/src/destinations/tiktok-conversions/reportWebEvent/fields/travel_fields.ts @@ -173,8 +173,8 @@ export const travel_fields: InputField = { origin_airport: { '@path': '$.properties.origin_airport' }, - destination_airiport: { - '@path': '$.properties.destination_airiport' + destination_airport: { + '@path': '$.properties.destination_airport' }, destination_ids: { '@path': '$.properties.destination_ids' // Confirmed this can be a single string or an array of strings