@segment/analytics-browser-actions-braze 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 +40 -0
- package/src/__tests__/__snapshots__/initialization.test.ts.snap +24 -0
- package/src/__tests__/__snapshots__/integration.test.ts.snap +96 -0
- package/src/__tests__/__snapshots__/trackPurchase.test.ts.snap +97 -0
- package/src/__tests__/debounce.test.ts +133 -0
- package/src/__tests__/initialization.test.ts +139 -0
- package/src/__tests__/integration.test.ts +156 -0
- package/src/__tests__/trackEvent.test.ts +65 -0
- package/src/__tests__/trackPurchase.test.ts +65 -0
- package/src/__tests__/updateUserProfile.test.ts +145 -0
- package/src/braze-types.ts +9 -0
- package/src/debounce/generated-types.ts +3 -0
- package/src/debounce/index.ts +67 -0
- package/src/generated-types.ts +104 -0
- package/src/index.ts +358 -0
- package/src/trackEvent/generated-types.ts +14 -0
- package/src/trackEvent/index.ts +40 -0
- package/src/trackPurchase/generated-types.ts +31 -0
- package/src/trackPurchase/index.ts +83 -0
- package/src/updateUserProfile/generated-types.ts +70 -0
- package/src/updateUserProfile/index.ts +227 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,227 @@
|
|
|
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 * as braze from '@braze/web-sdk'
|
|
5
|
+
import dayjs from 'dayjs'
|
|
6
|
+
import { BrazeDestinationClient } from '../braze-types'
|
|
7
|
+
|
|
8
|
+
const action: BrowserActionDefinition<Settings, BrazeDestinationClient, Payload> = {
|
|
9
|
+
title: 'Update User Profile',
|
|
10
|
+
description: 'Updates a users profile attributes in Braze',
|
|
11
|
+
defaultSubscription: 'type = "identify" or type = "group"',
|
|
12
|
+
platform: 'web',
|
|
13
|
+
fields: {
|
|
14
|
+
external_id: {
|
|
15
|
+
label: 'External User ID',
|
|
16
|
+
description: 'The unique user identifier',
|
|
17
|
+
type: 'string',
|
|
18
|
+
default: {
|
|
19
|
+
'@path': '$.userId'
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
country: {
|
|
23
|
+
label: 'Country',
|
|
24
|
+
description: 'The country code of the user',
|
|
25
|
+
type: 'string',
|
|
26
|
+
allowNull: true,
|
|
27
|
+
default: {
|
|
28
|
+
'@path': '$.context.location.country'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
current_location: {
|
|
32
|
+
label: 'Current Location',
|
|
33
|
+
description: "The user's current longitude/latitude.",
|
|
34
|
+
type: 'object',
|
|
35
|
+
allowNull: true,
|
|
36
|
+
properties: {
|
|
37
|
+
key: {
|
|
38
|
+
label: 'Key',
|
|
39
|
+
type: 'string',
|
|
40
|
+
required: true
|
|
41
|
+
},
|
|
42
|
+
latitude: {
|
|
43
|
+
label: 'Latitude',
|
|
44
|
+
type: 'number',
|
|
45
|
+
required: true
|
|
46
|
+
},
|
|
47
|
+
longitude: {
|
|
48
|
+
label: 'Longitude',
|
|
49
|
+
type: 'number',
|
|
50
|
+
required: true
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
custom_attributes: {
|
|
55
|
+
label: 'Custom Attributes',
|
|
56
|
+
description:
|
|
57
|
+
'Sets a custom user attribute. This can be any key/value pair and is used to collect extra information about the user.',
|
|
58
|
+
type: 'object',
|
|
59
|
+
default: {
|
|
60
|
+
'@path': '$.traits'
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
dob: {
|
|
64
|
+
label: 'Date of Birth',
|
|
65
|
+
description: "The user's date of birth",
|
|
66
|
+
type: 'datetime',
|
|
67
|
+
allowNull: true
|
|
68
|
+
},
|
|
69
|
+
email: {
|
|
70
|
+
label: 'Email',
|
|
71
|
+
description: "The user's email",
|
|
72
|
+
type: 'string',
|
|
73
|
+
format: 'email',
|
|
74
|
+
allowNull: true,
|
|
75
|
+
default: {
|
|
76
|
+
'@path': '$.traits.email'
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
email_subscribe: {
|
|
80
|
+
label: 'Email Subscribe',
|
|
81
|
+
description: `The user's email subscription preference: “opted_in” (explicitly registered to receive email messages), “unsubscribed” (explicitly opted out of email messages), and “subscribed” (neither opted in nor out).`,
|
|
82
|
+
type: 'string'
|
|
83
|
+
},
|
|
84
|
+
first_name: {
|
|
85
|
+
label: 'First Name',
|
|
86
|
+
description: `The user's first name`,
|
|
87
|
+
type: 'string',
|
|
88
|
+
allowNull: true,
|
|
89
|
+
default: {
|
|
90
|
+
'@path': '$.traits.firstName'
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
last_name: {
|
|
94
|
+
label: 'Last Name',
|
|
95
|
+
description: "The user's last name",
|
|
96
|
+
type: 'string',
|
|
97
|
+
default: {
|
|
98
|
+
'@path': '$.traits.lastName'
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
gender: {
|
|
102
|
+
label: 'Gender',
|
|
103
|
+
description:
|
|
104
|
+
"The user's gender: “M”, “F”, “O” (other), “N” (not applicable), “P” (prefer not to say) or nil (unknown).",
|
|
105
|
+
type: 'string',
|
|
106
|
+
allowNull: true,
|
|
107
|
+
default: {
|
|
108
|
+
'@path': '$.traits.gender'
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
home_city: {
|
|
112
|
+
label: 'Home City',
|
|
113
|
+
description: "The user's home city.",
|
|
114
|
+
type: 'string',
|
|
115
|
+
allowNull: true,
|
|
116
|
+
default: {
|
|
117
|
+
'@path': '$.traits.address.city'
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
image_url: {
|
|
121
|
+
label: 'Image URL',
|
|
122
|
+
description: 'URL of image to be associated with user profile.',
|
|
123
|
+
type: 'string',
|
|
124
|
+
format: 'uri',
|
|
125
|
+
default: {
|
|
126
|
+
'@path': '$.traits.avatar'
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
language: {
|
|
130
|
+
label: 'Language',
|
|
131
|
+
description: "The user's preferred language.",
|
|
132
|
+
type: 'string',
|
|
133
|
+
allowNull: true
|
|
134
|
+
},
|
|
135
|
+
phone: {
|
|
136
|
+
label: 'Phone Number',
|
|
137
|
+
description: "The user's phone number",
|
|
138
|
+
type: 'string',
|
|
139
|
+
allowNull: true,
|
|
140
|
+
default: {
|
|
141
|
+
'@path': '$.traits.phone'
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
push_subscribe: {
|
|
145
|
+
label: 'Push Subscribe',
|
|
146
|
+
description: `The user's push subscription preference: “opted_in” (explicitly registered to receive push messages), “unsubscribed” (explicitly opted out of push messages), and “subscribed” (neither opted in nor out).`,
|
|
147
|
+
type: 'string'
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
perform: (client, { payload }) => {
|
|
152
|
+
if (!client.ready()) {
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// TODO - addAlias / addToCustomAttributeArray?
|
|
157
|
+
if (payload.external_id !== undefined) {
|
|
158
|
+
client.instance.changeUser(payload.external_id)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const user = client.instance.getUser()
|
|
162
|
+
if (!user) return
|
|
163
|
+
|
|
164
|
+
payload.country !== undefined && user.setCountry(payload.country)
|
|
165
|
+
|
|
166
|
+
payload.current_location?.key !== undefined &&
|
|
167
|
+
user.setCustomLocationAttribute(
|
|
168
|
+
payload.current_location.key,
|
|
169
|
+
payload.current_location.latitude,
|
|
170
|
+
payload.current_location.longitude
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if (payload.dob !== undefined) {
|
|
174
|
+
if (payload.dob === null) {
|
|
175
|
+
user.setDateOfBirth(null, null, null)
|
|
176
|
+
} else {
|
|
177
|
+
const date = dayjs(payload.dob)
|
|
178
|
+
user.setDateOfBirth(date.year(), date.month() + 1, date.date())
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Adding `firstName` and `lastName` here as these fields are mapped using cammel_case.
|
|
183
|
+
const reservedFields = [...Object.keys(action.fields), 'firstName', 'lastName']
|
|
184
|
+
if (payload.custom_attributes !== undefined) {
|
|
185
|
+
Object.entries(payload.custom_attributes).forEach(([key, value]) => {
|
|
186
|
+
if (!reservedFields.includes(key)) {
|
|
187
|
+
user.setCustomUserAttribute(key, value as string | number | boolean | Date | string[] | null)
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
payload.email_subscribe !== undefined &&
|
|
193
|
+
user.setEmailNotificationSubscriptionType(payload.email_subscribe as braze.NotificationSubscriptionTypes)
|
|
194
|
+
|
|
195
|
+
payload.email !== undefined && user.setEmail(payload.email)
|
|
196
|
+
payload.first_name !== undefined && user.setFirstName(payload.first_name)
|
|
197
|
+
payload.gender !== undefined && user.setGender(toBrazeGender(payload.gender) as braze.Genders)
|
|
198
|
+
payload.home_city !== undefined && user.setHomeCity(payload.home_city)
|
|
199
|
+
payload.language !== undefined && user.setLanguage(payload.language)
|
|
200
|
+
payload.current_location !== undefined &&
|
|
201
|
+
user.setLastKnownLocation(payload.current_location.latitude, payload.current_location.longitude)
|
|
202
|
+
payload.last_name !== undefined && user.setLastName(payload.last_name)
|
|
203
|
+
payload.phone !== undefined && user.setPhoneNumber(payload.phone)
|
|
204
|
+
payload.push_subscribe !== undefined &&
|
|
205
|
+
user.setPushNotificationSubscriptionType(payload.push_subscribe as braze.NotificationSubscriptionTypes)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function toBrazeGender(gender: string | undefined | null): string | null | undefined {
|
|
210
|
+
if (!gender) {
|
|
211
|
+
return gender
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const genders: { [key: string]: string[] } = {
|
|
215
|
+
M: ['man', 'male', 'm'],
|
|
216
|
+
F: ['woman', 'female', 'w', 'f'],
|
|
217
|
+
O: ['other', 'o'],
|
|
218
|
+
U: ['u', 'unknown'],
|
|
219
|
+
N: ['not applicable', 'n'],
|
|
220
|
+
P: ['prefer not to say', 'p']
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const brazeGender = Object.keys(genders).find((key) => genders[key].includes(gender.toLowerCase()))
|
|
224
|
+
return brazeGender || gender
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export default action
|