@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.
@@ -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
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
+ }