Skip to content
Open
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
160 changes: 157 additions & 3 deletions src/Rokt-Kit.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,138 @@ var constructor = function () {
self.userAttributes = {};
self.testHelpers = null;
self.placementEventMappingLookup = {};
self.placementEventAttributeMappingLookup = {};
self.eventQueue = [];

function getEventAttributeValue(event, eventAttributeKey) {
var attributes = event && event.EventAttributes;
if (!attributes) {
return null;
}

if (typeof attributes[eventAttributeKey] === 'undefined') {
return null;
}

return attributes[eventAttributeKey];
}

function doesEventAttributeConditionMatch(condition, actualValue) {
if (!condition || !isString(condition.operator)) {
return false;
}

var operator = condition.operator.toLowerCase();
var expectedValue = condition.attributeValue;

if (operator === 'exists') {
return actualValue !== null;
}

if (actualValue == null) {
return false;
}

if (operator === 'equals') {
return String(actualValue) === String(expectedValue);
}

if (operator === 'contains') {
return String(actualValue).indexOf(String(expectedValue)) !== -1;
}

Comment on lines +71 to +78
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider adding some additional test cases to add some potential edge cases. Something like 2 === "2" would likley pass as intended but what if you're testing true === 'True'or even"TRUE" === 'True'"`?

I think you have some guard clauses that should catch this, but also make sure something like "0" === "false" or "0" === "" is covered in tests.

return false;
}

function doesEventMatchRule(event, rule) {
if (!rule || !isString(rule.eventAttributeKey)) {
return false;
}

var conditions = rule.conditions;
if (!Array.isArray(conditions)) {
return false;
}

var actualValue = getEventAttributeValue(event, rule.eventAttributeKey);

if (conditions.length === 0) {
return actualValue !== null;
}
for (var i = 0; i < conditions.length; i++) {
if (!doesEventAttributeConditionMatch(conditions[i], actualValue)) {
return false;
}
}

return true;
}

function generateMappedEventAttributeLookup(
placementEventAttributeMapping
) {
var mappedAttributeKeys = {};
if (!Array.isArray(placementEventAttributeMapping)) {
return mappedAttributeKeys;
}
for (var i = 0; i < placementEventAttributeMapping.length; i++) {
var mapping = placementEventAttributeMapping[i];
if (
!mapping ||
!isString(mapping.value) ||
!isString(mapping.map)
) {
continue;
}

var mappedAttributeKey = mapping.value;
var eventAttributeKey = mapping.map;

if (!mappedAttributeKeys[mappedAttributeKey]) {
mappedAttributeKeys[mappedAttributeKey] = [];
}

mappedAttributeKeys[mappedAttributeKey].push({
eventAttributeKey: eventAttributeKey,
conditions: Array.isArray(mapping.conditions)
? mapping.conditions
: [],
});
}
return mappedAttributeKeys;
}

function applyPlacementEventAttributeMapping(event) {
var mappedAttributeKeys = Object.keys(
self.placementEventAttributeMappingLookup
);
for (var i = 0; i < mappedAttributeKeys.length; i++) {
var mappedAttributeKey = mappedAttributeKeys[i];
var rulesForMappedAttributeKey =
self.placementEventAttributeMappingLookup[mappedAttributeKey];
if (isEmpty(rulesForMappedAttributeKey)) {
continue;
}

// Require ALL rules for the same key to match (AND).
var allMatch = true;
for (var j = 0; j < rulesForMappedAttributeKey.length; j++) {
if (!doesEventMatchRule(event, rulesForMappedAttributeKey[j])) {
allMatch = false;
break;
}
}
if (!allMatch) {
continue;
}

window.mParticle.Rokt.setLocalSessionAttribute(
mappedAttributeKey,
true
);
}
}

/**
* Generates the Rokt launcher script URL with optional domain override and extensions
* @param {string} domain - The CNAME domain to use for overriding the launcher url
Expand Down Expand Up @@ -92,6 +222,12 @@ var constructor = function () {
placementEventMapping
);

var placementEventAttributeMapping = parseSettingsString(
settings.placementEventAttributeMapping
);
self.placementEventAttributeMappingLookup =
generateMappedEventAttributeLookup(placementEventAttributeMapping);

// Set dynamic OTHER_IDENTITY based on server settings
// Convert to lowercase since server sends TitleCase (e.g., 'Other' -> 'other')
if (settings.hashedEmailUserIdentityType) {
Expand All @@ -115,6 +251,8 @@ var constructor = function () {
hashEventMessage: hashEventMessage,
parseSettingsString: parseSettingsString,
generateMappedEventLookup: generateMappedEventLookup,
generateMappedEventAttributeLookup:
generateMappedEventAttributeLookup,
};
attachLauncher(accountId, launcherOptions);
return;
Expand Down Expand Up @@ -172,13 +310,18 @@ var constructor = function () {

function returnLocalSessionAttributes() {
if (
isEmpty(self.placementEventMappingLookup) ||
!window.mParticle.Rokt ||
typeof window.mParticle.Rokt.getLocalSessionAttributes !==
'function'
) {
return {};
}
if (
isEmpty(self.placementEventMappingLookup) &&
isEmpty(self.placementEventAttributeMappingLookup)
) {
return {};
}
return window.mParticle.Rokt.getLocalSessionAttributes();
}

Expand Down Expand Up @@ -268,7 +411,7 @@ var constructor = function () {
console.error('Rokt Kit: Not initialized');
return Promise.reject(new Error('Rokt Kit: Not initialized'));
}
if (!extensionName || typeof extensionName !== 'string') {
if (!extensionName || !isString(extensionName)) {
return Promise.reject(
new Error('Rokt Kit: Invalid extension name')
);
Expand Down Expand Up @@ -306,12 +449,19 @@ var constructor = function () {
}

if (
isEmpty(self.placementEventMappingLookup) ||
typeof window.mParticle.Rokt.setLocalSessionAttribute !== 'function'
) {
return;
}

if (!isEmpty(self.placementEventAttributeMappingLookup)) {
applyPlacementEventAttributeMapping(event);
}

if (isEmpty(self.placementEventMappingLookup)) {
return;
}

var hashedEvent = hashEventMessage(
event.EventDataType,
event.EventCategory,
Expand Down Expand Up @@ -580,6 +730,10 @@ function isEmpty(value) {
return value == null || !(Object.keys(value) || value).length;
}

function isString(value) {
return typeof value === 'string';
}

if (window && window.mParticle && window.mParticle.addForwarder) {
window.mParticle.addForwarder({
name: name,
Expand Down
Loading