Skip to content

Commit fd50e3d

Browse files
committed
feat: enrich commerce event action from Rokt.CommerceEventType custom flag
1 parent 63267e1 commit fd50e3d

2 files changed

Lines changed: 215 additions & 1 deletion

File tree

src/Rokt-Kit.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -921,10 +921,29 @@ class RoktKit implements KitInterface {
921921
this.batchQueue.push(batch);
922922
return 'Batch queued for forwarder: ' + name;
923923
}
924-
this.sendBatchStream(this.mergePendingIdentityEvents(batch));
924+
const enrichedBatch = this.enrichCommerceEventTypes(this.mergePendingIdentityEvents(batch));
925+
this.sendBatchStream(enrichedBatch);
925926
return 'Successfully sent batch to forwarder: ' + name;
926927
}
927928

929+
private enrichCommerceEventTypes(batch: Batch): Batch {
930+
if (!batch.events) {
931+
return batch;
932+
}
933+
for (const event of batch.events) {
934+
if (event.event_type !== 'commerce_event') continue;
935+
936+
const data = event.data as Record<string, unknown> | undefined;
937+
if (!data) continue;
938+
939+
const commerceType = (data.custom_flags as Record<string, string> | undefined)?.['Rokt.CommerceEventType'];
940+
if (commerceType) {
941+
(data.product_action as Record<string, unknown>).action = commerceType;
942+
}
943+
}
944+
return batch;
945+
}
946+
928947
private sendBatchStream(batch: Batch): void {
929948
if (window.Rokt && typeof window.Rokt.__batch_stream__ === 'function') {
930949
if (this.batchStreamQueue.length) {

test/src/tests.spec.ts

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5758,6 +5758,201 @@ describe('Rokt Forwarder', () => {
57585758
});
57595759
});
57605760

5761+
describe('#enrichCommerceEventTypes', () => {
5762+
let mockCommerceBatch: Batch;
5763+
5764+
beforeEach(() => {
5765+
(window as any).mParticle.forwarder.batchQueue = [];
5766+
(window as any).mParticle.forwarder.batchStreamQueue = [];
5767+
(window as any).mParticle.forwarder.pendingIdentityEvents = [];
5768+
(window as any).Rokt = new (MockRoktForwarder as any)();
5769+
(window as any).Rokt.createLauncher = async function () {
5770+
return Promise.resolve({
5771+
selectPlacements: function (options: any) {
5772+
(window as any).mParticle.Rokt.selectPlacementsOptions = options;
5773+
(window as any).mParticle.Rokt.selectPlacementsCalled = true;
5774+
},
5775+
});
5776+
};
5777+
(window as any).mParticle.Rokt = (window as any).Rokt;
5778+
(window as any).mParticle.Rokt.attachKitCalled = false;
5779+
(window as any).mParticle.Rokt.attachKit = async (kit: any) => {
5780+
(window as any).mParticle.Rokt.attachKitCalled = true;
5781+
(window as any).mParticle.Rokt.kit = kit;
5782+
Promise.resolve();
5783+
};
5784+
(window as any).mParticle.Rokt.setLocalSessionAttribute = function (key: any, value: any) {
5785+
(window as any).mParticle._Store.localSessionAttributes[key] = value;
5786+
};
5787+
(window as any).mParticle.Rokt.getLocalSessionAttributes = function () {
5788+
return (window as any).mParticle._Store.localSessionAttributes;
5789+
};
5790+
(window as any).mParticle.forwarder.launcher = {
5791+
selectPlacements: function (options: any) {
5792+
(window as any).mParticle.Rokt.selectPlacementsOptions = options;
5793+
(window as any).mParticle.Rokt.selectPlacementsCalled = true;
5794+
},
5795+
};
5796+
(window as any).mParticle.Rokt.filters = {
5797+
userAttributesFilters: [],
5798+
filterUserAttributes: function (attributes: any) {
5799+
return attributes;
5800+
},
5801+
filteredUser: {
5802+
getMPID: function () {
5803+
return '123';
5804+
},
5805+
},
5806+
};
5807+
5808+
mockCommerceBatch = {
5809+
mpid: 'test-mpid-123',
5810+
events: [
5811+
{
5812+
event_type: 'commerce_event',
5813+
data: {
5814+
custom_flags: { 'Rokt.CommerceEventType': 'payment_succeeded' },
5815+
product_action: {
5816+
action: 'unknown',
5817+
products: [{ id: 'SKU-1', name: 'Test Product', price: 50, quantity: 1 }],
5818+
},
5819+
},
5820+
},
5821+
],
5822+
};
5823+
});
5824+
5825+
afterEach(() => {
5826+
delete (window as any).Rokt.__batch_stream__;
5827+
(window as any).mParticle.forwarder.batchQueue = [];
5828+
(window as any).mParticle.forwarder.batchStreamQueue = [];
5829+
(window as any).mParticle.forwarder.pendingIdentityEvents = [];
5830+
(window as any).mParticle.forwarder.isInitialized = false;
5831+
(window as any).mParticle.Rokt.attachKitCalled = false;
5832+
});
5833+
5834+
it('should replace action with Rokt.CommerceEventType custom flag for commerce events', async () => {
5835+
const receivedBatches: any[] = [];
5836+
(window as any).Rokt.__batch_stream__ = function (payload: any) {
5837+
receivedBatches.push(payload);
5838+
};
5839+
5840+
await (window as any).mParticle.forwarder.init({ accountId: '123456' }, reportService.cb, true, null, {});
5841+
await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);
5842+
5843+
(window as any).mParticle.forwarder.processBatch(mockCommerceBatch);
5844+
5845+
expect(receivedBatches.length).toBe(1);
5846+
expect(receivedBatches[0].events[0].data.product_action.action).toBe('payment_succeeded');
5847+
});
5848+
5849+
it('should not modify action when Rokt.CommerceEventType custom flag is absent', async () => {
5850+
const receivedBatches: any[] = [];
5851+
(window as any).Rokt.__batch_stream__ = function (payload: any) {
5852+
receivedBatches.push(payload);
5853+
};
5854+
5855+
mockCommerceBatch.events[0].data.custom_flags = {};
5856+
5857+
await (window as any).mParticle.forwarder.init({ accountId: '123456' }, reportService.cb, true, null, {});
5858+
await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);
5859+
5860+
(window as any).mParticle.forwarder.processBatch(mockCommerceBatch);
5861+
5862+
expect(receivedBatches.length).toBe(1);
5863+
expect(receivedBatches[0].events[0].data.product_action.action).toBe('unknown');
5864+
});
5865+
5866+
it('should not modify non-commerce events', async () => {
5867+
const receivedBatches: any[] = [];
5868+
(window as any).Rokt.__batch_stream__ = function (payload: any) {
5869+
receivedBatches.push(payload);
5870+
};
5871+
5872+
const nonCommerceBatch: Batch = {
5873+
mpid: 'test-mpid-123',
5874+
events: [
5875+
{
5876+
event_type: 'custom_event',
5877+
data: {
5878+
event_name: 'Test Event',
5879+
custom_event_type: 'other',
5880+
custom_flags: { 'Rokt.CommerceEventType': 'payment_succeeded' },
5881+
},
5882+
},
5883+
],
5884+
};
5885+
5886+
await (window as any).mParticle.forwarder.init({ accountId: '123456' }, reportService.cb, true, null, {});
5887+
await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);
5888+
5889+
(window as any).mParticle.forwarder.processBatch(nonCommerceBatch);
5890+
5891+
expect(receivedBatches.length).toBe(1);
5892+
expect(receivedBatches[0].events[0].event_type).toBe('custom_event');
5893+
expect(receivedBatches[0].events[0].data.product_action).toBeUndefined();
5894+
});
5895+
5896+
it('should enrich only commerce events in a mixed batch', async () => {
5897+
const receivedBatches: any[] = [];
5898+
(window as any).Rokt.__batch_stream__ = function (payload: any) {
5899+
receivedBatches.push(payload);
5900+
};
5901+
5902+
const mixedBatch: Batch = {
5903+
mpid: 'test-mpid-123',
5904+
events: [
5905+
{
5906+
event_type: 'custom_event',
5907+
data: { event_name: 'Page View', custom_event_type: 'other' },
5908+
},
5909+
{
5910+
event_type: 'commerce_event',
5911+
data: {
5912+
custom_flags: { 'Rokt.CommerceEventType': 'refund_initiated' },
5913+
product_action: { action: 'unknown', products: [] },
5914+
},
5915+
},
5916+
{
5917+
event_type: 'commerce_event',
5918+
data: {
5919+
custom_flags: {},
5920+
product_action: { action: 'purchase', products: [] },
5921+
},
5922+
},
5923+
],
5924+
};
5925+
5926+
await (window as any).mParticle.forwarder.init({ accountId: '123456' }, reportService.cb, true, null, {});
5927+
await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);
5928+
5929+
(window as any).mParticle.forwarder.processBatch(mixedBatch);
5930+
5931+
expect(receivedBatches.length).toBe(1);
5932+
const events = receivedBatches[0].events;
5933+
expect(events[0].event_type).toBe('custom_event');
5934+
expect(events[1].data.product_action.action).toBe('refund_initiated');
5935+
expect(events[2].data.product_action.action).toBe('purchase');
5936+
});
5937+
5938+
it('should handle batch with no events', async () => {
5939+
const receivedBatches: any[] = [];
5940+
(window as any).Rokt.__batch_stream__ = function (payload: any) {
5941+
receivedBatches.push(payload);
5942+
};
5943+
5944+
const emptyBatch: Batch = { mpid: 'test-mpid-123', events: [] };
5945+
5946+
await (window as any).mParticle.forwarder.init({ accountId: '123456' }, reportService.cb, true, null, {});
5947+
await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);
5948+
5949+
(window as any).mParticle.forwarder.processBatch(emptyBatch);
5950+
5951+
expect(receivedBatches.length).toBe(1);
5952+
expect(receivedBatches[0].events.length).toBe(0);
5953+
});
5954+
});
5955+
57615956
describe('#_setRoktSessionId', () => {
57625957
let setIntegrationAttributeCalls: any[];
57635958

0 commit comments

Comments
 (0)