Skip to content

Commit 0596bc4

Browse files
authored
Add page data to web signals (#1238)
1 parent 3d10bd9 commit 0596bc4

File tree

19 files changed

+225
-50
lines changed

19 files changed

+225
-50
lines changed

.changeset/pink-ladybugs-impress.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 page data to web signals
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { PageData } from '@segment/analytics-signals-runtime'
2+
3+
const pageData: PageData = {
4+
hash: '',
5+
hostname: 'localhost',
6+
path: '/src/tests/signals-vanilla/index.html',
7+
referrer: '',
8+
search: '',
9+
title: '',
10+
url: 'http://localhost:5432/src/tests/signals-vanilla/index.html',
11+
}
12+
13+
export const commonSignalData = {
14+
page: pageData,
15+
}

packages/signals/signals-integration-tests/src/tests/signals-vanilla/basic.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { test, expect } from '@playwright/test'
2+
import { commonSignalData } from '../../helpers/fixtures'
23
import { IndexPage } from './index-page'
34

45
const basicEdgeFn = `
@@ -57,6 +58,7 @@ test('network signals xhr', async () => {
5758
)
5859
expect(responses).toHaveLength(1)
5960
expect(responses[0].properties!.data.data).toEqual({ someResponse: 'yep' })
61+
expect(responses[0].properties!.data.page).toEqual(commonSignalData.page)
6062
})
6163

6264
test('instrumentation signals', async () => {
@@ -113,6 +115,7 @@ test('interaction signals', async () => {
113115
type: 'submit',
114116
value: '',
115117
},
118+
page: commonSignalData.page,
116119
}
117120

118121
expect(interactionSignals[0]).toMatchObject({
@@ -182,6 +185,7 @@ test('navigation signals', async ({ page }) => {
182185
hash: '#foo',
183186
search: '',
184187
title: '',
188+
page: expect.any(Object),
185189
},
186190
})
187191
}

packages/signals/signals-integration-tests/src/tests/signals-vanilla/index-page.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@ export class IndexPage extends BasePage {
2727
return this.page.evaluate(
2828
(args) => {
2929
window.signalsPlugin.addSignal({
30-
type: 'userDefined',
31-
data: {
32-
foo: 'bar',
33-
...args.data,
34-
},
30+
foo: 'bar',
31+
...args.data,
3532
})
3633
},
3734
{ data }

packages/signals/signals-integration-tests/src/tests/signals-vanilla/network-signals-fetch.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { test, expect } from '@playwright/test'
2+
import { commonSignalData } from '../../helpers/fixtures'
23
import { IndexPage } from './index-page'
34

45
const basicEdgeFn = `const processSignal = (signal) => {}`
@@ -32,6 +33,7 @@ test.describe('network signals - fetch', () => {
3233
data: null,
3334
method: 'POST',
3435
url: 'http://localhost/upload',
36+
...commonSignalData,
3537
})
3638
})
3739

@@ -61,6 +63,7 @@ test.describe('network signals - fetch', () => {
6163
action: 'request',
6264
url: 'http://localhost/test',
6365
data: { key: 'value' },
66+
...commonSignalData,
6467
})
6568
})
6669

@@ -90,6 +93,7 @@ test.describe('network signals - fetch', () => {
9093
action: 'request',
9194
url: 'http://localhost/test',
9295
data: 'hello world',
96+
...commonSignalData,
9397
})
9498
})
9599

@@ -104,6 +108,7 @@ test.describe('network signals - fetch', () => {
104108
method: 'POST',
105109
body: JSON.stringify({ key: 'value' }),
106110
contentType: 'application/json',
111+
...commonSignalData,
107112
}
108113
)
109114

@@ -124,6 +129,7 @@ test.describe('network signals - fetch', () => {
124129
url: 'http://localhost/test',
125130
method: 'POST',
126131
data: { key: 'value' },
132+
...commonSignalData,
127133
})
128134

129135
const responses = networkEvents.filter(
@@ -137,6 +143,7 @@ test.describe('network signals - fetch', () => {
137143
data: { foo: 'test' },
138144
status: 200,
139145
ok: true,
146+
...commonSignalData,
140147
})
141148
})
142149

@@ -165,6 +172,7 @@ test.describe('network signals - fetch', () => {
165172
action: 'request',
166173
url: `${indexPage.origin()}/test`,
167174
data: { key: 'value' },
175+
...commonSignalData,
168176
})
169177

170178
const responses = networkEvents.filter(
@@ -175,6 +183,7 @@ test.describe('network signals - fetch', () => {
175183
action: 'response',
176184
url: `${indexPage.origin()}/test`,
177185
data: { foo: 'test' },
186+
...commonSignalData,
178187
})
179188
})
180189

@@ -214,6 +223,7 @@ test.describe('network signals - fetch', () => {
214223
data: { errorMsg: 'foo' },
215224
status: 400,
216225
ok: false,
226+
page: expect.any(Object),
217227
})
218228
expect(responses).toHaveLength(1)
219229
})
@@ -253,6 +263,7 @@ test.describe('network signals - fetch', () => {
253263
data: 'foo',
254264
status: 400,
255265
ok: false,
266+
...commonSignalData,
256267
})
257268
expect(responses).toHaveLength(1)
258269
})

packages/signals/signals-runtime/src/__tests__/signals-runtime.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { InstrumentationSignal, InteractionSignal, Signal } from '../index'
22
import {
33
mockInstrumentationSignal,
44
mockInteractionSignal,
5+
mockPageData,
56
} from '../test-helpers/mocks/mock-signal-types-web'
67

78
import { WebSignalsRuntime } from '../web/web-signals-runtime'
@@ -17,6 +18,7 @@ describe(WebSignalsRuntime, () => {
1718
signal3 = {
1819
...mockInteractionSignal,
1920
data: {
21+
page: mockPageData,
2022
eventType: 'change',
2123
target: {} as any,
2224
change: {},

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,24 @@ import {
44
InstrumentationSignal,
55
UserDefinedSignal,
66
NetworkSignal,
7+
PageData,
78
} from '../../web/web-signals-types'
89
// Mock data for testing
10+
11+
export const mockPageData: PageData = {
12+
url: 'https://www.segment.com/docs/connections/sources/catalog/libraries/website/javascript/',
13+
path: '/docs/connections/sources/catalog/libraries/website/javascript/',
14+
search: '',
15+
hostname: 'www.segment.com',
16+
hash: '',
17+
referrer: '',
18+
title: 'Segment - Documentation',
19+
}
20+
921
export const mockInteractionSignal: InteractionSignal = {
1022
type: 'interaction',
1123
data: {
24+
page: mockPageData,
1225
eventType: 'click',
1326
target: {
1427
id: 'button1',
@@ -22,6 +35,7 @@ export const mockInteractionSignal: InteractionSignal = {
2235
export const mockNavigationSignal: NavigationSignal = {
2336
type: 'navigation',
2437
data: {
38+
page: mockPageData,
2539
action: 'urlChange',
2640
url: 'https://example.com',
2741
hash: '#section1',
@@ -33,6 +47,7 @@ export const mockNavigationSignal: NavigationSignal = {
3347
export const mockInstrumentationSignal: InstrumentationSignal = {
3448
type: 'instrumentation',
3549
data: {
50+
page: mockPageData,
3651
rawEvent: { type: 'customEvent', detail: 'example' },
3752
},
3853
metadata: { timestamp: Date.now() },
@@ -41,6 +56,7 @@ export const mockInstrumentationSignal: InstrumentationSignal = {
4156
export const mockNetworkSignal: NetworkSignal = {
4257
type: 'network',
4358
data: {
59+
page: mockPageData,
4460
action: 'request',
4561
contentType: 'application/json',
4662
url: 'https://api.example.com/data',
@@ -53,6 +69,7 @@ export const mockNetworkSignal: NetworkSignal = {
5369
export const mockUserDefinedSignal: UserDefinedSignal = {
5470
type: 'userDefined',
5571
data: {
72+
page: mockPageData,
5673
customField: 'customValue',
5774
},
5875
metadata: { timestamp: Date.now() },

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

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,55 @@ import { BaseSignal, JSONValue } from '../shared/shared-types'
22

33
export type SignalTypes = Signal['type']
44

5+
export interface PageData {
6+
/**
7+
* The full URL of the page
8+
* If there is a canonical URL, this should be the canonical URL
9+
* @example https://www.segment.com/docs/connections/sources/catalog/libraries/website/javascript/
10+
*/
11+
url: string
12+
/**
13+
* The path of the page
14+
* @example /docs/connections/sources/catalog/libraries/website/javascript/
15+
*/
16+
path: string
17+
/**
18+
* The search parameters of the page
19+
* @example ?utm_source=google
20+
*/
21+
search: string
22+
/**
23+
* The hostname of the page
24+
* @example www.segment.com
25+
*/
26+
hostname: string
27+
/**
28+
* The hash of the page
29+
* @example #hash
30+
*/
31+
hash: string
32+
/**
33+
* The referrer of the page
34+
* @example https://www.google.com/
35+
*/
36+
referrer: string
37+
/**
38+
* The title of the page
39+
* @example Segment - Documentation
40+
*/
41+
title: string
42+
}
43+
44+
/**
45+
* The base data that all web signal data must have
46+
*/
47+
export interface BaseWebData {
48+
page: PageData
49+
}
50+
551
export interface RawSignal<T extends SignalTypes, Data> extends BaseSignal {
652
type: T
7-
data: Data
53+
data: BaseWebData & Data
854
metadata?: Record<string, any>
955
}
1056
export type InteractionData = ClickData | SubmitData | ChangeData

packages/signals/signals/README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,13 @@ analytics.load({
5959
```ts
6060
import { signalsPlugin } from './analytics' // assuming you exported your plugin instance.
6161
62-
signalsPlugin.addSignal({
63-
type: 'userDefined',
64-
data: { foo: 'bar' }
65-
})
62+
signalsPlugin.addSignal({ someData: 'foo' })
63+
64+
// emits a signal with the following shape
65+
{
66+
type: 'userDefined'
67+
data: { someData: 'foo', ... }
68+
}
6669
```
6770

6871
### Debugging

packages/signals/signals/src/core/analytics-service/__tests__/analytics-service.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@ describe(AnalyticsService, () => {
3838
middleware({ payload: { obj: mockEvent }, next: jest.fn() })
3939

4040
expect(mockSignalEmitter.emit).toHaveBeenCalledTimes(1)
41-
expect(mockSignalEmitter.emit.mock.calls[0]).toMatchInlineSnapshot(`
42-
[
43-
{
44-
"data": {
45-
"rawEvent": {
46-
"context": {
47-
"foo": 123,
48-
},
49-
"type": "track",
41+
const call = mockSignalEmitter.emit.mock.calls[0][0]
42+
delete call.data.page
43+
expect(call).toMatchInlineSnapshot(`
44+
{
45+
"data": {
46+
"rawEvent": {
47+
"context": {
48+
"foo": 123,
5049
},
50+
"type": "track",
5151
},
52-
"type": "instrumentation",
5352
},
54-
]
53+
"type": "instrumentation",
54+
}
5555
`)
5656
})
5757
it('should not emit signals if the event is a Signal event', async () => {

0 commit comments

Comments
 (0)