UNPKG

33.3 kBMarkdownView Raw
1# Omnichannel Chat SDK 💬
2
3[![npm version](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk.svg)](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk)
4[![install size](https://packagephobia.com/badge?p=@microsoft/omnichannel-chat-sdk)](https://packagephobia.com/result?p=@microsoft/omnichannel-chat-sdk)
5![Release CI](https://github.com/microsoft/omnichannel-chat-sdk/workflows/Release%20CI/badge.svg)
6![npm](https://img.shields.io/npm/dm/@microsoft/omnichannel-chat-sdk)
7
8> ❗ We recommend using official release versions in production as listed [here](#releases). Support will be provided only on official versions.
9
10> 📢 Try out our new React component library [omnichannel-chat-widget](https://github.com/microsoft/omnichannel-chat-widget) with Chat SDK
11
12Headless Chat SDK to build your own chat widget against Dynamics 365 Omnichannel Services.
13
14Please 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)
15
16## Table of Contents
17- [Live Chat Widget vs. Chat SDK](#live-chat-widget-vs-chat-sdk)
18- [Releases](#releases)
19- [Installation](#installation)
20- [Installation on React Native](#installation-on-react-native)
21- [SDK Methods](#sdk-methods)
22 - [Initialization](#initialization)
23 - [Start Chat](#start-chat)
24 - [End Chat](#end-chat)
25 - [Get Pre-Chat Survey](#get-pre-chat-survey)
26 - [Get Live Chat Config](#get-live-chat-config)
27 - [Get Current Live Chat Context](#get-current-live-chat-context)
28 - [Get Data Masking Rules](#get-data-masking-rules)
29 - [Get Chat Reconnect Context](#get-chat-reconnect-context)
30 - [Get Conversation Details](#get-conversation-details)
31 - [Get Chat Token](#get-chat-token)
32 - [Get Calling Token](#get-calling-token)
33 - [Get Messages](#get-messages)
34 - [Send Messages](#send-messages)
35 - [On New Message](#on-new-message)
36 - [On Typing Event](#on-typing-event)
37 - [On Agent End Session](#on-agent-end-session)
38 - [Send Typing Event](#send-typing-event)
39 - [Email Live Chat Transcript](#email-live-chat-transcript)
40 - [Get Live Chat Transcript](#get-live-chat-transcript)
41 - [Upload File Attachment](#upload-file-attachment)
42 - [Download File Attachment](#download-file-attachment)
43 - [Create Chat Adapter](#create-chat-adapter)
44 - [Get Voice & Video Calling](#get-voice--video-calling)
45 - [Get Post Chat Survey Context](#get-post-chat-survey-context)
46- [Common Scenarios](#common-scenarios)
47 - [Using BotFramework-WebChat](#using-botframework-webchat)
48 - [Escalation to Voice & Video](#escalation-to-voice--video)
49 - [Pre-Chat Survey](#pre-chat-survey)
50 - [Post-Chat Survey](#post-chat-survey)
51 - [Reconnect to existing Chat](#reconnect-to-existing-chat)
52 - [Authenticated Chat](#authenticated-chat)
53 - [Persistent Chat](#persistent-chat)
54 - [Chat Reconnect with Authenticated User](#chat-reconnect-with-authenticated-user)
55 - [Chat Reconnect with Unauthenticated User](#chat-reconnect-with-unauthenticated-user)
56 - [Operating Hours](#operating-hours)
57 - [Single Sign-on for Bots](/docs/scenarios/SINGLE_SIGN_ON_FOR_BOTS.md)
58- [Sample Apps](https://github.com/microsoft/omnichannel-chat-sdk-samples)
59- [Feature Comparisons](#feature-comparisons)
60- [Telemetry](#telemetry)
61- [Development Guide](docs/DEVELOPMENT_GUIDE.md)
62- [Troubleshooting Guide](docs/TROUBLESHOOTING_GUIDE.md)
63
64## Live Chat Widget vs. Chat SDK
65
66Omnichannel offers an live chat widget (LCW) by default. You can use the Chat SDK to build your custom chat widget if:
67- You want to fully customize the user interface of the chat widget to conform with your branding.
68- You want to integrate Omnichannel in your mobile app using React Native.
69- You want to integrate additional functionalities that LCW does not offer.
70- Some other cool ideas. Please share with us on what you've achieved with the Chat SDK! 🙂
71
72### Feature Comparisons
73
74| Feature | Live Chat Widget | Chat SDK | Notes |
75| ----- | ----- | ----- | ----- |
76| Bring Your Own Widget | ❌ | ✔ | |
77| Web Support | ✔ | ✔ |
78| React Native Support | ❌ | ✔ |
79| Escalation to Voice & Video | ✔ | ✔ | Only supported on Web |
80| Co-browse | ✔ | 3rd party add-on | Only supported on Web |
81| Screen Sharing | ✔ | 3rd party add-on | Only supported on Web |
82| Authenticated Chat | ✔ | ✔ |
83| Pre-chat Survey | ✔ | ✔ |
84| Post-chat Survey | ✔ | ✔ |
85| Download Transcript | ✔ | ✔ |
86| Email Transcript | ✔ | ✔ |
87| Data Masking | ✔ | ✔ |
88| File Attachments | ✔ | ✔ |
89| Custom Context | ✔ | ✔ |
90| Proactive Chat | ✔ | BYOI **\*** |
91| Persistent Chat | ✔ | ✔ |
92| Chat Reconnect | ✔ | ✔ |
93| Operating Hours | ✔ | ✔ |
94| Get Agent Availability | ✔ | ✔ |
95| Queue Position | ✔ | ✔ | No SDK method. Handled as *system message* |
96| Average Wait Time | ✔ | ✔ | No SDK method. Handled as *system message* |
97
98**\*** BYOI: Bring Your Own Implementation
99
100## Releases
101
102New releases are published on a regular basis to ensure the product quality.
103
104| Version | Docs | Release Date | End of Support | Deprecated |
105| -- | -- | -- | -- | -- |
106| 1.6.2 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.6.2) | Dec 12th 2023 | Dec 12th 2024 | |
107| 1.6.1 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.6.1) | Dec 7th 2023 | Dec 7th 2024 | |
108| 1.6.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.6.0) | Dec 4th 2023 | Dec 4th 2024 | |
109| 1.5.7 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.7) | Nov 20th 2023 | Nov 20th 2024 | |
110| 1.5.6 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.6) | Nov 11th 2023 | Nov 11th 2024 | |
111| 1.5.5 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.5) | Oct 31st 2023 | Oct 31st 2024 | |
112| 1.5.4 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.4) | Oct 20th 2023 | Oct 20th 2024 | |
113| 1.5.3 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.3) | Oct 18th 2023 | Oct 18th 2024 | |
114| 1.5.2 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.2) | Oct 14th 2023 | Oct 14th 2024 | |
115| 1.5.1 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.1) | Oct 10th 2023 | Oct 10th 2024 | |
116| 1.5.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.5.0) | Sep 29th 2023 | Sep 29th 2024 | |
117| 1.4.7 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.7) | Sep 13th 2023 | Sep 13th 2024 | |
118| 1.4.6 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.6) | Aug 15th 2023 | Aug 15th 2024 | |
119| 1.4.5 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.5) | Aug 2nd 2023 | Aug 2nd 2024 | |
120| 1.4.4 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.4) | Jul 19th 2023 | Jul 19th 2024 | |
121| 1.4.3 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.3) | Jun 15th 2023 | Jun 15th 2024 | |
122| 1.4.2 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.2) | May 19th 2023 | May 19th 2024 | |
123| 1.4.1 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.1) | May 5th 2023 | May 5th 2024 | |
124| 1.4.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.4.0) | May 2nd 2023 | May 2nd 2024 | |
125| 1.3.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.3.0) | Apr 5th 2023 | Apr 5th 2024 | |
126| 1.2.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.2.0) | Nov 11th 2022 | Nov 11th 2023 | ✔️ |
127| 1.1.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.1.0) | Apr 15th 2021 | Apr 15th 2022 | ✔️ |
128| 1.0.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.0.0) | Oct 8th 2021 | Oct 8th 2022 | ✔️ |
129| 0.3.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v0.3.0) | Sep 3rd 2021 | Sep 3rd 2022 | ✔️ |
130| 0.2.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v0.2.0) | Apr 30th 2021 | Apr 30th 2022 | ✔️ |
131| 0.1.0 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v0.1.0) | Oct 26th 2020 | Oct 26th 2021 | ✔️ |
132
133## Installation
134
135```
136npm install @microsoft/omnichannel-chat-sdk --save
137```
138
139## Installation on React Native
140
141The following steps will be required to run Omnichannel Chat SDK on React Native:
142
1431. Install `node-libs-react-native`
144 ```
145 npm install node-libs-react-native --save-dev
146 ```
147
1481. Install `react-native-randomBytes`
149 ```
150 npm install react-native-randombytes --save-dev
151 ```
152
1531. Install `react-native-get-random-values`
154 ```
155 npm install react-native-get-random-values --save-dev
156 ```
157
1581. Install `react-native-url-polyfill`
159 ```
160 npm install react-native-url-polyfill --save-dev
161 ```
162
1631. Install `@azure/core-asynciterator-polyfill`
164 ```
165 npm install @azure/core-asynciterator-polyfill --save-dev
166 ```
167
1681. Update *metro.config.js* to use React Native compatible Node Core modules
169 ```ts
170 module.exports = {
171 // ...
172 resolver: {
173 extraNodeModules: {
174 ...require('node-libs-react-native'),
175 net: require.resolve('node-libs-react-native/mock/net'),
176 tls: require.resolve('node-libs-react-native/mock/tls')
177 }
178 }
179 };
180 ```
181
1821. Add following *import* on top of your entry point file
183 ```ts
184 import 'node-libs-react-native/globals';
185 import 'react-native-get-random-values';
186 import 'react-native-url-polyfill/auto';
187 import '@azure/core-asynciterator-polyfill';
188 ```
189
190## SDK Methods
191
192### Initialization
193
194It handles the initialization of ChatSDK internal data.
195
196```ts
197import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
198
199const omnichannelConfig = {
200 orgUrl: "",
201 orgId: "",
202 widgetId: ""
203};
204
205const chatSDKConfig = { // Optional
206 dataMasking: {
207 disable: false,
208 maskingCharacter: '#'
209 }
210};
211
212const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
213
214const optionalParams = {
215 getLiveChatConfigOptionalParams: {
216 sendCacheHeaders: false // Whether to send Cache-Control HTTP header to GetChatConfig call
217 }
218};
219
220await chatSDK.initialize(optionalParams);
221```
222
223### Start Chat
224
225It starts an Omnichannel conversation.
226
227```ts
228const customContext = {
229 'contextKey1': {'value': 'contextValue1', 'isDisplayable': true},
230 'contextKey2': {'value': 12.34, 'isDisplayable': false},
231 'contextKey3': {'value': true}
232};
233
234const optionalParams = {
235 preChatResponse: '', // PreChatSurvey response
236 liveChatContext: {}, // EXISTING chat context data
237 customContext, // Custom Context
238 sendDefaultInitContext: true // Send default init context ⚠️ Web only
239};
240
241await chatSDK.startChat(optionalParams);
242```
243
244### End Chat
245
246It ends the current Omnichannel conversation.
247
248```ts
249await chatSDK.endChat();
250```
251
252### Get Pre-Chat Survey
253
254It gets the Pre-Chat Survey from Live Chat Config. Pre-Chat Survey is in Adaptive Card format.
255
256`Option 1`
257```ts
258const preChatSurvey = await getPreChatSurvey(); // Adaptive Cards JSON payload data
259```
260`Option 2`
261```ts
262const parseToJSON = false;
263const preChatSurvey = await getPreChatSurvey(parseToJSON); // Adaptive Cards payload data as string
264```
265
266### Get Live Chat Config
267
268It fetches the Live Chat Config.
269
270```ts
271const liveChatConfig = await chatSDK.getLiveChatConfig();
272```
273
274### Get Current Live Chat Context
275
276It gets the current live chat context information to be used to reconnect to the same conversation.
277
278```ts
279const liveChatContext = await chatSDK.getCurrentLiveChatContext();
280```
281
282### Get Data Masking Rules
283
284It gets the active data masking rules from Live Chat Config.
285
286```ts
287const dataMaskingRules = await chatSDK.getDataMaskingRules();
288```
289
290### Get Chat Reconnect Context
291
292It gets the current reconnectable chat context information to connect to a previous existing chat session.
293
294`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)
295
296```ts
297const optionalParams = {
298 reconnectId: '', // reconnect Id
299};
300
301const chatReconnectContext = await chatSDK.getChatReconnectContext(optionalParams);
302```
303
304### Get Conversation Details
305
306It gets the details of the current conversation such as its state & when the agent joined the conversation.
307
308```ts
309const optionalParams = {
310 liveChatContext: {}, // EXISTING chat context data
311};
312
313const conversationDetails = await chatSDK.getConversationDetails(optionalParams);
314```
315
316### Get chat Token
317
318It gets the chat token used to initiates a chat with Omnichannel messaging client.
319
320```ts
321const chatToken = await chatSDK.getChatToken();
322```
323
324### Get Calling Token
325
326It gets the calling token used to initiates a Voice & Video Call.
327
328```ts
329const callingToken = await chatSDK.getCallingToken();
330```
331
332### Get Messages
333
334It gets all the messages of the current conversation.
335
336```ts
337const messages = await chatSDK.getMessages();
338```
339
340### Send Messages
341
342It sends a message to Omnichannel.
343
344```ts
345import {DeliveryMode, MessageContentType, MessageType, PersonType} from '@microsoft/omnichannel-chat-sdk';
346
347...
348
349const displayName = "Contoso"
350const message = "Sample message from customer";
351const messageToSend = {
352 content: message
353};
354
355await chatSDK.sendMessage(messageToSend);
356```
357
358### On New Message
359
360It subscribes to new incoming messages of the current conversation such as system messages, client messages, agent messages, adaptive cards and attachments.
361
362```ts
363const optionalParams = {
364 rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
365}
366
367chatSDK.onNewMessage((message) => {
368 console.log(`[NewMessage] ${message.content}`);
369 console.log(message);
370}, optionalParams);
371```
372### On Typing Event
373
374It subscribes to agent typing event.
375
376```ts
377chatSDK.onTypingEvent(() => {
378 console.log("Agent is typing...");
379})
380```
381
382### On Agent End Session
383
384It subscribes to agent ending the session of the conversation.
385
386```ts
387chatSDK.onAgentEndSession(() => {
388 console.log("Session ended!");
389});
390```
391
392### Send Typing Event
393
394It sends a customer typing event.
395
396```ts
397await chatSDK.sendTypingEvent();
398```
399
400### Email Live Chat Transcript
401
402It sends an email of the live chat transcript.
403
404```ts
405const body = {
406 emailAddress: 'contoso@microsoft.com',
407 attachmentMessage: 'Attachment Message'
408};
409await chatSDK.emailLiveChatTranscript(body);
410```
411
412### Get Live Chat Transcript
413
414It fetches the current conversation transcript data in JSON.
415
416```ts
417const optionalParams = {
418 liveChatContext: {}, // EXISTING chat context data
419};
420
421await chatSDK.getLiveChatTranscript(optionalParams);
422```
423
424### Upload File Attachment
425
426It sends a file attachment to the current conversation.
427
428```ts
429const fileInfo = {
430 name: '',
431 type: '',
432 size: '',
433 data: ''
434};
435await chatSDK.uploadFileAttachment(fileInfo);
436```
437
438### Download File Attachment
439
440It downloads the file attachment of the incoming message as a Blob response.
441
442```ts
443const blobResponse = await chatsdk.downloadFileAttachment(message.fileMetadata);
444
445...
446
447// React Native implementation
448const fileReaderInstance = new FileReader();
449fileReaderInstance.readAsDataURL(blobResponse);
450fileReaderInstance.onload = () => {
451 const base64data = fileReaderInstance.result;
452 return <Image source={{uri: base64data}}/>
453}
454```
455
456### Create Chat Adapter
457
458> :warning: Currently supported on web only
459
460It creates a chat adapter to use with [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat).
461
462```ts
463const chatAdapter = await chatSDK.createChatAdapter();
464```
465
466### Get Voice & Video Calling
467
468> :warning: Currently supported on web only
469
470> :warning: Please ensure voice & video call is stopped before leveraging endChat SDK method
471
472It fetches the SDK for Escalation to Voice & Video.
473
474```ts
475try {
476 const VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
477 console.log("VoiceVideoCalling loaded");
478} catch (e) {
479 console.log(`Failed to load VoiceVideoCalling: ${e}`);
480
481 if (e.message === 'UnsupportedPlatform') {
482 // Voice Video Calling feature is not supported on this platform
483 }
484
485 if (e.message === 'FeatureDisabled') {
486 // Voice Video Calling feature is disabled on admin side
487 }
488}
489```
490### Get Post Chat Survey Context
491
492It gets the participant type that should be used for the survey and both the default and bot survey details.
493
494```ts
495const postChatSurveyContext = await chatSDK.getPostChatSurveyContext();
496```
497
498### Get Agent Availability
499
500It gets information on whether a queue is available, and whether there are agents available in that queue, as well as queue position and average wait time. This call only supports authenticated chat.
501
502```ts
503const agentAvailability = await chatSDK.getAgentAvailability();
504```
505
506## Common Scenarios
507
508### Pre-Chat Survey
509
510> See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-pre-chat-survey?tabs=customerserviceadmincenter on how to set up pre-conversation surveys
511
512```ts
513 import * as AdaptiveCards, { Action } from "adaptivecards";
514
515 ...
516
517 const preChatSurvey = await chatSDK.getPreChatSurvey();
518
519 ...
520
521 // Web implementation
522 const renderPreChatSurvey = () => {
523 const adaptiveCard = new AdaptiveCards.AdaptiveCard();
524 adaptiveCard.parse(preChatSurvey); // Parses Adaptive Card JSON data
525 adaptiveCard.onExecuteAction = async (action: Action) => { // Adaptive Card event handler
526 const preChatResponse = (action as any).data;
527 const optionalParams: any = {};
528 if (preChatResponse) {
529 optionalParams.preChatResponse = preChatResponse;
530 }
531 await chatSDK.startChat(optionalParams);
532 }
533
534 const renderedCard = adaptiveCard.render(); // Renders as HTML element
535 return <div ref={(n) => { // Returns React element
536 n && n.firstChild && n.removeChild(n.firstChild); // Removes duplicates fix
537 renderedCard && n && n.appendChild(renderedCard);
538 }} />
539 }
540
541```
542
543### Post-Chat Survey
544
545> See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-post-conversation-survey?tabs=customerserviceadmincenter on how to set up post-conversation surveys
546
547> ❗ `chatSDK.getPostChatSurveyContext()` needs to be called before `chatSDK.endChat()` is called
548
549```ts
550// 1. Start chat
551await chatSDK.startChat();
552
553// 2. Save post chat survey context before ending chat
554try {
555 const context = await chatSDK.getPostChatSurveyContext();
556 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.
557 // formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
558 // If "&lang=" is not set on the url, the locale will be English.
559 const link = context.participantType === "Bot" ? context.botSurveyInviteLink : context.surveyInviteLink;
560 const locale = context.participantType === "Bot" ? context.botFormsProLocale : context.formsProLocale;
561 const linkToSend = link + "&lang=" + locale;
562 // This link is accessible and will redirect to the survey page. Use it as you see fit.
563 }
564} catch (ex) {
565 // If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
566}
567
568// 3. End chat
569await chatSDK.endChat();
570
571// 4. Display Post Chat
572```
573
574### Reconnect to existing Chat
575
576```ts
577await chatSDK.startChat(); // Starts NEW chat
578
579const liveChatContext = await chatSDK.getCurrentLiveChatContext(); // Gets chat context
580
581cache.saveChatContext(liveChatContext); // Custom logic to save chat context to cache
582
583...
584
585// Page/component reloads, ALL previous states are GONE
586
587...
588
589const liveChatContext = cache.loadChatContext() // Custom logic to load chat context from cache
590
591const optionalParams = {};
592optionalParams.liveChatContext = liveChatContext;
593
594await chatSDK.startChat(optionalParams); // Reconnects to EXISTING chat
595
596...
597
598const messages = await chatSDK.getMessages(); // Gets all messages from EXISTING chat
599messages.reverse().forEach((message: any) => renderMessage(message)); // Logic to render all messages to UI
600```
601
602### Authenticated Chat
603
604> 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
605
606```ts
607const chatSDKConfig = {
608 getAuthToken: async () => {
609 const response = await fetch("http://contosohelp.com/token");
610 if (response.ok) {
611 return await response.text();
612 }
613 else {
614 return null
615 }
616 }
617}
618
619const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
620await chatSDK.initialize();
621
622// from this point, this acts like a regular chat widget
623```
624
625### Persistent Chat
626
627> See https://docs.microsoft.com/en-us/dynamics365/customer-service/persistent-chat on how to set up persistent chat
628
629```ts
630const chatSDKConfig = {
631 persistentChat: {
632 disable: false,
633 tokenUpdateTime: 21600000
634 },
635 getAuthToken: async () => {
636 const response = await fetch("http://contosohelp.com/token");
637 if (response.ok) {
638 return await response.text();
639 }
640 else {
641 return null
642 }
643 }
644}
645
646const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
647await chatSDK.initialize();
648
649// from this point, this acts like a persistent chat
650```
651### Chat Reconnect with Authenticated User
652
653> 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
654
655```ts
656const chatSDKConfig = {
657 chatReconnect: {
658 disable: false,
659 },
660 getAuthToken: async () => {
661 const response = await fetch("http://contosohelp.com/token");
662 if (response.ok) {
663 return await response.text();
664 }
665 else {
666 return null
667 }
668 }
669}
670
671const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
672await chatSDK.initialize();
673
674...
675
676const chatReconnectContext = await chatSDK.getChatReconnectContext();
677
678if (chatReconnectContext.reconnectId) {
679 // Add UX with options to reconnect to previous existing chat or start new chat
680}
681
682// Reconnect chat option
683const optionalParams = {};
684optionalParams.reconnectId = chatReconnectContext.reconnectId;
685chatSDK.startChat(optionalParams);
686
687// Start new chat option
688chatSDK.startChat();
689```
690
691### Chat Reconnect with Unauthenticated User
692
693> 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
694
695```ts
696const chatSDKConfig = {
697 chatReconnect: {
698 disable: false,
699 },
700}
701
702const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
703await chatSDK.initialize();
704
705....
706
707const optionalParams: any = {};
708
709// Retrieve reconnect id from the URL
710const urlParams = new URLSearchParams(window.location.search);
711const reconnectId = urlParams.get('oc.reconnectid');
712
713const params = {
714 reconnectId
715};
716
717// Validate reconnect id
718const chatReconnectContext = await chatSDK.getChatReconnectContext(params);
719
720// If the reconnect id is invalid or expired, redirect URL if there is any URL set in the configuration
721if (chatReconnectContext.redirectURL) {
722 window.location.replace(chatReconnectContext.redirectURL);
723}
724
725// Valid reconnect id, reconnect to previous chat
726if (chatReconnectContext.reconnectId) {
727 await chatSDK.startChat({
728 reconnectId: chatReconnectContext.reconnectId
729 });
730} else { // Reconnect id from URL is not valid, start new chat session
731 await chatSDK.startChat();
732}
733```
734
735### Operating Hours
736
737> See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-operating-hours?tabs=customerserviceadmincenter on how to set up operating hours
738
739```ts
740const chatConfig = await chatSDK.getLiveChatConfig();
741const {LiveWSAndLiveChatEngJoin: liveWSAndLiveChatEngJoin} = liveChatConfig;
742const {OutOfOperatingHours: outOfOperatingHours} = liveWSAndLiveChatEngJoin;
743
744if (outOfOperatingHours === "True") {
745 // Handles UX on Out of Operating Hours
746} else {
747 await chatSDK.startChat();
748 // Renders Custom Chat Widget
749}
750```
751
752### Using [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat)
753> :warning: Currently supported on web only
754
755Minimum Requirement Checklist
7561. [ ] Initialize ChatSDK
7571. [ ] Start new conversation
7581. [ ] Create Chat Adapter
7591. [ ] Create WebChat store with default middlewares
760 1. [ ] Send Default Channel Message Tags using Store Middleware (See [here](/docs//DEVELOPMENT_GUIDE.md#send-default-channel-message-tags-using-store-middleware)) ❗ Required
7611. [ ] Render WebChat
762
763```ts
764import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
765import ReactWebChat, {createStore} from 'botframework-webchat';
766
767// 1. ChatSDK Initialization
768const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig);
769await chatSDK.initialize();
770
771// 2. Start new conversation
772await chatSDK.startChat();
773
774// 3. Create chat adapter
775const chatAdapter = await chatSDK.createChatAdapter();
776
777// 4. Create WebChat store with middlewares
778const store = createStore(
779 {}, // initial state
780 sendDefaultMessagingTagsMiddleware // ❗ Required
781);
782
783// 5. Render WebChat
784<ReactWebChat
785 store={store}
786 userID="teamsvisitor"
787 directLine={chatAdapter}
788 sendTypingIndicator={true}
789/>
790```
791
792### Escalation to Voice & Video
793> :warning: Currently supported on web only
794
795> See https://docs.microsoft.com/en-us/dynamics365/customer-service/call-options-visual-engagement on how to set up calling options
796
797```ts
798import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
799
800...
801
802const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
803await chatSDK.initialize();
804
805let VoiceVideoCallingSDK;
806try {
807 VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
808 console.log("VoiceVideoCalling loaded");
809} catch (e) {
810 console.log(`Failed to load VoiceVideoCalling: ${e}`);
811
812 if (e.message === 'UnsupportedPlatform') {
813 // Voice Video Calling feature is not supported on this platform
814 }
815
816 if (e.message === 'FeatureDisabled') {
817 // Voice Video Calling feature is disabled on admin side
818 }
819}
820
821await chatSDK.startChat();
822
823const chatToken: any = await chatSDK.getChatToken();
824
825// Initialize only if VoiceVideoCallingSDK is defined
826if (VoiceVideoCallingSDK) {
827 try {
828 await VoiceVideoCallingSDK.initialize({
829 chatToken,
830 selfVideoHTMLElementId: 'selfVideo', // HTML element id where video stream of the agent will be rendered
831 remoteVideoHTMLElementId: 'remoteVideo', // HTML element id where video stream of the customer will be rendered
832 OCClient: chatSDK.OCClient
833 });
834 } catch (e) {
835 console.error("Failed to initialize VoiceVideoCalling!");
836 }
837
838 // Triggered when there's an incoming call
839 VoiceVideoCallingSDK.onCallAdded(() => {
840 ...
841 });
842
843 // Triggered when local video stream is available (e.g.: Local video added succesfully in selfVideoHTMLElement)
844 VoiceVideoCallingSDK.onLocalVideoStreamAdded(() => {
845 ...
846 });
847
848 // Triggered when local video stream is unavailable (e.g.: Customer turning off local video)
849 VoiceVideoCallingSDK.onLocalVideoStreamRemoved(() => {
850 ...
851 });
852
853 // Triggered when remote video stream is available (e.g.: Remote video added succesfully in remoteVideoHTMLElement)
854 VoiceVideoCallingSDK.onRemoteVideoStreamAdded(() => {
855 ...
856 });
857
858 // Triggered when remote video stream is unavailable (e.g.: Agent turning off remote video)
859 VoiceVideoCallingSDK.onRemoteVideoStreamRemoved(() => {
860 ...
861 });
862
863 // Triggered when current call has ended or disconnected regardless the party
864 VoiceVideoCalling.onCallDisconnected(() => {
865 ...
866 });
867
868 // Check if microphone is muted
869 const isMicrophoneMuted = VoiceVideoCallingSDK.isMicrophoneMuted();
870
871 // Check if remote video is available
872 const isRemoteVideoEnabled = VoiceVideoCallingSDK.isRemoteVideoEnabled();
873
874 // Check if local video is available
875 const isLocalVideoEnabled = VoiceVideoCallingSDK.isLocalVideoEnabled();
876
877 // Accepts incoming call
878 const acceptCallConfig = {
879 withVideo: true // Accept call with/without video stream
880 };
881 await VoiceVideoCallingSDK.acceptCall(acceptCallConfig);
882
883 // Rejects incoming call
884 await VoiceVideoCallingSDK.rejectCall();
885
886 // Ends/Stops current call
887 await VoiceVideoCallingSDK.stopCall();
888
889 // Mute/Unmute current call
890 await VoiceVideoCallingSDK.toggleMute()
891
892 // Display/Hide local video of current call
893 await VoiceVideoCallingSDK.toggleLocalVideo()
894
895 // Clean up VoiceVideoCallingSDK (e.g.: Usually called when customer ends chat session)
896 VoiceVideoCallingSDK.close();
897}
898```
899
900## Feature Comparisons
901
902### Web
903| | Custom Control | WebChat Control |
904| --- | --- | --- |
905| **Features** | | |
906| Chat Widget UI | Not provided | Basic chat client provided |
907| Data Masking | Embedded | Requires `Data Masking Middleware` implementation |
908| Send Typing indicator | Embedded | Requires `sendTypingIndicator` flag set to `true` |
909| PreChat Survey | Requires Adaptive Cards renderer | Requires Adaptive Cards renderer
910| Display Attachments | Requires implementation | Basic interface provided & Customizable |
911| Incoming messages handling | IC3 protocol message data | DirectLine activity data |
912
913### React Native
914| | Custom Control | Gifted Chat Control | WebChat Control |
915| --- | --- | --- | --- |
916| **Features** | | | Currently not supported |
917| Chat Widget UI | Not provided | Basic chat client provided | X |
918| Data Masking | Embedded | Embedded | X |
919| Send Typing indicator | Embedded | Requires Implementation | X |
920| PreChat Survey | Requires Adaptive Cards renderer | Requires Adaptive Cards renderer | X |
921| Display Attachments | Requires implementation| Embedded | X |
922| Incoming messages handling |IC3 protocol message data | IC3 protocol message data | X |
923
924## Telemetry
925
926Omnichannel Chat SDK collects telemetry by default to improve the feature’s capabilities, reliability, and performance over time by helping Microsoft understand usage patterns, plan new features, and troubleshoot and fix problem areas.
927
928Some of the data being collected are the following:
929
930| Field | Sample |
931| --- | --- |
932| Organization Id | `e00e67ee-a60e-4b49-b28c-9d279bf42547` |
933| Organization Url | `org60082947.crm.oc.crmlivetie.com` |
934| Widget Id | `1893e4ae-2859-4ac4-9cf5-97cffbb9c01b` |
935| Browser Name | `Edge` |
936| Os Name | `Windows` |
937| Anonymized IP Address (last octet redacted) | `19.207.000.000` |
938
939If 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`.
940
941```ts
942const omnichannelConfig = {
943 orgUrl: "",
944 orgId: "",
945 widgetId: ""
946};
947
948const chatSDKConfig = {
949 telemetry: {
950 disable: true // Disable telemetry
951 }
952};
953
954const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
955await chatSDK.initialize();
956```
957
958# Contributing
959
960This project welcomes contributions and suggestions. Most contributions require you to agree to a
961Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
962the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
963
964When you submit a pull request, a CLA bot will automatically determine whether you need to provide
965a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
966provided by the bot. You will only need to do this once across all repos using our CLA.
967
968This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
969For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
970contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.