@microsoft/omnichannel-chat-sdk 1.1.1-main.131f36d → 1.1.1-main.211b61c
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/CHANGELOG.md +10 -1
- package/README.md +532 -382
- package/lib/OmnichannelChatSDK.d.ts +4 -2
- package/lib/OmnichannelChatSDK.js +40 -18
- package/lib/OmnichannelChatSDK.js.map +1 -1
- package/lib/core/GetLiveChatConfigOptionalParams.d.ts +5 -0
- package/lib/core/GetLiveChatConfigOptionalParams.js +3 -0
- package/lib/core/GetLiveChatConfigOptionalParams.js.map +1 -0
- package/lib/core/InitializeOptionalParams.d.ts +5 -0
- package/lib/core/InitializeOptionalParams.js +3 -0
- package/lib/core/InitializeOptionalParams.js.map +1 -0
- package/lib/core/StartChatOptionalParams.d.ts +1 -0
- package/lib/external/ACSAdapter/AMSFileManager.js +12 -0
- package/lib/external/ACSAdapter/AMSFileManager.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +45 -13
- package/package.json +2 -2
package/README.md
CHANGED
@@ -1,23 +1,62 @@
|
|
1
|
-
# Omnichannel Chat SDK
|
1
|
+
# Omnichannel Chat SDK 💬
|
2
2
|
|
3
3
|
[](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk)
|
4
|
+
[](https://packagephobia.com/result?p=@microsoft/omnichannel-chat-sdk)
|
4
5
|

|
5
6
|

|
6
7
|
|
8
|
+
> ❗ Chat SDK **v1.1.0** is the minimum version to support the **new** messaging platform. More [here](https://docs.microsoft.com/en-us/dynamics365/customer-service/migrate-acs)
|
9
|
+
|
10
|
+
> 📢 Try out our new React component library [omnichannel-chat-widget](https://github.com/microsoft/omnichannel-chat-widget) with Chat SDK
|
11
|
+
|
7
12
|
Headless Chat SDK to build your own chat widget against Dynamics 365 Omnichannel Services.
|
8
13
|
|
9
|
-
Please make sure you have a chat widget configured before using this package or you can follow this [link](https://docs.microsoft.com/en-us/dynamics365/customer-service/
|
14
|
+
Please make sure you have a chat widget configured before using this package or you can follow this [link](https://docs.microsoft.com/en-us/dynamics365/customer-service/add-chat-widget)
|
10
15
|
|
11
16
|
## Table of Contents
|
12
17
|
- [Live Chat Widget vs. Chat SDK](#live-chat-widget-vs-chat-sdk)
|
13
18
|
- [Installation](#installation)
|
14
19
|
- [Installation on React Native](#installation-on-react-native)
|
15
|
-
- [
|
16
|
-
- [
|
17
|
-
- [
|
20
|
+
- [SDK Methods](#sdk-methods)
|
21
|
+
- [Initialization](#initialization)
|
22
|
+
- [Start Chat](#start-chat)
|
23
|
+
- [End Chat](#end-chat)
|
24
|
+
- [Get Pre-Chat Survey](#get-pre-chat-survey)
|
25
|
+
- [Get Live Chat Config](#get-live-chat-config)
|
26
|
+
- [Get Current Live Chat Context](#get-current-live-chat-context)
|
27
|
+
- [Get Data Masking Rules](#get-data-masking-rules)
|
28
|
+
- [Get Chat Reconnect Context](#get-chat-reconnect-context)
|
29
|
+
- [Get Conversation Details](#get-conversation-details)
|
30
|
+
- [Get Chat Token](#get-chat-token)
|
31
|
+
- [Get Calling Token](#get-calling-token)
|
32
|
+
- [Get Messages](#get-messages)
|
33
|
+
- [Send Messages](#send-messages)
|
34
|
+
- [On New Message](#on-new-message)
|
35
|
+
- [On Typing Event](#on-typing-event)
|
36
|
+
- [On Agent End Session](#on-agent-end-session)
|
37
|
+
- [Send Typing Event](#send-typing-event)
|
38
|
+
- [Email Live Chat Transcript](#email-live-chat-transcript)
|
39
|
+
- [Get Live Chat Transcript](#get-live-chat-transcript)
|
40
|
+
- [Upload File Attachment](#upload-file-attachment)
|
41
|
+
- [Download File Attachment](#download-file-attachment)
|
42
|
+
- [Create Chat Adapter](#create-chat-adapter)
|
43
|
+
- [Get Voice & Video Calling](#get-voice--video-calling)
|
44
|
+
- [Get Post Chat Survey Context](#get-post-chat-survey-context)
|
18
45
|
- [Common Scenarios](#common-scenarios)
|
46
|
+
- [Using BotFramework-WebChat](#using-botframework-webchat)
|
47
|
+
- [Escalation to Voice & Video](#escalation-to-voice--video)
|
48
|
+
- [Pre-Chat Survey](#pre-chat-survey)
|
49
|
+
- [Post-Chat Survey](#post-chat-survey)
|
50
|
+
- [Reconnect to existing Chat](#reconnect-to-existing-chat)
|
51
|
+
- [Authenticated Chat](#authenticated-chat)
|
52
|
+
- [Persistent Chat](#persistent-chat)
|
53
|
+
- [Chat Reconnect with Authenticated User](#chat-reconnect-with-authenticated-user)
|
54
|
+
- [Chat Reconnect with Unauthenticated User](#chat-reconnect-with-unauthenticated-user)
|
55
|
+
- [Operating Hours](#operating-hours)
|
56
|
+
- [Sample Apps](https://github.com/microsoft/omnichannel-chat-sdk-samples)
|
19
57
|
- [Feature Comparisons](#feature-comparisons)
|
20
58
|
- [Telemetry](#telemetry)
|
59
|
+
- [Development Guide](docs/DEVELOPMENT_GUIDE.md)
|
21
60
|
- [Troubleshooting Guide](docs/TROUBLESHOOTING_GUIDE.md)
|
22
61
|
|
23
62
|
## Live Chat Widget vs. Chat SDK
|
@@ -58,7 +97,7 @@ Omnichannel offers an live chat widget (LCW) by default. You can use the Chat SD
|
|
58
97
|
## Installation
|
59
98
|
|
60
99
|
```
|
61
|
-
|
100
|
+
npm install @microsoft/omnichannel-chat-sdk --save
|
62
101
|
```
|
63
102
|
|
64
103
|
## Installation on React Native
|
@@ -106,243 +145,309 @@ The following steps will be required to run Omnichannel Chat SDK on React Native
|
|
106
145
|
import 'react-native-url-polyfill';
|
107
146
|
```
|
108
147
|
|
109
|
-
##
|
110
|
-
|
111
|
-
| Method | Description | Notes |
|
112
|
-
| ------ | ----------- | ----- |
|
113
|
-
| OmnichannelChatSDK.initialize() | Initializes ChatSDK internal data | |
|
114
|
-
| OmnichannelChatSDK.startChat() | Starts OC chat, handles prechat response | |
|
115
|
-
| OmnichannelChatSDK.endChat() | Ends OC chat | |
|
116
|
-
| OmnichannelChatSDK.getPreChatSurvey() | Adaptive card data of PreChat survey | |
|
117
|
-
| OmnichannelChatSDK.getLiveChatConfig() | Get live chat config | |
|
118
|
-
| OmnichannelChatSDK.getDataMaskingRules() | Get active data masking rules | |
|
119
|
-
| OmnichannelChatSDK.getCurrentLiveChatContext() | Get current live chat context information to reconnect to the same chat | |
|
120
|
-
| OmnichannelChatSDK.getChatReconnectContext() | Get current reconnectable chat context information to reconnect to a previous existing chat session | |
|
121
|
-
| OmnichannelChatSDK.getConversationDetails() | Get details of the current conversation such as its state & when the agent joined the conversation | |
|
122
|
-
| OmnichannelChatSDK.getChatToken() | Get chat token | |
|
123
|
-
| OmnichannelChatSDK.getCallingToken() | Get calling token | |
|
124
|
-
| OmnichannelChatSDK.getMessages() | Get all messages | |
|
125
|
-
| OmnichannelChatSDK.sendMessage() | Send message | |
|
126
|
-
| OmnichannelChatSDK.onNewMessage() | Handles system message, client/agent messages, adaptive cards, attachments to download | |
|
127
|
-
| OmnichannelChatSDK.onTypingEvent() | Handles agent typing event | |
|
128
|
-
| OmnichannelChatSDK.onAgentEndSession() | Handler when agent ends session | |
|
129
|
-
| OmnichannelChatSDK.sendTypingEvent() | Sends customer typing event | |
|
130
|
-
| OmnichannelChatSDK.emailLiveChatTranscript() | Email transcript | |
|
131
|
-
| OmnichannelChatSDK.getLiveChatTranscript() | Get transcript data (JSON) | |
|
132
|
-
| OmnichannelChatSDK.uploadFileAttachment() | Send file attachment | |
|
133
|
-
| OmnichannelChatSDK.downloadFileAttachment() | Download file attachment | |
|
134
|
-
| OmnichannelChatSDK.createChatAdapter() | Get Chat Adapter | **Web only** |
|
135
|
-
| OmnichannelChatSDK.getVoiceVideoCalling() | Get VoiceVideoCall SDK for Escalation to Voice & Video | **Web only** |
|
136
|
-
| OmnichannelChatSDK.getPostChatSurveyContext() | Get post chat survey link, survey locale, and whether an agent has joined the survey | |
|
137
|
-
|
138
|
-
## API examples
|
139
|
-
|
140
|
-
### Import
|
141
|
-
```ts
|
142
|
-
import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
|
143
|
-
```
|
148
|
+
## SDK Methods
|
144
149
|
|
145
150
|
### Initialization
|
151
|
+
|
152
|
+
It handles the initialization of ChatSDK internal data.
|
153
|
+
|
146
154
|
```ts
|
147
|
-
|
148
|
-
orgUrl: "",
|
149
|
-
orgId: "",
|
150
|
-
widgetId: ""
|
151
|
-
};
|
155
|
+
import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
|
152
156
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
};
|
157
|
+
const omnichannelConfig = {
|
158
|
+
orgUrl: "",
|
159
|
+
orgId: "",
|
160
|
+
widgetId: ""
|
161
|
+
};
|
159
162
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
+
const chatSDKConfig = { // Optional
|
164
|
+
dataMasking: {
|
165
|
+
disable: false,
|
166
|
+
maskingCharacter: '#'
|
167
|
+
}
|
168
|
+
};
|
163
169
|
|
164
|
-
|
165
|
-
|
166
|
-
|
170
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
171
|
+
|
172
|
+
const optionalParams = {
|
173
|
+
getLiveChatConfigOptionalParams: {
|
174
|
+
sendCacheHeaders: false // Whether to send Cache-Control HTTP header to GetChatConfig call
|
175
|
+
}
|
176
|
+
};
|
177
|
+
|
178
|
+
await chatSDK.initialize(optionalParams);
|
167
179
|
```
|
168
180
|
|
169
|
-
###
|
181
|
+
### Start Chat
|
182
|
+
|
183
|
+
It starts an Omnichannel conversation.
|
184
|
+
|
170
185
|
```ts
|
171
|
-
|
172
|
-
|
173
|
-
}
|
186
|
+
const customContext = {
|
187
|
+
'contextKey1': {'value': 'contextValue1', 'isDisplayable': true},
|
188
|
+
'contextKey2': {'value': 12.34, 'isDisplayable': false},
|
189
|
+
'contextKey3': {'value': true}
|
190
|
+
};
|
191
|
+
|
192
|
+
const optionalParams = {
|
193
|
+
preChatResponse: '', // PreChatSurvey response
|
194
|
+
liveChatContext: {}, // EXISTING chat context data
|
195
|
+
customContext, // Custom Context
|
196
|
+
sendDefaultInitContext: true // Send default init context ⚠️ Web only
|
197
|
+
};
|
174
198
|
|
175
|
-
|
199
|
+
await chatSDK.startChat(optionalParams);
|
176
200
|
```
|
177
201
|
|
178
|
-
###
|
202
|
+
### End Chat
|
203
|
+
|
204
|
+
It ends the current Omnichannel conversation.
|
205
|
+
|
179
206
|
```ts
|
180
|
-
|
207
|
+
await chatSDK.endChat();
|
181
208
|
```
|
182
209
|
|
183
|
-
### Get Chat
|
210
|
+
### Get Pre-Chat Survey
|
211
|
+
|
212
|
+
It gets the Pre-Chat Survey from Live Chat Config. Pre-Chat Survey is in Adaptive Card format.
|
213
|
+
|
214
|
+
`Option 1`
|
184
215
|
```ts
|
185
|
-
|
216
|
+
const preChatSurvey = await getPreChatSurvey(); // Adaptive Cards JSON payload data
|
186
217
|
```
|
187
|
-
|
188
|
-
### Get Calling Token
|
218
|
+
`Option 2`
|
189
219
|
```ts
|
190
|
-
|
220
|
+
const parseToJSON = false;
|
221
|
+
const preChatSurvey = await getPreChatSurvey(parseToJSON); // Adaptive Cards payload data as string
|
191
222
|
```
|
192
223
|
|
193
224
|
### Get Live Chat Config
|
225
|
+
|
226
|
+
It fetches the Live Chat Config.
|
227
|
+
|
194
228
|
```ts
|
195
|
-
|
229
|
+
const liveChatConfig = await chatSDK.getLiveChatConfig();
|
196
230
|
```
|
197
231
|
|
198
|
-
### Get
|
232
|
+
### Get Current Live Chat Context
|
233
|
+
|
234
|
+
It gets the current live chat context information to be used to reconnect to the same conversation.
|
235
|
+
|
199
236
|
```ts
|
200
|
-
|
237
|
+
const liveChatContext = await chatSDK.getCurrentLiveChatContext();
|
201
238
|
```
|
202
239
|
|
203
|
-
### Get
|
204
|
-
|
240
|
+
### Get Data Masking Rules
|
241
|
+
|
242
|
+
It gets the active data masking rules from Live Chat Config.
|
243
|
+
|
205
244
|
```ts
|
206
|
-
|
245
|
+
const dataMaskingRules = await chatSDK.getDataMaskingRules();
|
207
246
|
```
|
208
|
-
|
247
|
+
|
248
|
+
### Get Chat Reconnect Context
|
249
|
+
|
250
|
+
It gets the current reconnectable chat context information to connect to a previous existing chat session.
|
251
|
+
|
252
|
+
`Reconnection options` is required. See [documentation](https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session)
|
253
|
+
|
209
254
|
```ts
|
210
|
-
|
211
|
-
|
255
|
+
const optionalParams = {
|
256
|
+
reconnectId: '', // reconnect Id
|
257
|
+
};
|
258
|
+
|
259
|
+
const chatReconnectContext = await chatSDK.getChatReconnectContext(optionalParams);
|
212
260
|
```
|
213
261
|
|
214
|
-
### Get
|
262
|
+
### Get Conversation Details
|
263
|
+
|
264
|
+
It gets the details of the current conversation such as its state & when the agent joined the conversation.
|
265
|
+
|
215
266
|
```ts
|
216
|
-
|
217
|
-
const context = await chatSDK.getPostChatSurveyContext();
|
218
|
-
if (context.participantJoined) { // participantJoined will be true if an agent has joined the conversation, or a bot has joined the conversation and the bot survey flag has been turned on on the admin side.
|
219
|
-
// formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
|
220
|
-
// If "&lang=" is not set on the url, the locale will be English.
|
221
|
-
const linkToSend = context.surveyInviteLink + "&lang=" + context.formsProLocale;
|
222
|
-
// This link is accessible and will redirect to the survey page. Use it as you see fit.
|
223
|
-
}
|
224
|
-
} catch (ex) {
|
225
|
-
// If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
|
226
|
-
}
|
267
|
+
const conversationDetails = await chatSDK.getConversationDetails();
|
227
268
|
```
|
228
269
|
|
229
|
-
###
|
270
|
+
### Get chat Token
|
271
|
+
|
272
|
+
It gets the chat token used to initiates a chat with Omnichannel messaging client.
|
273
|
+
|
230
274
|
```ts
|
231
|
-
|
232
|
-
|
233
|
-
'contextKey2': {'value': 12.34, 'isDisplayable': false},
|
234
|
-
'contextKey3': {'value': true}
|
235
|
-
};
|
275
|
+
const chatToken = await chatSDK.getChatToken();
|
276
|
+
```
|
236
277
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
278
|
+
### Get Calling Token
|
279
|
+
|
280
|
+
It gets the calling token used to initiates a Voice & Video Call.
|
281
|
+
|
282
|
+
```ts
|
283
|
+
const callingToken = await chatSDK.getCallingToken();
|
243
284
|
```
|
244
285
|
|
245
|
-
###
|
286
|
+
### Get Messages
|
287
|
+
|
288
|
+
It gets all the messages of the current conversation.
|
289
|
+
|
246
290
|
```ts
|
247
|
-
|
291
|
+
const messages = await chatSDK.getMessages();
|
248
292
|
```
|
249
293
|
|
250
|
-
###
|
294
|
+
### Send Messages
|
295
|
+
|
296
|
+
It sends a message to Omnichannel.
|
297
|
+
|
251
298
|
```ts
|
252
|
-
|
253
|
-
rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
|
254
|
-
}
|
299
|
+
import {DeliveryMode, MessageContentType, MessageType, PersonType} from '@microsoft/omnichannel-chat-sdk';
|
255
300
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
301
|
+
...
|
302
|
+
|
303
|
+
const displayName = "Contoso"
|
304
|
+
const message = "Sample message from customer";
|
305
|
+
const messageToSend = {
|
306
|
+
content: message
|
307
|
+
};
|
308
|
+
|
309
|
+
await chatSDK.sendMessage(messageToSend);
|
260
310
|
```
|
261
311
|
|
262
|
-
### On
|
312
|
+
### On New Message
|
313
|
+
|
314
|
+
It subscribes to new incoming messages of the current conversation such as system messages, client messages, agent messages, adaptive cards and attachments.
|
315
|
+
|
263
316
|
```ts
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
```
|
317
|
+
const optionalParams = {
|
318
|
+
rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
|
319
|
+
}
|
268
320
|
|
321
|
+
chatSDK.onNewMessage((message) => {
|
322
|
+
console.log(`[NewMessage] ${message.content}`);
|
323
|
+
console.log(message);
|
324
|
+
}, optionalParams);
|
325
|
+
```
|
269
326
|
### On Typing Event
|
327
|
+
|
328
|
+
It subscribes to agent typing event.
|
329
|
+
|
270
330
|
```ts
|
271
|
-
|
272
|
-
|
273
|
-
|
331
|
+
chatSDK.onTypingEvent(() => {
|
332
|
+
console.log("Agent is typing...");
|
333
|
+
})
|
274
334
|
```
|
275
335
|
|
276
|
-
###
|
336
|
+
### On Agent End Session
|
337
|
+
|
338
|
+
It subscribes to agent ending the session of the conversation.
|
339
|
+
|
277
340
|
```ts
|
278
|
-
|
341
|
+
chatSDK.onAgentEndSession(() => {
|
342
|
+
console.log("Session ended!");
|
343
|
+
});
|
279
344
|
```
|
280
345
|
|
281
|
-
### Send
|
346
|
+
### Send Typing Event
|
347
|
+
|
348
|
+
It sends a customer typing event.
|
349
|
+
|
282
350
|
```ts
|
283
|
-
|
351
|
+
await chatSDK.sendTypingEvent();
|
352
|
+
```
|
284
353
|
|
285
|
-
|
354
|
+
### Email Live Chat Transcript
|
286
355
|
|
287
|
-
|
288
|
-
const message = "Sample message from customer";
|
289
|
-
const messageToSend = {
|
290
|
-
content: message
|
291
|
-
};
|
356
|
+
It sends an email of the live chat transcript.
|
292
357
|
|
293
|
-
|
358
|
+
```ts
|
359
|
+
const body = {
|
360
|
+
emailAddress: 'contoso@microsoft.com',
|
361
|
+
attachmentMessage: 'Attachment Message'
|
362
|
+
};
|
363
|
+
await chatSDK.emailLiveChatTranscript(body);
|
294
364
|
```
|
295
365
|
|
296
|
-
###
|
366
|
+
### Get Live Chat Transcript
|
367
|
+
|
368
|
+
It fetches the current conversation transcript data in JSON.
|
369
|
+
|
297
370
|
```ts
|
298
|
-
|
371
|
+
await chatSDK.getLiveChatTranscript();
|
299
372
|
```
|
300
373
|
|
301
|
-
### Upload Attachment
|
374
|
+
### Upload File Attachment
|
375
|
+
|
376
|
+
It sends a file attachment to the current conversation.
|
377
|
+
|
302
378
|
```ts
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
379
|
+
const fileInfo = {
|
380
|
+
name: '',
|
381
|
+
type: '',
|
382
|
+
size: '',
|
383
|
+
data: ''
|
384
|
+
};
|
385
|
+
await chatSDK.uploadFileAttachment(fileInfo);
|
310
386
|
```
|
311
387
|
|
312
|
-
### Download Attachment
|
388
|
+
### Download File Attachment
|
389
|
+
|
390
|
+
It downloads the file attachment of the incoming message as a Blob response.
|
391
|
+
|
313
392
|
```ts
|
314
|
-
|
393
|
+
const blobResponse = await chatsdk.downloadFileAttachment(message.fileMetadata);
|
315
394
|
|
316
|
-
|
395
|
+
...
|
317
396
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
397
|
+
// React Native implementation
|
398
|
+
const fileReaderInstance = new FileReader();
|
399
|
+
fileReaderInstance.readAsDataURL(blobResponse);
|
400
|
+
fileReaderInstance.onload = () => {
|
401
|
+
const base64data = fileReaderInstance.result;
|
402
|
+
return <Image source={{uri: base64data}}/>
|
403
|
+
}
|
325
404
|
```
|
326
405
|
|
327
|
-
###
|
406
|
+
### Create Chat Adapter
|
407
|
+
|
408
|
+
> :warning: Currently supported on web only
|
409
|
+
|
410
|
+
It creates a chat adapter to use with [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat).
|
328
411
|
|
329
412
|
```ts
|
330
|
-
|
413
|
+
const chatAdapter = await chatSDK.createChatAdapter();
|
331
414
|
```
|
332
415
|
|
333
|
-
###
|
416
|
+
### Get Voice & Video Calling
|
417
|
+
|
418
|
+
> :warning: Currently supported on web only
|
419
|
+
|
420
|
+
It fetches the SDK for Escalation to Voice & Video.
|
334
421
|
|
335
422
|
```ts
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
423
|
+
try {
|
424
|
+
const VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
|
425
|
+
console.log("VoiceVideoCalling loaded");
|
426
|
+
} catch (e) {
|
427
|
+
console.log(`Failed to load VoiceVideoCalling: ${e}`);
|
428
|
+
|
429
|
+
if (e.message === 'UnsupportedPlatform') {
|
430
|
+
// Voice Video Calling feature is not supported on this platform
|
431
|
+
}
|
432
|
+
|
433
|
+
if (e.message === 'FeatureDisabled') {
|
434
|
+
// Voice Video Calling feature is disabled on admin side
|
435
|
+
}
|
436
|
+
}
|
437
|
+
```
|
438
|
+
### Get Post Chat Survey Context
|
439
|
+
|
440
|
+
It gets post chat survey link, survey locale, and whether an agent has joined the survey.
|
441
|
+
|
442
|
+
```ts
|
443
|
+
const context = await chatSDK.getPostChatSurveyContext();
|
341
444
|
```
|
342
445
|
|
343
446
|
## Common Scenarios
|
344
447
|
|
345
|
-
###
|
448
|
+
### Pre-Chat Survey
|
449
|
+
|
450
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-pre-chat-survey?tabs=customerserviceadmincenter on how to set up pre-conversation surveys
|
346
451
|
|
347
452
|
```ts
|
348
453
|
import * as AdaptiveCards, { Action } from "adaptivecards";
|
@@ -375,314 +480,359 @@ The following steps will be required to run Omnichannel Chat SDK on React Native
|
|
375
480
|
|
376
481
|
```
|
377
482
|
|
483
|
+
### Post-Chat Survey
|
484
|
+
|
485
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-post-conversation-survey?tabs=customerserviceadmincenter on how to set up post-conversation surveys
|
486
|
+
|
487
|
+
> ❗ `chatSDK.getPostChatSurveyContext()` needs to be called before `chatSDK.endChat()` is called
|
488
|
+
|
489
|
+
```ts
|
490
|
+
// 1. Start chat
|
491
|
+
await chatSDK.startChat();
|
492
|
+
|
493
|
+
// 2. Save post chat survey context before ending chat
|
494
|
+
try {
|
495
|
+
const context = await chatSDK.getPostChatSurveyContext();
|
496
|
+
if (context.participantJoined) { // participantJoined will be true if an agent has joined the conversation, or a bot has joined the conversation and the bot survey flag has been turned on on the admin side.
|
497
|
+
// formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
|
498
|
+
// If "&lang=" is not set on the url, the locale will be English.
|
499
|
+
const linkToSend = context.surveyInviteLink + "&lang=" + context.formsProLocale;
|
500
|
+
// This link is accessible and will redirect to the survey page. Use it as you see fit.
|
501
|
+
}
|
502
|
+
} catch (ex) {
|
503
|
+
// If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
|
504
|
+
}
|
505
|
+
|
506
|
+
// 3. End chat
|
507
|
+
await chatSDK.endChat();
|
508
|
+
|
509
|
+
// 4. Display Post Chat
|
510
|
+
```
|
511
|
+
|
378
512
|
### Reconnect to existing Chat
|
379
513
|
|
380
514
|
```ts
|
381
|
-
|
515
|
+
await chatSDK.startChat(); // Starts NEW chat
|
382
516
|
|
383
|
-
|
517
|
+
const liveChatContext = await chatSDK.getCurrentLiveChatContext(); // Gets chat context
|
384
518
|
|
385
|
-
|
519
|
+
cache.saveChatContext(liveChatContext); // Custom logic to save chat context to cache
|
386
520
|
|
387
|
-
|
521
|
+
...
|
388
522
|
|
389
|
-
|
523
|
+
// Page/component reloads, ALL previous states are GONE
|
390
524
|
|
391
|
-
|
525
|
+
...
|
392
526
|
|
393
|
-
|
527
|
+
const liveChatContext = cache.loadChatContext() // Custom logic to load chat context from cache
|
394
528
|
|
395
|
-
|
396
|
-
|
529
|
+
const optionalParams = {};
|
530
|
+
optionalParams.liveChatContext = liveChatContext;
|
397
531
|
|
398
|
-
|
532
|
+
await chatSDK.startChat(optionalParams); // Reconnects to EXISTING chat
|
399
533
|
|
400
|
-
|
534
|
+
...
|
401
535
|
|
402
|
-
|
403
|
-
|
536
|
+
const messages = await chatSDK.getMessages(); // Gets all messages from EXISTING chat
|
537
|
+
messages.reverse().forEach((message: any) => renderMessage(message)); // Logic to render all messages to UI
|
404
538
|
```
|
405
539
|
|
406
540
|
### Authenticated Chat
|
407
541
|
|
408
|
-
|
409
|
-
// add if using against an authenticated chat endpoint
|
410
|
-
// see https://docs.microsoft.com/en-us/dynamics365/omnichannel/administrator/create-chat-auth-settings on how to set up an authenticated chat widget
|
542
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-chat-auth-settings?tabs=customerserviceadmincenter#create-a-chat-authentication-setting-record on how to set up an authenticated chat
|
411
543
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
544
|
+
```ts
|
545
|
+
const chatSDKConfig = {
|
546
|
+
getAuthToken: async () => {
|
547
|
+
const response = await fetch("http://contosohelp.com/token");
|
548
|
+
if (response.ok) {
|
549
|
+
return await response.text();
|
550
|
+
}
|
551
|
+
else {
|
552
|
+
return null
|
421
553
|
}
|
422
554
|
}
|
555
|
+
}
|
423
556
|
|
424
|
-
|
425
|
-
|
557
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
558
|
+
await chatSDK.initialize();
|
426
559
|
|
427
|
-
|
560
|
+
// from this point, this acts like a regular chat widget
|
428
561
|
```
|
429
562
|
|
430
563
|
### Persistent Chat
|
431
564
|
|
565
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/persistent-chat on how to set up persistent chat
|
566
|
+
|
432
567
|
```ts
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
}
|
568
|
+
const chatSDKConfig = {
|
569
|
+
persistentChat: {
|
570
|
+
disable: false,
|
571
|
+
tokenUpdateTime: 21600000
|
572
|
+
},
|
573
|
+
getAuthToken: async () => {
|
574
|
+
const response = await fetch("http://contosohelp.com/token");
|
575
|
+
if (response.ok) {
|
576
|
+
return await response.text();
|
577
|
+
}
|
578
|
+
else {
|
579
|
+
return null
|
446
580
|
}
|
447
581
|
}
|
582
|
+
}
|
448
583
|
|
449
|
-
|
450
|
-
|
584
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
585
|
+
await chatSDK.initialize();
|
451
586
|
|
452
|
-
|
587
|
+
// from this point, this acts like a persistent chat
|
453
588
|
```
|
454
589
|
### Chat Reconnect with Authenticated User
|
455
590
|
|
591
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session on how to set up chat reconnect
|
592
|
+
|
456
593
|
```ts
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
}
|
594
|
+
const chatSDKConfig = {
|
595
|
+
chatReconnect: {
|
596
|
+
disable: false,
|
597
|
+
},
|
598
|
+
getAuthToken: async () => {
|
599
|
+
const response = await fetch("http://contosohelp.com/token");
|
600
|
+
if (response.ok) {
|
601
|
+
return await response.text();
|
602
|
+
}
|
603
|
+
else {
|
604
|
+
return null
|
469
605
|
}
|
470
606
|
}
|
607
|
+
}
|
471
608
|
|
472
|
-
|
473
|
-
|
609
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
610
|
+
await chatSDK.initialize();
|
474
611
|
|
475
|
-
|
612
|
+
...
|
476
613
|
|
477
|
-
|
614
|
+
const chatReconnectContext = await chatSDK.getChatReconnectContext();
|
478
615
|
|
479
|
-
|
480
|
-
|
481
|
-
|
616
|
+
if (chatReconnectContext.reconnectId) {
|
617
|
+
// Add UX with options to reconnect to previous existing chat or start new chat
|
618
|
+
}
|
482
619
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
620
|
+
// Reconnect chat option
|
621
|
+
const optionalParams = {};
|
622
|
+
optionalParams.reconnectId = chatReconnectContext.reconnectId;
|
623
|
+
chatSDK.startChat(optionalParams);
|
487
624
|
|
488
|
-
|
489
|
-
|
625
|
+
// Start new chat option
|
626
|
+
chatSDK.startChat();
|
490
627
|
```
|
491
628
|
|
492
629
|
### Chat Reconnect with Unauthenticated User
|
493
630
|
|
631
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session on how to set up chat reconnect
|
632
|
+
|
494
633
|
```ts
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
634
|
+
const chatSDKConfig = {
|
635
|
+
chatReconnect: {
|
636
|
+
disable: false,
|
637
|
+
},
|
638
|
+
}
|
500
639
|
|
501
|
-
|
502
|
-
|
640
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
641
|
+
await chatSDK.initialize();
|
503
642
|
|
504
|
-
|
643
|
+
....
|
505
644
|
|
506
|
-
|
645
|
+
const optionalParams: any = {};
|
507
646
|
|
508
|
-
|
509
|
-
|
510
|
-
|
647
|
+
// Retrieve reconnect id from the URL
|
648
|
+
const urlParams = new URLSearchParams(window.location.search);
|
649
|
+
const reconnectId = urlParams.get('oc.reconnectid');
|
511
650
|
|
512
|
-
|
513
|
-
|
514
|
-
|
651
|
+
const params = {
|
652
|
+
reconnectId
|
653
|
+
};
|
515
654
|
|
516
|
-
|
517
|
-
|
655
|
+
// Validate reconnect id
|
656
|
+
const chatReconnectContext = await chatSDK.getChatReconnectContext(params);
|
518
657
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
658
|
+
// If the reconnect id is invalid or expired, redirect URL if there is any URL set in the configuration
|
659
|
+
if (chatReconnectContext.redirectURL) {
|
660
|
+
window.location.replace(chatReconnectContext.redirectURL);
|
661
|
+
}
|
523
662
|
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
663
|
+
// Valid reconnect id, reconnect to previous chat
|
664
|
+
if (chatReconnectContext.reconnectId) {
|
665
|
+
await chatSDK.startChat({
|
666
|
+
reconnectId: chatReconnectContext.reconnectId
|
667
|
+
});
|
668
|
+
} else { // Reconnect id from URL is not valid, start new chat session
|
669
|
+
await chatSDK.startChat();
|
670
|
+
}
|
532
671
|
```
|
533
672
|
|
534
673
|
### Operating Hours
|
535
674
|
|
675
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-operating-hours?tabs=customerserviceadmincenter on how to set up operating hours
|
676
|
+
|
536
677
|
```ts
|
537
|
-
|
538
|
-
|
539
|
-
|
678
|
+
const chatConfig = await chatSDK.getLiveChatConfig();
|
679
|
+
const {LiveWSAndLiveChatEngJoin: liveWSAndLiveChatEngJoin} = liveChatConfig;
|
680
|
+
const {OutOfOperatingHours: outOfOperatingHours} = liveWSAndLiveChatEngJoin;
|
540
681
|
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
682
|
+
if (outOfOperatingHours === "True") {
|
683
|
+
// Handles UX on Out of Operating Hours
|
684
|
+
} else {
|
685
|
+
await chatSDK.startChat();
|
686
|
+
// Renders Custom Chat Widget
|
687
|
+
}
|
547
688
|
```
|
548
689
|
|
549
|
-
###
|
550
|
-
|
551
|
-
**NOTE**: Currently supported on web only
|
552
|
-
```ts
|
553
|
-
import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
|
554
|
-
import ReactWebChat from 'botframework-webchat';
|
690
|
+
### Using [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat)
|
691
|
+
> :warning: Currently supported on web only
|
555
692
|
|
556
|
-
|
693
|
+
Minimum Requirement Checklist
|
694
|
+
1. [ ] Initialize ChatSDK
|
695
|
+
1. [ ] Start new conversation
|
696
|
+
1. [ ] Create Chat Adapter
|
697
|
+
1. [ ] Create WebChat store with default middlewares
|
698
|
+
1. [ ] Send Default Channel Message Tags using Store Middleware (See [here](/docs//DEVELOPMENT_GUIDE.md#send-default-channel-message-tags-using-store-middleware)) ❗ Required
|
699
|
+
1. [ ] Render WebChat
|
557
700
|
|
558
|
-
|
559
|
-
|
701
|
+
```ts
|
702
|
+
import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
|
703
|
+
import ReactWebChat, {createStore} from 'botframework-webchat';
|
560
704
|
|
561
|
-
|
562
|
-
|
563
|
-
|
705
|
+
// 1. ChatSDK Initialization
|
706
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig);
|
707
|
+
await chatSDK.initialize();
|
564
708
|
|
565
|
-
|
566
|
-
|
709
|
+
// 2. Start new conversation
|
710
|
+
await chatSDK.startChat();
|
567
711
|
|
568
|
-
|
569
|
-
|
570
|
-
console.log(`[NewMessage] ${message.content}`); // IC3 protocol message data
|
571
|
-
console.log(message);
|
572
|
-
});
|
712
|
+
// 3. Create chat adapter
|
713
|
+
const chatAdapter = await chatSDK.createChatAdapter();
|
573
714
|
|
574
|
-
|
715
|
+
// 4. Create WebChat store with middlewares
|
716
|
+
const store = createStore(
|
717
|
+
{}, // initial state
|
718
|
+
sendDefaultMessagingTagsMiddleware // ❗ Required
|
719
|
+
);
|
575
720
|
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
721
|
+
// 5. Render WebChat
|
722
|
+
<ReactWebChat
|
723
|
+
store={store}
|
724
|
+
userID="teamsvisitor"
|
725
|
+
directLine={chatAdapter}
|
726
|
+
sendTypingIndicator={true}
|
727
|
+
/>
|
581
728
|
```
|
582
729
|
|
583
730
|
### Escalation to Voice & Video
|
584
|
-
|
731
|
+
> :warning: Currently supported on web only
|
732
|
+
|
733
|
+
> See https://docs.microsoft.com/en-us/dynamics365/customer-service/call-options-visual-engagement on how to set up calling options
|
734
|
+
|
585
735
|
```ts
|
586
|
-
|
736
|
+
import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
|
587
737
|
|
588
|
-
|
738
|
+
...
|
589
739
|
|
590
|
-
|
591
|
-
|
740
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
741
|
+
await chatSDK.initialize();
|
592
742
|
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
743
|
+
let VoiceVideoCallingSDK;
|
744
|
+
try {
|
745
|
+
VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
|
746
|
+
console.log("VoiceVideoCalling loaded");
|
747
|
+
} catch (e) {
|
748
|
+
console.log(`Failed to load VoiceVideoCalling: ${e}`);
|
599
749
|
|
600
|
-
|
601
|
-
|
602
|
-
|
750
|
+
if (e.message === 'UnsupportedPlatform') {
|
751
|
+
// Voice Video Calling feature is not supported on this platform
|
752
|
+
}
|
603
753
|
|
604
|
-
|
605
|
-
|
606
|
-
}
|
754
|
+
if (e.message === 'FeatureDisabled') {
|
755
|
+
// Voice Video Calling feature is disabled on admin side
|
607
756
|
}
|
757
|
+
}
|
608
758
|
|
609
|
-
|
759
|
+
await chatSDK.startChat();
|
610
760
|
|
611
|
-
|
612
|
-
|
613
|
-
// Initialize only if VoiceVideoCallingSDK is defined
|
614
|
-
if (VoiceVideoCallingSDK) {
|
615
|
-
try {
|
616
|
-
await VoiceVideoCallingSDK.initialize({
|
617
|
-
chatToken,
|
618
|
-
selfVideoHTMLElementId: 'selfVideo', // HTML element id where video stream of the agent will be rendered
|
619
|
-
remoteVideoHTMLElementId: 'remoteVideo', // HTML element id where video stream of the customer will be rendered
|
620
|
-
OCClient: chatSDK.OCClient
|
621
|
-
});
|
622
|
-
} catch (e) {
|
623
|
-
console.error("Failed to initialize VoiceVideoCalling!");
|
624
|
-
}
|
761
|
+
const chatToken: any = await chatSDK.getChatToken();
|
625
762
|
|
626
|
-
|
627
|
-
|
628
|
-
|
763
|
+
// Initialize only if VoiceVideoCallingSDK is defined
|
764
|
+
if (VoiceVideoCallingSDK) {
|
765
|
+
try {
|
766
|
+
await VoiceVideoCallingSDK.initialize({
|
767
|
+
chatToken,
|
768
|
+
selfVideoHTMLElementId: 'selfVideo', // HTML element id where video stream of the agent will be rendered
|
769
|
+
remoteVideoHTMLElementId: 'remoteVideo', // HTML element id where video stream of the customer will be rendered
|
770
|
+
OCClient: chatSDK.OCClient
|
629
771
|
});
|
772
|
+
} catch (e) {
|
773
|
+
console.error("Failed to initialize VoiceVideoCalling!");
|
774
|
+
}
|
630
775
|
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
776
|
+
// Triggered when there's an incoming call
|
777
|
+
VoiceVideoCallingSDK.onCallAdded(() => {
|
778
|
+
...
|
779
|
+
});
|
635
780
|
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
781
|
+
// Triggered when local video stream is available (e.g.: Local video added succesfully in selfVideoHTMLElement)
|
782
|
+
VoiceVideoCallingSDK.onLocalVideoStreamAdded(() => {
|
783
|
+
...
|
784
|
+
});
|
640
785
|
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
786
|
+
// Triggered when local video stream is unavailable (e.g.: Customer turning off local video)
|
787
|
+
VoiceVideoCallingSDK.onLocalVideoStreamRemoved(() => {
|
788
|
+
...
|
789
|
+
});
|
645
790
|
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
791
|
+
// Triggered when remote video stream is available (e.g.: Remote video added succesfully in remoteVideoHTMLElement)
|
792
|
+
VoiceVideoCallingSDK.onRemoteVideoStreamAdded(() => {
|
793
|
+
...
|
794
|
+
});
|
650
795
|
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
796
|
+
// Triggered when remote video stream is unavailable (e.g.: Agent turning off remote video)
|
797
|
+
VoiceVideoCallingSDK.onRemoteVideoStreamRemoved(() => {
|
798
|
+
...
|
799
|
+
});
|
800
|
+
|
801
|
+
// Triggered when current call has ended or disconnected regardless the party
|
802
|
+
VoiceVideoCalling.onCallDisconnected(() => {
|
803
|
+
...
|
804
|
+
});
|
655
805
|
|
656
|
-
|
657
|
-
|
806
|
+
// Check if microphone is muted
|
807
|
+
const isMicrophoneMuted = VoiceVideoCallingSDK.isMicrophoneMuted();
|
658
808
|
|
659
|
-
|
660
|
-
|
809
|
+
// Check if remote video is available
|
810
|
+
const isRemoteVideoEnabled = VoiceVideoCallingSDK.isRemoteVideoEnabled();
|
661
811
|
|
662
|
-
|
663
|
-
|
812
|
+
// Check if local video is available
|
813
|
+
const isLocalVideoEnabled = VoiceVideoCallingSDK.isLocalVideoEnabled();
|
664
814
|
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
815
|
+
// Accepts incoming call
|
816
|
+
const acceptCallConfig = {
|
817
|
+
withVideo: true // Accept call with/without video stream
|
818
|
+
};
|
819
|
+
await VoiceVideoCallingSDK.acceptCall(acceptCallConfig);
|
670
820
|
|
671
|
-
|
672
|
-
|
821
|
+
// Rejects incoming call
|
822
|
+
await VoiceVideoCallingSDK.rejectCall();
|
673
823
|
|
674
|
-
|
675
|
-
|
824
|
+
// Ends/Stops current call
|
825
|
+
await VoiceVideoCallingSDK.stopCall();
|
676
826
|
|
677
|
-
|
678
|
-
|
827
|
+
// Mute/Unmute current call
|
828
|
+
await VoiceVideoCallingSDK.toggleMute()
|
679
829
|
|
680
|
-
|
681
|
-
|
830
|
+
// Display/Hide local video of current call
|
831
|
+
await VoiceVideoCallingSDK.toggleLocalVideo()
|
682
832
|
|
683
|
-
|
684
|
-
|
685
|
-
|
833
|
+
// Clean up VoiceVideoCallingSDK (e.g.: Usually called when customer ends chat session)
|
834
|
+
VoiceVideoCallingSDK.close();
|
835
|
+
}
|
686
836
|
```
|
687
837
|
|
688
838
|
## Feature Comparisons
|
@@ -727,20 +877,20 @@ Some of the data being collected are the following:
|
|
727
877
|
If your organization is concerned about the data collected by the Chat SDK, you have the option to turn off automatic data collection by adding a flag in the `ChatSDKConfig`.
|
728
878
|
|
729
879
|
```ts
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
880
|
+
const omnichannelConfig = {
|
881
|
+
orgUrl: "",
|
882
|
+
orgId: "",
|
883
|
+
widgetId: ""
|
884
|
+
};
|
735
885
|
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
886
|
+
const chatSDKConfig = {
|
887
|
+
telemetry: {
|
888
|
+
disable: true // Disable telemetry
|
889
|
+
}
|
890
|
+
};
|
741
891
|
|
742
|
-
|
743
|
-
|
892
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
893
|
+
await chatSDK.initialize();
|
744
894
|
```
|
745
895
|
|
746
896
|
# Contributing
|