From 944aeaa817a793a936d27f6a2fbf1b90365eebff Mon Sep 17 00:00:00 2001 From: Alexander Sapountzis Date: Thu, 12 Mar 2026 11:43:32 -0400 Subject: [PATCH 1/3] feat: Add Event Stream for Rokt Events --- src/Rokt-Kit.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Rokt-Kit.js b/src/Rokt-Kit.js index 2f5e621..b1574fd 100644 --- a/src/Rokt-Kit.js +++ b/src/Rokt-Kit.js @@ -491,6 +491,8 @@ var constructor = function () { return; } + _sendEventStream(event); + if ( typeof window.mParticle.Rokt.setLocalSessionAttribute !== 'function' ) { @@ -517,6 +519,12 @@ var constructor = function () { } } + function _sendEventStream(event) { + if (window.Rokt && typeof window.Rokt.__event_stream__ === 'function') { + window.Rokt.__event_stream__(event); + } + } + function onUserIdentified(filteredUser) { self.filters.filteredUser = filteredUser; self.userAttributes = filteredUser.getAllUserAttributes(); From 4ea1885e9c621af08d637972a1a0a5de62e4eba2 Mon Sep 17 00:00:00 2001 From: Alexander Sapountzis Date: Thu, 12 Mar 2026 11:51:23 -0400 Subject: [PATCH 2/3] test: Add tests --- test/src/tests.js | 280 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) diff --git a/test/src/tests.js b/test/src/tests.js index 6fa9269..8d3c554 100644 --- a/test/src/tests.js +++ b/test/src/tests.js @@ -4315,6 +4315,286 @@ describe('Rokt Forwarder', () => { }); }); + describe('#_sendEventStream', () => { + beforeEach(() => { + window.Rokt = new MockRoktForwarder(); + window.Rokt.createLauncher = async function () { + return Promise.resolve({ + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, + }); + }; + window.mParticle.Rokt = window.Rokt; + window.mParticle.Rokt.attachKitCalled = false; + window.mParticle.Rokt.attachKit = async (kit) => { + window.mParticle.Rokt.attachKitCalled = true; + window.mParticle.Rokt.kit = kit; + Promise.resolve(); + }; + window.mParticle.Rokt.setLocalSessionAttribute = function ( + key, + value + ) { + window.mParticle._Store.localSessionAttributes[key] = value; + }; + window.mParticle.Rokt.getLocalSessionAttributes = function () { + return window.mParticle._Store.localSessionAttributes; + }; + window.mParticle.forwarder.launcher = { + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, + }; + window.mParticle.Rokt.filters = { + userAttributesFilters: [], + filterUserAttributes: function (attributes) { + return attributes; + }, + filteredUser: { + getMPID: function () { + return '123'; + }, + }, + }; + }); + + afterEach(() => { + delete window.Rokt.__event_stream__; + window.mParticle.forwarder.eventQueue = []; + window.mParticle.forwarder.isInitialized = false; + window.mParticle.Rokt.attachKitCalled = false; + }); + + it('should forward event to window.Rokt.__event_stream__ when available', async () => { + var receivedEvents = []; + window.Rokt.__event_stream__ = function (event) { + receivedEvents.push(event); + }; + + await window.mParticle.forwarder.init( + { accountId: '123456' }, + reportService.cb, + true, + null, + {} + ); + + await waitForCondition( + () => window.mParticle.Rokt.attachKitCalled + ); + + var testEvent = { + EventName: 'Test Event', + EventCategory: EventType.Other, + EventDataType: MessageType.PageEvent, + }; + + window.mParticle.forwarder.process(testEvent); + + receivedEvents.length.should.equal(1); + receivedEvents[0].should.deepEqual(testEvent); + }); + + it('should not throw when window.Rokt.__event_stream__ is not defined', async () => { + await window.mParticle.forwarder.init( + { accountId: '123456' }, + reportService.cb, + true, + null, + {} + ); + + await waitForCondition( + () => window.mParticle.Rokt.attachKitCalled + ); + + (function () { + window.mParticle.forwarder.process({ + EventName: 'Test Event', + EventCategory: EventType.Other, + EventDataType: MessageType.PageEvent, + }); + }.should.not.throw()); + }); + + it('should not throw when window.Rokt is undefined', async () => { + await window.mParticle.forwarder.init( + { accountId: '123456' }, + reportService.cb, + true, + null, + {} + ); + + await waitForCondition( + () => window.mParticle.Rokt.attachKitCalled + ); + + var savedRokt = window.Rokt; + window.Rokt = undefined; + + (function () { + window.mParticle.forwarder.process({ + EventName: 'Test Event', + EventCategory: EventType.Other, + EventDataType: MessageType.PageEvent, + }); + }.should.not.throw()); + + window.Rokt = savedRokt; + }); + + it('should forward event with attributes to the event stream', async () => { + var receivedEvents = []; + window.Rokt.__event_stream__ = function (event) { + receivedEvents.push(event); + }; + + await window.mParticle.forwarder.init( + { accountId: '123456' }, + reportService.cb, + true, + null, + {} + ); + + await waitForCondition( + () => window.mParticle.Rokt.attachKitCalled + ); + + var testEvent = { + EventName: 'Purchase', + EventCategory: EventType.Transaction, + EventDataType: MessageType.PageEvent, + EventAttributes: { + product: 'shoes', + price: '49.99', + }, + }; + + window.mParticle.forwarder.process(testEvent); + + receivedEvents.length.should.equal(1); + receivedEvents[0].EventAttributes.should.deepEqual({ + product: 'shoes', + price: '49.99', + }); + }); + + it('should forward multiple events to the event stream', async () => { + var receivedEvents = []; + window.Rokt.__event_stream__ = function (event) { + receivedEvents.push(event); + }; + + await window.mParticle.forwarder.init( + { accountId: '123456' }, + reportService.cb, + true, + null, + {} + ); + + await waitForCondition( + () => window.mParticle.Rokt.attachKitCalled + ); + + window.mParticle.forwarder.process({ + EventName: 'Event A', + EventCategory: EventType.Other, + EventDataType: MessageType.PageEvent, + }); + + window.mParticle.forwarder.process({ + EventName: 'Event B', + EventCategory: EventType.Navigation, + EventDataType: MessageType.PageView, + }); + + receivedEvents.length.should.equal(2); + receivedEvents[0].EventName.should.equal('Event A'); + receivedEvents[1].EventName.should.equal('Event B'); + }); + + it('should forward queued events to the event stream after init', async () => { + var receivedEvents = []; + window.Rokt.__event_stream__ = function (event) { + receivedEvents.push(event); + }; + + window.mParticle.forwarder.process({ + EventName: 'Queued Event', + EventCategory: EventType.Other, + EventDataType: MessageType.PageEvent, + }); + + receivedEvents.length.should.equal(0); + window.mParticle.forwarder.eventQueue.length.should.equal(1); + + await window.mParticle.forwarder.init( + { accountId: '123456' }, + reportService.cb, + true, + null, + {} + ); + + await waitForCondition( + () => window.mParticle.Rokt.attachKitCalled + ); + + receivedEvents.length.should.equal(1); + receivedEvents[0].EventName.should.equal('Queued Event'); + }); + + it('should still process placement event mapping alongside event stream', async () => { + var receivedEvents = []; + window.Rokt.__event_stream__ = function (event) { + receivedEvents.push(event); + }; + + var placementEventMapping = JSON.stringify([ + { + jsmap: 'hashed-<48Video Watched>-value', + map: '123466', + maptype: 'EventClass.Id', + value: 'foo-mapped-flag', + }, + ]); + + await window.mParticle.forwarder.init( + { + accountId: '123456', + placementEventMapping: placementEventMapping, + }, + reportService.cb, + true, + null, + {} + ); + + await waitForCondition( + () => window.mParticle.Rokt.attachKitCalled + ); + + window.mParticle.forwarder.process({ + EventName: 'Video Watched', + EventCategory: EventType.Other, + EventDataType: MessageType.PageEvent, + }); + + receivedEvents.length.should.equal(1); + receivedEvents[0].EventName.should.equal('Video Watched'); + + window.mParticle._Store.localSessionAttributes.should.deepEqual({ + 'foo-mapped-flag': true, + }); + }); + }); + describe('#parseSettingsString', () => { it('should parse null values in a settings string appropriately', () => { const settingsString = From e1fbb9145a51297ff5dae40968d2febc9c8c99a3 Mon Sep 17 00:00:00 2001 From: Alexander Sapountzis Date: Thu, 12 Mar 2026 12:34:03 -0400 Subject: [PATCH 3/3] style: Fix prettier formatting in tests --- test/src/tests.js | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/test/src/tests.js b/test/src/tests.js index 8d3c554..2d05873 100644 --- a/test/src/tests.js +++ b/test/src/tests.js @@ -4382,9 +4382,7 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition( - () => window.mParticle.Rokt.attachKitCalled - ); + await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); var testEvent = { EventName: 'Test Event', @@ -4407,9 +4405,7 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition( - () => window.mParticle.Rokt.attachKitCalled - ); + await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); (function () { window.mParticle.forwarder.process({ @@ -4417,7 +4413,7 @@ describe('Rokt Forwarder', () => { EventCategory: EventType.Other, EventDataType: MessageType.PageEvent, }); - }.should.not.throw()); + }).should.not.throw(); }); it('should not throw when window.Rokt is undefined', async () => { @@ -4429,9 +4425,7 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition( - () => window.mParticle.Rokt.attachKitCalled - ); + await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); var savedRokt = window.Rokt; window.Rokt = undefined; @@ -4442,7 +4436,7 @@ describe('Rokt Forwarder', () => { EventCategory: EventType.Other, EventDataType: MessageType.PageEvent, }); - }.should.not.throw()); + }).should.not.throw(); window.Rokt = savedRokt; }); @@ -4461,9 +4455,7 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition( - () => window.mParticle.Rokt.attachKitCalled - ); + await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); var testEvent = { EventName: 'Purchase', @@ -4498,9 +4490,7 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition( - () => window.mParticle.Rokt.attachKitCalled - ); + await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); window.mParticle.forwarder.process({ EventName: 'Event A', @@ -4542,9 +4532,7 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition( - () => window.mParticle.Rokt.attachKitCalled - ); + await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); receivedEvents.length.should.equal(1); receivedEvents[0].EventName.should.equal('Queued Event'); @@ -4576,9 +4564,7 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition( - () => window.mParticle.Rokt.attachKitCalled - ); + await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); window.mParticle.forwarder.process({ EventName: 'Video Watched',