diff --git a/src/Rokt-Kit.js b/src/Rokt-Kit.js index b1574fd..9775abf 100644 --- a/src/Rokt-Kit.js +++ b/src/Rokt-Kit.js @@ -17,6 +17,13 @@ var name = 'Rokt'; var moduleId = 181; var EVENT_NAME_SELECT_PLACEMENTS = 'selectPlacements'; +var PRELOAD_CONFIGS = { + '2550745407543340151': { + requiredAttributes: ['email', 'firstname', 'cartitems'], + identifier: 'RoktExperience', + }, +}; + var constructor = function () { var self = this; var PerformanceMarks = { @@ -40,6 +47,8 @@ var constructor = function () { self.placementEventAttributeMappingLookup = {}; self.eventQueue = []; self.integrationName = null; + self.accountId = null; + self.hasPreloaded = false; function getEventAttributeValue(event, eventAttributeKey) { var attributes = event && event.EventAttributes; @@ -221,6 +230,7 @@ var constructor = function () { filteredUserAttributes ) { var accountId = settings.accountId; + self.accountId = accountId; var roktExtensions = extractRoktExtensions(settings.roktExtensions); self.userAttributes = filteredUserAttributes || {}; self.onboardingExpProvider = settings.onboardingExpProvider; @@ -517,6 +527,8 @@ var constructor = function () { var mappedValue = self.placementEventMappingLookup[hashedEvent]; window.mParticle.Rokt.setLocalSessionAttribute(mappedValue, true); } + + tryPreloadIfReady(); } function _sendEventStream(event) { @@ -528,10 +540,12 @@ var constructor = function () { function onUserIdentified(filteredUser) { self.filters.filteredUser = filteredUser; self.userAttributes = filteredUser.getAllUserAttributes(); + tryPreloadIfReady(); } function setUserAttribute(key, value) { self.userAttributes[key] = value; + tryPreloadIfReady(); } function removeUserAttribute(key) { @@ -583,6 +597,7 @@ var constructor = function () { // Attaches the kit to the Rokt manager window.mParticle.Rokt.attachKit(self); processEventQueue(); + tryPreloadIfReady(); } // mParticle Kit Callback Methods @@ -651,6 +666,34 @@ var constructor = function () { return !!(self.isInitialized && self.launcher); } + function tryPreloadIfReady() { + if (!isKitReady() || self.hasPreloaded) { + return; + } + var config = PRELOAD_CONFIGS[self.accountId]; + if (!config) { + return; + } + var mergedAttributes = mergeObjects( + returnUserIdentities(self.filters && self.filters.filteredUser), + self.userAttributes, + returnLocalSessionAttributes() + ); + for (var i = 0; i < config.requiredAttributes.length; i++) { + if (mergedAttributes[config.requiredAttributes[i]] == null) { + return; + } + } + self.hasPreloaded = true; + selectPlacements({ + identifier: config.identifier, + omitUrl: true, + preload: true, + }).catch(function (err) { + console.error('Rokt Kit: preload failed', err); + }); + } + function isPartnerInLocalLauncherTestGroup() { return ( window.mParticle.config && diff --git a/test/src/tests.js b/test/src/tests.js index 2d05873..a0e8d52 100644 --- a/test/src/tests.js +++ b/test/src/tests.js @@ -2895,6 +2895,124 @@ describe('Rokt Forwarder', () => { }); }); + describe('#tryPreloadIfReady', () => { + var ULTA_ACCOUNT_ID = '2550745407543340151'; + var preloadCallOptions; + var preloadCallCount; + + beforeEach(() => { + preloadCallOptions = null; + preloadCallCount = 0; + + window.mParticle.Rokt.setLocalSessionAttribute = function ( + key, + value + ) { + mParticle._Store.localSessionAttributes[key] = value; + }; + window.mParticle.Rokt.getLocalSessionAttributes = function () { + return mParticle._Store.localSessionAttributes || {}; + }; + mParticle._Store.localSessionAttributes = {}; + + window.mParticle.forwarder.isInitialized = true; + window.mParticle.forwarder.accountId = ULTA_ACCOUNT_ID; + window.mParticle.forwarder.hasPreloaded = false; + window.mParticle.forwarder.launcher = { + selectPlacements: function (options) { + preloadCallCount++; + preloadCallOptions = options; + return Promise.resolve(); + }, + }; + window.mParticle.forwarder.filters = { + filterUserAttributes: function (attributes) { + return attributes; + }, + filteredUser: { + getMPID: function () { + return '123'; + }, + getUserIdentities: function () { + return { userIdentities: {} }; + }, + }, + }; + }); + + it('should not preload for an unknown account id', () => { + window.mParticle.forwarder.accountId = '999999'; + window.mParticle.forwarder.userAttributes = { + email: 'test@example.com', + firstname: 'Jane', + cartitems: '2', + }; + + window.mParticle.forwarder.setUserAttribute('email', 'test@example.com'); + + preloadCallCount.should.equal(0); + }); + + it('should not preload when only some required attributes are present', () => { + window.mParticle.forwarder.setUserAttribute('email', 'test@example.com'); + window.mParticle.forwarder.setUserAttribute('firstname', 'Jane'); + + preloadCallCount.should.equal(0); + }); + + it('should preload when all required attributes are set via setUserAttribute', async () => { + window.mParticle.forwarder.setUserAttribute('email', 'test@example.com'); + window.mParticle.forwarder.setUserAttribute('firstname', 'Jane'); + window.mParticle.forwarder.setUserAttribute('cartitems', '3'); + + preloadCallCount.should.equal(1); + preloadCallOptions.identifier.should.equal('RoktExperience'); + preloadCallOptions.omitUrl.should.equal(true); + preloadCallOptions.preload.should.equal(true); + }); + + it('should preload when all required attributes are provided via onUserIdentified', () => { + window.mParticle.forwarder.onUserIdentified({ + getAllUserAttributes: function () { + return { + email: 'test@example.com', + firstname: 'Jane', + cartitems: '3', + }; + }, + getMPID: function () { + return '123'; + }, + getUserIdentities: function () { + return { userIdentities: {} }; + }, + }); + + preloadCallCount.should.equal(1); + preloadCallOptions.identifier.should.equal('RoktExperience'); + preloadCallOptions.omitUrl.should.equal(true); + preloadCallOptions.preload.should.equal(true); + }); + + it('should only preload once per session even when attributes are updated again', () => { + window.mParticle.forwarder.setUserAttribute('email', 'test@example.com'); + window.mParticle.forwarder.setUserAttribute('firstname', 'Jane'); + window.mParticle.forwarder.setUserAttribute('cartitems', '3'); + window.mParticle.forwarder.setUserAttribute('cartitems', '5'); + + preloadCallCount.should.equal(1); + }); + + it('should not preload if the kit is not initialized', () => { + window.mParticle.forwarder.isInitialized = false; + window.mParticle.forwarder.setUserAttribute('email', 'test@example.com'); + window.mParticle.forwarder.setUserAttribute('firstname', 'Jane'); + window.mParticle.forwarder.setUserAttribute('cartitems', '3'); + + preloadCallCount.should.equal(0); + }); + }); + describe('#fetchOptimizely', () => { // Helper functions for setting up Optimizely mocks function setupValidOptimizelyMock(experiments) {