diff --git a/src/v0/destinations/tiktok_ads/config.js b/src/v0/destinations/tiktok_ads/config.js index 641b2e0865..61009d4c31 100644 --- a/src/v0/destinations/tiktok_ads/config.js +++ b/src/v0/destinations/tiktok_ads/config.js @@ -9,6 +9,10 @@ const ConfigCategory = { type: 'track', name: 'TikTokTrack', }, + TRACK_V2: { + type: 'track', + name: 'TikTokTrackV2', + }, }; const PARTNER_NAME = 'RudderStack'; @@ -32,12 +36,18 @@ const eventNameMapping = { const mappingConfig = getMappingConfig(ConfigCategory, __dirname); +// tiktok docs for max batch size for events 2.0: https://business-api.tiktok.com/portal/docs?id=1771100779668482 +const maxBatchSizeV2 = 1000; +const trackEndpointV2 = 'https://business-api.tiktok.com/open_api/v1.3/event/track/'; module.exports = { TRACK_ENDPOINT, BATCH_ENDPOINT, MAX_BATCH_SIZE, PARTNER_NAME, trackMapping: mappingConfig[ConfigCategory.TRACK.name], + trackMappingV2: mappingConfig[ConfigCategory.TRACK_V2.name], eventNameMapping, DESTINATION: 'TIKTOK_ADS', + trackEndpointV2, + maxBatchSizeV2, }; diff --git a/src/v0/destinations/tiktok_ads/data/TikTokTrack.json b/src/v0/destinations/tiktok_ads/data/TikTokTrack.json index cc5f4886e0..62688b7952 100644 --- a/src/v0/destinations/tiktok_ads/data/TikTokTrack.json +++ b/src/v0/destinations/tiktok_ads/data/TikTokTrack.json @@ -42,6 +42,22 @@ "type": "toString" } }, + { + "destKey": "properties.shop_id", + "sourceKeys": ["properties.shop_id", "properties.shopId"], + "required": false, + "metadata": { + "type": "toString" + } + }, + { + "destKey": "properties.order_id", + "sourceKeys": ["properties.order_id", "properties.orderId"], + "required": false, + "metadata": { + "type": "toString" + } + }, { "destKey": "properties.content_type", "sourceKeys": ["properties.contentType", "properties.content_type"], diff --git a/src/v0/destinations/tiktok_ads/data/TikTokTrackV2.json b/src/v0/destinations/tiktok_ads/data/TikTokTrackV2.json new file mode 100644 index 0000000000..8a31d67199 --- /dev/null +++ b/src/v0/destinations/tiktok_ads/data/TikTokTrackV2.json @@ -0,0 +1,133 @@ +[ + { + "destKey": "event_id", + "sourceKeys": ["properties.eventId", "properties.event_id", "messageId"], + "required": false + }, + { + "destKey": "event_time", + "sourceKeys": "timestamp", + "sourceFromGenericMap": true, + "required": true, + "metadata": { + "type": "secondTimestamp" + } + }, + { + "destKey": "limited_data_use", + "sourceKeys": "properties.limited_data_use", + "required": false + }, + { + "destKey": "properties.contents", + "sourceKeys": "properties.contents", + "required": false + }, + { + "destKey": "properties.content_type", + "sourceKeys": ["properties.contentType", "properties.content_type"], + "metadata": { + "defaultValue": "product" + } + }, + { + "destKey": "properties.shop_id", + "sourceKeys": ["properties.shop_id", "properties.shopId"], + "required": false, + "metadata": { + "type": "toString" + } + }, + { + "destKey": "properties.order_id", + "sourceKeys": ["properties.order_id", "properties.orderId"], + "required": false, + "metadata": { + "type": "toString" + } + }, + { + "destKey": "properties.currency", + "sourceKeys": "properties.currency", + "required": false + }, + { + "destKey": "properties.value", + "sourceKeys": "properties.value", + "required": false + }, + { + "destKey": "properties.description", + "sourceKeys": "properties.description", + "required": false + }, + { + "destKey": "properties.query", + "sourceKeys": "properties.query", + "required": false + }, + { + "destKey": "page.url", + "sourceKeys": ["properties.context.page.url", "properties.url", "context.page.url"], + "required": true + }, + { + "destKey": "page.referrer", + "sourceKeys": [ + "properties.context.page.referrer", + "properties.referrer", + "context.page.referrer" + ], + "required": false + }, + { + "destKey": "user.locale", + "sourceKeys": ["properties.context.user.locale", "context.locale"], + "required": false + }, + { + "destKey": "user.ttclid", + "sourceKeys": "properties.ttclid", + "required": false + }, + { + "destKey": "user.ttp", + "sourceKeys": ["properties.context.user.ttp", "properties.ttp"], + "required": false + }, + { + "destKey": "user.email", + "sourceKeys": [ + "properties.context.user.email", + "context.user.email", + "traits.email", + "context.traits.email", + "properties.email" + ], + "metadata": { + "type": ["trim", "toLower"] + }, + "required": false + }, + { + "destKey": "user.phone", + "sourceKeys": [ + "properties.context.user.phone", + "traits.phone", + "context.traits.phone", + "properties.phone" + ], + "sourceFromGenericMap": false, + "required": false + }, + { + "destKey": "user.ip", + "sourceKeys": ["properties.context.user.ip", "context.ip", "request_ip"], + "required": false + }, + { + "destKey": "user.user_agent", + "sourceKeys": ["properties.context.user.userAgent", "context.userAgent"], + "required": false + } +] diff --git a/src/v0/destinations/tiktok_ads/transform.js b/src/v0/destinations/tiktok_ads/transform.js index 91e2189170..bdf3a0defe 100644 --- a/src/v0/destinations/tiktok_ads/transform.js +++ b/src/v0/destinations/tiktok_ads/transform.js @@ -21,6 +21,7 @@ const { handleRtTfSingleEventError, batchMultiplexedEvents, } = require('../../util'); +const { process: processV2, processRouterDest: processRouterDestV2 } = require('./transformV2'); const { getContents } = require('./util'); const { trackMapping, @@ -165,7 +166,9 @@ const trackResponseBuilder = async (message, { Config }) => { const process = async (event) => { const { message, destination } = event; - + if (destination.Config?.version === 'v2') { + return processV2(event); + } if (!destination.Config.accessToken) { throw new ConfigurationError('Access Token not found. Aborting '); } @@ -240,6 +243,11 @@ function getEventChunks(event, trackResponseList, eventsChunk) { } const processRouterDest = async (inputs, reqMetadata) => { + const { destination } = inputs[0]; + const { Config } = destination; + if (Config?.version === 'v2') { + return processRouterDestV2(inputs, reqMetadata); + } const errorRespEvents = checkInvalidRtTfEvents(inputs); if (errorRespEvents.length > 0) { return errorRespEvents; diff --git a/src/v0/destinations/tiktok_ads/transformV2.js b/src/v0/destinations/tiktok_ads/transformV2.js new file mode 100644 index 0000000000..91078dfe65 --- /dev/null +++ b/src/v0/destinations/tiktok_ads/transformV2.js @@ -0,0 +1,738 @@ +/* eslint-disable camelcase */ +/* eslint-disable @typescript-eslint/naming-convention */ +const set = require('set-value'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); +const { EventType } = require('../../../constants'); +const { + constructPayload, + defaultRequestConfig, + defaultPostRequestConfig, + removeUndefinedAndNullValues, + defaultBatchRequestConfig, + getSuccessRespEvents, + isDefinedAndNotNullAndNotEmpty, + getDestinationExternalID, + getHashFromArrayWithDuplicate, + checkInvalidRtTfEvents, + handleRtTfSingleEventError, +} = require('../../util'); +const { getContents, hashUserField } = require('./util'); +const config = require('./config'); + +const { trackMappingV2, trackEndpointV2, eventNameMapping, PARTNER_NAME } = config; +const { JSON_MIME_TYPE } = require('../../util/constant'); + +/** + * Generated track payload for an event using TikTokTrackV2.json config mapping, + * hashing user properties and + * defining contents from products + * @param {*} message + * @param {*} Config + * @param {*} event + * @returns track payload + */ +const getTrackResponsePayload = (message, destConfig, event) => { + const payload = constructPayload(message, trackMappingV2); + + // if contents is not an array converting it into array + if (payload.properties?.contents && !Array.isArray(payload.properties.contents)) { + payload.properties.contents = [payload.properties.contents]; + } + + // if contents is not present but we have properties.products present which has fields with superset of contents fields + if (payload.properties && !payload.properties.contents && message.properties.products) { + // retreiving data from products only when contents is not present + payload.properties.contents = getContents(message, false); + } + + // getting externalId and hashing it and storing it in + const externalId = getDestinationExternalID(message, 'tiktokExternalId'); + if (isDefinedAndNotNullAndNotEmpty(externalId)) { + set(payload, 'user.external_id', externalId); + } + if (destConfig.hashUserProperties && isDefinedAndNotNullAndNotEmpty(payload.user)) { + payload.user = hashUserField(payload.user); + } + payload.event = event; + // add partner name and return payload + return removeUndefinedAndNullValues(payload); +}; + +const trackResponseBuilder = async (message, { Config }) => { + const { eventsToStandard, sendCustomEvents, accessToken, pixelCode } = Config; + + let event = message.event?.toLowerCase().trim(); + if (!event) { + throw new InstrumentationError('Event name is required'); + } + + const standardEventsMap = getHashFromArrayWithDuplicate(eventsToStandard); + + if (!sendCustomEvents && eventNameMapping[event] === undefined && !standardEventsMap[event]) { + throw new InstrumentationError( + `Event name (${event}) is not valid, must be mapped to one of standard events`, + ); + } + const response = defaultRequestConfig(); + response.headers = { + 'Access-Token': accessToken, + 'Content-Type': JSON_MIME_TYPE, + }; + // tiktok doc for request: https://business-api.tiktok.com/portal/docs?id=1771100865818625 + response.method = defaultPostRequestConfig.requestMethod; + response.endpoint = trackEndpointV2; + const responseList = []; + if (standardEventsMap[event]) { + Object.keys(standardEventsMap).forEach((key) => { + if (key === event) { + standardEventsMap[event].forEach((eventName) => { + responseList.push(getTrackResponsePayload(message, Config, eventName)); + }); + } + }); + } else { + /* + For custom event we do not want to lower case the event or trim it we just want to send those as it is + Doc https://ads.tiktok.com/help/article/standard-events-parameters?lang=en + */ + event = eventNameMapping[event] || message.event; + // if there exists no event mapping we will build payload with custom event recieved + responseList.push(getTrackResponsePayload(message, Config, event)); + } + // set event source and event_source_id + response.body.JSON = { + event_source: 'web', + event_source_id: pixelCode, + partner_name: PARTNER_NAME, + test_event_code: message.properties?.testEventCode, + }; + response.body.JSON.data = responseList; + return response; +}; + +const process = async (event) => { + const { message, destination } = event; + + if (!destination.Config.accessToken) { + throw new ConfigurationError('Access Token not found. Aborting'); + } + + if (!destination.Config.pixelCode) { + throw new ConfigurationError('Pixel Code not found. Aborting'); + } + + if (!message.type) { + throw new InstrumentationError('Event type is required'); + } + + const messageType = message.type.toLowerCase(); + + let response; + if (messageType === EventType.TRACK) { + response = await trackResponseBuilder(message, destination); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); + } + return response; +}; + +/** + * it builds batch response for an event using defaultBatchRequestConfig() utility + * @param {*} eventsChunk + * @returns batchedRequest + * + * Example: + * inputEvent: + *{ + event: { + event_source_id: "dummyPixelCode", + event_source: "web", + partner_name: "RudderStack", + data: [ + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + referrer: "http://demo.mywebsite.com", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id5", + }, + event: "CompletePayment", + partner_name: "RudderStack", + }, + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id1", + }, + event: "CompletePayment", + partner_name: "RudderStack", + } + ], + }, + metadata: [ + { + jobId: 5, + }, + { + jobId: 1, + } + ], + destination: { + Config: { + accessToken: "dummyAccessToken", + pixelCode: "dummyPixelCode", + hashUserProperties: false, + version: "v2", + }, + }, +} + * returns: + * + { + version: "1", + type: "REST", + method: "POST", + endpoint: "https://business-api.tiktok.com/open_api/v1.3/event/track/", + headers: { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json", + }, + params: { + }, + body: { + JSON: { + event_source_id: "asdfg", + event_source: "web", + partner_name: "RudderStack", + data: [ + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + referrer: "http://demo.mywebsite.com", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id5", + }, + event: "CompletePayment", + }, + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id1", + }, + event: "CompletePayment", + } + ], + }, + JSON_ARRAY: { + }, + XML: { + }, + FORM: { + }, + }, + files: { + }, +} + */ +const buildBatchResponseForEvent = (inputEvent) => { + const { destination, event } = inputEvent; + const { accessToken } = destination.Config; + const { batchedRequest } = defaultBatchRequestConfig(); + batchedRequest.body.JSON = event; + batchedRequest.endpoint = trackEndpointV2; + batchedRequest.headers = { + 'Access-Token': accessToken, + 'Content-Type': 'application/json', + }; + return batchedRequest; +}; + +const getEventChunks = (event, trackResponseList, eventsChunk) => { + // only for already transformed payload + // eslint-disable-next-line no-param-reassign + event.message = Array.isArray(event.message) ? event.message : [event.message]; + + // not performing batching for test events as it is not supported + if (event.message[0].body.JSON.test_event_code) { + const { metadata, destination, message } = event; + trackResponseList.push(getSuccessRespEvents(message, [metadata], destination)); + } else { + eventsChunk.push({ ...event }); + } +}; + +/** + * This clubs eventsChunk request body and metadat based upon maxBatchSize + * @param {*} eventsChunk + * @param {*} maxBatchSize + * @returns array of objects as + * { + * event, // Batched Event + * metadata, // metadata of all the requests combined to form above event + * destination, // destination object + * } + * + * Example: + * + * eventsChunk:[ + { + message: [ + { + version: "1", + type: "REST", + method: "POST", + endpoint: "https://business-api.tiktok.com/open_api/v1.3/event/track/", + headers: { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json", + }, + params: { + }, + body: { + JSON: { + event_source: "web", + event_source_id: "pixel_code", + data: [ + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + referrer: "http://demo.mywebsite.com", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id5", + }, + event: "CompletePayment", + partner_name: "RudderStack", + }, + ], + }, + JSON_ARRAY: { + }, + XML: { + }, + FORM: { + }, + }, + files: { + }, + }, + ], + metadata: { + jobId: 5, + }, + destination: { + Config: { + accessToken: "dummyAccessToken", + pixelCode: "pixel_code", + hashUserProperties: false, + version: "v2", + }, + }, + }, + { + message: [ + { + version: "1", + type: "REST", + method: "POST", + endpoint: "https://business-api.tiktok.com/open_api/v1.3/event/track/", + headers: { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json", + }, + params: { + }, + body: { + JSON: { + event_source: "web", + event_source_id: "pixel_code", + data: [ + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id1", + }, + event: "CompletePayment", + partner_name: "RudderStack", + }, + ], + }, + JSON_ARRAY: { + }, + XML: { + }, + FORM: { + }, + }, + files: { + }, + }, + ], + metadata: { + jobId: 1, + }, + destination: { + Config: { + accessToken: "dummyAccessToken", + pixelCode: "pixel_code", + hashUserProperties: false, + version: "v2", + }, + }, + } +] + * maxBatchSize = 1000 + +Returns +[ + { + event: { + event_source_id: "dummyPixelCode", + event_source: "web", + partner_name: "RudderStack", + data: [ + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + referrer: "http://demo.mywebsite.com", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id5", + }, + event: "CompletePayment", + partner_name: "RudderStack", + }, + { + event_id: "1616318632825_357", + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: "socks", + content_id: "1077218", + }, + { + price: 30, + quantity: 1, + content_type: "dress", + content_id: "1197218", + }, + ], + content_type: "product", + currency: "USD", + value: 46, + }, + page: { + url: "http://demo.mywebsite.com/purchase", + }, + user: { + locale: "en-US", + email: "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc", + phone: "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", + ip: "13.57.97.131", + user_agent: "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + external_id: "id1", + }, + event: "CompletePayment", + partner_name: "RudderStack", + } + ], + }, + metadata: [ + { + jobId: 5, + }, + { + jobId: 1, + } + ], + destination: { + Config: { + accessToken: "dummyAccessToken", + pixelCode: "dummyPixelCode", + hashUserProperties: false, + version: "v2", + }, + }, + } +] + */ +const batchEvents = (eventsChunk) => { + const events = []; + let data = []; + let metadata = []; + const { destination } = eventsChunk[0]; + const { pixelCode } = destination.Config; + eventsChunk.forEach((event) => { + const eventData = event.message[0]?.body.JSON.data; + // eslint-disable-next-line unicorn/consistent-destructuring + if (Array.isArray(eventData) && eventData?.length > config.maxBatchSizeV2 - data.length) { + // Partner name must be added above "data": [..]; + events.push({ + event: { + event_source_id: pixelCode, + event_source: 'web', + partner_name: PARTNER_NAME, + data: [...data], + }, + metadata: [...metadata], + destination, + }); + data = []; + metadata = []; + } + data.push(...eventData); + metadata.push(event.metadata); + }); + // Partner name must be added above "data": [..]; + events.push({ + event: { + event_source_id: pixelCode, + event_source: 'web', + partner_name: PARTNER_NAME, + data: [...data], + }, + metadata: [...metadata], + destination, + }); + return events; +}; +const processRouterDest = async (inputs, reqMetadata) => { + const errorRespEvents = checkInvalidRtTfEvents(inputs); + if (errorRespEvents.length > 0) { + return errorRespEvents; + } + const trackResponseList = []; // list containing single track event in batched format + const eventsChunk = []; // temporary variable to divide payload into chunks + const errorRespList = []; + await Promise.all( + inputs.map(async (event) => { + try { + if (event.message.statusCode) { + // already transformed event + getEventChunks(event, trackResponseList, eventsChunk); + } else { + // if not transformed + getEventChunks( + { + message: await process(event), + metadata: event.metadata, + destination: event.destination, + }, + trackResponseList, + eventsChunk, + ); + } + } catch (error) { + const errRespEvent = handleRtTfSingleEventError(event, error, reqMetadata); + errorRespList.push(errRespEvent); + } + }), + ); + + const batchedResponseList = []; + if (eventsChunk.length > 0) { + const batchedEvents = batchEvents(eventsChunk); + batchedEvents.forEach((batch) => { + const batchedRequest = buildBatchResponseForEvent(batch); + batchedResponseList.push( + getSuccessRespEvents(batchedRequest, batch.metadata, batch.destination, true), + ); + }); + } + return [...batchedResponseList.concat(trackResponseList), ...errorRespList]; +}; + +module.exports = { process, processRouterDest }; diff --git a/src/v0/destinations/tiktok_ads/util.js b/src/v0/destinations/tiktok_ads/util.js index dbc8b344fc..5f86193531 100644 --- a/src/v0/destinations/tiktok_ads/util.js +++ b/src/v0/destinations/tiktok_ads/util.js @@ -1,11 +1,12 @@ -const { removeUndefinedAndNullValues } = require('../../util'); +const { removeUndefinedAndNullValues, hashToSha256 } = require('../../util'); /** * Prepare contents array from products array * @param {*} message + * @param {*} getContentType if true contents.$.content_type is mapped otherwise not * @returns */ -const getContents = (message) => { +const getContents = (message, getContentType = true) => { const contents = []; const { properties } = message; // eslint-disable-next-line @typescript-eslint/naming-convention @@ -13,20 +14,50 @@ const getContents = (message) => { if (products && Array.isArray(products) && products.length > 0) { products.forEach((product) => { const singleProduct = { - content_type: - product.contentType || contentType || product.content_type || content_type || 'product', + content_type: getContentType + ? product.contentType || contentType || product.contentType || content_type || 'product' + : undefined, content_id: String(product.product_id), content_category: product.category, content_name: product.name, price: product.price, quantity: product.quantity, description: product.description, - brand: product.brand + brand: product.brand, }; contents.push(removeUndefinedAndNullValues(singleProduct)); }); } return contents; }; - -module.exports = { getContents }; +const hashString = (input) => hashToSha256(input.toString().trim()); +/* + * Hashing user related detail i.e external_id, email, phone_number + */ +const hashUserField = (user) => { + const updatedUser = { ...user }; + // hashing external_id + const { email, phone, external_id: externalId } = user; + if (externalId) { + // if there are multiple externalId's in form of array that tiktok supports then hashing every + if (Array.isArray(externalId)) { + updatedUser.external_id = externalId.map((extId) => hashString(extId).toString()); + } else { + updatedUser.external_id = hashString(externalId).toString(); + } + } + // hashing email + if (email && email.length > 0) { + updatedUser.email = hashString(email).toString(); + } + // hashing phone + if (phone && phone.length > 0) { + if (Array.isArray(phone)) { + updatedUser.phone = phone.map((num) => hashString(num).toString()); + } else { + updatedUser.phone = hashString(phone).toString(); + } + } + return updatedUser; +}; +module.exports = { getContents, hashUserField }; diff --git a/src/v0/destinations/tiktok_ads/util.test.js b/src/v0/destinations/tiktok_ads/util.test.js index 5a5cc2c505..67473ad9dd 100644 --- a/src/v0/destinations/tiktok_ads/util.test.js +++ b/src/v0/destinations/tiktok_ads/util.test.js @@ -1,4 +1,4 @@ -const { getContents } = require('./util'); +const { getContents, hashUserField } = require('./util'); describe('getContents utility test', () => { it('product id sent as number', () => { @@ -95,3 +95,80 @@ describe('getContents utility test', () => { expect(expectedOutput).toEqual(getContents(message)); }); }); + +describe('hashUserField utility test', () => { + it('should return the updated user object with hashed fields', () => { + const user = { + external_id: 123, + email: 'test@example.com', + phone: '+1234567890', + }; + + const hashedUser = hashUserField(user); + + expect(hashedUser).toEqual({ + external_id: "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3", + email: '973dfe463ec85785f5f95af5ba3906eedb2d931c24e69824a89ea65dba4e813b', + phone: '422ce82c6fc1724ac878042f7d055653ab5e983d186e616826a72d4384b68af8', + }); + }); + it('should hash external_id, email and phone fields when they are defined and not null or empty', () => { + const user = { + external_id: '123', + email: 'test@example.com', + phone: '+1234567890', + }; + + const hashedUser = hashUserField(user); + + expect(hashedUser.external_id).toBeDefined(); + expect(hashedUser.email).toBeDefined(); + expect(hashedUser.phone).toBeDefined(); + }); + + it('should hash external_id field even if it contains multiple values in form of array', () => { + const user = { + external_id: ['123', '456', '789'], + phone: ['+1234130697', '+e211134234'], + }; + + const hashedUser = hashUserField(user); + + expect(Array.isArray(hashedUser.external_id)).toBe(true); + expect(hashedUser.external_id.length).toBe(user.external_id.length); + hashedUser.external_id.forEach((hashedId, index) => { + expect(hashedId).toBeDefined(); + expect(hashedId).not.toBe(user.external_id[index]); + }); + hashedUser.phone.forEach((hashedId, index) => { + expect(hashedId).toBeDefined(); + expect(hashedId).not.toBe(user.phone[index]); + }); + }); + + it('should not hash external_id, email or phone fields when they are undefined, null or empty', () => { + const user = { + external_id: undefined, + email: null, + phone: '', + }; + + const hashedUser = hashUserField(user); + + expect(hashedUser.external_id).toBeUndefined(); + expect(hashedUser.email).toBeNull(); + expect(hashedUser.phone).toBe(''); + }); + + it('should not modify the original user object', () => { + const user = { + external_id: '123', + email: 'test@example.com', + phone: '1234567890', + }; + + const hashedUser = hashUserField(user); + + expect(hashedUser).not.toBe(user); + }); +}); diff --git a/src/v0/util/index.js b/src/v0/util/index.js index 34182a7685..5433529b5e 100644 --- a/src/v0/util/index.js +++ b/src/v0/util/index.js @@ -2165,6 +2165,7 @@ module.exports = { getValueFromPropertiesOrTraits, getValuesAsArrayFromConfig, handleSourceKeysOperation, + hashToSha256, isAppleFamily, isBlank, isCdkDestination, diff --git a/test/integrations/destinations/tiktok_ads/mocks.ts b/test/integrations/destinations/tiktok_ads/mocks.ts new file mode 100644 index 0000000000..6003027d23 --- /dev/null +++ b/test/integrations/destinations/tiktok_ads/mocks.ts @@ -0,0 +1,6 @@ +import config from '../../../../src/v0/destinations/tiktok_ads/config'; + +export const defaultMockFns = () => { + + jest.replaceProperty(config, 'maxBatchSizeV2', 3) + }; diff --git a/test/integrations/destinations/tiktok_ads/processor/data.ts b/test/integrations/destinations/tiktok_ads/processor/data.ts index 76a4a1ca89..21a12e5174 100644 --- a/test/integrations/destinations/tiktok_ads/processor/data.ts +++ b/test/integrations/destinations/tiktok_ads/processor/data.ts @@ -89,7 +89,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -114,7 +114,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'CompletePayment', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -256,7 +256,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -281,7 +281,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'InitiateCheckout', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -418,7 +418,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -443,7 +443,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'AddToWishlist', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -581,7 +581,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -697,7 +697,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -722,7 +722,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'AddToWishlist', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -863,7 +863,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -888,7 +888,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'AddToWishlist', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -1028,7 +1028,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: true, }, }, @@ -1053,7 +1053,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'Subscribe', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -1192,7 +1192,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -1217,7 +1217,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'AddPaymentInfo', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -1355,7 +1355,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -1467,7 +1467,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -1580,7 +1580,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -1605,7 +1605,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'AddPaymentInfo', event_id: '1616318632825_357', properties: { @@ -1743,7 +1743,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -1768,7 +1768,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'SubmitForm', event_id: '16163186328257', timestamp: '2020-09-17T19:49:27Z', @@ -1894,7 +1894,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -1919,7 +1919,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'SubmitForm', event_id: '16163186328257', timestamp: '2020-09-17T19:49:27Z', @@ -2040,7 +2040,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -2065,7 +2065,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'Contact', event_id: '16163186328257', timestamp: '2020-09-17T19:49:27Z', @@ -2204,7 +2204,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -2318,7 +2318,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -2343,7 +2343,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'CompletePayment', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -2482,7 +2482,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -2507,7 +2507,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'PlaceAnOrder', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -2650,7 +2650,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: true, }, }, @@ -2675,7 +2675,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'Subscribe', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -2819,7 +2819,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: true, }, }, @@ -2844,7 +2844,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'Subscribe', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -2984,7 +2984,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -3009,7 +3009,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'CompletePayment', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -3148,7 +3148,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, eventsToStandard: [ { @@ -3187,7 +3187,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'download', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -3249,7 +3249,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'search', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -3388,7 +3388,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, eventsToStandard: [ { @@ -3508,7 +3508,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, eventsToStandard: [ { @@ -3543,7 +3543,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'download', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -3681,7 +3681,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: true, eventsToStandard: [ { @@ -3716,7 +3716,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'download', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -3854,7 +3854,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: true, eventsToStandard: [ { @@ -3889,7 +3889,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'download', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -4048,7 +4048,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -4073,7 +4073,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'CompletePayment', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -4219,7 +4219,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -4244,7 +4244,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'CompletePayment', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -4394,7 +4394,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -4419,7 +4419,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'CompletePayment', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -4541,7 +4541,7 @@ export const data = [ category: 'Games', url: 'https://www.website.com/product/path', image_url: 'https://www.website.com/product/path.jpg', - brand:"brand_name" + brand: 'brand_name', }, { product_id: '345', @@ -4574,7 +4574,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, }, }, @@ -4599,7 +4599,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'CompletePayment', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -4619,7 +4619,7 @@ export const data = [ content_name: 'Monopoly', price: 14, quantity: 1, - brand:"brand_name" + brand: 'brand_name', }, { content_type: 'product_group', @@ -4752,7 +4752,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, sendCustomEvents: true, }, @@ -4778,7 +4778,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'custom_event', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -4924,7 +4924,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, sendCustomEvents: false, }, @@ -4956,7 +4956,7 @@ export const data = [ }, { name: 'tiktok_ads', - description: 'Test 29 -> Camel Case Custom Event Pass', + description: 'Test 31 -> Camel Case Custom Event Pass', feature: 'processor', module: 'destination', version: 'v0', @@ -5044,7 +5044,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: '{{PIXEL-CODE}}', hashUserProperties: false, sendCustomEvents: true, }, @@ -5070,7 +5070,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: '{{PIXEL-CODE}}', event: 'customEvent', event_id: '1616318632825_357', timestamp: '2020-09-17T19:49:27Z', @@ -5126,4 +5126,1730 @@ export const data = [ }, }, }, + { + name: 'tiktok_ads', + description: 'Test 32 -> V2 -> Camel Case Custom Event Pass', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + traits: { + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f' + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'customEvent', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + url: "http://demo.mywebsite.com/purchase", + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + version: 'v2', + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + sendCustomEvents: true, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source: 'web', + event_source_id: '{{PIXEL-CODE}}', + partner_name: 'RudderStack', + data: [ + { + event: 'customEvent', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase' + }, + user: { + locale: "en-US", + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 33 -> V2 -> Event mapped to one standard event with contents present as it is in properties', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + traits: { + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f' + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'addToCart', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + version: 'v2', + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + sendCustomEvents: true, + eventsToStandard: [ + { + from: 'addToCart', + to: 'download', + } + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source: 'web', + event_source_id: '{{PIXEL-CODE}}', + partner_name: 'RudderStack', + data: [ + { + event: 'download', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + locale: "en-US", + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 34 -> V2 -> Event mapped to multiple standard events and no phone', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + traits: { + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f' + }, + page: { + url: 'http://demo.mywebsite.com/purchase' + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'addToCart', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + version: 'v2', + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + sendCustomEvents: true, + eventsToStandard: [ + { + from: 'addToCart', + to: 'download', + }, + { + from: 'AddToCart', + to: 'AddToWishlist', + } + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source: 'web', + event_source_id: '{{PIXEL-CODE}}', + partner_name: 'RudderStack', + data: [ + { + event: 'download', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + }, + user: { + locale: "en-US", + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + }, + { + event: 'AddToWishlist', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + }, + user: { + locale: "en-US", + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 35 -> V2 -> array of external_id and phone number', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + externalId: [ + { + type: 'tiktokExternalId', + id: ['f0e388f53921a51f0bb0fc8a2944109ec188b5', '1f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc'], + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'addToCart', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + phone: ['+12345432', '+134234325'], + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f' + + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + version: 'v2', + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + sendCustomEvents: true, + eventsToStandard: [ + { + from: 'addToCart', + to: 'download', + }, + { + from: 'AddToCart', + to: 'AddToWishlist', + } + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source: 'web', + event_source_id: '{{PIXEL-CODE}}', + partner_name: 'RudderStack', + data: [ + { + event: 'download', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone: ['+12345432', '+134234325'], + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: ['f0e388f53921a51f0bb0fc8a2944109ec188b5', '1f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc'], + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + }, + { + event: 'AddToWishlist', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone: ['+12345432', '+134234325'], + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: ['f0e388f53921a51f0bb0fc8a2944109ec188b5', '1f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc'], + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 36-> V2 -> Event not standard and no custom events allowed', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + traits: { + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f' + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'Product Added to Wishlist1', + properties: { + eventId: '1616318632825_357', + testEventCode: 'sample rudder test_event_code', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'Event name (product added to wishlist1) is not valid, must be mapped to one of standard events', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 37-> V2 -> No Message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + event: 'Product Added to Wishlist1', + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + version: 'v2' + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'Event type is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 38-> V2 -> Event not found', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'Event name is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 39-> V2 -> Access Token not found', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + pixelCode: 'configuration', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'Access Token not found. Aborting', + statTags: { + errorCategory: 'dataValidation', + errorType: 'configuration', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 40-> V2 -> Pixel Code not found. Aborting', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'Pixel Code not found. Aborting', + statTags: { + errorCategory: 'dataValidation', + errorType: 'configuration', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 41 -> V2 -> One of standard event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + traits: { + email: 'abc@xyz.com' + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + externalId: [ + { + type: 'tiktokExternalId', + id: ['f0e388f53921a51f0bb0fc8a2944109ec188b5', '1f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc'], + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'viewcontent', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + phone: ['+12345432', '+134234325'] + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + version: 'v2', + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: true, + sendCustomEvents: false, + eventsToStandard: [ + { + from: 'addToCart', + to: 'download', + }, + { + from: 'AddToCart', + to: 'AddToWishlist', + } + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source: 'web', + event_source_id: '{{PIXEL-CODE}}', + partner_name: 'RudderStack', + data: [ + { + event: 'ViewContent', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + email: 'ee278943de84e5d6243578ee1a1057bcce0e50daad9755f45dfa64b60b13bc5d', + external_id: ["3e0c7a51acd326b87f29596e38c22cbeb732df37bc5c8f5f524c14b55d3472db", "f8be04e62f5a3eba31c8b9380843666f28f3ab5f44a380f47fac04e9ce7b2168",], + ip: '13.57.97.131', + phone: [ + "49a15e38bdc2572d362a924c2ddd100baed0fe29db44270d3700fcef03b18c39", + "5a6a7a09b18278e220312ce26d711ff7c8263d0965ee3b1d26b1b6f0ac7e71b3", + ], + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + } + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 42 -> V2 -> One of standard event and contents from products', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + traits: { + email: 'abc@xyz.com' + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + externalId: [ + { + type: 'tiktokExternalId', + id: ['f0e388f53921a51f0bb0fc8a2944109ec188b5', '1f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc'], + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'viewcontent', + properties: { + order_id: 1234, + shop_id: 4567, + description: "Viewed games", + query: "New age games", + contentType: 'product_group', + eventId: '1616318632825_357', + products: [ + { + product_id: 123, + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + contentType: 'product_group', + category: 'Games', + brand: 'adidas', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + product_id: 345, + sku: 'F-32', + name: 'UNO', + price: 3.45, + contentType: 'product_group', + quantity: 2, + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + phone: ['+12345432', '+134234325'] + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + version: 'v2', + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: true, + sendCustomEvents: false, + eventsToStandard: [ + { + from: 'addToCart', + to: 'download', + }, + { + from: 'AddToCart', + to: 'AddToWishlist', + } + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source: 'web', + event_source_id: '{{PIXEL-CODE}}', + partner_name: 'RudderStack', + data: [ + { + event: 'ViewContent', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + order_id: "1234", + shop_id: "4567", + description: "Viewed games", + query: "New age games", + content_type: "product_group", + contents: [ + { + price: 14, + quantity: 1, + content_category: 'Games', + content_id: '123', + content_name: 'Monopoly', + brand: 'adidas' + }, + { + price: 3.45, + quantity: 2, + content_id: '345', + content_name: 'UNO' + }, + ], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + email: 'ee278943de84e5d6243578ee1a1057bcce0e50daad9755f45dfa64b60b13bc5d', + external_id: ["3e0c7a51acd326b87f29596e38c22cbeb732df37bc5c8f5f524c14b55d3472db", "f8be04e62f5a3eba31c8b9380843666f28f3ab5f44a380f47fac04e9ce7b2168",], + ip: '13.57.97.131', + phone: [ + "49a15e38bdc2572d362a924c2ddd100baed0fe29db44270d3700fcef03b18c39", + "5a6a7a09b18278e220312ce26d711ff7c8263d0965ee3b1d26b1b6f0ac7e71b3", + ], + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + } + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 43 -> V2 -> Contents present as object in properties', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + traits: { + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f' + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'addToCart', + properties: { + eventId: '1616318632825_357', + contents: { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + version: 'v2', + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + sendCustomEvents: true, + eventsToStandard: [ + { + from: 'addToCart', + to: 'download', + } + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source: 'web', + event_source_id: '{{PIXEL-CODE}}', + partner_name: 'RudderStack', + data: [ + { + event: 'download', + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + content_type: "product", + contents: [{ + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }], + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + locale: "en-US", + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 44 -> Events 2.0 Event type identify not suported', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + timestamp: '2020-09-17T19:49:27Z', + type: 'identify', + event: 'contact', + properties: {}, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + version: "v2" + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Event type identify is not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 45-> events 1.0 build contents from properties.product.$ where length of prodicts is 0', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + products: [], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: '{{PIXEL-CODE}}', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: '{{PIXEL-CODE}}', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + currency: 'USD', + value: 46, + contents: [], + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/tiktok_ads/router/data.ts b/test/integrations/destinations/tiktok_ads/router/data.ts index a8c233c7a8..cbf8da0cf8 100644 --- a/test/integrations/destinations/tiktok_ads/router/data.ts +++ b/test/integrations/destinations/tiktok_ads/router/data.ts @@ -1,9 +1,9 @@ import { FEATURES } from '../../../../../src/v0/util/tags'; - +import { defaultMockFns } from '../mocks'; export const data = [ { name: 'tiktok_ads', - description: 'Test 0', + description: 'Test 0 -> Events 1.0 Multiple events in single batch', feature: FEATURES.ROUTER, module: 'destination', version: 'v0', @@ -22,21 +22,13 @@ export const data = [ namespace: 'com.rudderlabs.javascript', version: '1.0.0', }, - library: { - name: 'RudderLabs JavaScript SDK', - version: '1.0.0', - }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, userAgent: 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', ip: '13.57.97.131', locale: 'en-US', - os: { - name: '', - version: '', - }, - screen: { - density: 2, - }, + os: { name: '', version: '' }, + screen: { density: 2 }, externalId: [ { type: 'tiktokExternalId', @@ -54,18 +46,8 @@ export const data = [ eventId: '1616318632825_357', clickId: 'dummyClickId', contents: [ - { - price: 8, - quantity: 2, - content_type: 'socks', - content_id: '1077218', - }, - { - price: 30, - quantity: 1, - content_type: 'dress', - content_id: '1197218', - }, + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, ], currency: 'USD', value: 46.0, @@ -92,7 +74,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: 'dummyPixelCode', hashUserProperties: false, }, }, @@ -108,21 +90,13 @@ export const data = [ namespace: 'com.rudderlabs.javascript', version: '1.0.0', }, - library: { - name: 'RudderLabs JavaScript SDK', - version: '1.0.0', - }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, userAgent: 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', locale: 'en-US', ip: '13.57.97.131', - os: { - name: '', - version: '', - }, - screen: { - density: 2, - }, + os: { name: '', version: '' }, + screen: { density: 2 }, externalId: [ { type: 'tiktokExternalId', @@ -150,18 +124,8 @@ export const data = [ }, }, contents: [ - { - price: 8, - quantity: 2, - content_type: 'socks', - content_id: '1077218', - }, - { - price: 30, - quantity: 1, - content_type: 'dress', - content_id: '1197218', - }, + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, ], currency: 'USD', value: 46.0, @@ -177,7 +141,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: 'dummyPixelCode', hashUserProperties: false, }, }, @@ -193,21 +157,13 @@ export const data = [ namespace: 'com.rudderlabs.javascript', version: '1.0.0', }, - library: { - name: 'RudderLabs JavaScript SDK', - version: '1.0.0', - }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, userAgent: 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', locale: 'en-US', ip: '13.57.97.131', - os: { - name: '', - version: '', - }, - screen: { - density: 2, - }, + os: { name: '', version: '' }, + screen: { density: 2 }, externalId: [ { type: 'tiktokExternalId', @@ -238,18 +194,8 @@ export const data = [ ip: '13.57.97.131', }, contents: [ - { - price: 8, - quantity: 2, - content_type: 'socks', - content_id: '1077218', - }, - { - price: 30, - quantity: 1, - content_type: 'dress', - content_id: '1197218', - }, + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, ], currency: 'USD', value: 46.0, @@ -265,7 +211,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: 'dummyPixelCode', hashUserProperties: false, }, }, @@ -281,21 +227,13 @@ export const data = [ namespace: 'com.rudderlabs.javascript', version: '1.0.0', }, - library: { - name: 'RudderLabs JavaScript SDK', - version: '1.0.0', - }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, userAgent: 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', locale: 'en-US', ip: '13.57.97.131', - os: { - name: '', - version: '', - }, - screen: { - density: 2, - }, + os: { name: '', version: '' }, + screen: { density: 2 }, externalId: [ { type: 'tiktokExternalId', @@ -326,18 +264,8 @@ export const data = [ ip: '13.57.97.131', }, contents: [ - { - price: 8, - quantity: 2, - content_type: 'socks', - content_id: '1077218', - }, - { - price: 30, - quantity: 1, - content_type: 'dress', - content_id: '1197218', - }, + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, ], currency: 'USD', value: 46.0, @@ -353,7 +281,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: 'dummyPixelCode', hashUserProperties: false, }, }, @@ -382,7 +310,7 @@ export const data = [ params: {}, body: { JSON: { - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: 'dummyPixelCode', partner_name: 'RudderStack', batch: [ { @@ -392,12 +320,7 @@ export const data = [ timestamp: '2020-09-17T19:49:27Z', properties: { contents: [ - { - price: 8, - quantity: 2, - content_type: 'socks', - content_id: '1077218', - }, + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, { price: 30, quantity: 1, @@ -409,9 +332,7 @@ export const data = [ value: 46, }, context: { - ad: { - callback: 'dummyClickId', - }, + ad: { callback: 'dummyClickId' }, page: { url: 'http://demo.mywebsite.com/purchase', referrer: 'http://demo.mywebsite.com', @@ -454,12 +375,7 @@ export const data = [ properties: { value: 46, contents: [ - { - price: 8, - quantity: 2, - content_id: '1077218', - content_type: 'socks', - }, + { price: 8, quantity: 2, content_id: '1077218', content_type: 'socks' }, { price: 30, quantity: 1, @@ -495,12 +411,7 @@ export const data = [ properties: { value: 46, contents: [ - { - price: 8, - quantity: 2, - content_id: '1077218', - content_type: 'socks', - }, + { price: 8, quantity: 2, content_id: '1077218', content_type: 'socks' }, { price: 30, quantity: 1, @@ -536,12 +447,7 @@ export const data = [ properties: { value: 46, contents: [ - { - price: 8, - quantity: 2, - content_id: '1077218', - content_type: 'socks', - }, + { price: 8, quantity: 2, content_id: '1077218', content_type: 'socks' }, { price: 30, quantity: 1, @@ -579,7 +485,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: 'dummyPixelCode', hashUserProperties: false, }, }, @@ -591,7 +497,7 @@ export const data = [ }, { name: 'tiktok_ads', - description: 'Test 1', + description: 'Test 1 -> Events 1.0 Single Event inside batch', feature: FEATURES.ROUTER, module: 'destination', version: 'v0', @@ -610,27 +516,14 @@ export const data = [ namespace: 'com.rudderlabs.javascript', version: '1.0.0', }, - library: { - name: 'RudderLabs JavaScript SDK', - version: '1.0.0', - }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, userAgent: 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', locale: 'en-US', ip: '13.57.97.131', - os: { - name: '', - version: '', - }, - screen: { - density: 2, - }, - externalId: [ - { - type: 'tiktokExternalId', - id: '1234', - }, - ], + os: { name: '', version: '' }, + screen: { density: 2 }, + externalId: [{ type: 'tiktokExternalId', id: '1234' }], }, messageId: '84e26acc-56a5-4835-8233-591137fca468', session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', @@ -646,27 +539,14 @@ export const data = [ url: 'http://demo.mywebsite.com/purchase', referrer: 'http://demo.mywebsite.com', }, - user: { - phone_number: '+858987675687', - email: 'sample@sample.com', - }, + user: { phone_number: '+858987675687', email: 'sample@sample.com' }, userAgent: 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', ip: '13.57.97.131', }, contents: [ - { - price: 8, - quantity: 2, - content_type: 'socks', - content_id: '1077218', - }, - { - price: 30, - quantity: 1, - content_type: 'dress', - content_id: '1197218', - }, + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, ], currency: 'USD', value: 46.0, @@ -682,7 +562,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: 'dummyPixelCode', hashUserProperties: true, }, }, @@ -723,22 +603,12 @@ export const data = [ }, event: 'AddToWishlist', event_id: '1616318632825_357', - pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + pixel_code: 'dummyPixelCode', partner_name: 'RudderStack', properties: { contents: [ - { - content_id: '1077218', - content_type: 'socks', - price: 8, - quantity: 2, - }, - { - content_id: '1197218', - content_type: 'dress', - price: 30, - quantity: 1, - }, + { content_id: '1077218', content_type: 'socks', price: 8, quantity: 2 }, + { content_id: '1197218', content_type: 'dress', price: 30, quantity: 1 }, ], currency: 'USD', value: 46, @@ -764,7 +634,7 @@ export const data = [ destination: { Config: { accessToken: 'dummyAccessToken', - pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + pixelCode: 'dummyPixelCode', hashUserProperties: true, }, }, @@ -780,4 +650,2109 @@ export const data = [ }, }, }, + { + name: 'tiktok_ads', + description: + 'Test 2 -> Events 2.0 Single event is mapped to multiple tiktok event in config and exceeding max batch size', + feature: FEATURES.ROUTER, + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id5' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 5, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id1' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'addToCart', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 1, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id2' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id4' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 4, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + destType: 'tiktok_ads', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id5', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id1', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id1', + }, + event: 'download', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + jobId: 5, + }, + { + jobId: 1, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id2', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id4', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + jobId: 2, + }, + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + ], + }, + }, + }, + mockFns: defaultMockFns, + }, + { + name: 'tiktok_ads', + description: + 'Test 3 -> Events 2.0 Single event is mapped to single tiktok event in config and over the max batch limit', + feature: FEATURES.ROUTER, + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id5' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 5, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id1' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 1, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id2' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id4' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 4, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + destType: 'tiktok_ads', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id5', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id1', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id2', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + jobId: 5, + }, + { + jobId: 1, + }, + { + jobId: 2, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id4', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + }, + }, + }, + mockFns: defaultMockFns, + }, + { + name: 'tiktok_ads', + description: 'Test 4 -> One input event is invalid with one event to multiple events', + feature: FEATURES.ROUTER, + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id5' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 5, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id1' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'abc', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 1, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id2' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id4' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 4, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + destType: 'tiktok_ads', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id5', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id2', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id4', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + jobId: 5, + }, + { + jobId: 2, + }, + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + batched: false, + destination: { + Config: { + accessToken: 'dummyAccessToken', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + hashUserProperties: false, + pixelCode: 'dummyPixelCode', + version: 'v2', + }, + }, + error: 'Event name (abc) is not valid, must be mapped to one of standard events', + metadata: [ + { + jobId: 1, + }, + ], + statTags: { + destType: 'TIKTOK_ADS', + feature: 'router', + implementation: 'native', + module: 'destination', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + }, + statusCode: 400, + }, + ], + }, + }, + }, + mockFns: defaultMockFns, + }, + { + name: 'tiktok_ads', + description: 'Test 5 -> Some input events are test events with one event to multiple events', + feature: FEATURES.ROUTER, + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id5' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 5, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id1' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'addToCart', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 1, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id2' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + testEventCode: 'Some test event code for testing setup', + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id4' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 4, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + destType: 'tiktok_ads', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id5', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id1', + }, + event: 'CompletePayment', + }, + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id1', + }, + event: 'download', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + jobId: 5, + }, + { + jobId: 1, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id4', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + test_event_code: 'Some test event code for testing setup', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id2', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 2, + }, + ], + batched: false, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + }, + }, + }, + mockFns: defaultMockFns, + }, + { + name: 'tiktok_ads', + description: 'Test 6 -> All input events are test events', + feature: FEATURES.ROUTER, + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id5' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + testEventCode: 'TEST_EVENT_CODE', + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 5, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + externalId: [{ type: 'tiktokExternalId', id: 'id2' }], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + testEventCode: 'TEST_EVENT_CODE', + eventId: '1616318632825_357', + clickId: 'dummyClickId', + contents: [ + { price: 8, quantity: 2, content_type: 'socks', content_id: '1077218' }, + { price: 30, quantity: 1, content_type: 'dress', content_id: '1197218' }, + ], + currency: 'USD', + value: 46, + url: 'http://demo.mywebsite.com/purchase', + phone: '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + destType: 'tiktok_ads', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + test_event_code: 'TEST_EVENT_CODE', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id5', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 5, + }, + ], + batched: false, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + eventsToStandard: [ + { from: 'addToCart', to: 'CompletePayment' }, + { from: 'addToCart', to: 'download' }, + ], + }, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/event/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_source_id: 'dummyPixelCode', + event_source: 'web', + partner_name: 'RudderStack', + test_event_code: 'TEST_EVENT_CODE', + data: [ + { + event_id: '1616318632825_357', + event_time: 1600372167, + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + content_type: 'product', + currency: 'USD', + value: 46, + }, + page: { url: 'http://demo.mywebsite.com/purchase' }, + user: { + locale: 'en-US', + email: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + phone: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + external_id: 'id2', + }, + event: 'CompletePayment', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 2, + }, + ], + batched: false, + statusCode: 200, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'dummyPixelCode', + hashUserProperties: false, + version: 'v2', + }, + }, + }, + ], + + }, + }, + }, + mockFns: defaultMockFns, + }, ];