Sunday, May 22, 2022

Trailblazer Community Event: In Person Event Kolkata May 2022

 

Motivation behind this


This is the first in-person event organized by "Salesforce Women in Tech Group, Kolkata" and "Salesforce User Group, Kolkata" on 21st May, 2022.

This is my first session as a speaker at in-person event which was quite exciting to me.

At the end, it's a great success with due to great collaboration and support from all participants and organizers.

Attendees: 45



Link to the Deck: In Person Event May 2022

Glimpse



Testimonials

From Amit Agarwal



Follow @witkolkata and @UserGroupKol at Twitter and Women In Tech Kolkata Trailblazer Community for future events.

Thanks for joining with us!

Monday, May 16, 2022

Building Service Cloud Einstein Bot and Communicate Components through Lightning Message Service

 

Motivation behind this


Building Einstein Bot is nothing new and there are plenty of blogs and documentations are available on searching. Recently I got a use case from a Customer who wants on-demand transfer to agent as well as want to see end-to-end functionality.

As no such blogs or documentations exist on this specific requirement which drives me to setup and explore a quick proof of concept.



Let's start with basics first.

Capabilities of Einstein Bot
 
It is used to increase deflection and reduce call handling time.
  • Automatically resolves customer issues - through providing answers using NLP and connected CRM data.
  • Collect and qualify customer information - seamlessly handover real agent
  • Easily connect to a business process - initiate & complete actions on behalf
  • Quickly train, deploy and learn - Bot Builder is available to build it quick.

Product Requirements of Einstein Bot
  • Enable Lightning Experience
  • Service Cloud License or Chat or Messaging License
  • Enable Chat
  • Publish a Salesforce Community
  • Create and deploy chat button to Community
  • Provide chat at Service console
To know more, refer Einstein Bots Basics and Build an Einstein Bot

Use Case 


Business wants to see the capabilities of Einstein Bot and wants to transfer to agent upon clicking on a button on Bot Header.


Solution Approach


Lets first build the bot what can be done in a quicker way and mostly through configuration and later we will proceed with customization as per need.

Build a Bot from Pre-defined Template

Reach from Setup -> Service Cloud Einstein -> Einstein Bots -> New button

1. Select a bot from template


2. Personalize your bot


3. How your bot help customers

Here choose, Report an issue and Check status for an existing issue.


4. Finishing


Embedded Service Deployments

From Setup -> Search with "Embedded Service Deployments" and create a new deployment as follows.


Next screen, name it as Customer Service and choose Site Endpoint as "Default_Help_Center"


After creating, we will find this as below.


From this screen, we can configure chat settings, change the branding as per requirement.

Build the intent

From Einstein Bot configurations, build intent and utterances.
    

Finally activate the Bot.

Set up Chat

1. From Service Cloud Setup Home, Recommended Setup Section, click on View All and Choose "Chat with Customers" menu


2. Create a chat queue and assign your user or other user in the queue.


3. Prioritize chat with other network.

Here I have mentioned Customer Service Queue with highest priority

4. Adjust Agent Workload

Choose which mentioned as default.


5. Define Website URL



6. Chat Type

Select as Service for this purpose.



7. Create support form


8. Code Snippet Generated


9. Done


Chat Settings



Keep this API Endpoint which will be needed for Community Setup.

Create Community

1. Digital Experiences -> All Sites -> Click on New button and choose Customer Service Template and follow guided process.



2. Builder --> Settings -> Security & Privacy

Choose Security Level as Relaxed CSP.


The chat settings URL to be added into trusted site



Overall, it will look like this.


3. Add Embedded Chat to Community

Go to your Customer Support page and add Embedded Service Chat Component to the page and define parameters as Chat Deployment as Customer Service.


Chat Agent Configuration

Define Chat Agent configuration as follows:



Up to this point no customizations required, but to match business requirements let's proceed for customization.


Customization of Einstein Bot




To meet above requirement, Setup LMS and BotChatHeader Component will be publisher and BotChatMessage component will be subscriber.

1. Setup Lightning Message Service

To start with, first create a message channel and push it to the org. the xml will be placed under force-app/main/default/messageChannels/ directory.

