Skip to content

Commit 6753b4b

Browse files
authored
Add anonymousId and timestamp to web signalData (#1263)
1 parent 83c25bb commit 6753b4b

File tree

32 files changed

+397
-101
lines changed

32 files changed

+397
-101
lines changed

.changeset/late-bikes-notice.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@segment/analytics-signals': minor
3+
'@segment/analytics-signals-runtime': minor
4+
---
5+
6+
Add anonymousID and timestamp to signals

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ module.exports = () =>
1818
'<rootDir>/packages/consent/consent-wrapper-onetrust',
1919
'<rootDir>/scripts',
2020
'<rootDir>/packages/signals/signals',
21+
'<rootDir>/packages/test-helpers',
2122
],
2223
})
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { test, expect } from '@playwright/test'
2+
import { waitForCondition } from '../../helpers/playwright-utils'
3+
import { IndexPage } from './index-page'
4+
5+
const basicEdgeFn = `
6+
// this is a process signal function
7+
const processSignal = (signal) => {
8+
if (signal.type === 'interaction') {
9+
analytics.track('hello', { myAnonId: signal.anonymousId, myTimestamp: signal.timestamp })
10+
}
11+
}
12+
`
13+
14+
let indexPage: IndexPage
15+
16+
const isoDateRegEx = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
17+
18+
test.beforeEach(async ({ page }) => {
19+
indexPage = await new IndexPage().loadAndWait(page, basicEdgeFn)
20+
})
21+
22+
test('Signals should have anonymousId and timestamp at top level', async () => {
23+
await indexPage.network.mockTestRoute()
24+
await indexPage.network.makeFetchCall()
25+
await Promise.all([
26+
indexPage.clickButton(),
27+
indexPage.makeAnalyticsPageCall(),
28+
indexPage.waitForSignalsApiFlush(),
29+
indexPage.waitForTrackingApiFlush(),
30+
])
31+
32+
const types = [
33+
'network',
34+
'interaction',
35+
'instrumentation',
36+
'navigation',
37+
] as const
38+
39+
const evs = types.map((type) => ({
40+
type,
41+
networkCalls: indexPage.signalsAPI.getEvents(type),
42+
}))
43+
44+
evs.forEach((events) => {
45+
if (!events.networkCalls.length) {
46+
throw new Error(`No events found for type ${events.type}`)
47+
}
48+
events.networkCalls.forEach((event) => {
49+
const expected = {
50+
anonymousId: event.anonymousId,
51+
timestamp: expect.stringMatching(isoDateRegEx),
52+
type: event.properties!.type,
53+
}
54+
expect(event.properties).toMatchObject(expected)
55+
})
56+
})
57+
58+
const getCreatedEvent = () =>
59+
indexPage.trackingAPI
60+
.getEvents()
61+
.find((el) => el.type === 'track' && el.event === 'hello')
62+
63+
await waitForCondition(() => !!getCreatedEvent(), {
64+
errorMessage: 'No track events found, should have an event',
65+
})
66+
const event = getCreatedEvent()!
67+
expect(event.properties).toEqual({
68+
myAnonId: event.anonymousId,
69+
myTimestamp: expect.stringMatching(isoDateRegEx),
70+
})
71+
})

packages/signals/signals-runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"build:cjs": "yarn tsc -p tsconfig.build.json --outDir ./dist/cjs --module commonjs",
2727
"build:global": "node build-signals-runtime-global.js",
2828
"assert-generated": "bash scripts/assert-generated.sh",
29-
"watch": "rm -rf dist/esm && yarn build:esm --watch",
29+
"watch": "rm -rf dist/esm && yarn build:esm && yarn build:esm --watch",
3030
"watch:test": "yarn test --watch",
3131
"tsc": "yarn run -T tsc",
3232
"eslint": "yarn run -T eslint",

packages/signals/signals-runtime/src/shared/shared-types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
export type ID = string | null | undefined
2+
13
export interface BaseSignal {
24
type: string
5+
anonymousId: ID
6+
timestamp: string
37
}
48

