@segment/analytics-browser-actions-sprig 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__/__snapshots__/index.test.ts.snap +18 -0
- package/src/__tests__/index.test.ts +48 -0
- package/src/generated-types.ts +12 -0
- package/src/identifyUser/__tests__/index.test.ts +65 -0
- package/src/identifyUser/generated-types.ts +18 -0
- package/src/identifyUser/index.ts +78 -0
- package/src/index.ts +91 -0
- package/src/signoutUser/generated-types.ts +3 -0
- package/src/signoutUser/index.ts +17 -0
- package/src/trackEvent/__tests__/index.test.ts +60 -0
- package/src/trackEvent/generated-types.ts +22 -0
- package/src/trackEvent/index.ts +80 -0
- package/src/types.ts +7 -0
- package/src/updateUserId/__tests__/index.test.ts +81 -0
- package/src/updateUserId/generated-types.ts +12 -0
- package/src/updateUserId/index.ts +55 -0
- package/tsconfig.json +9 -0
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@segment/analytics-browser-actions-sprig",
|
|
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,18 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Sprig initialization can load Sprig:
|
|
4
|
+
<script
|
|
5
|
+
src="https://cdn.sprig.com/shim.js?id=testEnvId"
|
|
6
|
+
status="loaded"
|
|
7
|
+
type="text/javascript"
|
|
8
|
+
/>,
|
|
9
|
+
<script>
|
|
10
|
+
// the emptiness
|
|
11
|
+
</script>,
|
|
12
|
+
1`] = `
|
|
13
|
+
NodeList [
|
|
14
|
+
<script>
|
|
15
|
+
// the emptiness
|
|
16
|
+
</script>,
|
|
17
|
+
]
|
|
18
|
+
`;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import sprigWebDestination, { destination } from '../index'
|
|
3
|
+
import { Subscription } from '@segment/browser-destination-runtime/types'
|
|
4
|
+
|
|
5
|
+
const subscriptions: Subscription[] = [
|
|
6
|
+
{
|
|
7
|
+
partnerAction: 'trackEvent',
|
|
8
|
+
name: 'Track Event',
|
|
9
|
+
enabled: true,
|
|
10
|
+
subscribe: 'type = "track"',
|
|
11
|
+
mapping: {
|
|
12
|
+
name: {
|
|
13
|
+
'@path': '$.name'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
describe('Sprig initialization', () => {
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
jest.mock('@segment/browser-destination-runtime/load-script', () => ({
|
|
22
|
+
loadScript: (_src: any, _attributes: any) => {}
|
|
23
|
+
}))
|
|
24
|
+
})
|
|
25
|
+
test('can load Sprig', async () => {
|
|
26
|
+
const [event] = await sprigWebDestination({
|
|
27
|
+
envId: 'testEnvId',
|
|
28
|
+
subscriptions
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
jest.spyOn(destination, 'initialize')
|
|
32
|
+
|
|
33
|
+
await event.load(Context.system(), {} as Analytics)
|
|
34
|
+
expect(destination.initialize).toHaveBeenCalled()
|
|
35
|
+
|
|
36
|
+
const scripts = window.document.querySelectorAll('script')
|
|
37
|
+
expect(scripts).toMatchSnapshot(`
|
|
38
|
+
<script
|
|
39
|
+
src="https://cdn.sprig.com/shim.js?id=testEnvId"
|
|
40
|
+
status="loaded"
|
|
41
|
+
type="text/javascript"
|
|
42
|
+
/>,
|
|
43
|
+
<script>
|
|
44
|
+
// the emptiness
|
|
45
|
+
</script>,
|
|
46
|
+
`)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import sprigWebDestination, { destination } from '../../index'
|
|
3
|
+
import { Subscription } from '@segment/browser-destination-runtime/types'
|
|
4
|
+
|
|
5
|
+
const subscriptions: Subscription[] = [
|
|
6
|
+
{
|
|
7
|
+
partnerAction: 'identifyUser',
|
|
8
|
+
name: 'Identify User',
|
|
9
|
+
enabled: true,
|
|
10
|
+
subscribe: 'type = "identify"',
|
|
11
|
+
mapping: {
|
|
12
|
+
anonymousId: {
|
|
13
|
+
'@path': '$.anonymousId'
|
|
14
|
+
},
|
|
15
|
+
userId: {
|
|
16
|
+
'@path': '$.userId'
|
|
17
|
+
},
|
|
18
|
+
traits: {
|
|
19
|
+
'@path': '$.traits'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
describe('identifyUser', () => {
|
|
26
|
+
beforeAll(() => {
|
|
27
|
+
jest.mock('@segment/browser-destination-runtime/load-script', () => ({
|
|
28
|
+
loadScript: (_src: any, _attributes: any) => {}
|
|
29
|
+
}))
|
|
30
|
+
})
|
|
31
|
+
test('it maps event parameters correctly to identify function ', async () => {
|
|
32
|
+
const [identifyEvent] = await sprigWebDestination({
|
|
33
|
+
envId: 'testEnvId',
|
|
34
|
+
subscriptions
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
destination.actions.identifyUser.perform = jest.fn()
|
|
38
|
+
jest.spyOn(destination.actions.identifyUser, 'perform')
|
|
39
|
+
await identifyEvent.load(Context.system(), {} as Analytics)
|
|
40
|
+
|
|
41
|
+
await identifyEvent.identify?.(
|
|
42
|
+
new Context({
|
|
43
|
+
type: 'identify',
|
|
44
|
+
anonymousId: 'anonymous-id-0',
|
|
45
|
+
userId: 'user-id-1',
|
|
46
|
+
traits: {
|
|
47
|
+
email: 'test-email-2@gmail.com'
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
expect(destination.actions.identifyUser.perform).toHaveBeenCalledWith(
|
|
53
|
+
expect.anything(),
|
|
54
|
+
expect.objectContaining({
|
|
55
|
+
payload: {
|
|
56
|
+
anonymousId: 'anonymous-id-0',
|
|
57
|
+
userId: 'user-id-1',
|
|
58
|
+
traits: {
|
|
59
|
+
email: 'test-email-2@gmail.com'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Payload {
|
|
4
|
+
/**
|
|
5
|
+
* Unique identifier for the user
|
|
6
|
+
*/
|
|
7
|
+
userId?: string
|
|
8
|
+
/**
|
|
9
|
+
* Anonymous identifier for the user
|
|
10
|
+
*/
|
|
11
|
+
anonymousId?: string
|
|
12
|
+
/**
|
|
13
|
+
* The Segment user traits to be forwarded to Sprig and set as attributes
|
|
14
|
+
*/
|
|
15
|
+
traits?: {
|
|
16
|
+
[k: string]: unknown
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import type { Settings } from '../generated-types'
|
|
3
|
+
import type { Payload } from './generated-types'
|
|
4
|
+
import type { Sprig } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, Sprig, Payload> = {
|
|
7
|
+
title: 'Identify User',
|
|
8
|
+
description: 'Set user ID and/or attributes.',
|
|
9
|
+
platform: 'web',
|
|
10
|
+
defaultSubscription: 'type = "identify"',
|
|
11
|
+
fields: {
|
|
12
|
+
userId: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
required: false,
|
|
15
|
+
description: 'Unique identifier for the user',
|
|
16
|
+
label: 'User ID',
|
|
17
|
+
default: {
|
|
18
|
+
'@path': '$.userId'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
anonymousId: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
required: false,
|
|
24
|
+
description: 'Anonymous identifier for the user',
|
|
25
|
+
label: 'Anonymous ID',
|
|
26
|
+
default: {
|
|
27
|
+
'@path': '$.anonymousId'
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
traits: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
required: false,
|
|
33
|
+
description: 'The Segment user traits to be forwarded to Sprig and set as attributes',
|
|
34
|
+
label: 'User Attributes',
|
|
35
|
+
default: {
|
|
36
|
+
'@path': '$.traits'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
perform: (Sprig, event) => {
|
|
41
|
+
const payload = event.payload
|
|
42
|
+
if (!payload || typeof payload !== 'object' || !(payload.userId || payload.anonymousId || payload.traits)) {
|
|
43
|
+
console.warn(
|
|
44
|
+
'[Sprig] received invalid payload (expected userId, anonymousId, or traits to be present); skipping identifyUser',
|
|
45
|
+
payload
|
|
46
|
+
)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
const sprigIdentifyAndSetAttributesPayload: {
|
|
52
|
+
userId?: string
|
|
53
|
+
anonymousId?: string
|
|
54
|
+
attributes?: { [key: string]: any }
|
|
55
|
+
} = {}
|
|
56
|
+
|
|
57
|
+
if (payload.userId) {
|
|
58
|
+
sprigIdentifyAndSetAttributesPayload.userId = payload.userId
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (payload.anonymousId) {
|
|
62
|
+
sprigIdentifyAndSetAttributesPayload.anonymousId = payload.anonymousId
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (payload.traits && Object.keys(payload.traits).length > 0) {
|
|
66
|
+
const traits = { ...payload.traits }
|
|
67
|
+
if (traits.email) {
|
|
68
|
+
traits['!email'] = traits.email
|
|
69
|
+
delete traits.email
|
|
70
|
+
}
|
|
71
|
+
sprigIdentifyAndSetAttributesPayload.attributes = traits
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
Sprig('identifyAndSetAttributes', sprigIdentifyAndSetAttributesPayload)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default action
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
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 { Sprig } from './types'
|
|
5
|
+
import identifyUser from './identifyUser'
|
|
6
|
+
import signoutUser from './signoutUser'
|
|
7
|
+
import trackEvent from './trackEvent'
|
|
8
|
+
import updateUserId from './updateUserId'
|
|
9
|
+
import { defaultValues } from '@segment/actions-core'
|
|
10
|
+
|
|
11
|
+
declare global {
|
|
12
|
+
interface Window {
|
|
13
|
+
Sprig: Sprig
|
|
14
|
+
UserLeap: Sprig
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const destination: BrowserDestinationDefinition<Settings, Sprig> = {
|
|
19
|
+
name: 'Sprig (Actions)',
|
|
20
|
+
slug: 'sprig-web',
|
|
21
|
+
mode: 'device',
|
|
22
|
+
|
|
23
|
+
presets: [
|
|
24
|
+
{
|
|
25
|
+
name: 'Identify User',
|
|
26
|
+
subscribe: 'type = "identify"',
|
|
27
|
+
partnerAction: 'identifyUser',
|
|
28
|
+
mapping: defaultValues(identifyUser.fields)
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Sign Out User',
|
|
32
|
+
subscribe: 'type = "track" and event = "Signed Out"',
|
|
33
|
+
partnerAction: 'signoutUser',
|
|
34
|
+
mapping: defaultValues(signoutUser.fields)
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'Track Event',
|
|
38
|
+
subscribe: 'type = "track" and event != "Signed Out"',
|
|
39
|
+
partnerAction: 'trackEvent',
|
|
40
|
+
mapping: defaultValues(trackEvent.fields)
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Update User ID',
|
|
44
|
+
subscribe: 'type = "alias"',
|
|
45
|
+
partnerAction: 'updateUserId',
|
|
46
|
+
mapping: defaultValues(updateUserId.fields)
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
|
|
50
|
+
settings: {
|
|
51
|
+
envId: {
|
|
52
|
+
description: 'Your environment ID (production or development).',
|
|
53
|
+
label: 'Environment ID',
|
|
54
|
+
type: 'string',
|
|
55
|
+
required: true
|
|
56
|
+
},
|
|
57
|
+
debugMode: {
|
|
58
|
+
description: 'Enable debug mode for testing purposes.',
|
|
59
|
+
label: 'Debug mode',
|
|
60
|
+
type: 'boolean',
|
|
61
|
+
required: false,
|
|
62
|
+
default: false
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
actions: {
|
|
67
|
+
identifyUser,
|
|
68
|
+
signoutUser,
|
|
69
|
+
trackEvent,
|
|
70
|
+
updateUserId
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
initialize: async ({ settings }, deps) => {
|
|
74
|
+
if (!window.Sprig || !window.Sprig.envId) {
|
|
75
|
+
window.Sprig = function (...args) {
|
|
76
|
+
S._queue && S._queue.push(args)
|
|
77
|
+
}
|
|
78
|
+
const S = window.Sprig
|
|
79
|
+
S.envId = settings.envId
|
|
80
|
+
S.debugMode = !!settings.debugMode
|
|
81
|
+
S._queue = []
|
|
82
|
+
S._segment = 1
|
|
83
|
+
window.UserLeap = S
|
|
84
|
+
await deps.loadScript(`https://cdn.sprig.com/shim.js?id=${S.envId}`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return window.Sprig
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default browserDestination(destination)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import type { Settings } from '../generated-types'
|
|
3
|
+
import type { Payload } from './generated-types'
|
|
4
|
+
import type { Sprig } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, Sprig, Payload> = {
|
|
7
|
+
title: 'Sign Out User',
|
|
8
|
+
description: 'Clear stored user ID so that future events and traits are not associated with this user.',
|
|
9
|
+
platform: 'web',
|
|
10
|
+
defaultSubscription: 'type = "track" and event = "Signed Out"',
|
|
11
|
+
fields: {},
|
|
12
|
+
perform: (Sprig, _event) => {
|
|
13
|
+
Sprig('logoutUser')
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default action
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import sprigWebDestination, { destination } from '../../index'
|
|
3
|
+
import { Subscription } from '@segment/browser-destination-runtime/types'
|
|
4
|
+
|
|
5
|
+
const subscriptions: Subscription[] = [
|
|
6
|
+
{
|
|
7
|
+
partnerAction: 'trackEvent',
|
|
8
|
+
name: 'Track Event',
|
|
9
|
+
enabled: true,
|
|
10
|
+
subscribe: 'type = "track"',
|
|
11
|
+
mapping: {
|
|
12
|
+
name: {
|
|
13
|
+
'@path': '$.name'
|
|
14
|
+
},
|
|
15
|
+
anonymousId: {
|
|
16
|
+
'@path': '$.anonymousId'
|
|
17
|
+
},
|
|
18
|
+
userId: {
|
|
19
|
+
'@path': '$.userId'
|
|
20
|
+
},
|
|
21
|
+
properties: {
|
|
22
|
+
'@path': '$.properties'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
describe('trackEvent', () => {
|
|
29
|
+
beforeAll(() => {
|
|
30
|
+
jest.mock('@segment/browser-destination-runtime/load-script', () => ({
|
|
31
|
+
loadScript: (_src: any, _attributes: any) => {}
|
|
32
|
+
}))
|
|
33
|
+
})
|
|
34
|
+
test('it maps event parameters correctly to track function ', async () => {
|
|
35
|
+
const [trackEvent] = await sprigWebDestination({
|
|
36
|
+
envId: 'testEnvId',
|
|
37
|
+
subscriptions
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
destination.actions.trackEvent.perform = jest.fn()
|
|
41
|
+
jest.spyOn(destination.actions.trackEvent, 'perform')
|
|
42
|
+
await trackEvent.load(Context.system(), {} as Analytics)
|
|
43
|
+
const properties = { property1: 'value1', property2: false }
|
|
44
|
+
await trackEvent.track?.(
|
|
45
|
+
new Context({
|
|
46
|
+
type: 'track',
|
|
47
|
+
name: 'Button Clicked',
|
|
48
|
+
anonymousId: 'anonymous-id-0',
|
|
49
|
+
properties
|
|
50
|
+
})
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith(
|
|
54
|
+
expect.anything(),
|
|
55
|
+
expect.objectContaining({
|
|
56
|
+
payload: { name: 'Button Clicked', anonymousId: 'anonymous-id-0', properties }
|
|
57
|
+
})
|
|
58
|
+
)
|
|
59
|
+
})
|
|
60
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Payload {
|
|
4
|
+
/**
|
|
5
|
+
* The event name that will be shown on Sprig's dashboard
|
|
6
|
+
*/
|
|
7
|
+
name: string
|
|
8
|
+
/**
|
|
9
|
+
* Unique identifier for the user
|
|
10
|
+
*/
|
|
11
|
+
userId?: string
|
|
12
|
+
/**
|
|
13
|
+
* Anonymous identifier for the user
|
|
14
|
+
*/
|
|
15
|
+
anonymousId?: string
|
|
16
|
+
/**
|
|
17
|
+
* Object containing the properties of the event
|
|
18
|
+
*/
|
|
19
|
+
properties?: {
|
|
20
|
+
[k: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import type { Settings } from '../generated-types'
|
|
3
|
+
import type { Payload } from './generated-types'
|
|
4
|
+
import type { Sprig } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, Sprig, Payload> = {
|
|
7
|
+
title: 'Track Event',
|
|
8
|
+
description: 'Track event to potentially filter user studies (microsurveys) later, or trigger a study now.',
|
|
9
|
+
platform: 'web',
|
|
10
|
+
defaultSubscription: 'type = "track" and event != "Signed Out"',
|
|
11
|
+
fields: {
|
|
12
|
+
name: {
|
|
13
|
+
description: "The event name that will be shown on Sprig's dashboard",
|
|
14
|
+
label: 'Event name',
|
|
15
|
+
required: true,
|
|
16
|
+
type: 'string',
|
|
17
|
+
default: {
|
|
18
|
+
'@path': '$.event'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
userId: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
required: false,
|
|
24
|
+
description: 'Unique identifier for the user',
|
|
25
|
+
label: 'User ID',
|
|
26
|
+
default: {
|
|
27
|
+
'@path': '$.userId'
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
anonymousId: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
required: false,
|
|
33
|
+
description: 'Anonymous identifier for the user',
|
|
34
|
+
label: 'Anonymous ID',
|
|
35
|
+
default: {
|
|
36
|
+
'@path': '$.anonymousId'
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
properties: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
required: false,
|
|
42
|
+
description: 'Object containing the properties of the event',
|
|
43
|
+
label: 'Event Properties',
|
|
44
|
+
default: {
|
|
45
|
+
'@path': '$.properties'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
perform: (Sprig, event) => {
|
|
50
|
+
const payload = event.payload
|
|
51
|
+
if (!payload || typeof payload !== 'object' || !payload.name) {
|
|
52
|
+
console.warn('[Sprig] received invalid payload (expected name to be present); skipping trackEvent', payload)
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const sprigIdentifyAndTrackPayload: {
|
|
57
|
+
eventName: string
|
|
58
|
+
userId?: string
|
|
59
|
+
anonymousId?: string
|
|
60
|
+
properties?: { [key: string]: unknown }
|
|
61
|
+
} = {
|
|
62
|
+
eventName: payload.name
|
|
63
|
+
}
|
|
64
|
+
if (payload.userId) {
|
|
65
|
+
sprigIdentifyAndTrackPayload.userId = payload.userId
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (payload.anonymousId) {
|
|
69
|
+
sprigIdentifyAndTrackPayload.anonymousId = payload.anonymousId
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (payload.properties) {
|
|
73
|
+
sprigIdentifyAndTrackPayload.properties = payload.properties
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Sprig('identifyAndTrack', sprigIdentifyAndTrackPayload)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default action
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import sprigWebDestination, { destination } from '../../index'
|
|
3
|
+
import { Subscription } from '@segment/browser-destination-runtime/types'
|
|
4
|
+
|
|
5
|
+
const subscriptions: Subscription[] = [
|
|
6
|
+
{
|
|
7
|
+
partnerAction: 'updateUserId',
|
|
8
|
+
name: 'Update User ID',
|
|
9
|
+
enabled: true,
|
|
10
|
+
subscribe: 'type = "alias"',
|
|
11
|
+
mapping: {
|
|
12
|
+
anonymousId: {
|
|
13
|
+
'@path': '$.anonymousId'
|
|
14
|
+
},
|
|
15
|
+
userId: {
|
|
16
|
+
'@path': '$.userId'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
describe('updateUserId', () => {
|
|
23
|
+
beforeAll(() => {
|
|
24
|
+
jest.mock('@segment/browser-destination-runtime/load-script', () => ({
|
|
25
|
+
loadScript: (_src: any, _attributes: any) => {}
|
|
26
|
+
}))
|
|
27
|
+
})
|
|
28
|
+
test('it maps event parameters correctly to alias function with user id', async () => {
|
|
29
|
+
const [aliasEvent] = await sprigWebDestination({
|
|
30
|
+
envId: 'testEnvId',
|
|
31
|
+
subscriptions
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
destination.actions.updateUserId.perform = jest.fn()
|
|
35
|
+
jest.spyOn(destination.actions.updateUserId, 'perform')
|
|
36
|
+
await aliasEvent.load(Context.system(), {} as Analytics)
|
|
37
|
+
|
|
38
|
+
await aliasEvent.alias?.(
|
|
39
|
+
new Context({
|
|
40
|
+
type: 'alias',
|
|
41
|
+
userId: 'user-id-1'
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
expect(destination.actions.updateUserId.perform).toHaveBeenCalledWith(
|
|
46
|
+
expect.anything(),
|
|
47
|
+
expect.objectContaining({
|
|
48
|
+
payload: {
|
|
49
|
+
userId: 'user-id-1'
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('it maps event parameters correctly to alias function with anonymous id', async () => {
|
|
56
|
+
const [aliasEvent] = await sprigWebDestination({
|
|
57
|
+
envId: 'testEnvId',
|
|
58
|
+
subscriptions
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
destination.actions.updateUserId.perform = jest.fn()
|
|
62
|
+
jest.spyOn(destination.actions.updateUserId, 'perform')
|
|
63
|
+
await aliasEvent.load(Context.system(), {} as Analytics)
|
|
64
|
+
|
|
65
|
+
await aliasEvent.alias?.(
|
|
66
|
+
new Context({
|
|
67
|
+
type: 'alias',
|
|
68
|
+
anonymousId: 'anonymous-id-0'
|
|
69
|
+
})
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
expect(destination.actions.updateUserId.perform).toHaveBeenCalledWith(
|
|
73
|
+
expect.anything(),
|
|
74
|
+
expect.objectContaining({
|
|
75
|
+
payload: {
|
|
76
|
+
anonymousId: 'anonymous-id-0'
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import type { Settings } from '../generated-types'
|
|
3
|
+
import type { Payload } from './generated-types'
|
|
4
|
+
import type { Sprig } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, Sprig, Payload> = {
|
|
7
|
+
title: 'Update User ID',
|
|
8
|
+
description: 'Set updated user ID.',
|
|
9
|
+
platform: 'web',
|
|
10
|
+
defaultSubscription: 'type = "alias"',
|
|
11
|
+
fields: {
|
|
12
|
+
userId: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
required: false,
|
|
15
|
+
description: 'New unique identifier for the user',
|
|
16
|
+
label: 'User ID',
|
|
17
|
+
default: {
|
|
18
|
+
'@path': '$.userId'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
anonymousId: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
required: false,
|
|
24
|
+
description: 'New anonymous identifier for the user',
|
|
25
|
+
label: 'Anonymous ID',
|
|
26
|
+
default: {
|
|
27
|
+
'@path': '$.anonymousId'
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
perform: (Sprig, event) => {
|
|
32
|
+
const payload = event.payload
|
|
33
|
+
if (!payload || typeof payload !== 'object' || !(payload.userId || payload.anonymousId)) {
|
|
34
|
+
console.warn(
|
|
35
|
+
'[Sprig] received invalid payload (expected userId or anonymousId to be present); skipping updateUserId',
|
|
36
|
+
payload
|
|
37
|
+
)
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const sprigIdentifyAndSetAttributesPayload: { userId?: string; anonymousId?: string } = {}
|
|
42
|
+
|
|
43
|
+
if (payload.userId) {
|
|
44
|
+
sprigIdentifyAndSetAttributesPayload.userId = payload.userId
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (payload.anonymousId) {
|
|
48
|
+
sprigIdentifyAndSetAttributesPayload.anonymousId = payload.anonymousId
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
Sprig('identifyAndSetAttributes', sprigIdentifyAndSetAttributesPayload)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default action
|