Here message channel name has given as Bot_EntityId and the file name will be Bot_EntityId.messageChannel-meta.xml

For more information, refer Create a Message Channel

<?xml version="1.0" encoding="UTF-8" ?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel>BotEntityId</masterLabel>
    <isExposed>true</isExposed>
    <description>Message Channel to pass a entity Id</description>
    <lightningMessageFields>
        <fieldName>entityInfo</fieldName>
        <description>This is information passed when Live Chat is clicked</description>
</lightningMessageFields> </LightningMessageChannel>

2. Create Chat Header Component

Follow the Base Chat header Documentation, create BotChatHeader component.

BotChatHeader.html

Here beside the text, button to be displayed and clicking on that it will send the message.

<template>    
    <h2 aria-live="polite">
        {text}
        <template if:true={isLiveChatButtonDisplay}>
            <button onclick={handleClick} aria-live="off">
                <lightning-icon icon-name="standard:messaging_user"   
                        alternative-text="Live Chat!" 
                        class="slds-m-left_xx-small" title="Live Chat!">
                </lightning-icon>
            </button>
        </template>
    </h2> 

    <button onclick={minimize} aria-live="off">
        <lightning-icon icon-name="utility:minimize_window"></lightning-icon>
    </button>
    <button onclick={close} aria-live="off">
        <lightning-icon icon-name="utility:close"></lightning-icon>
    </button>
</template>

BotChatHeader.js

Few notable points in this js file:
  • Importing message channel to communicate via LMS.

// Import message service features required for publishing and the message channel
import { publish, MessageContext } from 'lightning/messageService';
import selectedEntity from '@salesforce/messageChannel/Bot_EntityId__c';
  • Publishing a message "Representative please" which available as intent for Transferring an agent dialog and sending as payload in handleClick() event.
Entire js file as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { wire } from 'lwc';
// Import message service features required for publishing and the message channel
import { publish, MessageContext } from 'lightning/messageService';
import selectedEntity from '@salesforce/messageChannel/Bot_EntityId__c';
import BaseChatHeader from 'lightningsnapin/baseChatHeader';

export default class BotChatHeader extends BaseChatHeader  {
    /**
     * Text to display in h2 element.
     * @type {string}
     */
     text;
     isLiveChatButtonDisplay = false;
     @wire(MessageContext)
     messageContext;
     /**
      * Set handlers for events from the sidebar.
      */
     connectedCallback() {
        this.isLiveChatButtonDisplay = false;
         this.assignHandler("prechatState", (data) => {
             this.setText(data.label);             
         });
         this.assignHandler("offlineSupportState", (data) => {
             this.setText(data.label);             
         });
         this.assignHandler("waitingState", (data) => {
             this.setText(data.label);             
         });
         this.assignHandler("waitingEndedState", (data) => {
             this.setText(data.label);             
         });
         this.assignHandler("chatState", (data) => {
             this.setText(data.label);
             this.isLiveChatButtonDisplay = true;
         });
         this.assignHandler("chatTimeoutUpdate", (data) => {
             this.setText("You will time out soon.");             
         });
         this.assignHandler("chatTimeoutClear", (data) => {
             this.setText(data.label);             
         });
         this.assignHandler("chatEndedState", (data) => {
             this.setText(data.label);
         });
         this.assignHandler("reconnectingState", (data) => {
             this.setText(data.label);
         });
         this.assignHandler("postchatState", (data) => {
             this.setText(data.label);
         });
         this.assignHandler("chatConferenceState", (data) => {
             this.setText(data.label);
         });
     }
 
     setText(str) {
         if (typeof str !== "string") {
             throw new Error("Expected text value to be a `String` but received: " + str + ".");
         }
         this.text = str;
     }

     //clicking the div fires this event
    handleClick(event) {
        let msg = 'Representative please';
        let payload = { botMsg: msg };
        publish(this.messageContext, selectedEntity, payload);       
    }       
}

BotChatHeader.js-meta.xml


<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightningSnapin__ChatHeader</target>
    </targets>
</LightningComponentBundle>

Take .css file from documentation.

3. Create Chat Message Component

Refer Base Chat Message Documentation for reference

BotChatMessage.html


