From 5527ffd550b09a3d0475d4313465e060be1ad569 Mon Sep 17 00:00:00 2001 From: jkaho Date: Thu, 24 Jul 2025 08:14:46 +1000 Subject: [PATCH 1/8] fix product viewed typos --- .../generated-types.ts | 38 +++++++++++++++++++ .../productViewedEvents/generated-types.ts | 2 +- .../productViewedEvents/index.ts | 4 +- 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts new file mode 100644 index 00000000000..4d0f9b3d34b --- /dev/null +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts @@ -0,0 +1,38 @@ +// Generated file. DO NOT MODIFY IT BY HAND. + +export interface Payload { + /** + * Product IDs of the viewed items. + */ + objectIDs: string[] + /** + * Name of the targeted search index. + */ + index: string + /** + * Query ID of the list on which the items were viewed. + */ + queryID?: string + /** + * The ID associated with the user. + */ + userToken: string + /** + * The timestamp of the event. + */ + timestamp?: string + /** + * Additional fields for this event. This field may be useful for Algolia Insights fields which are not mapped in Segment. + */ + extraProperties?: { + [k: string]: unknown + } + /** + * The name of the event to be send to Algolia. Defaults to 'Product List Viewed' + */ + eventName?: string + /** + * The type of event to send to Algolia. Defaults to 'view' + */ + eventType?: string +} diff --git a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts index f9dae0471f0..a826cd57fab 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts @@ -2,7 +2,7 @@ export interface Payload { /** - * Product ID of the clicked item. + * Product ID of the viewed item. */ objectID: string /** diff --git a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts index 8b6e3bafd05..3e5b5db41bc 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts @@ -7,11 +7,11 @@ import type { Payload } from './generated-types' export const productViewedEvents: ActionDefinition = { title: 'Product Viewed Events', description: - 'Product view events act as a positive signal for associated record objects — the associated Product ID. Query ID is optional and indicates that the view events is the result of a search query.', + 'Product view events act as a positive signal for associated record objects — the associated Product ID. Query ID is optional and indicates that the view event is the result of a search query.', fields: { objectID: { label: 'Product ID', - description: 'Product ID of the clicked item.', + description: 'Product ID of the viewed item.', type: 'string', required: true, default: { From eff5ddd646ee5d49973120ad5611689e67d1e1f4 Mon Sep 17 00:00:00 2001 From: jkaho Date: Thu, 24 Jul 2025 08:48:55 +1000 Subject: [PATCH 2/8] add support for Product List Viewed events --- .../src/algoliaInsights/generated-types.ts | 3 + .../__snapshots__/snapshot.test.ts.snap | 35 +++++ .../destinations/algolia-insights/index.ts | 7 +- .../__snapshots__/snapshot.test.ts.snap | 37 ++++++ .../__tests__/index.test.ts | 88 +++++++++++++ .../__tests__/snapshot.test.ts | 79 +++++++++++ .../productListViewedEvents/index.ts | 124 ++++++++++++++++++ 7 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts create mode 100644 packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap create mode 100644 packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts create mode 100644 packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/snapshot.test.ts create mode 100644 packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts b/packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts new file mode 100644 index 00000000000..944d22b0857 --- /dev/null +++ b/packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts @@ -0,0 +1,3 @@ +// Generated file. DO NOT MODIFY IT BY HAND. + +export interface Payload {} diff --git a/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap index ca624207d3b..789a13eaac7 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap @@ -155,6 +155,41 @@ Object { } `; +exports[`Testing snapshot for actions-algolia-insights destination: productListViewedEvents action - all fields 1`] = ` +Object { + "events": Array [ + Object { + "eventName": "rV6HQ[S7QuqZWEj%HvC", + "eventType": "click", + "index": "rV6HQ[S7QuqZWEj%HvC", + "objectIDs": Array [ + "rV6HQ[S7QuqZWEj%HvC", + ], + "queryID": "rV6HQ[S7QuqZWEj%HvC", + "testType": "rV6HQ[S7QuqZWEj%HvC", + "timestamp": null, + "userToken": "rV6HQ[S7QuqZWEj%HvC", + }, + ], +} +`; + +exports[`Testing snapshot for actions-algolia-insights destination: productListViewedEvents action - required fields 1`] = ` +Object { + "events": Array [ + Object { + "eventName": "Product List Viewed", + "eventType": "view", + "index": "rV6HQ[S7QuqZWEj%HvC", + "objectIDs": Array [ + "rV6HQ[S7QuqZWEj%HvC", + ], + "userToken": "rV6HQ[S7QuqZWEj%HvC", + }, + ], +} +`; + exports[`Testing snapshot for actions-algolia-insights destination: productViewedEvents action - all fields 1`] = ` Object { "events": Array [ diff --git a/packages/destination-actions/src/destinations/algolia-insights/index.ts b/packages/destination-actions/src/destinations/algolia-insights/index.ts index 0cf6afc2228..286c01f6393 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/index.ts @@ -11,6 +11,7 @@ import { AlgoliaApiPermissions, algoliaApiPermissionsUrl } from './algolia-insig import { productAddedEvents } from './productAddedEvents' import { productListFilteredEvents, productListFilteredPresets } from './productListFilteredEvents' +import { productListViewedEvents, productListViewedPresets } from './productListViewedEvents' export const ALGOLIA_INSIGHTS_USER_AGENT = 'algolia-segment-action-destination: 0.1' @@ -67,14 +68,16 @@ const destination: DestinationDefinition = { purchasePreset, addToCartPreset, productViewedPresets, - productListFilteredPresets + productListFilteredPresets, + productListViewedPresets ], actions: { productClickedEvents, conversionEvents, productViewedEvents, productAddedEvents, - productListFilteredEvents + productListFilteredEvents, + productListViewedEvents } } diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap new file mode 100644 index 00000000000..529e1a83913 --- /dev/null +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing snapshot for AlgoliaInsights's productListViewedEvents destination action: all fields 1`] = ` +Object { + "events": Array [ + Object { + "eventName": "lx7Lx", + "eventType": "view", + "index": "lx7Lx", + "objectIDs": Array [ + "lx7Lx", + ], + "queryID": "lx7Lx", + "testType": "lx7Lx", + "timestamp": null, + "userToken": "lx7Lx", + }, + ], +} +`; + +exports[`Testing snapshot for AlgoliaInsights's productListViewedEvents destination action: required fields 1`] = ` +Object { + "events": Array [ + Object { + "eventName": "Product List Viewed", + "eventType": "view", + "index": "lx7Lx", + "objectIDs": Array [ + "lx7Lx", + ], + "timestamp": 1674843786677, + "userToken": "lx7Lx", + }, + ], +} +`; diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts new file mode 100644 index 00000000000..51f012c14f8 --- /dev/null +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts @@ -0,0 +1,88 @@ +import nock from 'nock' +import { createTestEvent, createTestIntegration, SegmentEvent } from '@segment/actions-core' +import Destination, { ALGOLIA_INSIGHTS_USER_AGENT } from '../../index' +import { AlgoliaProductViewedEvent, BaseAlgoliaInsightsURL } from '../../algolia-insight-api' + +const testDestination = createTestIntegration(Destination) + +const algoliaDestinationActionSettings = { + appId: 'algolia-application-id', + apiKey: 'algolia-api-key' +} +const testAlgoliaDestination = async (event: SegmentEvent): Promise => { + nock(BaseAlgoliaInsightsURL).post('/1/events').reply(200, {}) + const segmentEvent = { + event: { ...event }, + settings: algoliaDestinationActionSettings, + useDefaultMappings: true + } + const actionResponse = await testDestination.testAction('productListViewedEvents', segmentEvent) + const actionRequest = actionResponse[0].request + + expect(actionResponse.length).toBe(1) + expect(actionRequest.headers.get('X-Algolia-Application-Id')).toBe(algoliaDestinationActionSettings.appId) + expect(actionRequest.headers.get('X-Algolia-API-Key')).toBe(algoliaDestinationActionSettings.apiKey) + expect(actionRequest.headers.get('X-Algolia-Agent')).toBe(ALGOLIA_INSIGHTS_USER_AGENT) + + const rawBody = await actionRequest.text() + return JSON.parse(rawBody)['events'][0] +} + +describe('AlgoliaInsights.productListViewedEvents', () => { + it('should submit click on track "Product List Viewed" event', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [ + { product_id: '9876', name: 'foo', price: 10 }, + { product_id: '5432', category: 'bar' } + ] + } + }) + const algoliaEvent = await testAlgoliaDestination(event) + + expect(algoliaEvent.eventName).toBe('Product List Viewed') + expect(algoliaEvent.eventType).toBe('view') + expect(algoliaEvent.index).toBe(event.properties?.search_index) + expect(algoliaEvent.userToken).toBe(event.userId) + expect(algoliaEvent.objectIDs).toEqual(['9876', '5432']) + }) + + it('should pass timestamp if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Viewed', + properties: { + search_index: 'fashion_1', + products: [ + { product_id: '9876', name: 'foo', price: 10 }, + { product_id: '5432', category: 'bar' } + ] + }, + userId: undefined + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.timestamp).toBe(new Date(event.timestamp as string).valueOf()) + }) + + it('should pass queryId if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [ + { product_id: '9876', name: 'foo', price: 10 }, + { product_id: '5432', category: 'bar' } + ] + }, + userId: undefined + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.queryID).toBe(event.properties?.query_id) + }) +}) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/snapshot.test.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/snapshot.test.ts new file mode 100644 index 00000000000..2cc9a7a3389 --- /dev/null +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/snapshot.test.ts @@ -0,0 +1,79 @@ +import { createTestEvent, createTestIntegration } from '@segment/actions-core' +import { generateTestData } from '../../../../lib/test-data' +import destination from '../../index' +import nock from 'nock' + +const testDestination = createTestIntegration(destination) +const actionSlug = 'productListViewedEvents' +const destinationSlug = 'AlgoliaInsights' +const seedName = `${destinationSlug}#${actionSlug}` + +describe(`Testing snapshot for ${destinationSlug}'s ${actionSlug} destination action:`, () => { + it('required fields', async () => { + const action = destination.actions[actionSlug] + const [eventData, settingsData] = generateTestData(seedName, destination, action, true) + + nock(/.*/).persist().get(/.*/).reply(200) + nock(/.*/).persist().post(/.*/).reply(200) + nock(/.*/).persist().put(/.*/).reply(200) + + const event = createTestEvent({ + timestamp: new Date('2023-01-27T18:23:06.677Z').toISOString(), + properties: eventData + }) + + const responses = await testDestination.testAction(actionSlug, { + useDefaultMappings: true, + event: event, + mapping: event.properties, + settings: settingsData, + auth: undefined + }) + + const request = responses[0].request + const rawBody = await request.text() + + try { + const json = JSON.parse(rawBody) + expect(json).toMatchSnapshot() + return + } catch (err) { + expect(rawBody).toMatchSnapshot() + } + + expect(request.headers).toMatchSnapshot() + }) + + it('all fields', async () => { + const action = destination.actions[actionSlug] + const [eventData, settingsData] = generateTestData(seedName, destination, action, false) + + nock(/.*/).persist().get(/.*/).reply(200) + nock(/.*/).persist().post(/.*/).reply(200) + nock(/.*/).persist().put(/.*/).reply(200) + + const event = createTestEvent({ + timestamp: new Date('2023-01-27T18:23:06.677Z').toISOString(), + properties: eventData + }) + + const responses = await testDestination.testAction(actionSlug, { + useDefaultMappings: true, + event: event, + mapping: event.properties, + settings: settingsData, + auth: undefined + }) + + const request = responses[0].request + const rawBody = await request.text() + + try { + const json = JSON.parse(rawBody) + expect(json).toMatchSnapshot() + return + } catch (err) { + expect(rawBody).toMatchSnapshot() + } + }) +}) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts new file mode 100644 index 00000000000..5e132468983 --- /dev/null +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts @@ -0,0 +1,124 @@ +import type { ActionDefinition, Preset } from '@segment/actions-core' +import { defaultValues } from '@segment/actions-core' +import { AlgoliaBehaviourURL, AlgoliaProductViewedEvent, AlgoliaEventType } from '../algolia-insight-api' +import type { Settings } from '../generated-types' +import type { Payload } from './generated-types' + +const segmentEventName = 'Product List Viewed' + +export const productListViewedEvents: ActionDefinition = { + title: `${segmentEventName} Events`, + description: + 'Product list viewed events act as a positive signal for associated record objects — the associated Product IDs. Query ID is optional and indicates that the view events are the result of a search query.', + fields: { + objectIDs: { + label: 'Product IDs', + description: 'Product IDs of the viewed items.', + type: 'string', + multiple: true, + required: true, + default: { + '@arrayPath': ['$.properties.products', { '@path': '$.product_id' }] + } + }, + index: { + label: 'Index', + description: 'Name of the targeted search index.', + type: 'string', + required: true, + default: { + '@path': '$.properties.search_index' + } + }, + queryID: { + label: 'Query ID', + description: 'Query ID of the list on which the items were viewed.', + type: 'string', + required: false, + default: { + '@if': { + exists: { '@path': '$.properties.query_id' }, + then: { '@path': '$.properties.query_id' }, + else: { '@path': '$.integrations.Algolia Insights (Actions).query_id' } + } + } + }, + userToken: { + type: 'string', + required: true, + description: 'The ID associated with the user.', + label: 'User Token', + default: { + '@if': { + exists: { '@path': '$.userId' }, + then: { '@path': '$.userId' }, + else: { '@path': '$.anonymousId' } + } + } + }, + timestamp: { + type: 'string', + required: false, + description: 'The timestamp of the event.', + label: 'Timestamp', + default: { '@path': '$.timestamp' } + }, + extraProperties: { + label: 'Extra Properties', + required: false, + description: + 'Additional fields for this event. This field may be useful for Algolia Insights fields which are not mapped in Segment.', + type: 'object', + default: { + '@path': '$.properties' + } + }, + eventName: { + label: 'Event Name', + description: `The name of the event to be send to Algolia. Defaults to '${segmentEventName}'`, + type: 'string', + required: false, + default: segmentEventName + }, + eventType: { + label: 'Event Type', + description: "The type of event to send to Algolia. Defaults to 'view'", + type: 'string', + required: false, + default: 'view', + choices: [ + { label: 'view', value: 'view' }, + { label: 'conversion', value: 'conversion' }, + { label: 'click', value: 'click' } + ] + } + }, + defaultSubscription: `type = "track" and event = "${segmentEventName}"`, + perform: (request, data) => { + const insightEvent: AlgoliaProductViewedEvent = { + ...data.payload.extraProperties, + eventName: data.payload.eventName ?? segmentEventName, + eventType: (data.payload.eventType as AlgoliaEventType) ?? ('view' as AlgoliaEventType), + index: data.payload.index, + queryID: data.payload.queryID, + objectIDs: data.payload.objectIDs, + timestamp: data.payload.timestamp ? new Date(data.payload.timestamp).valueOf() : undefined, + userToken: data.payload.userToken + } + const insightPayload = { events: [insightEvent] } + + return request(AlgoliaBehaviourURL, { + method: 'post', + json: insightPayload + }) + } +} + +/** used in the quick setup */ +export const productListViewedPresets: Preset = { + name: 'Send product list viewed events to Algolia', + subscribe: productListViewedEvents.defaultSubscription as string, + partnerAction: 'productListViewedEvents', + mapping: defaultValues(productListViewedEvents.fields), + type: 'automatic' +} From 65e3d529bda981c76ccb88027ed7368fc49df950 Mon Sep 17 00:00:00 2001 From: jkaho Date: Thu, 24 Jul 2025 11:46:30 +1000 Subject: [PATCH 3/8] add support for authenticatedUsertoken --- .../__snapshots__/snapshot.test.ts.snap | 5 ++ .../algolia-insights/algolia-insight-api.ts | 1 + .../__snapshots__/snapshot.test.ts.snap | 2 + .../conversionEvents/__tests__/index.test.ts | 72 ++++++++++++++++++- .../conversionEvents/generated-types.ts | 6 +- .../conversionEvents/index.ts | 16 +++-- .../__snapshots__/snapshot.test.ts.snap | 2 + .../__tests__/index.test.ts | 54 +++++++++++++- .../productClickedEvents/generated-types.ts | 6 +- .../productClickedEvents/index.ts | 16 +++-- .../__snapshots__/snapshot.test.ts.snap | 1 + .../__tests__/index.test.ts | 51 ++++++++++++- .../generated-types.ts | 6 +- .../productListFilteredEvents/index.ts | 16 +++-- .../__snapshots__/snapshot.test.ts.snap | 2 + .../__tests__/index.test.ts | 51 ++++++++++++- .../generated-types.ts | 6 +- .../productListViewedEvents/index.ts | 18 +++-- .../__snapshots__/snapshot.test.ts.snap | 2 + .../__tests__/index.test.ts | 54 +++++++++++++- .../productViewedEvents/generated-types.ts | 6 +- .../productViewedEvents/index.ts | 18 +++-- 22 files changed, 378 insertions(+), 33 deletions(-) diff --git a/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap index 789a13eaac7..e2e8aef99d2 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/algolia-insights/__tests__/__snapshots__/snapshot.test.ts.snap @@ -4,6 +4,7 @@ exports[`Testing snapshot for actions-algolia-insights destination: conversionEv Object { "events": Array [ Object { + "authenticatedUserToken": "U[ABpE$k", "currency": "HTG", "eventName": "U[ABpE$k", "eventSubtype": "purchase", @@ -86,6 +87,7 @@ exports[`Testing snapshot for actions-algolia-insights destination: productClick Object { "events": Array [ Object { + "authenticatedUserToken": "LLjxSD^^GnH", "eventName": "LLjxSD^^GnH", "eventType": "conversion", "index": "LLjxSD^^GnH", @@ -124,6 +126,7 @@ exports[`Testing snapshot for actions-algolia-insights destination: productListF Object { "events": Array [ Object { + "authenticatedUserToken": "6O0djra", "eventName": "6O0djra", "eventType": "view", "filters": Array [ @@ -159,6 +162,7 @@ exports[`Testing snapshot for actions-algolia-insights destination: productListV Object { "events": Array [ Object { + "authenticatedUserToken": "rV6HQ[S7QuqZWEj%HvC", "eventName": "rV6HQ[S7QuqZWEj%HvC", "eventType": "click", "index": "rV6HQ[S7QuqZWEj%HvC", @@ -194,6 +198,7 @@ exports[`Testing snapshot for actions-algolia-insights destination: productViewe Object { "events": Array [ Object { + "authenticatedUserToken": "BLFCPcmz", "eventName": "BLFCPcmz", "eventType": "view", "index": "BLFCPcmz", diff --git a/packages/destination-actions/src/destinations/algolia-insights/algolia-insight-api.ts b/packages/destination-actions/src/destinations/algolia-insights/algolia-insight-api.ts index b910f83a49f..792ae8e1c8a 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/algolia-insight-api.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/algolia-insight-api.ts @@ -12,6 +12,7 @@ type EventCommon = { eventName: string index: string userToken: string + authenticatedUserToken?: string timestamp?: number queryID?: string eventType: AlgoliaEventType diff --git a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/__snapshots__/snapshot.test.ts.snap index 4107c80fc1e..982b099b583 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/__snapshots__/snapshot.test.ts.snap @@ -4,6 +4,7 @@ exports[`Testing snapshot for AlgoliaInsights's conversionEvents destination act Object { "events": Array [ Object { + "authenticatedUserToken": ")j)vR5%1AP*epuo8A%R", "currency": "CUC", "eventName": ")j)vR5%1AP*epuo8A%R", "eventSubtype": "addToCart", @@ -34,6 +35,7 @@ exports[`Testing snapshot for AlgoliaInsights's conversionEvents destination act Object { "events": Array [ Object { + "authenticatedUserToken": "user1234", "eventName": "Conversion Event", "eventSubtype": "purchase", "eventType": "conversion", diff --git a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/index.test.ts b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/index.test.ts index a8727e353db..14e9527131d 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/index.test.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/__tests__/index.test.ts @@ -55,7 +55,8 @@ describe('AlgoliaInsights.conversionEvents', () => { expect(algoliaEvent.eventType).toBe('conversion') expect(algoliaEvent.eventSubtype).toBe('purchase') expect(algoliaEvent.index).toBe(event.properties?.search_index) - expect(algoliaEvent.userToken).toBe(event.userId) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) expect(algoliaEvent.objectIDs).toContain('9876') expect(algoliaEvent.objectIDs).toContain('5432') }) @@ -277,4 +278,73 @@ describe('AlgoliaInsights.conversionEvents', () => { expect(algoliaEvent.objectData).toBeUndefined() }) }) + + it('should pass anonymousId as user token if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Order Completed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [ + { + product_id: '9876' + }, + { + product_id: '5432' + } + ] + }, + anonymousId: 'anon-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + }) + + it('should pass userId as user token if anonymousId not present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Order Completed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [ + { + product_id: '9876' + }, + { + product_id: '5432' + } + ] + }, + anonymousId: undefined, + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.userId) + }) + + it('should pass userId and anonymousId if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Order Completed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [ + { + product_id: '9876' + }, + { + product_id: '5432' + } + ] + }, + anonymousId: 'anon-user-1234', + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) + }) }) diff --git a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/generated-types.ts index 3bc33277a37..d3fd29d0861 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/generated-types.ts @@ -24,9 +24,13 @@ export interface Payload { */ queryID?: string /** - * The ID associated with the user. + * The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token */ userToken: string + /** + * The authenticated ID associated with the user. + */ + authenticatedUserToken?: string /** * The timestamp of the event. */ diff --git a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/index.ts index fe11e449d6e..2bda291aa61 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/conversionEvents/index.ts @@ -86,16 +86,23 @@ const getEventFields = (subtype: AlgoliaEventSubtype = 'purchase'): BaseActionDe userToken: { type: 'string', required: true, - description: 'The ID associated with the user.', + description: + 'The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token', label: 'User Token', default: { '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } + exists: { '@path': '$.anonymousId' }, + then: { '@path': '$.anonymousId' }, + else: { '@path': '$.userId' } } } }, + authenticatedUserToken: { + type: 'string', + description: 'The authenticated ID associated with the user.', + label: 'Authenticated User Token', + default: { '@path': '$.userId' } + }, timestamp: { type: 'string', required: false, @@ -178,6 +185,7 @@ export const conversionEvents: ActionDefinition = { value: data.payload.value, currency: data.payload.currency, userToken: data.payload.userToken, + authenticatedUserToken: data.payload.authenticatedUserToken, timestamp: data.payload.timestamp ? new Date(data.payload.timestamp).valueOf() : undefined } const insightPayload = { events: [insightEvent] } diff --git a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/__snapshots__/snapshot.test.ts.snap index 171113b996d..ff173936fac 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/__snapshots__/snapshot.test.ts.snap @@ -4,6 +4,7 @@ exports[`Testing snapshot for AlgoliaInsights's productClickedEvents destination Object { "events": Array [ Object { + "authenticatedUserToken": "tTO6#", "eventName": "tTO6#", "eventType": "view", "index": "tTO6#", @@ -26,6 +27,7 @@ exports[`Testing snapshot for AlgoliaInsights's productClickedEvents destination Object { "events": Array [ Object { + "authenticatedUserToken": "user1234", "eventName": "Product Clicked", "eventType": "click", "index": "tTO6#", diff --git a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/index.test.ts b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/index.test.ts index f51f18e5d3e..81918ad22bc 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/index.test.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/__tests__/index.test.ts @@ -45,7 +45,8 @@ describe('AlgoliaInsights.productClickedEvents', () => { expect(algoliaEvent.eventName).toBe('Product Clicked') expect(algoliaEvent.eventType).toBe('click') expect(algoliaEvent.index).toBe(event.properties?.search_index) - expect(algoliaEvent.userToken).toBe(event.userId) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) expect(algoliaEvent.queryID).toBe(event.properties?.query_id) expect(algoliaEvent.objectIDs).toContain('9876') expect(algoliaEvent.positions).toContain(5) @@ -92,4 +93,55 @@ describe('AlgoliaInsights.productClickedEvents', () => { const algoliaEvent = await testAlgoliaDestination(event) expect(algoliaEvent.positions?.[0]).toBe(event.properties?.position) }) + + it('should pass anonymousId as user token if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product Clicked', + properties: { + query_id: '1234', + search_index: 'fashion_1', + product_id: '9876', + position: 5 + }, + anonymousId: 'anon-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + }) + + it('should pass userId as user token if anonymousId not present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product Clicked', + properties: { + query_id: '1234', + search_index: 'fashion_1', + product_id: '9876', + position: 5 + }, + anonymousId: undefined, + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.userId) + }) + + it('should pass userId and anonymousId if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product Clicked', + properties: { + query_id: '1234', + search_index: 'fashion_1', + product_id: '9876', + position: 5 + }, + anonymousId: 'anon-user-1234', + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) + }) }) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/generated-types.ts index d932d1edde4..7e545089b36 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/generated-types.ts @@ -18,9 +18,13 @@ export interface Payload { */ position?: number /** - * The ID associated with the user. + * The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token */ userToken: string + /** + * The authenticated ID associated with the user. + */ + authenticatedUserToken?: string /** * The timestamp of the event. */ diff --git a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/index.ts index 13229ba8b46..d8286fe97c6 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productClickedEvents/index.ts @@ -51,16 +51,23 @@ export const productClickedEvents: ActionDefinition = { userToken: { type: 'string', required: true, - description: 'The ID associated with the user.', + description: + 'The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token', label: 'User Token', default: { '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } + exists: { '@path': '$.anonymousId' }, + then: { '@path': '$.anonymousId' }, + else: { '@path': '$.userId' } } } }, + authenticatedUserToken: { + type: 'string', + description: 'The authenticated ID associated with the user.', + label: 'Authenticated User Token', + default: { '@path': '$.userId' } + }, timestamp: { type: 'string', required: false, @@ -108,6 +115,7 @@ export const productClickedEvents: ActionDefinition = { queryID: data.payload.queryID, objectIDs: [data.payload.objectID], userToken: data.payload.userToken, + authenticatedUserToken: data.payload.authenticatedUserToken, positions: data.payload.position ? [data.payload.position] : undefined, timestamp: data.payload.timestamp ? new Date(data.payload.timestamp).valueOf() : undefined } diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/__snapshots__/snapshot.test.ts.snap index 7297765501f..35c082b7eaa 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/__snapshots__/snapshot.test.ts.snap @@ -4,6 +4,7 @@ exports[`Testing snapshot for AlgoliaInsights's productListFilteredEvents destin Object { "events": Array [ Object { + "authenticatedUserToken": "E625IsTOULbrg8", "eventName": "E625IsTOULbrg8", "eventType": "conversion", "filters": Array [ diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/index.test.ts b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/index.test.ts index b4745446551..c9815af9065 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/index.test.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/__tests__/index.test.ts @@ -45,7 +45,8 @@ describe('AlgoliaInsights.productListFilteredEvents', () => { expect(algoliaEvent.eventName).toBe('Product List Filtered') expect(algoliaEvent.eventType).toBe('click') expect(algoliaEvent.index).toBe(event.properties?.search_index) - expect(algoliaEvent.userToken).toBe(event.userId) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) expect(algoliaEvent.queryID).toBe(event.properties?.query_id) expect(algoliaEvent.filters).toContain('discount:10%25') }) @@ -76,4 +77,52 @@ describe('AlgoliaInsights.productListFilteredEvents', () => { const algoliaEvent = await testAlgoliaDestination(event) expect(algoliaEvent.queryID).toBe(event.properties?.query_id) }) + + it('should pass anonymousId as user token if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Filtered', + properties: { + query_id: '1234', + search_index: 'fashion_1', + filters: [{ attribute: 'discount', value: '10%25' }] + }, + anonymousId: 'anon-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + }) + + it('should pass userId as user token if anonymousId not present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Filtered', + properties: { + query_id: '1234', + search_index: 'fashion_1', + filters: [{ attribute: 'discount', value: '10%25' }] + }, + anonymousId: undefined, + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.userId) + }) + + it('should pass userId and anonymousId if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Filtered', + properties: { + query_id: '1234', + search_index: 'fashion_1', + filters: [{ attribute: 'discount', value: '10%25' }] + }, + anonymousId: 'anon-user-1234', + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) + }) }) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/generated-types.ts index 5cc63dbc347..05e617e23ee 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/generated-types.ts @@ -23,9 +23,13 @@ export interface Payload { */ queryID?: string /** - * The ID associated with the user. + * The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token */ userToken: string + /** + * The authenticated ID associated with the user. + */ + authenticatedUserToken?: string /** * The timestamp of the event. */ diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/index.ts index 79f9359c55f..b57d0231025 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListFilteredEvents/index.ts @@ -50,16 +50,23 @@ export const productListFilteredEvents: ActionDefinition = { userToken: { type: 'string', required: true, - description: 'The ID associated with the user.', + description: + 'The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token', label: 'User Token', default: { '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } + exists: { '@path': '$.anonymousId' }, + then: { '@path': '$.anonymousId' }, + else: { '@path': '$.userId' } } } }, + authenticatedUserToken: { + type: 'string', + description: 'The authenticated ID associated with the user.', + label: 'Authenticated User Token', + default: { '@path': '$.userId' } + }, timestamp: { type: 'string', required: false, @@ -108,6 +115,7 @@ export const productListFilteredEvents: ActionDefinition = { queryID: data.payload.queryID, filters, userToken: data.payload.userToken, + authenticatedUserToken: data.payload.authenticatedUserToken, timestamp: data.payload.timestamp ? new Date(data.payload.timestamp).valueOf() : undefined } const insightPayload = { events: [insightEvent] } diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap index 529e1a83913..43da696ca69 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap @@ -4,6 +4,7 @@ exports[`Testing snapshot for AlgoliaInsights's productListViewedEvents destinat Object { "events": Array [ Object { + "authenticatedUserToken": "lx7Lx", "eventName": "lx7Lx", "eventType": "view", "index": "lx7Lx", @@ -23,6 +24,7 @@ exports[`Testing snapshot for AlgoliaInsights's productListViewedEvents destinat Object { "events": Array [ Object { + "authenticatedUserToken": "user1234", "eventName": "Product List Viewed", "eventType": "view", "index": "lx7Lx", diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts index 51f012c14f8..aeeae32ae28 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/__tests__/index.test.ts @@ -47,7 +47,8 @@ describe('AlgoliaInsights.productListViewedEvents', () => { expect(algoliaEvent.eventName).toBe('Product List Viewed') expect(algoliaEvent.eventType).toBe('view') expect(algoliaEvent.index).toBe(event.properties?.search_index) - expect(algoliaEvent.userToken).toBe(event.userId) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) expect(algoliaEvent.objectIDs).toEqual(['9876', '5432']) }) @@ -85,4 +86,52 @@ describe('AlgoliaInsights.productListViewedEvents', () => { const algoliaEvent = await testAlgoliaDestination(event) expect(algoliaEvent.queryID).toBe(event.properties?.query_id) }) + + it('should pass anonymousId as user token if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [{ product_id: '9876' }] + }, + anonymousId: 'anon-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + }) + + it('should pass userId as user token if anonymousId not present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [{ product_id: '9876' }] + }, + anonymousId: undefined, + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.userId) + }) + + it('should pass userId and anonymousId if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product List Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + products: [{ product_id: '9876' }] + }, + anonymousId: 'anon-user-1234', + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) + }) }) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts index 4d0f9b3d34b..db8287a2d39 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts @@ -14,9 +14,13 @@ export interface Payload { */ queryID?: string /** - * The ID associated with the user. + * The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token */ userToken: string + /** + * The authenticated ID associated with the user. + */ + authenticatedUserToken?: string /** * The timestamp of the event. */ diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts index 5e132468983..397cc5852f0 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts @@ -46,16 +46,23 @@ export const productListViewedEvents: ActionDefinition = { userToken: { type: 'string', required: true, - description: 'The ID associated with the user.', + description: + 'The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token', label: 'User Token', default: { '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } + exists: { '@path': '$.anonymousId' }, + then: { '@path': '$.anonymousId' }, + else: { '@path': '$.userId' } } } }, + authenticatedUserToken: { + type: 'string', + description: 'The authenticated ID associated with the user.', + label: 'Authenticated User Token', + default: { '@path': '$.userId' } + }, timestamp: { type: 'string', required: false, @@ -103,7 +110,8 @@ export const productListViewedEvents: ActionDefinition = { queryID: data.payload.queryID, objectIDs: data.payload.objectIDs, timestamp: data.payload.timestamp ? new Date(data.payload.timestamp).valueOf() : undefined, - userToken: data.payload.userToken + userToken: data.payload.userToken, + authenticatedUserToken: data.payload.authenticatedUserToken } const insightPayload = { events: [insightEvent] } diff --git a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap index 499d433b8ec..ada091b9094 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/__snapshots__/snapshot.test.ts.snap @@ -4,6 +4,7 @@ exports[`Testing snapshot for AlgoliaInsights's productViewedEvents destination Object { "events": Array [ Object { + "authenticatedUserToken": "og&DCP)aINw@qxe)", "eventName": "og&DCP)aINw@qxe)", "eventType": "click", "index": "og&DCP)aINw@qxe)", @@ -23,6 +24,7 @@ exports[`Testing snapshot for AlgoliaInsights's productViewedEvents destination Object { "events": Array [ Object { + "authenticatedUserToken": "user1234", "eventName": "Product Viewed", "eventType": "view", "index": "og&DCP)aINw@qxe)", diff --git a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/index.test.ts b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/index.test.ts index fcd9dd5c6cb..f8c1182bdb7 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/index.test.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/__tests__/index.test.ts @@ -37,14 +37,16 @@ describe('AlgoliaInsights.productViewedEvents', () => { query_id: '1234', search_index: 'fashion_1', product_id: '9876' - } + }, + anonymousId: 'anon-user-1234' }) const algoliaEvent = await testAlgoliaDestination(event) expect(algoliaEvent.eventName).toBe('Product Viewed') expect(algoliaEvent.eventType).toBe('view') expect(algoliaEvent.index).toBe(event.properties?.search_index) - expect(algoliaEvent.userToken).toBe(event.userId) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) expect(algoliaEvent.objectIDs).toContain('9876') }) @@ -76,4 +78,52 @@ describe('AlgoliaInsights.productViewedEvents', () => { const algoliaEvent = await testAlgoliaDestination(event) expect(algoliaEvent.queryID).toBe(event.properties?.query_id) }) + + it('should pass anonymousId as user token if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + product_id: '9876' + }, + anonymousId: 'anon-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + }) + + it('should pass userId as user token if anonymousId not present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + product_id: '9876' + }, + anonymousId: undefined, + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.userId) + }) + + it('should pass userId and anonymousId if present', async () => { + const event = createTestEvent({ + type: 'track', + event: 'Product Viewed', + properties: { + query_id: '1234', + search_index: 'fashion_1', + product_id: '9876' + }, + anonymousId: 'anon-user-1234', + userId: 'authed-user-1234' + }) + const algoliaEvent = await testAlgoliaDestination(event) + expect(algoliaEvent.userToken).toBe(event.anonymousId) + expect(algoliaEvent.authenticatedUserToken).toBe(event.userId) + }) }) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts index a826cd57fab..a8a62b2601b 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/generated-types.ts @@ -14,9 +14,13 @@ export interface Payload { */ queryID?: string /** - * The ID associated with the user. + * The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token */ userToken: string + /** + * The authenticated ID associated with the user. + */ + authenticatedUserToken?: string /** * The timestamp of the event. */ diff --git a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts index 3e5b5db41bc..a14eac47309 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productViewedEvents/index.ts @@ -43,16 +43,23 @@ export const productViewedEvents: ActionDefinition = { userToken: { type: 'string', required: true, - description: 'The ID associated with the user.', + description: + 'The ID associated with the user. If a user is authenticated, this should be set to the same value as the Authenticated User Token', label: 'User Token', default: { '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } + exists: { '@path': '$.anonymousId' }, + then: { '@path': '$.anonymousId' }, + else: { '@path': '$.userId' } } } }, + authenticatedUserToken: { + type: 'string', + description: 'The authenticated ID associated with the user.', + label: 'Authenticated User Token', + default: { '@path': '$.userId' } + }, timestamp: { type: 'string', required: false, @@ -100,7 +107,8 @@ export const productViewedEvents: ActionDefinition = { queryID: data.payload.queryID, objectIDs: [data.payload.objectID], timestamp: data.payload.timestamp ? new Date(data.payload.timestamp).valueOf() : undefined, - userToken: data.payload.userToken + userToken: data.payload.userToken, + authenticatedUserToken: data.payload.authenticatedUserToken } const insightPayload = { events: [insightEvent] } From 090ae76278a357c3761f9044f495be76f66771f3 Mon Sep 17 00:00:00 2001 From: jkaho Date: Thu, 24 Jul 2025 12:06:03 +1000 Subject: [PATCH 4/8] update objectIDs description --- .../algolia-insights/productListViewedEvents/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts index 397cc5852f0..b78b8e0e580 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts @@ -13,7 +13,7 @@ export const productListViewedEvents: ActionDefinition = { fields: { objectIDs: { label: 'Product IDs', - description: 'Product IDs of the viewed items.', + description: 'Product IDs of the viewed items. Defaults to an array of `products.product_id`.', type: 'string', multiple: true, required: true, From 30ee990d4dbf3e42d45e724477c39579f2504c22 Mon Sep 17 00:00:00 2001 From: jkaho Date: Fri, 25 Jul 2025 08:35:20 +1000 Subject: [PATCH 5/8] remove gen types --- .../algolia-plugins/src/algoliaInsights/generated-types.ts | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts b/packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts deleted file mode 100644 index 944d22b0857..00000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/src/algoliaInsights/generated-types.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload {} From 1fd104f863b84f0cb348668d9074e8f3fdedcd10 Mon Sep 17 00:00:00 2001 From: jkaho Date: Tue, 12 Aug 2025 13:55:20 +1000 Subject: [PATCH 6/8] run yarn types --- .../algolia-insights/productListViewedEvents/generated-types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts index db8287a2d39..b6ae622ab50 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts @@ -2,7 +2,7 @@ export interface Payload { /** - * Product IDs of the viewed items. + * Product IDs of the viewed items. Defaults to an array of `products.product_id`. */ objectIDs: string[] /** From 199b5a12b6cbed5ddc8fce54d21629fd5a3b7d25 Mon Sep 17 00:00:00 2001 From: jkaho Date: Thu, 14 Aug 2025 18:08:04 +1000 Subject: [PATCH 7/8] update productIDs mapping --- .../generated-types.ts | 6 +++-- .../productListViewedEvents/index.ts | 24 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts index b6ae622ab50..ebe1a5196df 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts @@ -2,9 +2,11 @@ export interface Payload { /** - * Product IDs of the viewed items. Defaults to an array of `products.product_id`. + * The viewed products. Populates the ObjectIDs field in the Algolia Insights API. Each object must contain a product_id field. */ - objectIDs: string[] + products: { + product_id: string + }[] /** * Name of the targeted search index. */ diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts index b78b8e0e580..f9f5d1627dc 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts @@ -11,14 +11,26 @@ export const productListViewedEvents: ActionDefinition = { description: 'Product list viewed events act as a positive signal for associated record objects — the associated Product IDs. Query ID is optional and indicates that the view events are the result of a search query.', fields: { - objectIDs: { - label: 'Product IDs', - description: 'Product IDs of the viewed items. Defaults to an array of `products.product_id`.', - type: 'string', + products: { + label: 'Product Details', + description: + 'The viewed products. Populates the ObjectIDs field in the Algolia Insights API. Each object must contain a product_id field.', + type: 'object', + defaultObjectUI: 'keyvalue', multiple: true, required: true, + properties: { + product_id: { label: 'product_id', type: 'string', required: true } + }, default: { - '@arrayPath': ['$.properties.products', { '@path': '$.product_id' }] + '@arrayPath': [ + '$.properties.products', + { + product_id: { + '@path': '$.product_id' + } + } + ] } }, index: { @@ -108,7 +120,7 @@ export const productListViewedEvents: ActionDefinition = { eventType: (data.payload.eventType as AlgoliaEventType) ?? ('view' as AlgoliaEventType), index: data.payload.index, queryID: data.payload.queryID, - objectIDs: data.payload.objectIDs, + objectIDs: data.payload.products.map((obj) => obj.product_id), timestamp: data.payload.timestamp ? new Date(data.payload.timestamp).valueOf() : undefined, userToken: data.payload.userToken, authenticatedUserToken: data.payload.authenticatedUserToken From 51a91d4de96355c8c75ebfa9631892bbac620b0d Mon Sep 17 00:00:00 2001 From: jkaho Date: Fri, 15 Aug 2025 09:59:37 +1000 Subject: [PATCH 8/8] resolve comments --- .../productListViewedEvents/generated-types.ts | 3 +++ .../algolia-insights/productListViewedEvents/index.ts | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts index ebe1a5196df..97cbdef04dd 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/generated-types.ts @@ -5,6 +5,9 @@ export interface Payload { * The viewed products. Populates the ObjectIDs field in the Algolia Insights API. Each object must contain a product_id field. */ products: { + /** + * The unique ID of the product. + */ product_id: string }[] /** diff --git a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts index f9f5d1627dc..5b1f6928e44 100644 --- a/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts +++ b/packages/destination-actions/src/destinations/algolia-insights/productListViewedEvents/index.ts @@ -20,8 +20,14 @@ export const productListViewedEvents: ActionDefinition = { multiple: true, required: true, properties: { - product_id: { label: 'product_id', type: 'string', required: true } + product_id: { + label: 'product_id', + type: 'string', + description: 'The unique ID of the product.', + required: true + } }, + additionalProperties: false, default: { '@arrayPath': [ '$.properties.products',