@segment/analytics-browser-actions-userpilot 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 ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@segment/analytics-browser-actions-userpilot",
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,132 @@
1
+ import { Analytics, Context } from '@segment/analytics-next'
2
+ import { Subscription } from '@segment/browser-destination-runtime/types'
3
+ import userpilot, { destination } from '../index'
4
+
5
+ const example: Subscription[] = [
6
+ {
7
+ partnerAction: 'identifyUser',
8
+ name: 'Identify User',
9
+ enabled: true,
10
+ subscribe: 'type = "identify"',
11
+ mapping: {
12
+ userId: {
13
+ '@path': '$.userId'
14
+ },
15
+ anonymousId: {
16
+ '@path': '$.anonymousId'
17
+ },
18
+ traits: {
19
+ '@path': '$.traits'
20
+ }
21
+ }
22
+ },
23
+ {
24
+ partnerAction: 'trackEvent',
25
+ name: 'Track Event',
26
+ enabled: true,
27
+ subscribe: 'type = "track"',
28
+ mapping: {
29
+ name: {
30
+ '@path': '$.name'
31
+ },
32
+ properties: {
33
+ '@path': '$.properties'
34
+ }
35
+ }
36
+ },
37
+ {
38
+ partnerAction: 'pageView',
39
+ name: 'Page View',
40
+ enabled: true,
41
+ subscribe: 'type = "page"',
42
+ mapping: {
43
+ name: {
44
+ '@path': '$.name'
45
+ },
46
+ properties: {
47
+ '@path': '$.properties'
48
+ }
49
+ }
50
+ }
51
+ ]
52
+
53
+ describe('Userpilot', () => {
54
+ it('should load the Userpilot script', async () => {
55
+ const [event] = await userpilot({
56
+ token: 'NX-917089a3',
57
+ subscriptions: example
58
+ })
59
+ jest.spyOn(destination, 'initialize')
60
+
61
+ await event.load(Context.system(), {} as Analytics)
62
+ expect(window.userpilot).toBeDefined()
63
+ })
64
+ })
65
+
66
+ describe('IdentifyUser', () => {
67
+ it('should call identify if user id is provided', async () => {
68
+ const [identifyUser] = await userpilot({
69
+ token: 'NX-917089a3',
70
+ subscriptions: example
71
+ })
72
+ await identifyUser.load(Context.system(), {} as Analytics)
73
+ const up = jest.spyOn(window.userpilot, 'identify')
74
+
75
+ await identifyUser.identify?.(
76
+ new Context({
77
+ type: 'identify',
78
+ userId: 'test',
79
+ traits: {
80
+ example: 'test prop'
81
+ }
82
+ })
83
+ )
84
+ expect(up).toHaveBeenCalledWith('test', { example: 'test prop' })
85
+ })
86
+ })
87
+
88
+ describe('TrackEvent', () => {
89
+ it('should call track if event name is provided', async () => {
90
+ const [_identifyUser, trackEvent] = await userpilot({
91
+ token: 'NX-917089a3',
92
+ subscriptions: example
93
+ })
94
+
95
+ await trackEvent.load(Context.system(), {} as Analytics)
96
+ const up = jest.spyOn(window.userpilot, 'track')
97
+
98
+ await trackEvent.track?.(
99
+ new Context({
100
+ type: 'track',
101
+ name: 'test',
102
+ properties: {
103
+ example: 'test prop'
104
+ }
105
+ })
106
+ )
107
+ expect(up).toHaveBeenCalledWith('test', { example: 'test prop' })
108
+ })
109
+ })
110
+
111
+ describe('PageView', () => {
112
+ it('should call Userpilot reload', async () => {
113
+ const [_identifyUser, _trackEvent, pageView] = await userpilot({
114
+ token: 'NX-917089a3',
115
+ subscriptions: example
116
+ })
117
+ await pageView.load(Context.system(), {} as Analytics)
118
+
119
+ const up = jest.spyOn(window.userpilot, 'reload')
120
+
121
+ await pageView.page?.(
122
+ new Context({
123
+ type: 'page',
124
+ name: 'test',
125
+ properties: {
126
+ example: 'test prop'
127
+ }
128
+ })
129
+ )
130
+ expect(up).toHaveBeenCalledWith('test', { example: 'test prop' })
131
+ })
132
+ })
@@ -0,0 +1,16 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Settings {
4
+ /**
5
+ * Your Userpilot app token, you can find it in the [Userpilot installation](https://run.userpilot.io/installation) dashboard.
6
+ */
7
+ token: string
8
+ /**
9
+ * By default, Userpilot would use a service discovery mechanism to determine the API endpoint to connect to. If you are using a proxy or a firewall, you can specify the API endpoint here.
10
+ */
11
+ endpoint?: string
12
+ /**
13
+ * By default, Segment will load the Userpilot JS snippet onto the page. If you are already loading the Userpilot JS onto the page then disable this setting and Segment will detect the Userpilot JS on the page
14
+ */
15
+ shouldSegmentLoadSDK: boolean
16
+ }
@@ -0,0 +1,14 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Payload {
4
+ /**
5
+ * The ID of the company.
6
+ */
7
+ groupId: string
8
+ /**
9
+ * Company traits
10
+ */
11
+ traits?: {
12
+ [k: string]: unknown
13
+ }
14
+ }
@@ -0,0 +1,36 @@
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 { Userpilot } from '../types'
5
+ // Change from unknown to the partner SDK types
6
+ const action: BrowserActionDefinition<Settings, Userpilot, Payload> = {
7
+ title: 'Identify Company',
8
+ description: 'Create or update a company entity in Userpilot',
9
+ platform: 'web',
10
+ defaultSubscription: 'type = "group"',
11
+ fields: {
12
+ groupId: {
13
+ type: 'string',
14
+ required: true,
15
+ description: 'The ID of the company.',
16
+ label: 'Company ID',
17
+ default: {
18
+ '@path': '$.groupId'
19
+ }
20
+ },
21
+ traits: {
22
+ type: 'object',
23
+ required: false,
24
+ description: 'Company traits',
25
+ label: 'Traits',
26
+ default: {
27
+ '@path': '$.traits'
28
+ }
29
+ }
30
+ },
31
+ perform: (_, events) => {
32
+ window.userpilot.group(events.payload.groupId ?? '', events.payload.traits ?? {})
33
+ }
34
+ }
35
+
36
+ export default action
@@ -0,0 +1,18 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Payload {
4
+ /**
5
+ * The ID of the logged-in user.
6
+ */
7
+ userId: string
8
+ /**
9
+ * The date the user profile was created at
10
+ */
11
+ createdAt?: string | number
12
+ /**
13
+ * User traits.
14
+ */
15
+ traits?: {
16
+ [k: string]: unknown
17
+ }
18
+ }
@@ -0,0 +1,54 @@
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 { Userpilot } from '../types'
5
+
6
+ const action: BrowserActionDefinition<Settings, Userpilot, Payload> = {
7
+ title: 'Identify User',
8
+ description:
9
+ "Create or update a user entity in Userpilot. It's mandatory to identify a user by calling identify() prior to invoking other methods such as track(), page(), or group(). You can learn more by visiting the [Userpilot documentation](https://docs.userpilot.com/article/23-identify-users-track-custom-events).",
10
+ platform: 'web',
11
+ defaultSubscription: 'type = "identify"',
12
+ fields: {
13
+ userId: {
14
+ type: 'string',
15
+ required: true,
16
+ description: 'The ID of the logged-in user.',
17
+ label: 'User ID',
18
+ default: {
19
+ '@if': {
20
+ exists: { '@path': '$.userId' },
21
+ then: { '@path': '$.userId' },
22
+ else: { '@path': '$.anonymousId' }
23
+ }
24
+ }
25
+ },
26
+ createdAt: {
27
+ type: 'datetime',
28
+ required: false,
29
+ description: 'The date the user profile was created at',
30
+ label: 'User Created At Date',
31
+ default: {
32
+ '@path': '$.traits.createdAt'
33
+ }
34
+ },
35
+ traits: {
36
+ type: 'object',
37
+ required: false,
38
+ description: 'User traits.',
39
+ label: 'Traits',
40
+ default: {
41
+ '@path': '$.traits'
42
+ }
43
+ }
44
+ },
45
+ perform: (_, event) => {
46
+ const { userId, traits } = event.payload
47
+
48
+ traits?.createdAt && delete traits.createdAt
49
+
50
+ window.userpilot.identify(userId, { ...traits, created_at: event.payload.createdAt || traits?.created_at })
51
+ }
52
+ }
53
+
54
+ export default action
package/src/index.ts ADDED
@@ -0,0 +1,96 @@
1
+ import type { Settings } from './generated-types'
2
+ import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types'
3
+ import type { Userpilot } from './types'
4
+
5
+ import { browserDestination } from '@segment/browser-destination-runtime/shim'
6
+ import { defaultValues } from '@segment/actions-core'
7
+
8
+ import identifyUser from './identifyUser'
9
+ import trackEvent from './trackEvent'
10
+ import pageView from './pageView'
11
+
12
+ import identifyCompany from './identifyCompany'
13
+
14
+ declare global {
15
+ interface Window {
16
+ userpilot: Userpilot
17
+ userpilotSettings: Settings
18
+ }
19
+ }
20
+
21
+ // Switch from unknown to the partner SDK client types
22
+ export const destination: BrowserDestinationDefinition<Settings, Userpilot> = {
23
+ name: 'Userpilot Web (Actions)',
24
+ slug: 'actions-userpilot-web',
25
+ mode: 'device',
26
+ presets: [
27
+ {
28
+ name: 'Identify User',
29
+ subscribe: 'type = "identify"',
30
+ partnerAction: 'identifyUser',
31
+ mapping: defaultValues(identifyUser.fields)
32
+ },
33
+ {
34
+ name: 'Track Event',
35
+ subscribe: 'type = "track"',
36
+ partnerAction: 'trackEvent',
37
+ mapping: defaultValues(trackEvent.fields)
38
+ },
39
+ {
40
+ name: 'Page View',
41
+ subscribe: 'type = "page"',
42
+ partnerAction: 'pageView',
43
+ mapping: defaultValues(pageView.fields)
44
+ }
45
+ ],
46
+ settings: {
47
+ token: {
48
+ label: 'App Token',
49
+ description:
50
+ 'Your Userpilot app token, you can find it in the [Userpilot installation](https://run.userpilot.io/installation) dashboard.',
51
+ required: true,
52
+ type: 'string'
53
+ },
54
+ endpoint: {
55
+ label: 'The API endpoint the SDK would connect to',
56
+ description:
57
+ 'By default, Userpilot would use a service discovery mechanism to determine the API endpoint to connect to. If you are using a proxy or a firewall, you can specify the API endpoint here.',
58
+ required: false,
59
+ type: 'string'
60
+ },
61
+ shouldSegmentLoadSDK: {
62
+ label: 'Segment Loads Userpilot JS',
63
+ description:
64
+ 'By default, Segment will load the Userpilot JS snippet onto the page. If you are already loading the Userpilot JS onto the page then disable this setting and Segment will detect the Userpilot JS on the page',
65
+ required: true,
66
+ type: 'boolean',
67
+ default: true
68
+ }
69
+ },
70
+ initialize: async ({ settings }, deps) => {
71
+ const shouldLoadSDK = settings.shouldSegmentLoadSDK ?? true
72
+
73
+ if (shouldLoadSDK) {
74
+ window.userpilotSettings = {
75
+ token: settings.token,
76
+ endpoint: settings.endpoint,
77
+ shouldSegmentLoadSDK: shouldLoadSDK
78
+ }
79
+
80
+ await deps.loadScript('//js.userpilot.io/sdk/latest.js')
81
+ await deps.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, 'userpilot'), 100)
82
+ } else {
83
+ await deps.resolveWhen(() => window.userpilot !== undefined, 100)
84
+ }
85
+ return window.userpilot
86
+ },
87
+
88
+ actions: {
89
+ identifyUser,
90
+ trackEvent,
91
+ pageView,
92
+ identifyCompany
93
+ }
94
+ }
95
+
96
+ export default browserDestination(destination)
@@ -0,0 +1,14 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Payload {
4
+ /**
5
+ * The name of the page that was viewed.
6
+ */
7
+ name?: string
8
+ /**
9
+ * The properties of the page that was viewed.
10
+ */
11
+ properties?: {
12
+ [k: string]: unknown
13
+ }
14
+ }
@@ -0,0 +1,38 @@
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 { Userpilot } from '../types'
5
+
6
+ // Change from unknown to the partner SDK types
7
+ const action: BrowserActionDefinition<Settings, Userpilot, Payload> = {
8
+ title: 'Page View',
9
+ description:
10
+ "Update the content queue designed to trigger on a specific page. It's mandatory to identify a user by calling identify() prior to invoking other methods such as page()",
11
+ platform: 'web',
12
+ defaultSubscription: 'type = "page"',
13
+ fields: {
14
+ name: {
15
+ type: 'string',
16
+ required: false,
17
+ description: 'The name of the page that was viewed.',
18
+ label: 'Page Name',
19
+ default: {
20
+ '@path': '$.name'
21
+ }
22
+ },
23
+ properties: {
24
+ type: 'object',
25
+ required: false,
26
+ description: 'The properties of the page that was viewed.',
27
+ label: 'Properties',
28
+ default: {
29
+ '@path': '$.properties'
30
+ }
31
+ }
32
+ },
33
+ perform: (_, event) => {
34
+ window.userpilot.reload(event.payload.name ?? '', event.payload.properties ?? {})
35
+ }
36
+ }
37
+
38
+ export default action
@@ -0,0 +1,14 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Payload {
4
+ /**
5
+ * Event name
6
+ */
7
+ name: string
8
+ /**
9
+ * Event properties
10
+ */
11
+ properties?: {
12
+ [k: string]: unknown
13
+ }
14
+ }
@@ -0,0 +1,37 @@
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 { Userpilot } from '../types'
5
+
6
+ const action: BrowserActionDefinition<Settings, Userpilot, Payload> = {
7
+ title: 'Track Event',
8
+ description:
9
+ "Send an event to Userpilot. It's mandatory to identify a user by calling identify() prior to invoking other methods such as track(). You can learn more by visiting the [Userpilot documentation](https://docs.userpilot.com/article/23-identify-users-track-custom-events).",
10
+ platform: 'web',
11
+ defaultSubscription: 'type = "track"',
12
+ fields: {
13
+ name: {
14
+ type: 'string',
15
+ required: true,
16
+ description: 'Event name',
17
+ label: 'Name',
18
+ default: {
19
+ '@path': '$.event'
20
+ }
21
+ },
22
+ properties: {
23
+ type: 'object',
24
+ required: false,
25
+ description: 'Event properties',
26
+ label: 'Properties',
27
+ default: {
28
+ '@path': '$.properties'
29
+ }
30
+ }
31
+ },
32
+ perform: (_, event) => {
33
+ window.userpilot.track(event.payload.name, event.payload.properties ?? {})
34
+ }
35
+ }
36
+
37
+ export default action
package/src/types.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type Userpilot = {
2
+ identify: (user_id: String, traits: { [key: string]: unknown }) => void
3
+ track: (eventName: String, eventProperties: { [key: string]: unknown }) => void
4
+ reload: (pageName: String, pageProperties: Object) => void
5
+ group: (groupId: String, groupTraits: Object) => void
6
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.build.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "baseUrl": "."
6
+ },
7
+ "include": ["src"],
8
+ "exclude": ["dist", "**/__tests__"]
9
+ }