<template>    
    <div class={messageStyle}>
        <lightning-formatted-rich-text
            value={content}>
        </lightning-formatted-rich-text>
    </div>
</template>

BotChatMessage.js

Few important points:
  • Defining the scope where subscriber component receives the message in our application. Here APPLICATION_SCOPE has been used.
  • Scope feature is only available using @wire(MessageContext)
  • There are methods to subscribe, unsubscribe and import message channel for using it.
  • In the subscribe method, you can see arrow function has been used so it can call any methods of the class using this operator. Scope can be passed as parameter.
  • handleMessage() method retrieves the bot message and post as window's message. For this extra configuration is needed which has been mentioned after.
Entire js file as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import BaseChatMessage from 'lightningsnapin/baseChatMessage';
import { wire } from 'lwc';
// Import message service features required for subscribing and the message channel
import {
    subscribe,
    unsubscribe,
    APPLICATION_SCOPE,
    MessageContext
} from 'lightning/messageService';
import botEntity from '@salesforce/messageChannel/Bot_EntityId__c';

const CHAT_CONTENT_CLASS = 'chat-content';
const AGENT_USER_TYPE = 'agent';
const CHASITOR_USER_TYPE = 'chasitor';
const SUPPORTED_USER_TYPES = [AGENT_USER_TYPE, CHASITOR_USER_TYPE];

var showLiveAgentDialog = false;

export default class BotChatMessage extends BaseChatMessage {
    subscription = null;
    /**
     * Displays a chat message using the inherited api messageContent 
     * and is styled based on the inherited api userType 
     * and messageContent api objects passed in from BaseChatMessage.
     */

    messageStyle = '';
    content = '';   
    
    @wire(MessageContext)
    messageContext;

    isSupportedUserType(userType) {
        return SUPPORTED_USER_TYPES.some((supportedUserType) => supportedUserType === userType);
    }
    
    // Standard lifecycle hooks used to subscribe and unsubsubscribe to the message channel
    connectedCallback() {
        this.subscribeToMessageChannel();
        showLiveAgentDialog = false;

        if (this.isSupportedUserType(this.userType)) {            
            this.messageStyle = `${CHAT_CONTENT_CLASS} ${this.userType}`;
        } else {
            throw new Error(`Unsupported user type passed in: ${this.userType}`);
        }
        this.content = this.messageContent.value;
        
    }

    disconnectedCallback() {
        this.unsubscribeToMessageChannel();
    }

    // Encapsulate logic for Lightning message service subscribe and unsubsubscribe
    subscribeToMessageChannel() {
        if (!this.subscription) {
            this.subscription = subscribe(
                this.messageContext,
                botEntity,
                (message) => this.handleMessage(message),
                { scope: APPLICATION_SCOPE }
            );
        }
    }

    //This is post the message using window's postMessage
    handleMessage(message) {
        console.log('handleMessage',message.botMsg);
        if(!showLiveAgentDialog){
            window.postMessage(
                {
                    message: message.botMsg,
                    type: "chasitor.sendMessage"
                },
                window.parent.location.href
            );            
            showLiveAgentDialog =true;
        }        
    }
    
    unsubscribeToMessageChannel() {
        unsubscribe(this.subscription);
        this.subscription = null;
        showLiveAgentDialog =false;
    }

    get isAgent() {
        return this.userType === 'agent';
    }
    
}

BotChatMessage.js-meta.xml

It will have a target as lightningSnapin__ChatMessage
Take .css file from documentation.

4. Window's message snippet

Add the bot message to be posted as window's message so following code to be added in Head Markup at Community from Settings -> Advanced.


<script>
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
    var payload = event.data;
    
    if(payload && payload.type === "chasitor.sendMessage") {
        embedded_svc.postMessage("chasitor.sendMessage", payload.message);
    }
};
</script>

5. Define LWC Components in Deployment Settings

Go to Embedded Service Deployment Settings and choose Customer Service and define as follows:


Let's test this

Lets publish the Community and test the functionality as follows.

From one browser, choose Service Console App and Omni-channel, choose agent as online.
From other browser, open the community and choose "Chat with an expert".

For detailed interaction, refer the video.






Finally we are done and thanks for reading.


Further Reading