@segment/analytics-browser-actions-stackadapt 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +20 -0
- package/src/__tests__/index.test.ts +59 -0
- package/src/__tests__/page.test.ts +49 -0
- package/src/__tests__/track.test.ts +54 -0
- package/src/generated-types.ts +8 -0
- package/src/index.ts +56 -0
- package/src/init-script.ts +17 -0
- package/src/trackEvent/generated-types.ts +14 -0
- package/src/trackEvent/index.ts +43 -0
- package/src/trackPage/generated-types.ts +10 -0
- package/src/trackPage/index.ts +33 -0
- package/src/types.ts +1 -0
- package/tsconfig.json +9 -0
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@segment/analytics-browser-actions-stackadapt",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "./dist/cjs",
|
|
6
|
+
"module": "./dist/esm",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "yarn build:esm && yarn build:cjs",
|
|
9
|
+
"build:cjs": "tsc --module commonjs --outDir ./dist/cjs",
|
|
10
|
+
"build:esm": "tsc --outDir ./dist/esm"
|
|
11
|
+
},
|
|
12
|
+
"typings": "./dist/esm",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@segment/actions-core": "^3.71.0",
|
|
15
|
+
"@segment/browser-destination-runtime": "^1.0.0"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@segment/analytics-next": "*"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import stackadapt, { destination } from '..'
|
|
3
|
+
|
|
4
|
+
describe('StackAdapt', () => {
|
|
5
|
+
test('can load stackadapt pixel', async () => {
|
|
6
|
+
const [event] = await stackadapt({
|
|
7
|
+
universalPixelId: 'test',
|
|
8
|
+
subscriptions: [
|
|
9
|
+
{
|
|
10
|
+
enabled: true,
|
|
11
|
+
name: 'Track Event',
|
|
12
|
+
subscribe: 'type = "track"',
|
|
13
|
+
partnerAction: 'trackEvent',
|
|
14
|
+
mapping: {
|
|
15
|
+
name: {
|
|
16
|
+
'@path': '$.name'
|
|
17
|
+
},
|
|
18
|
+
properties: {
|
|
19
|
+
'@path': '$.properties'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
destination.actions.trackEvent.perform = jest.fn()
|
|
27
|
+
jest.spyOn(destination.actions.trackEvent, 'perform')
|
|
28
|
+
jest.spyOn(destination, 'initialize')
|
|
29
|
+
|
|
30
|
+
await event.load(Context.system(), {} as Analytics)
|
|
31
|
+
expect(destination.initialize).toHaveBeenCalled()
|
|
32
|
+
|
|
33
|
+
const ctx = await event.track?.(
|
|
34
|
+
new Context({
|
|
35
|
+
type: 'track',
|
|
36
|
+
properties: {
|
|
37
|
+
abc: 'abc'
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
expect(destination.actions.trackEvent.perform).toHaveBeenCalled()
|
|
43
|
+
expect(ctx).not.toBeUndefined()
|
|
44
|
+
|
|
45
|
+
const scripts = window.document.querySelectorAll('script')
|
|
46
|
+
expect(scripts).toMatchInlineSnapshot(`
|
|
47
|
+
NodeList [
|
|
48
|
+
<script
|
|
49
|
+
src="https://tags.srv.stackadapt.com/events.js"
|
|
50
|
+
status="loaded"
|
|
51
|
+
type="text/javascript"
|
|
52
|
+
/>,
|
|
53
|
+
<script>
|
|
54
|
+
// the emptiness
|
|
55
|
+
</script>,
|
|
56
|
+
]
|
|
57
|
+
`)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import stackadapt, { destination } from '..'
|
|
3
|
+
|
|
4
|
+
describe('StackAdapt', () => {
|
|
5
|
+
test('can track page views', async () => {
|
|
6
|
+
const [trackPage] = await stackadapt({
|
|
7
|
+
universalPixelId: 'test',
|
|
8
|
+
subscriptions: [
|
|
9
|
+
{
|
|
10
|
+
enabled: true,
|
|
11
|
+
name: 'Track Page',
|
|
12
|
+
subscribe: 'type = "page"',
|
|
13
|
+
partnerAction: 'trackPage',
|
|
14
|
+
mapping: {
|
|
15
|
+
properties: {
|
|
16
|
+
'@path': '$.properties'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
destination.actions.trackPage.perform = jest.fn()
|
|
24
|
+
jest.spyOn(destination.actions.trackPage, 'perform')
|
|
25
|
+
jest.spyOn(destination, 'initialize')
|
|
26
|
+
|
|
27
|
+
await trackPage.load(Context.system(), {} as Analytics)
|
|
28
|
+
expect(destination.initialize).toHaveBeenCalled()
|
|
29
|
+
await trackPage.page?.(
|
|
30
|
+
new Context({
|
|
31
|
+
type: 'page',
|
|
32
|
+
properties: {
|
|
33
|
+
title: 'stackadapt.com'
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
expect(destination.actions.trackPage.perform).toHaveBeenCalledWith(
|
|
39
|
+
expect.any(Function),
|
|
40
|
+
expect.objectContaining({
|
|
41
|
+
payload: {
|
|
42
|
+
properties: {
|
|
43
|
+
title: 'stackadapt.com'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
)
|
|
48
|
+
})
|
|
49
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import stackadapt, { destination } from '..'
|
|
3
|
+
|
|
4
|
+
describe('StackAdapt', () => {
|
|
5
|
+
test('can track events', async () => {
|
|
6
|
+
const [event] = await stackadapt({
|
|
7
|
+
universalPixelId: 'test',
|
|
8
|
+
subscriptions: [
|
|
9
|
+
{
|
|
10
|
+
enabled: true,
|
|
11
|
+
name: 'Track Event',
|
|
12
|
+
subscribe: 'type = "track"',
|
|
13
|
+
partnerAction: 'trackEvent',
|
|
14
|
+
mapping: {
|
|
15
|
+
name: {
|
|
16
|
+
'@path': '$.event'
|
|
17
|
+
},
|
|
18
|
+
properties: {
|
|
19
|
+
'@path': '$.properties'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
destination.actions.trackEvent.perform = jest.fn()
|
|
27
|
+
jest.spyOn(destination.actions.trackEvent, 'perform')
|
|
28
|
+
jest.spyOn(destination, 'initialize')
|
|
29
|
+
|
|
30
|
+
await event.load(Context.system(), {} as Analytics)
|
|
31
|
+
expect(destination.initialize).toHaveBeenCalled()
|
|
32
|
+
await event.track?.(
|
|
33
|
+
new Context({
|
|
34
|
+
type: 'track',
|
|
35
|
+
event: 'checkout',
|
|
36
|
+
properties: {
|
|
37
|
+
item: 'nike react'
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith(
|
|
43
|
+
expect.any(Function),
|
|
44
|
+
expect.objectContaining({
|
|
45
|
+
payload: {
|
|
46
|
+
name: 'checkout',
|
|
47
|
+
properties: {
|
|
48
|
+
item: 'nike react'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
)
|
|
53
|
+
})
|
|
54
|
+
})
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Settings } from './generated-types'
|
|
2
|
+
import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types'
|
|
3
|
+
import { browserDestination } from '@segment/browser-destination-runtime/shim'
|
|
4
|
+
import { defaultValues } from '@segment/actions-core'
|
|
5
|
+
import { initScript } from './init-script'
|
|
6
|
+
import trackEvent, { trackEventDefaultSubscription } from './trackEvent'
|
|
7
|
+
import trackPage, { trackPageDefaultSubscription } from './trackPage'
|
|
8
|
+
import type { StackAdaptSDK } from './types'
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
interface Window {
|
|
12
|
+
saq: StackAdaptSDK
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const destination: BrowserDestinationDefinition<Settings, StackAdaptSDK> = {
|
|
17
|
+
name: 'StackAdapt (Actions)',
|
|
18
|
+
slug: 'actions-stackadapt',
|
|
19
|
+
mode: 'device',
|
|
20
|
+
presets: [
|
|
21
|
+
{
|
|
22
|
+
name: 'Track Event',
|
|
23
|
+
subscribe: trackEventDefaultSubscription,
|
|
24
|
+
partnerAction: 'trackEvent',
|
|
25
|
+
mapping: defaultValues(trackEvent.fields)
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'Track Page',
|
|
29
|
+
subscribe: trackPageDefaultSubscription,
|
|
30
|
+
partnerAction: 'trackPage',
|
|
31
|
+
mapping: defaultValues(trackPage.fields)
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
settings: {
|
|
35
|
+
universalPixelId: {
|
|
36
|
+
description: 'The universal pixel id for StackAdapt.',
|
|
37
|
+
label: 'Universal Pixel Id',
|
|
38
|
+
type: 'string',
|
|
39
|
+
required: true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
initialize: async (_, dependencies) => {
|
|
44
|
+
initScript()
|
|
45
|
+
await dependencies.loadScript('https://tags.srv.stackadapt.com/events.js')
|
|
46
|
+
|
|
47
|
+
return window.saq
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
actions: {
|
|
51
|
+
trackEvent,
|
|
52
|
+
trackPage
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default browserDestination(destination)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
export function initScript() {
|
|
4
|
+
if (window.saq) return
|
|
5
|
+
|
|
6
|
+
// Slightly modified version of standard SA Pixel, as the script has already
|
|
7
|
+
// been loaded.
|
|
8
|
+
const sdk = (window.saq = function () {
|
|
9
|
+
sdk.callMethod ? sdk.callMethod.apply(sdk, arguments) : sdk.queue.push(arguments)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
if (!window._saq) window._saq = sdk
|
|
13
|
+
sdk.push = sdk
|
|
14
|
+
sdk.loaded = true
|
|
15
|
+
sdk.version = '1.0'
|
|
16
|
+
sdk.queue = []
|
|
17
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import type { Settings } from '../generated-types'
|
|
3
|
+
import type { StackAdaptSDK } from '../types'
|
|
4
|
+
import type { Payload } from './generated-types'
|
|
5
|
+
|
|
6
|
+
export const trackEventDefaultSubscription = 'type = "track"'
|
|
7
|
+
|
|
8
|
+
const action: BrowserActionDefinition<Settings, StackAdaptSDK, Payload> = {
|
|
9
|
+
title: 'Track Event',
|
|
10
|
+
description: 'Track events',
|
|
11
|
+
platform: 'web',
|
|
12
|
+
defaultSubscription: trackEventDefaultSubscription,
|
|
13
|
+
fields: {
|
|
14
|
+
eventName: {
|
|
15
|
+
description: 'The name of the event.',
|
|
16
|
+
label: 'Name',
|
|
17
|
+
required: true,
|
|
18
|
+
type: 'string',
|
|
19
|
+
default: {
|
|
20
|
+
'@path': '$.event'
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
eventProperties: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
required: false,
|
|
26
|
+
description: 'Hash of properties for this event.',
|
|
27
|
+
label: 'Event Properties',
|
|
28
|
+
default: {
|
|
29
|
+
'@path': '$.properties'
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
perform: (saq, { settings, payload }) => {
|
|
34
|
+
const pixelId = settings.universalPixelId
|
|
35
|
+
|
|
36
|
+
saq('ts', pixelId, {
|
|
37
|
+
eventName: payload.eventName,
|
|
38
|
+
...(payload.eventProperties ?? {})
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default action
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import type { Settings } from '../generated-types'
|
|
3
|
+
import type { StackAdaptSDK } from '../types'
|
|
4
|
+
import type { Payload } from './generated-types'
|
|
5
|
+
|
|
6
|
+
export const trackPageDefaultSubscription = 'type = "page"'
|
|
7
|
+
|
|
8
|
+
const action: BrowserActionDefinition<Settings, StackAdaptSDK, Payload> = {
|
|
9
|
+
title: 'Track Page',
|
|
10
|
+
description: 'Record when a user visits a page.',
|
|
11
|
+
platform: 'web',
|
|
12
|
+
defaultSubscription: trackPageDefaultSubscription,
|
|
13
|
+
fields: {
|
|
14
|
+
properties: {
|
|
15
|
+
type: 'object',
|
|
16
|
+
required: false,
|
|
17
|
+
description: 'Hash of properties for this page view.',
|
|
18
|
+
label: 'Page Properties',
|
|
19
|
+
default: {
|
|
20
|
+
'@path': '$.properties'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
perform: (saq, { settings, payload }) => {
|
|
25
|
+
const pixelId = settings.universalPixelId
|
|
26
|
+
|
|
27
|
+
const properties = payload.properties ?? {}
|
|
28
|
+
|
|
29
|
+
saq('ts', pixelId, properties)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default action
|
package/src/types.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type StackAdaptSDK = (name: string, pixelId: string, payload: Record<string, unknown>) => void
|