diff --git a/src/Rokt-Kit.js b/src/Rokt-Kit.js index dd86efc..6fec098 100644 --- a/src/Rokt-Kit.js +++ b/src/Rokt-Kit.js @@ -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} 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) { + 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 @@ -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; @@ -75,6 +83,7 @@ var constructor = function () { if (testMode) { self.testHelpers = { generateLauncherScript: generateLauncherScript, + extractRoktExtensions: extractRoktExtensions, }; attachLauncher(accountId, launcherOptions); return; @@ -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'; @@ -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(); @@ -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; @@ -365,6 +391,25 @@ function mergeObjects() { return resObj; } +function parseSettingsString(settingsString) { + try { + return JSON.parse(settingsString.replace(/"/g, '"')); + } 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, diff --git a/test/src/tests.js b/test/src/tests.js index b859ce7..8369f9e 100644 --- a/test/src/tests.js +++ b/test/src/tests.js @@ -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; @@ -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 = + '[{"jsmap":null,"map":null,"maptype":"StaticList","value":"cos-extension-detection"},{"jsmap":null,"map":null,"maptype":"StaticList","value":"experiment-monitoring"}]'; + const expectedExtensions = [ + 'cos-extension-detection', + 'experiment-monitoring', + ]; + + window.mParticle.forwarder.testHelpers + .extractRoktExtensions(settingsString) + .should.deepEqual(expectedExtensions); + }); + }); }); });