Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: mixpanel set once feature onboard #2820

Merged
merged 23 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
850397e
feat: initial commit
shrouti1507 Nov 10, 2023
03a0b7b
Merge branch 'develop' into feat.mp_set_once
shrouti1507 Nov 10, 2023
55715dd
feat: making sure existing functionality is intact
shrouti1507 Nov 10, 2023
682fc95
fix: edits for exclusion keys
shrouti1507 Nov 13, 2023
028104b
Merge branch 'develop' into feat.mp_set_once
shrouti1507 Nov 13, 2023
33927d4
fix: edits for supporting property paths
shrouti1507 Nov 13, 2023
5f3a35c
fix: delete wrong test case
shrouti1507 Nov 13, 2023
ea60161
fix: test cases
shrouti1507 Nov 13, 2023
2682a5d
Merge branch 'develop' into feat.mp_set_once
shrouti1507 Nov 13, 2023
1dafad7
fix: removed unnecessary code
shrouti1507 Nov 14, 2023
13edf54
Merge branch 'feat.mp_set_once' of github.com:rudderlabs/rudder-trans…
shrouti1507 Nov 14, 2023
3273c62
fix: adding unit test cases for trimTraits
shrouti1507 Nov 16, 2023
9271f11
fix: changing the order of priority in property mapping
shrouti1507 Nov 16, 2023
c0ac630
fix: edited distinct id logic
shrouti1507 Nov 16, 2023
94c3539
fix: small edit
shrouti1507 Nov 16, 2023
6ea3d1e
fix: review comments addressed
shrouti1507 Nov 16, 2023
91beb1e
fix: adding dedicated mappingJson for setOnce
shrouti1507 Nov 17, 2023
9656f63
Merge branch 'develop' into feat.mp_set_once
shrouti1507 Nov 17, 2023
51b0313
fix: adding all the fields to the dedicated json
shrouti1507 Nov 17, 2023
99396a1
Merge branch 'feat.mp_set_once' of github.com:rudderlabs/rudder-trans…
shrouti1507 Nov 17, 2023
c891da8
Merge branch 'develop' into feat.mp_set_once
shrouti1507 Nov 21, 2023
6f9ff79
fix: addressing review comments
shrouti1507 Nov 22, 2023
2949fa1
feat: review comments addressed
shrouti1507 Nov 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/v0/destinations/mp/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const ConfigCategory = {
IDENTIFY: {
name: 'MPIdentifyConfig',
},
SET_ONCE: {
name: 'MPSetOnceConfig',
},
PROFILE_ANDROID: {
name: 'MPProfilePropertiesAndroid',
},
Expand Down
122 changes: 122 additions & 0 deletions src/v0/destinations/mp/data/MPSetOnceConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
[
{
"destKey": "$created",
"sourceKeys": "createdAt",
"required": false
},
{
"destKey": "$email",
"sourceKeys": "email",
"required": false
},
{
"destKey": "$first_name",
"sourceKeys": ["firstName", "firstname", "first_name"],
"required": false
},
{
"destKey": "$last_name",
"sourceKeys": ["lastName", "lastname", "last_name"],
"required": false
},
{
"destKey": "$name",
"sourceKeys": "name",
"required": false
},
{
"destKey": "$username",
"sourceKeys": ["username", "userName"],
"required": false
},
{
"destKey": "$phone",
"sourceKeys": "phone",
"required": false
},
{
"destKey": "$avatar",
"sourceKeys": "avatar",
"required": false
},
{
"destKey": "$country_code",
"sourceKeys": ["country", "address.country"],
"required": false
},
{
"destKey": "$city",
"sourceKeys": ["city", "address.city"],
"required": false
},
{
"destKey": "$region",
"sourceKeys": ["state", "address.state", "location.region"],
"required": false
},
{
"destKey": "$unsubscribed",
"sourceKeys": "unsubscribed",
"required": false
},
{
"destKey": "$geo_source",
"sourceKeys": "location.geoSource",
"required": false
},
{
"destKey": "$timezone",
"sourceKeys": "location.timezone",
"required": false
},
{
"destKey": "$latitude",
"sourceKeys": "location.latitude",
"required": false
},
{
"destKey": "$longitude",
"sourceKeys": "location.longitude",
"required": false
},
{
"destKey": "$carrier",
"sourceKeys": "network.carrier",
"required": false
},
{
"destKey": "$manufacturer",
"sourceKeys": "device.manufacturer",
"required": false
},
{
"destKey": "$model",
"sourceKeys": "device.model",
"required": false
},
{
"destKey": "$screen_height",
"sourceKeys": "screen.height",
"required": false
},
{
"destKey": "$screen_width",
"sourceKeys": "screen.width",
"required": false
},
{
"destKey": "$wifi",
"sourceKeys": "network.wifi",
"required": false
},
{
"destKey": "$initial_referrer",
"sourceKeys": "page.initial_referrer",
"required": false
},
{
"destKey": "$initial_referring_domain",
"sourceKeys": ["page.initial_referring_domain", "page.initialReferringDomain"],
"required": false
}
]
50 changes: 44 additions & 6 deletions src/v0/destinations/mp/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const {
combineBatchRequestsWithSameJobIds,
groupEventsByEndpoint,
batchEvents,
parseConfigArray,
trimTraits,
} = require('./util');
const { CommonUtils } = require('../../../util/common');

Expand Down Expand Up @@ -226,17 +228,54 @@ const processTrack = (message, destination) => {
return returnValue;
};

const createSetOnceResponse = (message, type, destination, setOnce) => {
const payload = {
$set_once: setOnce,
$token: destination.Config.token,
$distinct_id: message.userId || message.anonymousId,
shrouti1507 marked this conversation as resolved.
Show resolved Hide resolved
};

if (destination?.Config.identityMergeApi === 'simplified') {
payload.$distinct_id = message.userId || `$device:${message.anonymousId}`;
}

return responseBuilderSimple(payload, message, type, destination.Config);
};

const processIdentifyEvents = async (message, type, destination) => {
const messageClone = { ...message };
let seggregatedTraits = {};
const returnValue = [];
let setOnceProperties = [];

// making payload for set_once properties
if (
destination.Config.setOnceProperties &&
Object.keys(destination.Config.setOnceProperties).length > 0
koladilip marked this conversation as resolved.
Show resolved Hide resolved
) {
setOnceProperties = parseConfigArray(destination.Config.setOnceProperties, 'property');
seggregatedTraits = trimTraits(
messageClone.traits,
messageClone.context.traits,
setOnceProperties,
);
messageClone.traits = seggregatedTraits.traits;
messageClone.context.traits = seggregatedTraits.contextTraits;
if (Object.keys(seggregatedTraits.setOnce).length > 0) {
returnValue.push(
createSetOnceResponse(messageClone, type, destination, seggregatedTraits.setOnce),
);
}
}

// Creating the user profile
// https://developer.mixpanel.com/reference/profile-set
returnValue.push(createIdentifyResponse(message, type, destination, responseBuilderSimple));
returnValue.push(createIdentifyResponse(messageClone, type, destination, responseBuilderSimple));

if (
destination.Config?.identityMergeApi !== 'simplified' &&
message.userId &&
message.anonymousId &&
messageClone.userId &&
messageClone.anonymousId &&
isImportAuthCredentialsAvailable(destination)
) {
// If userId and anonymousId both are present and required credentials for /import
Expand All @@ -245,13 +284,13 @@ const processIdentifyEvents = async (message, type, destination) => {
const trackPayload = {
event: '$merge',
properties: {
$distinct_ids: [message.userId, message.anonymousId],
$distinct_ids: [messageClone.userId, messageClone.anonymousId],
token: destination.Config.token,
},
};
const identifyTrackResponse = responseBuilderSimple(
trackPayload,
message,
messageClone,
'merge',
destination.Config,
);
Expand Down Expand Up @@ -440,7 +479,6 @@ const processRouterDest = async (inputs, reqMetadata) => {
destination: event.destination,
};
}

let processedEvents = await process(event);
processedEvents = CommonUtils.toArray(processedEvents);
return processedEvents.map((res) => ({
Expand Down
79 changes: 79 additions & 0 deletions src/v0/destinations/mp/util.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const lodash = require('lodash');
const set = require('set-value');
const get = require('get-value');
const { InstrumentationError } = require('@rudderstack/integrations-lib');
Expand All @@ -14,6 +15,7 @@ const {
defaultBatchRequestConfig,
IsGzipSupported,
isObject,
isDefinedAndNotNullAndNotEmpty,
} = require('../../util');
const {
ConfigCategory,
Expand All @@ -26,6 +28,7 @@ const { CommonUtils } = require('../../../util/common');
const mPIdentifyConfigJson = mappingConfig[ConfigCategory.IDENTIFY.name];
const mPProfileAndroidConfigJson = mappingConfig[ConfigCategory.PROFILE_ANDROID.name];
const mPProfileIosConfigJson = mappingConfig[ConfigCategory.PROFILE_IOS.name];
const mPSetOnceConfigJson = mappingConfig[ConfigCategory.SET_ONCE.name];

/**
* this function has been used to create
Expand Down Expand Up @@ -322,6 +325,80 @@ const combineBatchRequestsWithSameJobIds = (inputBatches) => {
return combineBatches(combineBatches(inputBatches));
};

const parseConfigArray = (arr, key) => {
Gauravudia marked this conversation as resolved.
Show resolved Hide resolved
if (!arr) {
return [];
}
return arr.map((item) => item[key]);
};

/**
* Trims the traits and contextTraits objects based on the setOnceProperties array and returns an object containing the modified traits, contextTraits, and setOnce properties.
*
* @param {object} traits - An object representing the traits.
* @param {object} contextTraits - An object representing the context traits.
* @param {string[]} setOnceProperties - An array of property paths to be considered for the setOnce transformation.
* @returns {object} - An object containing the modified traits, contextTraits, and setOnce properties.
*
* @example
* const traits = { name: 'John', age: 30 };
* const contextTraits = { country: 'USA', language: 'English', address: { city: 'New York', state: 'NY' }}};
* const setOnceProperties = ['name', 'country', 'address.city'];
*
* const result = trimTraits(traits, contextTraits, setOnceProperties);
* console.log(result);
* // Output: { traits: { age: 30 }, contextTraits: { language: 'English' }, setOnce: { $name: 'John', $country_code: 'USA', city: 'New York'} }
koladilip marked this conversation as resolved.
Show resolved Hide resolved
*/
function trimTraits(traits, contextTraits, setOnceProperties) {
let sentOnceTransform;
koladilip marked this conversation as resolved.
Show resolved Hide resolved
// Create a copy of the original traits object
const traitsCopy = { ...traits };
const contextTraitsCopy = { ...contextTraits };

// Initialize setOnce object
const setOnceEligible = {};

// Step 1: find the k-v pairs of setOnceProperties in traits and contextTraits

setOnceProperties.forEach((propertyPath) => {
const propName = lodash.last(propertyPath.split('.'));

const traitsValue = get(traitsCopy, propertyPath);
const contextTraitsValue = get(contextTraitsCopy, propertyPath);

if (isDefinedAndNotNullAndNotEmpty(traitsValue)) {
setOnceEligible[propName] = traitsValue;
lodash.unset(traitsCopy, propertyPath);
}
if (isDefinedAndNotNullAndNotEmpty(contextTraitsValue)) {
if (!setOnceEligible.hasOwnProperty(propName)) {
setOnceEligible[propName] = contextTraitsValue;
}
lodash.unset(contextTraitsCopy, propertyPath);
}
});

if (setOnceEligible && Object.keys(setOnceEligible).length > 0) {
// 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
sentOnceTransform = constructPayload(setOnceEligible, mPSetOnceConfigJson);

// Step 3: combine the transformed and custom setOnce traits
sentOnceTransform = extractCustomFields(
setOnceEligible,
sentOnceTransform,
'root',
MP_IDENTIFY_EXCLUSION_LIST,
);
}

return {
traits: traitsCopy,
contextTraits: contextTraitsCopy,
setOnce: sentOnceTransform || {},
};
}

module.exports = {
createIdentifyResponse,
isImportAuthCredentialsAvailable,
Expand All @@ -330,4 +407,6 @@ module.exports = {
generateBatchedPayloadForArray,
batchEvents,
combineBatchRequestsWithSameJobIds,
parseConfigArray,
trimTraits,
};
Loading
Loading