diff --git a/src/v0/destinations/mp/data/MPIdentifyConfig.json b/src/v0/destinations/mp/data/MPIdentifyConfig.json index 44c99fb56d..0abe7826f0 100644 --- a/src/v0/destinations/mp/data/MPIdentifyConfig.json +++ b/src/v0/destinations/mp/data/MPIdentifyConfig.json @@ -1,15 +1,13 @@ [ { "destKey": "$created", - "sourceKeys": "createdAtOnly", - "required": false, - "sourceFromGenericMap": true + "sourceKeys": ["createdAt","traits.createdAt", "context.traits.createdAt"], + "required": false }, { "destKey": "$email", - "sourceKeys": "email", - "required": false, - "sourceFromGenericMap": true + "sourceKeys": ["email","traits.email", "context.traits.email", "properties.email", "context.externalId.0.id"], + "required": false }, { "destKey": "$first_name", @@ -24,24 +22,33 @@ "context.traits.firstname", "context.traits.first_name" ], - "required": false, - "sourceFromGenericMap": true + "required": false }, { "destKey": "$last_name", - "sourceKeys": "lastName", - "required": false, - "sourceFromGenericMap": true + "sourceKeys": [ + "lastName", + "lastname", + "last_name", + "traits.lastName", + "traits.lastname", + "traits.last_name", + "context.traits.lastName", + "context.traits.lastname", + "context.traits.last_name" + ], + "required": false }, { "destKey": "$name", - "sourceKeys": "name", - "required": false, - "sourceFromGenericMap": true + "sourceKeys": ["name","traits.name", "context.traits.name"], + "required": false }, { "destKey": "$username", "sourceKeys": [ + "username", + "userName", "traits.username", "context.traits.username", "traits.userName", @@ -51,18 +58,19 @@ }, { "destKey": "$phone", - "sourceKeys": "phone", - "required": false, - "sourceFromGenericMap": true + "sourceKeys": ["phone","traits.phone", "context.traits.phone"], + "required": false }, { "destKey": "$avatar", - "sourceKeys": ["traits.avatar", "context.traits.avatar"], + "sourceKeys": ["avatar","traits.avatar", "context.traits.avatar"], "required": false }, { "destKey": "$country_code", "sourceKeys": [ + "country", + "address.country", "traits.address.country", "context.traits.address.country", "traits.country", @@ -74,6 +82,8 @@ { "destKey": "$city", "sourceKeys": [ + "city", + "address.city", "traits.city", "context.traits.city", "traits.address.city", @@ -85,6 +95,9 @@ { "destKey": "$region", "sourceKeys": [ + "state", + "address.state", + "location.region", "traits.state", "context.traits.state", "traits.address.state", @@ -95,7 +108,7 @@ }, { "destKey": "$geo_source", - "sourceKeys": "context.location.geoSource", + "sourceKeys": ["location.geoSource","context.location.geoSource"], "required": false }, { @@ -145,7 +158,7 @@ }, { "destKey": "$unsubscribed", - "sourceKeys": ["traits.unsubscribed", "context.traits.unsubscribed", "properties.unsubscribed"], + "sourceKeys": ["unsubscribed","traits.unsubscribed", "context.traits.unsubscribed", "properties.unsubscribed"], "required": false }, { diff --git a/src/v0/destinations/mp/transform.js b/src/v0/destinations/mp/transform.js index 9cf43b88f7..69f5d2bc7f 100644 --- a/src/v0/destinations/mp/transform.js +++ b/src/v0/destinations/mp/transform.js @@ -17,6 +17,7 @@ const { checkInvalidRtTfEvents, handleRtTfSingleEventError, groupEventsByType, + extractCustomFields, } = require('../../util'); const { ConfigCategory, @@ -27,6 +28,7 @@ const { TRACK_MAX_BATCH_SIZE, ENGAGE_MAX_BATCH_SIZE, GROUPS_MAX_BATCH_SIZE, + MP_IDENTIFY_EXCLUSION_LIST, } = require('./config'); const { createIdentifyResponse, @@ -241,28 +243,37 @@ function trimTraits(traits, contextTraits, setOnceProperties) { const contextTraitsCopy = { ...contextTraits }; // Initialize setOnce object - const setOnce = {}; + const setOnceEligible = {}; - // Iterate over setOnceProperties and move corresponding properties to setOnce - setOnceProperties.forEach((property) => { - if (traitsCopy.hasOwnProperty(property)) { - setOnce[property] = traitsCopy[property]; - delete traitsCopy[property]; + // Step 1: find the k-v pairs of setOnceProperties in traits and contextTraits + + setOnceProperties.forEach((propertyPath) => { + const pathSegments = propertyPath.split('.'); + const propName = pathSegments[pathSegments.length - 1]; + + if (Object.keys(traitsCopy).length > 0 && get(traitsCopy, propertyPath)) { + setOnceEligible[propName] = get(traitsCopy, propertyPath); + lodash.unset(traitsCopy, propertyPath); } - if (contextTraitsCopy.hasOwnProperty(property)) { - if(!setOnce.hasOwnProperty(property)) { - setOnce[property] = contextTraitsCopy[property]; + if (Object.keys(contextTraits).length > 0 && get(contextTraitsCopy, propertyPath)) { + if(!setOnceEligible.hasOwnProperty(propName)) { + setOnceEligible[propName] = get(contextTraitsCopy, propertyPath); } - delete contextTraitsCopy[property]; + lodash.unset(contextTraitsCopy, propertyPath); } }); + // Step 2: transform properties eligible as per rudderstack declared identify event mapping + // setOnce should have all traits from message.traits and message.context.traits by now + let sentOnceTransform = constructPayload(setOnceEligible, mPIdentifyConfigJson); + + // Step 3: combine the transformed and custom setOnce traits - const sentOnceTransform = constructPayload(setOnce, mPIdentifyConfigJson); + sentOnceTransform = extractCustomFields(setOnceEligible, sentOnceTransform, 'root', MP_IDENTIFY_EXCLUSION_LIST); return { traits: traitsCopy, contextTraits: contextTraitsCopy, - sentOnceTransform, + setOnce: sentOnceTransform, }; } diff --git a/test/integrations/destinations/mp/common.ts b/test/integrations/destinations/mp/common.ts index e2daaa8622..f5efc4cc48 100644 --- a/test/integrations/destinations/mp/common.ts +++ b/test/integrations/destinations/mp/common.ts @@ -38,6 +38,12 @@ const destinationWithSetOnceProperty = { setOnceProperties: [ { property: 'nationality' + }, + { + property: 'firstName' + }, + { + property: 'address.city' } ], superProperties: [ diff --git a/test/integrations/destinations/mp/processor/data.ts b/test/integrations/destinations/mp/processor/data.ts index 7038a24fac..e5313a93fe 100644 --- a/test/integrations/destinations/mp/processor/data.ts +++ b/test/integrations/destinations/mp/processor/data.ts @@ -5992,7 +5992,7 @@ export const data = [ request: { body: [ { - description: 'Alias: with property beyond exclusion list', + description: 'Alias: with property beyond and within exclusion list', destination: destinationWithSetOnceProperty, message: { anonymousId: 'e6ab2c5e-2cda-44a9-a962-e2f67df78bca', @@ -6018,7 +6018,9 @@ export const data = [ density: 2 }, traits: { - city: 'Disney', + address: { + city: 'Disney', + }, country: 'USA', email: 'TestSanity@disney.com', firstName: 'Mickey test', @@ -6072,7 +6074,7 @@ export const data = [ FORM: {}, JSON: {}, JSON_ARRAY: { - batch: "[{\"$set_once\":{\"nationality\":\"USA\"},\"$token\":\"dummyToken\",\"$distinct_id\":\"Santiy\"}]", + batch: "[{\"$set_once\":{\"$first_name\":\"Mickey test\",\"$city\":\"Disney\",\"nationality\":\"USA\"},\"$token\":\"dummyToken\",\"$distinct_id\":\"Santiy\"}]", }, XML: {}, }, @@ -6093,7 +6095,7 @@ export const data = [ FORM: {}, JSON: {}, JSON_ARRAY: { - batch: "[{\"$set\":{\"$created\":\"2020-01-23T08:54:02.362Z\",\"$email\":\"TestSanity@disney.com\",\"$country_code\":\"USA\",\"$city\":\"Disney\",\"$initial_referrer\":\"https://docs.rudderstack.com\",\"$initial_referring_domain\":\"docs.rudderstack.com\",\"$name\":\"Mickey test VarChange\",\"random\":\"superProp\",\"$firstName\":\"Mickey test\",\"$lastName\":\"VarChange\",\"$browser\":\"Chrome\",\"$browser_version\":\"79.0.3945.117\"},\"$token\":\"dummyToken\",\"$distinct_id\":\"Santiy\",\"$ip\":\"0.0.0.0\",\"$time\":null}]", + "batch": "[{\"$set\":{\"$created\":\"2020-01-23T08:54:02.362Z\",\"$email\":\"TestSanity@disney.com\",\"$country_code\":\"USA\",\"$initial_referrer\":\"https://docs.rudderstack.com\",\"$initial_referring_domain\":\"docs.rudderstack.com\",\"random\":\"superProp\",\"$lastName\":\"VarChange\",\"$browser\":\"Chrome\",\"$browser_version\":\"79.0.3945.117\"},\"$token\":\"dummyToken\",\"$distinct_id\":\"Santiy\",\"$ip\":\"0.0.0.0\",\"$time\":null}]" }, XML: {}, },