diff --git a/src/v0/destinations/braze/transform.js b/src/v0/destinations/braze/transform.js index 38c4b348db..6549f5658f 100644 --- a/src/v0/destinations/braze/transform.js +++ b/src/v0/destinations/braze/transform.js @@ -154,16 +154,19 @@ function getUserAttributesObject(message, mappingJson, destination) { Object.keys(mappingJson).forEach((destKey) => { let value = get(traits, mappingJson[destKey]); if (value || (value === null && reservedKeys.includes(destKey))) { - // if email is not string remove it from attributes - if (destKey === 'email' && typeof value !== 'string') { - throw new InstrumentationError('Invalid email, email must be a valid string'); - } - - // handle gender special case - if (destKey === 'gender') { - value = formatGender(value); - } else if (destKey === 'email' && isDefinedAndNotNull(value)) { - value = value.toString().toLowerCase(); + switch (destKey) { + case 'gender': + value = formatGender(value); + break; + case 'email': + if (typeof value === 'string') { + value = value.toLowerCase(); + } else if (isDefinedAndNotNull(value)) { + throw new InstrumentationError('Invalid email, email must be a valid string'); + } + break; + default: + break; } data[destKey] = value; } diff --git a/src/v0/destinations/tiktok_ads/transform.js b/src/v0/destinations/tiktok_ads/transform.js index 09f0d95dcc..91e2189170 100644 --- a/src/v0/destinations/tiktok_ads/transform.js +++ b/src/v0/destinations/tiktok_ads/transform.js @@ -155,7 +155,8 @@ const trackResponseBuilder = async (message, { Config }) => { return responseList; } // Doc https://ads.tiktok.com/help/article/standard-events-parameters?lang=en - event = eventNameMapping[event] || event; + // For custom event we do not want to lower case the event or trim it we just want to send those as it is + event = eventNameMapping[event] || message.event; // if there exists no event mapping we will build payload with custom event recieved responseList.push(getTrackResponse(message, Config, event)); diff --git a/test/__tests__/data/braze_input.json b/test/__tests__/data/braze_input.json index fb4e41b189..3fc1dbb905 100644 --- a/test/__tests__/data/braze_input.json +++ b/test/__tests__/data/braze_input.json @@ -1955,5 +1955,82 @@ "type": "identify", "userId": "" } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "sendPurchaseEventWithExtraProperties": true + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "traits": { + "city": "Disney", + "country": "USA", + "email": null, + "firstname": "Mickey" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "event": "Order Completed", + "integrations": { + "All": true + }, + "messageId": "aa5f5e44-8756-40ad-ad1e-b0d3b9fa710a", + "originalTimestamp": "2020-01-24T06:29:02.367Z", + "properties": { + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f", + "coupon": "hasbros", + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "products": [ + { + "category": "Games", + "image_url": "https:///www.example.com/product/path.jpg", + "name": "Monopoly: 3rd Edition", + "price": 0, + "product_id": "507f1f77bcf86cd799439023", + "quantity": 1, + "sku": "45790-32", + "url": "https://www.example.com/product/path" + }, + { + "category": "Games", + "name": "Uno Card Game", + "price": 0, + "product_id": "505bd76785ebb509fc183724", + "quantity": 2, + "sku": "46493-32" + } + ], + "revenue": 25, + "shipping": 3, + "subtotal": 22.5, + "tax": 2, + "total": 27.5 + }, + "receivedAt": "2020-01-24T11:59:02.403+05:30", + "request_ip": "[::1]:53712", + "sentAt": "2020-01-24T06:29:02.368Z", + "timestamp": "2020-01-24T11:59:02.402+05:30", + "type": "track", + "userId": "" + } } ] diff --git a/test/__tests__/data/braze_output.json b/test/__tests__/data/braze_output.json index ed39930569..7e0715f057 100644 --- a/test/__tests__/data/braze_output.json +++ b/test/__tests__/data/braze_output.json @@ -1038,5 +1038,76 @@ { "statusCode": 400, "message": "Invalid email, email must be a valid string" + }, + { + "body": { + "FORM": {}, + "JSON": { + "attributes": [ + { + "_update_existing_only": false, + "city": "Disney", + "country": "USA", + "email": null, + "firstname": "Mickey", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + } + ], + "partner": "RudderStack", + "purchases": [ + { + "_update_existing_only": false, + "currency": "USD", + "price": 0, + "product_id": "507f1f77bcf86cd799439023", + "properties": { + "category": "Games", + "image_url": "https:///www.example.com/product/path.jpg", + "name": "Monopoly: 3rd Edition", + "url": "https://www.example.com/product/path" + }, + "quantity": 1, + "time": "2020-01-24T11:59:02.402+05:30", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + }, + { + "_update_existing_only": false, + "currency": "USD", + "price": 0, + "product_id": "505bd76785ebb509fc183724", + "properties": { + "category": "Games", + "name": "Uno Card Game" + }, + "quantity": 2, + "time": "2020-01-24T11:59:02.402+05:30", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + } + ] + }, + "JSON_ARRAY": {}, + "XML": {} + }, + "endpoint": "https://rest.fra-01.braze.eu/users/track", + "files": {}, + "headers": { + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey", + "Content-Type": "application/json" + }, + "method": "POST", + "params": {}, + "type": "REST", + "userId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "version": "1" } ] diff --git a/test/integrations/destinations/tiktok_ads/processor/data.ts b/test/integrations/destinations/tiktok_ads/processor/data.ts index 46128f46b8..4a6a4bd812 100644 --- a/test/integrations/destinations/tiktok_ads/processor/data.ts +++ b/test/integrations/destinations/tiktok_ads/processor/data.ts @@ -4952,4 +4952,176 @@ export const data = [ }, }, }, + { + name: 'tiktok_ads', + description: 'Test 29 -> Camel Case Custom Event Pass', + 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: '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', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + context: { + ad: { + callback: '123ATXSfe', + }, + 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: 'A1T8T4UYGVIQA8ORZMX9', + 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/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'customEvent', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + 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, + }, + context: { + ad: { + callback: 'dummyclickId', + }, + 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, + }, + ], + }, + }, + }, ];