@segment/analytics-browser-actions-ripe 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/generated-types.ts +16 -0
- package/src/group/__tests__/index.test.ts +91 -0
- package/src/group/generated-types.ts +26 -0
- package/src/group/index.ts +61 -0
- package/src/identify/__tests__/index.test.ts +91 -0
- package/src/identify/generated-types.ts +26 -0
- package/src/identify/index.ts +61 -0
- package/src/index.ts +109 -0
- package/src/init-script.ts +17 -0
- package/src/page/__tests__/index.test.ts +102 -0
- package/src/page/generated-types.ts +34 -0
- package/src/page/index.ts +89 -0
- package/src/track/__tests__/index.test.ts +96 -0
- package/src/track/generated-types.ts +30 -0
- package/src/track/index.ts +71 -0
- package/src/types.ts +61 -0
- package/tsconfig.json +9 -0
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@segment/analytics-browser-actions-ripe",
|
|
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,16 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Settings {
|
|
4
|
+
/**
|
|
5
|
+
* The version of the Ripe Widget SDK to use
|
|
6
|
+
*/
|
|
7
|
+
sdkVersion?: string
|
|
8
|
+
/**
|
|
9
|
+
* The Ripe API key found in the Ripe App
|
|
10
|
+
*/
|
|
11
|
+
apiKey: string
|
|
12
|
+
/**
|
|
13
|
+
* The Ripe API endpoint (do not change this unless you know what you're doing)
|
|
14
|
+
*/
|
|
15
|
+
endpoint?: string
|
|
16
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Subscription } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
3
|
+
import RipeDestination, { destination } from '../../index'
|
|
4
|
+
|
|
5
|
+
import { loadScript } from '@segment/browser-destination-runtime/load-script'
|
|
6
|
+
import { RipeSDK } from '../../types'
|
|
7
|
+
|
|
8
|
+
jest.mock('@segment/browser-destination-runtime/load-script')
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
;(loadScript as jest.Mock).mockResolvedValue(true)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const subscriptions: Subscription[] = [
|
|
14
|
+
{
|
|
15
|
+
partnerAction: 'group',
|
|
16
|
+
name: 'Group user',
|
|
17
|
+
enabled: true,
|
|
18
|
+
subscribe: 'type = "group"',
|
|
19
|
+
mapping: {
|
|
20
|
+
messageId: {
|
|
21
|
+
'@path': '$.messageId'
|
|
22
|
+
},
|
|
23
|
+
anonymousId: {
|
|
24
|
+
'@path': '$.anonymousId'
|
|
25
|
+
},
|
|
26
|
+
userId: {
|
|
27
|
+
'@path': '$.userId'
|
|
28
|
+
},
|
|
29
|
+
groupId: {
|
|
30
|
+
'@path': '$.groupId'
|
|
31
|
+
},
|
|
32
|
+
traits: {
|
|
33
|
+
'@path': '$.traits'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
describe('Ripe.group', () => {
|
|
40
|
+
test('it maps the event name and properties and passes them into RipeSDK.track', async () => {
|
|
41
|
+
window.Ripe = {
|
|
42
|
+
init: jest.fn().mockResolvedValueOnce('123'),
|
|
43
|
+
group: jest.fn().mockResolvedValueOnce(undefined),
|
|
44
|
+
setIds: jest.fn().mockResolvedValueOnce(undefined)
|
|
45
|
+
} as unknown as RipeSDK
|
|
46
|
+
|
|
47
|
+
const [event] = await RipeDestination({
|
|
48
|
+
subscriptions,
|
|
49
|
+
apiKey: '123'
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const ajs = new Analytics({ writeKey: '123' })
|
|
53
|
+
await event.load(Context.system(), ajs)
|
|
54
|
+
jest.spyOn(destination.actions.group, 'perform')
|
|
55
|
+
|
|
56
|
+
await event.group?.(
|
|
57
|
+
new Context({
|
|
58
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
59
|
+
anonymousId: 'anonId1',
|
|
60
|
+
type: 'group',
|
|
61
|
+
groupId: 'groupId1',
|
|
62
|
+
traits: {
|
|
63
|
+
is_new_group: true
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
expect(destination.actions.group.perform).toHaveBeenCalledWith(
|
|
69
|
+
expect.anything(),
|
|
70
|
+
expect.objectContaining({
|
|
71
|
+
payload: {
|
|
72
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
73
|
+
anonymousId: 'anonId1',
|
|
74
|
+
userId: undefined,
|
|
75
|
+
groupId: 'groupId1',
|
|
76
|
+
traits: {
|
|
77
|
+
is_new_group: true
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
expect(window.Ripe.group).toHaveBeenCalledWith({
|
|
84
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
85
|
+
anonymousId: 'anonId1',
|
|
86
|
+
userId: undefined,
|
|
87
|
+
groupId: 'groupId1',
|
|
88
|
+
traits: expect.objectContaining({ is_new_group: true })
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Payload {
|
|
4
|
+
/**
|
|
5
|
+
* The anonymous id
|
|
6
|
+
*/
|
|
7
|
+
anonymousId: string
|
|
8
|
+
/**
|
|
9
|
+
* The ID associated with the user
|
|
10
|
+
*/
|
|
11
|
+
userId?: string | null
|
|
12
|
+
/**
|
|
13
|
+
* The ID associated groupId
|
|
14
|
+
*/
|
|
15
|
+
groupId: string | null
|
|
16
|
+
/**
|
|
17
|
+
* Traits to associate with the group
|
|
18
|
+
*/
|
|
19
|
+
traits?: {
|
|
20
|
+
[k: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The Segment messageId
|
|
24
|
+
*/
|
|
25
|
+
messageId?: string
|
|
26
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
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 { RipeSDK } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, RipeSDK, Payload> = {
|
|
7
|
+
title: 'Group',
|
|
8
|
+
description: 'Group user in Ripe',
|
|
9
|
+
defaultSubscription: 'type = "group"',
|
|
10
|
+
platform: 'web',
|
|
11
|
+
fields: {
|
|
12
|
+
anonymousId: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
required: true,
|
|
15
|
+
description: 'The anonymous id',
|
|
16
|
+
label: 'Anonymous ID',
|
|
17
|
+
default: { '@path': '$.anonymousId' }
|
|
18
|
+
},
|
|
19
|
+
userId: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
required: false,
|
|
22
|
+
allowNull: true,
|
|
23
|
+
description: 'The ID associated with the user',
|
|
24
|
+
label: 'User ID',
|
|
25
|
+
default: { '@path': '$.userId' }
|
|
26
|
+
},
|
|
27
|
+
groupId: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
required: true,
|
|
30
|
+
allowNull: true,
|
|
31
|
+
description: 'The ID associated groupId',
|
|
32
|
+
label: 'Group ID',
|
|
33
|
+
default: { '@path': '$.groupId' }
|
|
34
|
+
},
|
|
35
|
+
traits: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
label: 'Traits',
|
|
38
|
+
description: 'Traits to associate with the group',
|
|
39
|
+
required: false,
|
|
40
|
+
default: { '@path': '$.traits' }
|
|
41
|
+
},
|
|
42
|
+
messageId: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
required: false,
|
|
45
|
+
description: 'The Segment messageId',
|
|
46
|
+
label: 'MessageId',
|
|
47
|
+
default: { '@path': '$.messageId' }
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
perform: async (ripe, { payload }) => {
|
|
51
|
+
return ripe.group({
|
|
52
|
+
messageId: payload.messageId,
|
|
53
|
+
anonymousId: payload.anonymousId,
|
|
54
|
+
userId: payload.userId,
|
|
55
|
+
groupId: payload.groupId,
|
|
56
|
+
traits: payload.traits
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default action
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Subscription } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
3
|
+
import RipeDestination, { destination } from '../../index'
|
|
4
|
+
import { RipeSDK } from '../../types'
|
|
5
|
+
|
|
6
|
+
import { loadScript } from '@segment/browser-destination-runtime/load-script'
|
|
7
|
+
|
|
8
|
+
jest.mock('@segment/browser-destination-runtime/load-script')
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
;(loadScript as jest.Mock).mockResolvedValue(true)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const subscriptions: Subscription[] = [
|
|
14
|
+
{
|
|
15
|
+
partnerAction: 'identify',
|
|
16
|
+
name: 'Identify user',
|
|
17
|
+
enabled: true,
|
|
18
|
+
subscribe: 'type = "identify"',
|
|
19
|
+
mapping: {
|
|
20
|
+
messageId: {
|
|
21
|
+
'@path': '$.messageId'
|
|
22
|
+
},
|
|
23
|
+
anonymousId: {
|
|
24
|
+
'@path': '$.anonymousId'
|
|
25
|
+
},
|
|
26
|
+
userId: {
|
|
27
|
+
'@path': '$.userId'
|
|
28
|
+
},
|
|
29
|
+
groupId: {
|
|
30
|
+
'@path': '$.groupId'
|
|
31
|
+
},
|
|
32
|
+
traits: {
|
|
33
|
+
'@path': '$.traits'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
describe('Ripe.identify', () => {
|
|
40
|
+
test('it maps userId and traits and passes them into RipeSDK.identify', async () => {
|
|
41
|
+
window.Ripe = {
|
|
42
|
+
init: jest.fn().mockResolvedValueOnce('123'),
|
|
43
|
+
identify: jest.fn().mockResolvedValueOnce(undefined),
|
|
44
|
+
setIds: jest.fn().mockResolvedValueOnce(undefined)
|
|
45
|
+
} as unknown as RipeSDK
|
|
46
|
+
|
|
47
|
+
const [event] = await RipeDestination({
|
|
48
|
+
subscriptions,
|
|
49
|
+
apiKey: '123'
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const ajs = new Analytics({ writeKey: '123' })
|
|
53
|
+
await event.load(Context.system(), ajs)
|
|
54
|
+
jest.spyOn(destination.actions.identify, 'perform')
|
|
55
|
+
|
|
56
|
+
await event.identify?.(
|
|
57
|
+
new Context({
|
|
58
|
+
type: 'identify',
|
|
59
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
60
|
+
anonymousId: 'anonymousId',
|
|
61
|
+
userId: 'userId',
|
|
62
|
+
traits: {
|
|
63
|
+
name: 'Simon'
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
expect(destination.actions.identify.perform).toHaveBeenCalledWith(
|
|
69
|
+
expect.anything(),
|
|
70
|
+
expect.objectContaining({
|
|
71
|
+
payload: {
|
|
72
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
73
|
+
anonymousId: 'anonymousId',
|
|
74
|
+
userId: 'userId',
|
|
75
|
+
groupId: undefined,
|
|
76
|
+
traits: {
|
|
77
|
+
name: 'Simon'
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
expect(window.Ripe.identify).toHaveBeenCalledWith({
|
|
84
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
85
|
+
userId: expect.stringMatching('userId'),
|
|
86
|
+
anonymousId: 'anonymousId',
|
|
87
|
+
groupId: undefined,
|
|
88
|
+
traits: expect.objectContaining({ name: 'Simon' })
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Payload {
|
|
4
|
+
/**
|
|
5
|
+
* The anonymous id
|
|
6
|
+
*/
|
|
7
|
+
anonymousId: string
|
|
8
|
+
/**
|
|
9
|
+
* The ID associated with the user
|
|
10
|
+
*/
|
|
11
|
+
userId?: string | null
|
|
12
|
+
/**
|
|
13
|
+
* The ID associated groupId
|
|
14
|
+
*/
|
|
15
|
+
groupId?: string | null
|
|
16
|
+
/**
|
|
17
|
+
* Traits to associate with the user
|
|
18
|
+
*/
|
|
19
|
+
traits?: {
|
|
20
|
+
[k: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The Segment messageId
|
|
24
|
+
*/
|
|
25
|
+
messageId?: string
|
|
26
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
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 { RipeSDK } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, RipeSDK, Payload> = {
|
|
7
|
+
title: 'Identify',
|
|
8
|
+
description: 'Identify user in Ripe',
|
|
9
|
+
defaultSubscription: 'type = "identify"',
|
|
10
|
+
platform: 'web',
|
|
11
|
+
fields: {
|
|
12
|
+
anonymousId: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
required: true,
|
|
15
|
+
description: 'The anonymous id',
|
|
16
|
+
label: 'Anonymous ID',
|
|
17
|
+
default: { '@path': '$.anonymousId' }
|
|
18
|
+
},
|
|
19
|
+
userId: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
required: false,
|
|
22
|
+
allowNull: true,
|
|
23
|
+
description: 'The ID associated with the user',
|
|
24
|
+
label: 'User ID',
|
|
25
|
+
default: { '@path': '$.userId' }
|
|
26
|
+
},
|
|
27
|
+
groupId: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
required: false,
|
|
30
|
+
allowNull: true,
|
|
31
|
+
description: 'The ID associated groupId',
|
|
32
|
+
label: 'Group ID',
|
|
33
|
+
default: { '@path': '$.context.groupId' }
|
|
34
|
+
},
|
|
35
|
+
traits: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
label: 'Traits',
|
|
38
|
+
description: 'Traits to associate with the user',
|
|
39
|
+
required: false,
|
|
40
|
+
default: { '@path': '$.traits' }
|
|
41
|
+
},
|
|
42
|
+
messageId: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
required: false,
|
|
45
|
+
description: 'The Segment messageId',
|
|
46
|
+
label: 'MessageId',
|
|
47
|
+
default: { '@path': '$.messageId' }
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
perform: async (ripe, { payload }) => {
|
|
51
|
+
return ripe.identify({
|
|
52
|
+
messageId: payload.messageId,
|
|
53
|
+
anonymousId: payload.anonymousId,
|
|
54
|
+
userId: payload.userId,
|
|
55
|
+
groupId: payload.groupId,
|
|
56
|
+
traits: payload.traits
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default action
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
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 { RipeSDK } from './types'
|
|
5
|
+
|
|
6
|
+
import group from './group'
|
|
7
|
+
import identify from './identify'
|
|
8
|
+
import track from './track'
|
|
9
|
+
|
|
10
|
+
import { defaultValues } from '@segment/actions-core'
|
|
11
|
+
import { initScript } from './init-script'
|
|
12
|
+
|
|
13
|
+
import page from './page'
|
|
14
|
+
|
|
15
|
+
const defaultVersion = 'latest'
|
|
16
|
+
|
|
17
|
+
declare global {
|
|
18
|
+
interface Window {
|
|
19
|
+
Ripe: RipeSDK
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const destination: BrowserDestinationDefinition<Settings, RipeSDK> = {
|
|
24
|
+
name: 'Ripe Device Mode (Actions)',
|
|
25
|
+
slug: 'actions-ripe',
|
|
26
|
+
mode: 'device',
|
|
27
|
+
|
|
28
|
+
settings: {
|
|
29
|
+
sdkVersion: {
|
|
30
|
+
description: 'The version of the Ripe Widget SDK to use',
|
|
31
|
+
label: 'SDK Version',
|
|
32
|
+
type: 'string',
|
|
33
|
+
choices: [
|
|
34
|
+
{
|
|
35
|
+
value: 'latest',
|
|
36
|
+
label: 'latest'
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
default: defaultVersion,
|
|
40
|
+
required: false
|
|
41
|
+
},
|
|
42
|
+
apiKey: {
|
|
43
|
+
description: 'The Ripe API key found in the Ripe App',
|
|
44
|
+
label: 'API Key',
|
|
45
|
+
type: 'string',
|
|
46
|
+
required: true
|
|
47
|
+
},
|
|
48
|
+
endpoint: {
|
|
49
|
+
label: 'API Endpoint',
|
|
50
|
+
description: `The Ripe API endpoint (do not change this unless you know what you're doing)`,
|
|
51
|
+
type: 'string',
|
|
52
|
+
format: 'uri',
|
|
53
|
+
default: 'https://storage.getripe.com'
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
initialize: async ({ settings }, deps) => {
|
|
58
|
+
initScript()
|
|
59
|
+
|
|
60
|
+
const { sdkVersion, apiKey } = settings
|
|
61
|
+
const version = sdkVersion ?? defaultVersion
|
|
62
|
+
const endpoint = settings.endpoint || 'https://storage.getripe.com'
|
|
63
|
+
|
|
64
|
+
await deps
|
|
65
|
+
.loadScript(`${endpoint}/sdk/${version}/sdk.umd.js`)
|
|
66
|
+
.catch((err) => console.error('Unable to load Ripe SDK script', err))
|
|
67
|
+
|
|
68
|
+
await deps.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, 'Ripe'), 100)
|
|
69
|
+
await window.Ripe.init(apiKey)
|
|
70
|
+
|
|
71
|
+
return window.Ripe
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
actions: {
|
|
75
|
+
group,
|
|
76
|
+
identify,
|
|
77
|
+
page,
|
|
78
|
+
track
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
presets: [
|
|
82
|
+
{
|
|
83
|
+
name: 'Group user',
|
|
84
|
+
subscribe: 'type = "group"',
|
|
85
|
+
partnerAction: 'group',
|
|
86
|
+
mapping: defaultValues(group.fields)
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'Identify user',
|
|
90
|
+
subscribe: 'type = "identify"',
|
|
91
|
+
partnerAction: 'identify',
|
|
92
|
+
mapping: defaultValues(identify.fields)
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'Page view',
|
|
96
|
+
subscribe: 'type = "page"',
|
|
97
|
+
partnerAction: 'page',
|
|
98
|
+
mapping: defaultValues(page.fields)
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Track event',
|
|
102
|
+
subscribe: 'type = "track"',
|
|
103
|
+
partnerAction: 'track',
|
|
104
|
+
mapping: defaultValues(track.fields)
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default browserDestination(destination)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
export function initScript() {
|
|
4
|
+
if (window.Ripe) {
|
|
5
|
+
return
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
window.Ripe = []
|
|
9
|
+
;['group', 'identify', 'init', 'page', 'track'].forEach(function (method) {
|
|
10
|
+
window.Ripe[method] = function () {
|
|
11
|
+
let args = Array.from(arguments)
|
|
12
|
+
args.unshift(method)
|
|
13
|
+
window.Ripe.push(args)
|
|
14
|
+
return window.Ripe
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Subscription } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
3
|
+
import RipeDestination, { destination } from '../../index'
|
|
4
|
+
import { RipeSDK } from '../../types'
|
|
5
|
+
|
|
6
|
+
import { loadScript } from '@segment/browser-destination-runtime/load-script'
|
|
7
|
+
|
|
8
|
+
jest.mock('@segment/browser-destination-runtime/load-script')
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
;(loadScript as jest.Mock).mockResolvedValue(true)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const subscriptions: Subscription[] = [
|
|
14
|
+
{
|
|
15
|
+
partnerAction: 'page',
|
|
16
|
+
name: 'Page view',
|
|
17
|
+
enabled: true,
|
|
18
|
+
subscribe: 'type = "page"',
|
|
19
|
+
mapping: {
|
|
20
|
+
messageId: {
|
|
21
|
+
'@path': '$.messageId'
|
|
22
|
+
},
|
|
23
|
+
anonymousId: {
|
|
24
|
+
'@path': '$.anonymousId'
|
|
25
|
+
},
|
|
26
|
+
userId: {
|
|
27
|
+
'@path': '$.userId'
|
|
28
|
+
},
|
|
29
|
+
groupId: {
|
|
30
|
+
'@path': '$.groupId'
|
|
31
|
+
},
|
|
32
|
+
category: {
|
|
33
|
+
'@path': '$.category'
|
|
34
|
+
},
|
|
35
|
+
name: {
|
|
36
|
+
'@path': '$.name'
|
|
37
|
+
},
|
|
38
|
+
properties: {
|
|
39
|
+
'@path': '$.properties'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
describe('Ripe.page', () => {
|
|
46
|
+
test('it maps pageview properties and passes them into RipeSDK.page', async () => {
|
|
47
|
+
window.Ripe = {
|
|
48
|
+
init: jest.fn().mockResolvedValueOnce('123'),
|
|
49
|
+
page: jest.fn().mockResolvedValueOnce(undefined),
|
|
50
|
+
setIds: jest.fn().mockResolvedValueOnce(undefined)
|
|
51
|
+
} as unknown as RipeSDK
|
|
52
|
+
|
|
53
|
+
const [event] = await RipeDestination({
|
|
54
|
+
subscriptions,
|
|
55
|
+
apiKey: '123'
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const ajs = new Analytics({ writeKey: '123' })
|
|
59
|
+
await event.load(Context.system(), ajs)
|
|
60
|
+
jest.spyOn(destination.actions.page, 'perform')
|
|
61
|
+
|
|
62
|
+
await event.page?.(
|
|
63
|
+
new Context({
|
|
64
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
65
|
+
anonymousId: 'anonymousId',
|
|
66
|
+
type: 'page',
|
|
67
|
+
category: 'main',
|
|
68
|
+
name: 'page2',
|
|
69
|
+
properties: {
|
|
70
|
+
previous: 'page1'
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
expect(destination.actions.page.perform).toHaveBeenCalledWith(
|
|
76
|
+
expect.anything(),
|
|
77
|
+
expect.objectContaining({
|
|
78
|
+
payload: {
|
|
79
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
80
|
+
anonymousId: 'anonymousId',
|
|
81
|
+
userId: undefined,
|
|
82
|
+
groupId: undefined,
|
|
83
|
+
category: 'main',
|
|
84
|
+
name: 'page2',
|
|
85
|
+
properties: {
|
|
86
|
+
previous: 'page1'
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
expect(window.Ripe.page).toHaveBeenCalledWith({
|
|
93
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
94
|
+
userId: undefined,
|
|
95
|
+
groupId: undefined,
|
|
96
|
+
anonymousId: 'anonymousId',
|
|
97
|
+
category: 'main',
|
|
98
|
+
name: 'page2',
|
|
99
|
+
properties: expect.objectContaining({ previous: 'page1' })
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Payload {
|
|
4
|
+
/**
|
|
5
|
+
* The anonymous id
|
|
6
|
+
*/
|
|
7
|
+
anonymousId: string
|
|
8
|
+
/**
|
|
9
|
+
* The ID associated with the user
|
|
10
|
+
*/
|
|
11
|
+
userId?: string | null
|
|
12
|
+
/**
|
|
13
|
+
* The ID associated groupId
|
|
14
|
+
*/
|
|
15
|
+
groupId?: string | null
|
|
16
|
+
/**
|
|
17
|
+
* The category of the page
|
|
18
|
+
*/
|
|
19
|
+
category?: string
|
|
20
|
+
/**
|
|
21
|
+
* The name of the page
|
|
22
|
+
*/
|
|
23
|
+
name?: string
|
|
24
|
+
/**
|
|
25
|
+
* Page properties
|
|
26
|
+
*/
|
|
27
|
+
properties?: {
|
|
28
|
+
[k: string]: unknown
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The Segment messageId
|
|
32
|
+
*/
|
|
33
|
+
messageId?: string
|
|
34
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
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 { RipeSDK } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, RipeSDK, Payload> = {
|
|
7
|
+
title: 'Page',
|
|
8
|
+
description: 'Register page view in Ripe',
|
|
9
|
+
defaultSubscription: 'type = "page"',
|
|
10
|
+
platform: 'web',
|
|
11
|
+
fields: {
|
|
12
|
+
anonymousId: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
required: true,
|
|
15
|
+
description: 'The anonymous id',
|
|
16
|
+
label: 'Anonymous ID',
|
|
17
|
+
default: { '@path': '$.anonymousId' }
|
|
18
|
+
},
|
|
19
|
+
userId: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
required: false,
|
|
22
|
+
allowNull: true,
|
|
23
|
+
description: 'The ID associated with the user',
|
|
24
|
+
label: 'User ID',
|
|
25
|
+
default: { '@path': '$.userId' }
|
|
26
|
+
},
|
|
27
|
+
groupId: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
required: false,
|
|
30
|
+
allowNull: true,
|
|
31
|
+
description: 'The ID associated groupId',
|
|
32
|
+
label: 'Group ID',
|
|
33
|
+
default: { '@path': '$.context.groupId' }
|
|
34
|
+
},
|
|
35
|
+
category: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
required: false,
|
|
38
|
+
description: 'The category of the page',
|
|
39
|
+
label: 'Category',
|
|
40
|
+
default: {
|
|
41
|
+
'@if': {
|
|
42
|
+
exists: { '@path': '$.category' },
|
|
43
|
+
then: { '@path': '$.category' },
|
|
44
|
+
else: { '@path': '$.context.category' }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
name: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
required: false,
|
|
51
|
+
description: 'The name of the page',
|
|
52
|
+
label: 'Name',
|
|
53
|
+
default: {
|
|
54
|
+
'@if': {
|
|
55
|
+
exists: { '@path': '$.name' },
|
|
56
|
+
then: { '@path': '$.name' },
|
|
57
|
+
else: { '@path': '$.context.name' }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
properties: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
required: false,
|
|
64
|
+
description: 'Page properties',
|
|
65
|
+
label: 'Properties',
|
|
66
|
+
default: { '@path': '$.properties' }
|
|
67
|
+
},
|
|
68
|
+
messageId: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
required: false,
|
|
71
|
+
description: 'The Segment messageId',
|
|
72
|
+
label: 'MessageId',
|
|
73
|
+
default: { '@path': '$.messageId' }
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
perform: async (ripe, { payload }) => {
|
|
77
|
+
return ripe.page({
|
|
78
|
+
messageId: payload.messageId,
|
|
79
|
+
anonymousId: payload.anonymousId,
|
|
80
|
+
userId: payload.userId,
|
|
81
|
+
groupId: payload.groupId,
|
|
82
|
+
category: payload.category,
|
|
83
|
+
name: payload.name,
|
|
84
|
+
properties: payload.properties
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export default action
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Subscription } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
3
|
+
import RipeDestination, { destination } from '../../index'
|
|
4
|
+
import { RipeSDK } from '../../types'
|
|
5
|
+
|
|
6
|
+
import { loadScript } from '@segment/browser-destination-runtime/load-script'
|
|
7
|
+
|
|
8
|
+
jest.mock('@segment/browser-destination-runtime/load-script')
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
;(loadScript as jest.Mock).mockResolvedValue(true)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const subscriptions: Subscription[] = [
|
|
14
|
+
{
|
|
15
|
+
partnerAction: 'track',
|
|
16
|
+
name: 'Track user',
|
|
17
|
+
enabled: true,
|
|
18
|
+
subscribe: 'type = "track"',
|
|
19
|
+
mapping: {
|
|
20
|
+
messageId: {
|
|
21
|
+
'@path': '$.messageId'
|
|
22
|
+
},
|
|
23
|
+
anonymousId: {
|
|
24
|
+
'@path': '$.anonymousId'
|
|
25
|
+
},
|
|
26
|
+
userId: {
|
|
27
|
+
'@path': '$.userId'
|
|
28
|
+
},
|
|
29
|
+
groupId: {
|
|
30
|
+
'@path': '$.groupId'
|
|
31
|
+
},
|
|
32
|
+
event: {
|
|
33
|
+
'@path': '$.event'
|
|
34
|
+
},
|
|
35
|
+
properties: {
|
|
36
|
+
'@path': '$.properties'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
describe('Ripe.track', () => {
|
|
43
|
+
test('it maps the event name and properties and passes them into RipeSDK.track', async () => {
|
|
44
|
+
window.Ripe = {
|
|
45
|
+
init: jest.fn().mockResolvedValueOnce('123'),
|
|
46
|
+
setIds: jest.fn().mockResolvedValueOnce(undefined),
|
|
47
|
+
track: jest.fn().mockResolvedValueOnce(undefined)
|
|
48
|
+
} as unknown as RipeSDK
|
|
49
|
+
|
|
50
|
+
const [event] = await RipeDestination({
|
|
51
|
+
subscriptions,
|
|
52
|
+
apiKey: '123'
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const ajs = new Analytics({ writeKey: '123' })
|
|
56
|
+
await event.load(Context.system(), ajs)
|
|
57
|
+
jest.spyOn(destination.actions.track, 'perform')
|
|
58
|
+
|
|
59
|
+
await event.track?.(
|
|
60
|
+
new Context({
|
|
61
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
62
|
+
type: 'track',
|
|
63
|
+
anonymousId: 'anonymousId',
|
|
64
|
+
event: 'Form Submitted',
|
|
65
|
+
properties: {
|
|
66
|
+
is_new_lead: true
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
expect(destination.actions.track.perform).toHaveBeenCalledWith(
|
|
72
|
+
expect.anything(),
|
|
73
|
+
expect.objectContaining({
|
|
74
|
+
payload: {
|
|
75
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
76
|
+
anonymousId: 'anonymousId',
|
|
77
|
+
userId: undefined,
|
|
78
|
+
groupId: undefined,
|
|
79
|
+
event: 'Form Submitted',
|
|
80
|
+
properties: {
|
|
81
|
+
is_new_lead: true
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
expect(window.Ripe.track).toHaveBeenCalledWith({
|
|
88
|
+
messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
|
|
89
|
+
anonymousId: 'anonymousId',
|
|
90
|
+
userId: undefined,
|
|
91
|
+
groupId: undefined,
|
|
92
|
+
event: 'Form Submitted',
|
|
93
|
+
properties: expect.objectContaining({ is_new_lead: true })
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Payload {
|
|
4
|
+
/**
|
|
5
|
+
* The anonymous id
|
|
6
|
+
*/
|
|
7
|
+
anonymousId: string
|
|
8
|
+
/**
|
|
9
|
+
* The ID associated with the user
|
|
10
|
+
*/
|
|
11
|
+
userId?: string | null
|
|
12
|
+
/**
|
|
13
|
+
* The ID associated groupId
|
|
14
|
+
*/
|
|
15
|
+
groupId?: string | null
|
|
16
|
+
/**
|
|
17
|
+
* The event name
|
|
18
|
+
*/
|
|
19
|
+
event: string
|
|
20
|
+
/**
|
|
21
|
+
* Properties to send with the event
|
|
22
|
+
*/
|
|
23
|
+
properties?: {
|
|
24
|
+
[k: string]: unknown
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The Segment messageId
|
|
28
|
+
*/
|
|
29
|
+
messageId?: string
|
|
30
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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 { RipeSDK } from '../types'
|
|
5
|
+
|
|
6
|
+
const action: BrowserActionDefinition<Settings, RipeSDK, Payload> = {
|
|
7
|
+
title: 'Track',
|
|
8
|
+
description: 'Send user events to Ripe',
|
|
9
|
+
defaultSubscription: 'type = "track"',
|
|
10
|
+
platform: 'web',
|
|
11
|
+
fields: {
|
|
12
|
+
anonymousId: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
required: true,
|
|
15
|
+
description: 'The anonymous id',
|
|
16
|
+
label: 'Anonymous ID',
|
|
17
|
+
default: { '@path': '$.anonymousId' }
|
|
18
|
+
},
|
|
19
|
+
userId: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
required: false,
|
|
22
|
+
allowNull: true,
|
|
23
|
+
description: 'The ID associated with the user',
|
|
24
|
+
label: 'User ID',
|
|
25
|
+
default: { '@path': '$.userId' }
|
|
26
|
+
},
|
|
27
|
+
groupId: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
required: false,
|
|
30
|
+
allowNull: true,
|
|
31
|
+
description: 'The ID associated groupId',
|
|
32
|
+
label: 'Group ID',
|
|
33
|
+
default: { '@path': '$.context.groupId' }
|
|
34
|
+
},
|
|
35
|
+
event: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
required: true,
|
|
38
|
+
description: 'The event name',
|
|
39
|
+
label: 'Event Name',
|
|
40
|
+
default: { '@path': '$.event' }
|
|
41
|
+
},
|
|
42
|
+
properties: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
required: false,
|
|
45
|
+
description: 'Properties to send with the event',
|
|
46
|
+
label: 'Event properties',
|
|
47
|
+
default: { '@path': '$.properties' }
|
|
48
|
+
},
|
|
49
|
+
messageId: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
required: false,
|
|
52
|
+
description: 'The Segment messageId',
|
|
53
|
+
label: 'MessageId',
|
|
54
|
+
default: { '@path': '$.messageId' }
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
perform: async (ripe, { payload }) => {
|
|
58
|
+
if (payload?.event) {
|
|
59
|
+
return ripe.track({
|
|
60
|
+
messageId: payload.messageId,
|
|
61
|
+
anonymousId: payload.anonymousId,
|
|
62
|
+
userId: payload.userId,
|
|
63
|
+
groupId: payload.groupId,
|
|
64
|
+
event: payload.event,
|
|
65
|
+
properties: payload.properties
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default action
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export interface RipeSDK {
|
|
2
|
+
group: ({
|
|
3
|
+
anonymousId,
|
|
4
|
+
userId,
|
|
5
|
+
messageId,
|
|
6
|
+
groupId,
|
|
7
|
+
traits
|
|
8
|
+
}: {
|
|
9
|
+
messageId?: string
|
|
10
|
+
anonymousId: string
|
|
11
|
+
userId?: string | null
|
|
12
|
+
groupId: string | null
|
|
13
|
+
traits?: Record<string, unknown>
|
|
14
|
+
}) => Promise<void>
|
|
15
|
+
identify: ({
|
|
16
|
+
messageId,
|
|
17
|
+
anonymousId,
|
|
18
|
+
userId,
|
|
19
|
+
groupId,
|
|
20
|
+
traits
|
|
21
|
+
}: {
|
|
22
|
+
messageId?: string
|
|
23
|
+
anonymousId: string
|
|
24
|
+
userId?: string | null
|
|
25
|
+
groupId?: string | null
|
|
26
|
+
traits?: Record<string, unknown>
|
|
27
|
+
}) => Promise<void>
|
|
28
|
+
init: (apiKey: string) => Promise<void>
|
|
29
|
+
page: ({
|
|
30
|
+
messageId,
|
|
31
|
+
anonymousId,
|
|
32
|
+
userId,
|
|
33
|
+
groupId,
|
|
34
|
+
category,
|
|
35
|
+
name,
|
|
36
|
+
properties
|
|
37
|
+
}: {
|
|
38
|
+
messageId?: string
|
|
39
|
+
anonymousId: string
|
|
40
|
+
userId?: string | null
|
|
41
|
+
groupId?: string | null
|
|
42
|
+
category?: string
|
|
43
|
+
name?: string
|
|
44
|
+
properties?: Record<string, unknown>
|
|
45
|
+
}) => Promise<void>
|
|
46
|
+
track: ({
|
|
47
|
+
messageId,
|
|
48
|
+
anonymousId,
|
|
49
|
+
userId,
|
|
50
|
+
groupId,
|
|
51
|
+
event,
|
|
52
|
+
properties
|
|
53
|
+
}: {
|
|
54
|
+
messageId?: string
|
|
55
|
+
anonymousId: string
|
|
56
|
+
userId?: string | null
|
|
57
|
+
groupId?: string | null
|
|
58
|
+
event: string
|
|
59
|
+
properties?: Record<string, unknown>
|
|
60
|
+
}) => Promise<void>
|
|
61
|
+
}
|