59
export type SignalOfType<

packages/signals/signals-runtime/src/test-helpers/mocks/mock-signal-types-web.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { BaseSignal } from '../../shared/shared-types'
12
import {
23
InteractionSignal,
34
NavigationSignal,
@@ -8,6 +9,13 @@ import {
89
} from '../../web/web-signals-types'
910
// Mock data for testing
1011

12+
type DefaultProps = Pick<BaseSignal, 'anonymousId' | 'timestamp'>
13+
14+
const baseSignalProps: DefaultProps = {
15+
anonymousId: '123',
16+
timestamp: '2020-01-01T00:00:00.000Z',
17+
}
18+
1119
export const mockPageData: PageData = {
1220
url: 'https://www.segment.com/docs/connections/sources/catalog/libraries/website/javascript/',
1321
path: '/docs/connections/sources/catalog/libraries/website/javascript/',
@@ -29,7 +37,7 @@ export const mockInteractionSignal: InteractionSignal = {
2937
attributes: { id: 'button1', class: 'btn-primary' },
3038
},
3139
},
32-
metadata: { timestamp: Date.now() },
40+
...baseSignalProps,
3341
}
3442

3543
export const mockNavigationSignal: NavigationSignal = {
@@ -41,7 +49,7 @@ export const mockNavigationSignal: NavigationSignal = {
4149
hash: '#section1',
4250
prevUrl: 'https://example.com/home',
4351
},
44-
metadata: { timestamp: Date.now() },
52+
...baseSignalProps,
4553
}
4654

4755
export const mockInstrumentationSignal: InstrumentationSignal = {
@@ -50,7 +58,7 @@ export const mockInstrumentationSignal: InstrumentationSignal = {
5058
page: mockPageData,
5159
rawEvent: { type: 'customEvent', detail: 'example' },
5260
},
53-
metadata: { timestamp: Date.now() },
61+
...baseSignalProps,
5462
}
5563

5664
export const mockNetworkSignal: NetworkSignal = {
@@ -63,7 +71,7 @@ export const mockNetworkSignal: NetworkSignal = {
6371
method: 'GET',
6472
data: { key: 'value' },
6573
},
66-
metadata: { timestamp: Date.now() },
74+
...baseSignalProps,
6775
}
6876

6977
export const mockUserDefinedSignal: UserDefinedSignal = {
@@ -72,5 +80,5 @@ export const mockUserDefinedSignal: UserDefinedSignal = {
7280
page: mockPageData,
7381
customField: 'customValue',
7482
},
75-
metadata: { timestamp: Date.now() },
83+
...baseSignalProps,
7684
}

packages/signals/signals/jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ const { createJestTSConfig } = require('@internal/config')
22

33
module.exports = createJestTSConfig(__dirname, {
44
testEnvironment: 'jsdom',
5-
setupFilesAfterEnv: ['./jest.setup.js'],
5+
setupFilesAfterEnv: ['./jest.setup.ts'],
66
})

packages/signals/signals/jest.setup.js

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* eslint-disable no-undef */
2+
import './src/test-helpers/jest-extended'
3+
import { JestSerializers } from '@internal/test-helpers'
4+
import 'fake-indexeddb/auto'
5+
globalThis.structuredClone = (v: any) => JSON.parse(JSON.stringify(v))
6+
expect.addSnapshotSerializer(JestSerializers.jestSnapshotSerializerTimestamp)

packages/signals/signals/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
],
2626
"scripts": {
2727
".": "yarn run -T turbo run --filter=@segment/analytics-signals...",
28+
"..": "yarn run -T turbo run --filter=...@segment/analytics-signals...",
2829
"test": "yarn jest",
2930
"lint": "yarn concurrently 'yarn:eslint .' 'yarn:tsc --noEmit'",
3031
"build": "rm -rf dist && yarn concurrently 'yarn:build:*'",

0 commit comments

Comments
 (0)