@segment/analytics-browser-actions-intercom 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 +21 -0
- package/src/__tests__/index.test.ts +55 -0
- package/src/__tests__/utils.test.ts +90 -0
- package/src/api.ts +11 -0
- package/src/generated-types.ts +20 -0
- package/src/identifyCompany/__tests__/index.test.ts +308 -0
- package/src/identifyCompany/generated-types.ts +51 -0
- package/src/identifyCompany/index.ts +82 -0
- package/src/identifyUser/__tests__/index.test.ts +460 -0
- package/src/identifyUser/generated-types.ts +136 -0
- package/src/identifyUser/index.ts +237 -0
- package/src/index.ts +109 -0
- package/src/init-script.ts +49 -0
- package/src/sharedCompanyProperties.ts +59 -0
- package/src/trackEvent/__tests__/index.test.ts +179 -0
- package/src/trackEvent/generated-types.ts +22 -0
- package/src/trackEvent/index.ts +92 -0
- package/src/utils.ts +43 -0
- package/tsconfig.json +9 -0
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@segment/analytics-browser-actions-intercom",
|
|
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/actions-shared": "^1.53.0",
|
|
16
|
+
"@segment/browser-destination-runtime": "^1.0.0"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@segment/analytics-next": "*"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Subscription } from '@segment/browser-destination-runtime/types'
|
|
2
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
3
|
+
import intercomDestination, { destination } from '../index'
|
|
4
|
+
|
|
5
|
+
const subscriptions: Subscription[] = [
|
|
6
|
+
{
|
|
7
|
+
partnerAction: 'trackEvent',
|
|
8
|
+
name: 'Show',
|
|
9
|
+
enabled: true,
|
|
10
|
+
subscribe: 'type = "track"',
|
|
11
|
+
mapping: {
|
|
12
|
+
event_name: {
|
|
13
|
+
'@path': '$.event'
|
|
14
|
+
},
|
|
15
|
+
event_metadata: {
|
|
16
|
+
'@path': '$.properties'
|
|
17
|
+
},
|
|
18
|
+
revenue: {
|
|
19
|
+
'@path': '$.properties.revenue'
|
|
20
|
+
},
|
|
21
|
+
currency: {
|
|
22
|
+
'@path': '$.properties.currency'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
describe('Intercom (actions)', () => {
|
|
29
|
+
test('loads Intercom with just appID', async () => {
|
|
30
|
+
const [event] = await intercomDestination({
|
|
31
|
+
appId: 'topSecretKey',
|
|
32
|
+
richLinkProperties: ['article'],
|
|
33
|
+
activator: '#test',
|
|
34
|
+
subscriptions
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
jest.spyOn(destination, 'initialize')
|
|
38
|
+
|
|
39
|
+
await event.load(Context.system(), {} as Analytics)
|
|
40
|
+
expect(destination.initialize).toHaveBeenCalled()
|
|
41
|
+
|
|
42
|
+
const scripts = window.document.querySelectorAll('script')
|
|
43
|
+
expect(scripts).toMatchInlineSnapshot(`
|
|
44
|
+
NodeList [
|
|
45
|
+
<script
|
|
46
|
+
src="https://widget.intercom.io/widget/topSecretKey"
|
|
47
|
+
type="text/javascript"
|
|
48
|
+
/>,
|
|
49
|
+
<script>
|
|
50
|
+
// the emptiness
|
|
51
|
+
</script>,
|
|
52
|
+
]
|
|
53
|
+
`)
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import dayjs from 'dayjs'
|
|
2
|
+
import { convertDateToUnix, filterCustomTraits, getWidgetOptions, isEmpty } from '../utils'
|
|
3
|
+
|
|
4
|
+
describe('Utils test', () => {
|
|
5
|
+
describe('date handling tests', () => {
|
|
6
|
+
test('handles ISO datestrings', () => {
|
|
7
|
+
const date = new Date()
|
|
8
|
+
const isoDate = date.toISOString()
|
|
9
|
+
const unixDate = dayjs(isoDate).unix()
|
|
10
|
+
|
|
11
|
+
expect(convertDateToUnix(isoDate)).toEqual(unixDate)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('accepts Unix timestamps in seconds', () => {
|
|
15
|
+
const date = Math.floor(new Date().getTime() / 1000)
|
|
16
|
+
|
|
17
|
+
expect(convertDateToUnix(date)).toEqual(date)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('accepts Unix timestamps in milliseconds', () => {
|
|
21
|
+
const dateInMS = Math.floor(new Date().getTime())
|
|
22
|
+
const dateInS = Math.floor(dateInMS / 1000)
|
|
23
|
+
|
|
24
|
+
expect(convertDateToUnix(dateInMS)).toEqual(dateInS)
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe('custom trait filtering tests', () => {
|
|
29
|
+
test('objects & arrays will be filtered out of traits', () => {
|
|
30
|
+
const traits = {
|
|
31
|
+
name: 'ibum',
|
|
32
|
+
badObj: {
|
|
33
|
+
badKey: 'badValue'
|
|
34
|
+
},
|
|
35
|
+
badArray: ['i will be dropped']
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
expect(filterCustomTraits(traits)).toEqual({
|
|
39
|
+
name: 'ibum'
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('custom traits will be filtered with undefined traits object', () => {
|
|
44
|
+
const traits = undefined
|
|
45
|
+
expect(filterCustomTraits(traits)).toEqual({})
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
describe('isEmpty tests', () => {
|
|
50
|
+
test('isEmpty returns true if object is empty', () => {
|
|
51
|
+
const obj = {}
|
|
52
|
+
expect(isEmpty(obj)).toBe(true)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('isEmpty returns false if object is not empty', () => {
|
|
56
|
+
const obj = { prop: 'value' }
|
|
57
|
+
expect(isEmpty(obj)).toBe(false)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('isEmpty works for undefined obj', () => {
|
|
61
|
+
const obj = undefined
|
|
62
|
+
expect(isEmpty(obj)).toBe(true)
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
describe('widget options tests', () => {
|
|
67
|
+
test('attaches `activator` if activator is not default', () => {
|
|
68
|
+
const activator = '#my-widget'
|
|
69
|
+
const hide_default_launcher = undefined
|
|
70
|
+
|
|
71
|
+
expect(getWidgetOptions(hide_default_launcher, activator)).toEqual({
|
|
72
|
+
widget: {
|
|
73
|
+
activator: activator
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('attaches `hide_default_launcher` if its not undefined ', () => {
|
|
79
|
+
const activator = '#my-widget'
|
|
80
|
+
const hide_default_launcher = false
|
|
81
|
+
|
|
82
|
+
expect(getWidgetOptions(hide_default_launcher, activator)).toEqual({
|
|
83
|
+
widget: {
|
|
84
|
+
activator: activator
|
|
85
|
+
},
|
|
86
|
+
hide_default_launcher: false
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
})
|
package/src/api.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type method = 'trackEvent' | 'update'
|
|
2
|
+
|
|
3
|
+
type IntercomApi = {
|
|
4
|
+
richLinkProperties: string[] | undefined
|
|
5
|
+
appId: string
|
|
6
|
+
activator: string | undefined
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type IntercomFunction = (method: method, ...args: unknown[]) => void
|
|
10
|
+
|
|
11
|
+
export type Intercom = IntercomFunction & IntercomApi
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Settings {
|
|
4
|
+
/**
|
|
5
|
+
* The app_id of your Intercom app which will indicate where to store any data.
|
|
6
|
+
*/
|
|
7
|
+
appId: string
|
|
8
|
+
/**
|
|
9
|
+
* By default, Intercom will inject their own inbox button onto the page, but you can choose to use your own custom button instead by providing a CSS selector, e.g. #my-button. You must have the "Show the Intercom Inbox" setting enabled for this to work. The default value is #IntercomDefaultWidget.
|
|
10
|
+
*/
|
|
11
|
+
activator?: string
|
|
12
|
+
/**
|
|
13
|
+
* A list of rich link property keys.
|
|
14
|
+
*/
|
|
15
|
+
richLinkProperties?: string[]
|
|
16
|
+
/**
|
|
17
|
+
* The regional API to use for processing the data
|
|
18
|
+
*/
|
|
19
|
+
apiBase?: string
|
|
20
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
|
2
|
+
import { Subscription } from '@segment/browser-destination-runtime'
|
|
3
|
+
import intercomDestination, { destination } from '../../index'
|
|
4
|
+
|
|
5
|
+
const subscriptions: Subscription[] = [
|
|
6
|
+
{
|
|
7
|
+
partnerAction: 'identifyCompany',
|
|
8
|
+
name: 'Show',
|
|
9
|
+
enabled: true,
|
|
10
|
+
subscribe: 'type = "group"',
|
|
11
|
+
mapping: {
|
|
12
|
+
company: {
|
|
13
|
+
company_id: { '@path': '$.groupId' },
|
|
14
|
+
company_custom_traits: {
|
|
15
|
+
city: {
|
|
16
|
+
'@path': '$.traits.city'
|
|
17
|
+
},
|
|
18
|
+
tech: {
|
|
19
|
+
'@path': '$.traits.tech'
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
name: { '@path': '$.traits.name' },
|
|
23
|
+
plan: { '@path': '$.traits.plan' },
|
|
24
|
+
monthly_spend: { '@path': '$.traits.monthlySpend' },
|
|
25
|
+
created_at: {
|
|
26
|
+
'@if': {
|
|
27
|
+
exists: { '@path': '$.traits.createdAt' },
|
|
28
|
+
then: { '@path': '$.traits.createdAt' },
|
|
29
|
+
else: { '@path': '$.traits.created_at' }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
size: { '@path': '$.traits.size' },
|
|
33
|
+
website: { '@path': '$.traits.website' },
|
|
34
|
+
industry: { '@path': '$.traits.industry' }
|
|
35
|
+
},
|
|
36
|
+
hide_default_launcher: {
|
|
37
|
+
'@if': {
|
|
38
|
+
exists: { '@path': '$.context.Intercom.hideDefaultLauncher' },
|
|
39
|
+
then: { '@path': '$.context.Intercom.hideDefaultLauncher' },
|
|
40
|
+
else: { '@path': '$.context.Intercom.hide_default_launcher' }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
describe('Intercom.update (Company)', () => {
|
|
48
|
+
const settings = {
|
|
49
|
+
appId: 'superSecretAppID',
|
|
50
|
+
activator: '#IntercomDefaultWidget'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let mockIntercom: jest.Mock<any, any>
|
|
54
|
+
let identifyCompany: any
|
|
55
|
+
beforeEach(async () => {
|
|
56
|
+
jest.restoreAllMocks()
|
|
57
|
+
|
|
58
|
+
const [identifyCompanyPlugin] = await intercomDestination({
|
|
59
|
+
...settings,
|
|
60
|
+
subscriptions
|
|
61
|
+
})
|
|
62
|
+
identifyCompany = identifyCompanyPlugin
|
|
63
|
+
|
|
64
|
+
mockIntercom = jest.fn()
|
|
65
|
+
jest.spyOn(destination, 'initialize').mockImplementation(() => {
|
|
66
|
+
const mockedWithProps = Object.assign(mockIntercom as any, settings)
|
|
67
|
+
return Promise.resolve(mockedWithProps)
|
|
68
|
+
})
|
|
69
|
+
await identifyCompany.load(Context.system(), {} as Analytics)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('sends an id', async () => {
|
|
73
|
+
const context = new Context({
|
|
74
|
+
type: 'group',
|
|
75
|
+
groupId: 'id'
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
await identifyCompany.group?.(context)
|
|
79
|
+
|
|
80
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
81
|
+
company: {
|
|
82
|
+
company_id: 'id'
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('sends an id & properties', async () => {
|
|
88
|
+
const context = new Context({
|
|
89
|
+
type: 'group',
|
|
90
|
+
groupId: 'id',
|
|
91
|
+
traits: {
|
|
92
|
+
name: 'Jeff'
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
await identifyCompany.group?.(context)
|
|
97
|
+
|
|
98
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
99
|
+
company: {
|
|
100
|
+
company_id: 'id',
|
|
101
|
+
name: 'Jeff'
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('converts created_at from ISO-8601 to Unix', async () => {
|
|
107
|
+
const context = new Context({
|
|
108
|
+
type: 'group',
|
|
109
|
+
groupId: 'id',
|
|
110
|
+
traits: {
|
|
111
|
+
createdAt: '2018-01-23T22:28:55.111Z'
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
await identifyCompany.group?.(context)
|
|
116
|
+
|
|
117
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
118
|
+
company: {
|
|
119
|
+
company_id: 'id',
|
|
120
|
+
created_at: 1516746535
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('maps created_at properly regardless of it being sent in snake_case or camelCase', async () => {
|
|
126
|
+
const context = new Context({
|
|
127
|
+
type: 'group',
|
|
128
|
+
groupId: 'id',
|
|
129
|
+
traits: {
|
|
130
|
+
created_at: '2018-01-23T22:28:55.111Z'
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
await identifyCompany.group?.(context)
|
|
135
|
+
|
|
136
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
137
|
+
company: {
|
|
138
|
+
company_id: 'id',
|
|
139
|
+
created_at: 1516746535
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
test('sends custom traits', async () => {
|
|
145
|
+
const context = new Context({
|
|
146
|
+
type: 'group',
|
|
147
|
+
groupId: 'id',
|
|
148
|
+
traits: {
|
|
149
|
+
wave: 'Capitola',
|
|
150
|
+
city: 'SF',
|
|
151
|
+
tech: true
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
await identifyCompany.group?.(context)
|
|
156
|
+
|
|
157
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
158
|
+
company: {
|
|
159
|
+
company_id: 'id',
|
|
160
|
+
city: 'SF',
|
|
161
|
+
tech: true
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
test('drops arrays or objects in traits', async () => {
|
|
167
|
+
const context = new Context({
|
|
168
|
+
type: 'group',
|
|
169
|
+
groupId: 'id',
|
|
170
|
+
traits: {
|
|
171
|
+
badArray: ['i', 'shall', 'be', 'dropped'],
|
|
172
|
+
badObject: {
|
|
173
|
+
rip: 'i will cease to exist'
|
|
174
|
+
},
|
|
175
|
+
city: 'Belmar'
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
await identifyCompany.group?.(context)
|
|
180
|
+
|
|
181
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
182
|
+
company: {
|
|
183
|
+
company_id: 'id',
|
|
184
|
+
city: 'Belmar'
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
test('should set hide_default_launcher if the setting is there', async () => {
|
|
190
|
+
const context = new Context({
|
|
191
|
+
type: 'group',
|
|
192
|
+
groupId: 'id',
|
|
193
|
+
traits: {
|
|
194
|
+
name: 'Segment'
|
|
195
|
+
},
|
|
196
|
+
context: {
|
|
197
|
+
Intercom: {
|
|
198
|
+
hideDefaultLauncher: true
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
await identifyCompany.group?.(context)
|
|
204
|
+
|
|
205
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
206
|
+
company: {
|
|
207
|
+
company_id: 'id',
|
|
208
|
+
name: 'Segment'
|
|
209
|
+
},
|
|
210
|
+
hide_default_launcher: true
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
describe('Intercom.update (user) widget options', () => {
|
|
216
|
+
const settings = {
|
|
217
|
+
appId: 'superSecretAppID',
|
|
218
|
+
activator: '#customWidget'
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let mockIntercom: jest.Mock<any, any>
|
|
222
|
+
let identifyCompany: any
|
|
223
|
+
beforeEach(async () => {
|
|
224
|
+
jest.restoreAllMocks()
|
|
225
|
+
|
|
226
|
+
const [identifyCompanyPlugin] = await intercomDestination({
|
|
227
|
+
...settings,
|
|
228
|
+
subscriptions
|
|
229
|
+
})
|
|
230
|
+
identifyCompany = identifyCompanyPlugin
|
|
231
|
+
|
|
232
|
+
mockIntercom = jest.fn()
|
|
233
|
+
jest.spyOn(destination, 'initialize').mockImplementation(() => {
|
|
234
|
+
const mockedWithProps = Object.assign(mockIntercom as any, settings)
|
|
235
|
+
return Promise.resolve(mockedWithProps)
|
|
236
|
+
})
|
|
237
|
+
await identifyCompany.load(Context.system(), {} as Analytics)
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
test('sets activator if activator is not #IntercomDefaultWidget', async () => {
|
|
241
|
+
const context = new Context({
|
|
242
|
+
type: 'group',
|
|
243
|
+
groupId: 'id',
|
|
244
|
+
traits: {}
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
await identifyCompany.group?.(context)
|
|
248
|
+
|
|
249
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
250
|
+
company: {
|
|
251
|
+
company_id: 'id'
|
|
252
|
+
},
|
|
253
|
+
widget: {
|
|
254
|
+
activator: '#customWidget'
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
test('should set hide_default_launcher if the setting is there', async () => {
|
|
260
|
+
const context = new Context({
|
|
261
|
+
type: 'group',
|
|
262
|
+
groupId: 'id',
|
|
263
|
+
traits: {},
|
|
264
|
+
context: {
|
|
265
|
+
Intercom: {
|
|
266
|
+
hideDefaultLauncher: false
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
await identifyCompany.identify?.(context)
|
|
272
|
+
|
|
273
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
274
|
+
company: {
|
|
275
|
+
company_id: 'id'
|
|
276
|
+
},
|
|
277
|
+
hide_default_launcher: false,
|
|
278
|
+
widget: {
|
|
279
|
+
activator: '#customWidget'
|
|
280
|
+
}
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
test('maps hide_default_launcher correctly regardless of it being sent in snake_case or camelCase', async () => {
|
|
285
|
+
const context = new Context({
|
|
286
|
+
type: 'group',
|
|
287
|
+
groupId: 'id',
|
|
288
|
+
traits: {},
|
|
289
|
+
context: {
|
|
290
|
+
Intercom: {
|
|
291
|
+
hideDefaultLauncher: false
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
await identifyCompany.identify?.(context)
|
|
297
|
+
|
|
298
|
+
expect(mockIntercom).toHaveBeenCalledWith('update', {
|
|
299
|
+
company: {
|
|
300
|
+
company_id: 'id'
|
|
301
|
+
},
|
|
302
|
+
hide_default_launcher: false,
|
|
303
|
+
widget: {
|
|
304
|
+
activator: '#customWidget'
|
|
305
|
+
}
|
|
306
|
+
})
|
|
307
|
+
})
|
|
308
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
|
2
|
+
|
|
3
|
+
export interface Payload {
|
|
4
|
+
/**
|
|
5
|
+
* The user's company.
|
|
6
|
+
*/
|
|
7
|
+
company: {
|
|
8
|
+
/**
|
|
9
|
+
* The unique identifier of the company.
|
|
10
|
+
*/
|
|
11
|
+
company_id: string
|
|
12
|
+
/**
|
|
13
|
+
* The name of the company.
|
|
14
|
+
*/
|
|
15
|
+
name: string
|
|
16
|
+
/**
|
|
17
|
+
* The time the company was created in your system.
|
|
18
|
+
*/
|
|
19
|
+
created_at?: string | number
|
|
20
|
+
/**
|
|
21
|
+
* The name of the plan you have associated with the company.
|
|
22
|
+
*/
|
|
23
|
+
plan?: string
|
|
24
|
+
/**
|
|
25
|
+
* The monthly spend of the company, e.g. how much revenue the company generates for your business.
|
|
26
|
+
*/
|
|
27
|
+
monthly_spend?: number
|
|
28
|
+
/**
|
|
29
|
+
* The number of employees in the company.
|
|
30
|
+
*/
|
|
31
|
+
size?: number
|
|
32
|
+
/**
|
|
33
|
+
* The URL for the company website.
|
|
34
|
+
*/
|
|
35
|
+
website?: string
|
|
36
|
+
/**
|
|
37
|
+
* The industry that the company operates in.
|
|
38
|
+
*/
|
|
39
|
+
industry?: string
|
|
40
|
+
/**
|
|
41
|
+
* The custom attributes for the company object.
|
|
42
|
+
*/
|
|
43
|
+
company_custom_traits?: {
|
|
44
|
+
[k: string]: unknown
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Selectively show the chat widget. As per [Intercom docs](https://www.intercom.com/help/en/articles/189-turn-off-show-or-hide-the-intercom-messenger), you want to first hide the Messenger for all users inside the Intercom UI using Messenger settings. Then think about how you want to programmatically decide which users you would like to show the widget to.
|
|
49
|
+
*/
|
|
50
|
+
hide_default_launcher?: boolean
|
|
51
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { InputField } from '@segment/actions-core'
|
|
2
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
|
3
|
+
import { Intercom } from '../api'
|
|
4
|
+
import type { Settings } from '../generated-types'
|
|
5
|
+
import { getCompanyProperties } from '../sharedCompanyProperties'
|
|
6
|
+
import { convertDateToUnix, filterCustomTraits, getWidgetOptions } from '../utils'
|
|
7
|
+
import type { Payload } from './generated-types'
|
|
8
|
+
|
|
9
|
+
const companyProperties: Record<string, InputField> = getCompanyProperties()
|
|
10
|
+
|
|
11
|
+
const action: BrowserActionDefinition<Settings, Intercom, Payload> = {
|
|
12
|
+
title: 'Identify Company',
|
|
13
|
+
description: 'Create or update a company in Intercom.',
|
|
14
|
+
defaultSubscription: 'type = "group"',
|
|
15
|
+
platform: 'web',
|
|
16
|
+
fields: {
|
|
17
|
+
company: {
|
|
18
|
+
description: "The user's company.",
|
|
19
|
+
label: 'Company',
|
|
20
|
+
type: 'object',
|
|
21
|
+
required: true,
|
|
22
|
+
properties: companyProperties,
|
|
23
|
+
default: {
|
|
24
|
+
company_id: { '@path': '$.groupId' },
|
|
25
|
+
name: { '@path': '$.traits.name' },
|
|
26
|
+
created_at: {
|
|
27
|
+
'@if': {
|
|
28
|
+
exists: { '@path': '$.traits.createdAt' },
|
|
29
|
+
then: { '@path': '$.traits.createdAt' },
|
|
30
|
+
else: { '@path': '$.traits.created_at' }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
plan: { '@path': '$.traits.plan' },
|
|
34
|
+
size: { '@path': '$.traits.size' },
|
|
35
|
+
website: { '@path': '$.traits.website' },
|
|
36
|
+
industry: { '@path': '$.traits.industry' },
|
|
37
|
+
monthly_spend: { '@path': '$.traits.monthly_spend' }
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
hide_default_launcher: {
|
|
41
|
+
description:
|
|
42
|
+
'Selectively show the chat widget. As per [Intercom docs](https://www.intercom.com/help/en/articles/189-turn-off-show-or-hide-the-intercom-messenger), you want to first hide the Messenger for all users inside the Intercom UI using Messenger settings. Then think about how you want to programmatically decide which users you would like to show the widget to.',
|
|
43
|
+
label: 'Hide Default Launcher',
|
|
44
|
+
type: 'boolean',
|
|
45
|
+
required: false,
|
|
46
|
+
default: {
|
|
47
|
+
'@if': {
|
|
48
|
+
exists: { '@path': '$.context.Intercom.hideDefaultLauncher' },
|
|
49
|
+
then: { '@path': '$.context.Intercom.hideDefaultLauncher' },
|
|
50
|
+
else: { '@path': '$.context.Intercom.hide_default_launcher' }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
perform: (Intercom, event) => {
|
|
56
|
+
// remove properties that require extra handling
|
|
57
|
+
const { company_custom_traits, ...rest } = event.payload.company
|
|
58
|
+
let company = { ...rest }
|
|
59
|
+
|
|
60
|
+
// convert date from ISO-8601 to UNIX
|
|
61
|
+
if (company?.created_at) {
|
|
62
|
+
company.created_at = convertDateToUnix(company.created_at)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// drop custom objects & arrays
|
|
66
|
+
const filteredCustomTraits = filterCustomTraits(company_custom_traits)
|
|
67
|
+
|
|
68
|
+
// merge filtered custom traits back into company object
|
|
69
|
+
company = { ...company, ...filteredCustomTraits }
|
|
70
|
+
|
|
71
|
+
// get user's widget options
|
|
72
|
+
const widgetOptions = getWidgetOptions(event.payload.hide_default_launcher, Intercom.activator)
|
|
73
|
+
|
|
74
|
+
//API call
|
|
75
|
+
Intercom('update', {
|
|
76
|
+
company,
|
|
77
|
+
...widgetOptions
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default action
|