Skip to content
53 changes: 49 additions & 4 deletions src/Rokt-Kit.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,28 @@ var constructor = function () {
self.launcher = null;
self.filters = {};
self.userAttributes = {};
self.testHelpers = null;

/**
* Generates the Rokt launcher script URL with optional domain override
* 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
* @param {Array<string>} extensions - List of extension query parameters to append
* @returns {string} The complete launcher script URL
*/
function generateLauncherScript(_domain) {
function generateLauncherScript(_domain, extensions) {
// Override domain if a customer is using a CNAME
// If a customer is using a CNAME, a domain will be passed. If not, we use the default domain.
var domain = typeof _domain !== 'undefined' ? _domain : 'apps.rokt.com';
var protocol = 'https://';
var launcherPath = '/wsdk/integrations/launcher.js';
var baseUrl = [protocol, domain, launcherPath].join('');

return [protocol, domain, launcherPath].join('');
if (!extensions || extensions.length === 0) {
Comment thread
alexs-mparticle marked this conversation as resolved.
return baseUrl;
}
return baseUrl + '?extensions=' + extensions.join(',');
}

/**
* Passes attributes to the Rokt Web SDK for client-side hashing
* @see https://docs.rokt.com/developers/integration-guides/web/library/integration-launcher#hash-attributes
Expand All @@ -64,6 +71,7 @@ var constructor = function () {
filteredUserAttributes
) {
var accountId = settings.accountId;
var roktExtensions = extractRoktExtensions(settings.roktExtensions);
self.userAttributes = filteredUserAttributes;
self.onboardingExpProvider = settings.onboardingExpProvider;
var domain = window.mParticle.Rokt.domain;
Expand All @@ -75,6 +83,7 @@ var constructor = function () {
if (testMode) {
self.testHelpers = {
generateLauncherScript: generateLauncherScript,
extractRoktExtensions: extractRoktExtensions,
};
attachLauncher(accountId, launcherOptions);
return;
Expand All @@ -84,7 +93,7 @@ var constructor = function () {
var target = document.head || document.body;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = generateLauncherScript(domain);
script.src = generateLauncherScript(domain, roktExtensions);
script.async = true;
script.crossOrigin = 'anonymous';
script.fetchPriority = 'high';
Expand Down Expand Up @@ -189,6 +198,22 @@ var constructor = function () {
return self.launcher.selectPlacements(selectPlacementsOptions);
}

/**
* Sets extension data for Rokt Web SDK
* @param {Object} partnerExtensionData - The extension data object containing:
* - [extensionName] {string}: Name of the extension
* - [extensionName].options {Object}: Key-value pairs of options for the extension
* @returns {void} Nothing is returned
*/
function setExtensionData(partnerExtensionData) {
if (!isInitialized()) {
console.error('Rokt Kit: Not initialized');
return;
}

window.Rokt.setExtensionData(partnerExtensionData);
}

function onUserIdentified(filteredUser) {
self.filters.filteredUser = filteredUser;
self.userAttributes = filteredUser.getAllUserAttributes();
Expand Down Expand Up @@ -287,6 +312,7 @@ var constructor = function () {

// Kit Callback Methods
this.init = initForwarder;
this.setExtensionData = setExtensionData;
this.setUserAttribute = setUserAttribute;
this.onUserIdentified = onUserIdentified;
this.removeUserAttribute = removeUserAttribute;
Expand Down Expand Up @@ -365,6 +391,25 @@ function mergeObjects() {
return resObj;
}

function parseSettingsString(settingsString) {
try {
return JSON.parse(settingsString.replace(/&quot;/g, '"'));
Comment thread
alexs-mparticle marked this conversation as resolved.
} catch (error) {
throw new Error('Settings string contains invalid JSON');
}
}

function extractRoktExtensions(settingsString) {
var settings = settingsString ? parseSettingsString(settingsString) : [];

var roktExtensions = [];
for (var i = 0; i < settings.length; i++) {
roktExtensions.push(settings[i].value);
}

return roktExtensions;
}

if (window && window.mParticle && window.mParticle.addForwarder) {
window.mParticle.addForwarder({
name: name,
Expand Down
78 changes: 74 additions & 4 deletions test/src/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,11 @@ describe('Rokt Forwarder', () => {

this.initializeCalled = false;
this.isInitialized = false;

this.accountId = null;
this.sandbox = null;
this.integrationName = null;
this.noFunctional = null;
this.noTargeting = null;

this.createLauncherCalled = false;

this.createLauncher = function (options) {
self.accountId = options.accountId;
self.integrationName = options.integrationName;
Expand Down Expand Up @@ -1209,5 +1206,78 @@ describe('Rokt Forwarder', () => {
'https://cname.rokt.com/wsdk/integrations/launcher.js'
);
});

it('should return base URL when no extensions are provided', () => {
const url =
window.mParticle.forwarder.testHelpers.generateLauncherScript();
url.should.equal(baseUrl);
});

it('should return base URL when extensions is null or undefined', () => {
window.mParticle.forwarder.testHelpers
.generateLauncherScript(undefined, null)
.should.equal(baseUrl);

window.mParticle.forwarder.testHelpers
.generateLauncherScript(undefined, undefined)
.should.equal(baseUrl);
});

it('should correctly append a single extension', () => {
const url =
window.mParticle.forwarder.testHelpers.generateLauncherScript(
undefined,
['cos-extension-detection']
);
url.should.equal(baseUrl + '?extensions=cos-extension-detection');
});

it('should correctly append multiple extensions', () => {
const url =
window.mParticle.forwarder.testHelpers.generateLauncherScript(
undefined,
[
'cos-extension-detection',
'experiment-monitoring',
'sponsored-payments-apple-pay',
]
);
url.should.equal(
baseUrl +
'?extensions=cos-extension-detection,' +
'experiment-monitoring,' +
'sponsored-payments-apple-pay'
);
});
});

describe('#roktExtensions', () => {
beforeEach(async () => {
window.Rokt = new MockRoktForwarder();
window.mParticle.Rokt = window.Rokt;

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

describe('extractRoktExtensions', () => {
it('should correctly map known extension names to their query parameters', async () => {
const settingsString =
'[{&quot;jsmap&quot;:null,&quot;map&quot;:null,&quot;maptype&quot;:&quot;StaticList&quot;,&quot;value&quot;:&quot;cos-extension-detection&quot;},{&quot;jsmap&quot;:null,&quot;map&quot;:null,&quot;maptype&quot;:&quot;StaticList&quot;,&quot;value&quot;:&quot;experiment-monitoring&quot;}]';
const expectedExtensions = [
'cos-extension-detection',
'experiment-monitoring',
];

window.mParticle.forwarder.testHelpers
.extractRoktExtensions(settingsString)
.should.deepEqual(expectedExtensions);
});
});
});
});