Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 30 additions & 9 deletions src/Rokt-Kit.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@ var moduleId = 181;

var constructor = function () {
var self = this;
var EMAIL_SHA256_IDENTITY = 'emailsha256';
var OTHER_IDENTITY = 'other';
var PerformanceMarks = {
RoktScriptAppended: 'mp:RoktScriptAppended',
};

var EMAIL_SHA256_KEY = 'emailsha256';
var EMAIL_KEY = 'email';

// Dynamic identity type for Rokt's emailsha256 identity value which MP doesn't natively support - will be set during initialization
var mappedEmailSha256Key;

self.name = name;
self.moduleId = moduleId;
self.isInitialized = false;
Expand Down Expand Up @@ -89,6 +93,13 @@ var constructor = function () {
placementEventMapping
);

// Set dynamic OTHER_IDENTITY based on server settings
// Convert to lowercase since server sends TitleCase (e.g., 'Other' -> 'other')
if (settings.hashedEmailUserIdentityType) {
mappedEmailSha256Key =
settings.hashedEmailUserIdentityType.toLowerCase();
}

var domain = window.mParticle.Rokt.domain;
var launcherOptions = mergeObjects(
{},
Expand Down Expand Up @@ -157,7 +168,7 @@ var constructor = function () {

var userIdentities = filteredUser.getUserIdentities().userIdentities;

return replaceOtherWithEmailsha256(userIdentities);
return replaceOtherIdentityWithEmailsha256(userIdentities);
}

function returnLocalSessionAttributes() {
Expand All @@ -172,11 +183,21 @@ var constructor = function () {
return window.mParticle.Rokt.getLocalSessionAttributes();
}

function replaceOtherWithEmailsha256(_data) {
function replaceOtherIdentityWithEmailsha256(userIdentities) {
var newUserIdentities = mergeObjects({}, userIdentities || {});
if (userIdentities.hasOwnProperty(mappedEmailSha256Key)) {
newUserIdentities[EMAIL_SHA256_KEY] =
userIdentities[mappedEmailSha256Key];
delete newUserIdentities[mappedEmailSha256Key];
}

return newUserIdentities;
}

function sanitizeEmailIdentities(_data) {
var data = mergeObjects({}, _data || {});
if (_data.hasOwnProperty(OTHER_IDENTITY)) {
data[EMAIL_SHA256_IDENTITY] = _data[OTHER_IDENTITY];
delete data[OTHER_IDENTITY];
if (_data.hasOwnProperty(EMAIL_SHA256_KEY)) {
delete data[EMAIL_KEY];
}

return data;
Expand Down Expand Up @@ -232,7 +253,7 @@ var constructor = function () {

var selectPlacementsAttributes = mergeObjects(
filteredUserIdentities,
replaceOtherWithEmailsha256(filteredAttributes),
filteredAttributes,
optimizelyAttributes,
localSessionAttributes,
{
Expand All @@ -241,7 +262,7 @@ var constructor = function () {
);

var selectPlacementsOptions = mergeObjects(options, {
attributes: selectPlacementsAttributes,
attributes: sanitizeEmailIdentities(selectPlacementsAttributes),
});

return self.launcher.selectPlacements(selectPlacementsOptions);
Expand Down
206 changes: 199 additions & 7 deletions test/src/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,7 @@ describe('Rokt Forwarder', () => {
await window.mParticle.forwarder.init(
{
accountId: '123456',
hashedEmailUserIdentityType: 'Other',
},
reportService.cb,
true,
Expand Down Expand Up @@ -1420,21 +1421,21 @@ describe('Rokt Forwarder', () => {
await window.mParticle.forwarder.selectPlacements({
identifier: 'test-placement',
attributes: {
other: 'sha256-test@gmail.com',
other: 'other-attribute',
},
});

window.Rokt.selectPlacementsOptions.attributes.should.deepEqual(
{
'test-attribute': 'test-value',
customerid: 'customer123',
emailsha256: 'sha256-test@gmail.com',
other: 'other-attribute',
mpid: '123',
}
);
});

it('should prioritize other passed to selectPlacements over other in userIdentities', async () => {
it('should pass the attribute `other` in selectPlacements directly to Rokt', async () => {
window.mParticle.Rokt.filters = {
userAttributeFilters: [],
filterUserAttributes: function (attributes) {
Expand All @@ -1448,7 +1449,7 @@ describe('Rokt Forwarder', () => {
return {
userIdentities: {
customerid: 'customer123',
other: 'not-prioritized-from-userIdentities@gmail.com',
other: 'other-id',
},
};
},
Expand Down Expand Up @@ -1486,20 +1487,211 @@ describe('Rokt Forwarder', () => {
await window.mParticle.forwarder.selectPlacements({
identifier: 'test-placement',
attributes: {
other: 'prioritized-from-selectPlacements@gmail.com',
other: 'continues-to-exist',
},
});

window.Rokt.selectPlacementsOptions.attributes.should.deepEqual(
{
'test-attribute': 'test-value',
customerid: 'customer123',
emailsha256:
'prioritized-from-selectPlacements@gmail.com',
other: 'continues-to-exist',
emailsha256: 'other-id',
mpid: '123',
}
);
});

it('should use custom hashedEmailUserIdentityType when provided in settings', async () => {
window.mParticle.Rokt.filters = {
userAttributeFilters: [],
filterUserAttributes: function (attributes) {
return attributes;
},
filteredUser: {
getMPID: function () {
return '789';
},
getUserIdentities: function () {
return {
userIdentities: {
// Using 'customerid' as the identity type instead of 'other'
other5: 'hashed-customer-id-value',
},
};
},
},
};

// Set up the createLauncher to properly resolve asynchronously
window.Rokt.createLauncher = async function () {
return Promise.resolve({
selectPlacements: function (options) {
window.mParticle.Rokt.selectPlacementsOptions =
options;
window.mParticle.Rokt.selectPlacementsCalled = true;
},
});
};

await window.mParticle.forwarder.init(
{
accountId: '123456',
hashedEmailUserIdentityType: 'Other5', // TitleCase from server
},
reportService.cb,
true,
null,
{}
);

// Wait for initialization to complete (after launcher is created)
await waitForCondition(() => {
return window.mParticle.forwarder.isInitialized;
});

await window.mParticle.forwarder.selectPlacements({
identifier: 'test-placement',
attributes: {
'test-attribute': 'test-value',
},
});

// Should map customerid from userIdentities to emailsha256 since hashedEmailUserIdentityType was set to 'CustomerID'
window.Rokt.selectPlacementsOptions.attributes.should.deepEqual(
{
'test-attribute': 'test-value',
emailsha256: 'hashed-customer-id-value', // mapped from customerid in userIdentities
mpid: '789',
}
);
});

it('should NOT set emailsha256 on final select placements attributes when hashedEmailUserIdentityType is Unassigned', async () => {
window.mParticle.Rokt.filters = {
userAttributeFilters: [],
filterUserAttributes: function (attributes) {
return attributes;
},
filteredUser: {
getMPID: function () {
return '999';
},
getUserIdentities: function () {
return {
userIdentities: {
// Using lowercase identity name that matches the converted OTHER_IDENTITY
other: 'hashed-custom-identity-value',
},
};
},
},
};

// Set up the createLauncher to properly resolve asynchronously
window.Rokt.createLauncher = async function () {
return Promise.resolve({
selectPlacements: function (options) {
window.mParticle.Rokt.selectPlacementsOptions =
options;
window.mParticle.Rokt.selectPlacementsCalled = true;
},
});
};

await window.mParticle.forwarder.init(
{
accountId: '123456',
hashedEmailUserIdentityType: 'Unassigned', // Mixed case from server
},
reportService.cb,
true,
null,
{}
);

// Wait for initialization to complete (after launcher is created)
await waitForCondition(() => {
return window.mParticle.forwarder.isInitialized;
});

await window.mParticle.forwarder.selectPlacements({
identifier: 'test-placement',
attributes: {
'test-attr': 'test-value',
},
});

// Should map customidentity from userIdentities to emailsha256 (TitleCase converted to lowercase)
window.Rokt.selectPlacementsOptions.attributes.should.deepEqual(
{
'test-attr': 'test-value',
other: 'hashed-custom-identity-value',
mpid: '999',
}
);
});

it('should remove email identity if emailsha256 is passed through selectPlacements', async () => {
window.mParticle.Rokt.filters = {
userAttributeFilters: [],
filterUserAttributes: function (attributes) {
return attributes;
},
filteredUser: {
getMPID: function () {
return '456';
},
getUserIdentities: function () {
return {
userIdentities: {
email: 'test@example.com',
},
};
},
},
};

// Set up the createLauncher to properly resolve asynchronously
window.Rokt.createLauncher = async function () {
return Promise.resolve({
selectPlacements: function (options) {
window.mParticle.Rokt.selectPlacementsOptions =
options;
window.mParticle.Rokt.selectPlacementsCalled = true;
},
});
};

await window.mParticle.forwarder.init(
{
accountId: '123456',
},
reportService.cb,
true,
null,
{}
);

// Wait for initialization to complete (after launcher is created)
await waitForCondition(() => {
return window.mParticle.forwarder.isInitialized;
});

await window.mParticle.forwarder.selectPlacements({
identifier: 'test-placement',
attributes: {
emailsha256: 'hashed-email-value',
},
});

window.Rokt.selectPlacementsOptions.attributes.should.deepEqual(
{
emailsha256: 'hashed-email-value',
mpid: '456',
}
);
});
});
});

Expand Down