Bot Cookbook
Bot Cookbook
Cookbook
Version 59.0, Winter ’24
@salesforcedocs
Last updated: September 15, 2023
© Copyright 2000–2023 Salesforce, Inc. All rights reserved. Salesforce is a registered trademark of Salesforce, Inc., as are other
names and marks. Other marks appearing herein may be trademarks of their respective owners.
CONTENTS
Note: Even if you don’t plan on using Chat, you still need to enable it in order to use Einstein Bots.
2. Implement Chat and/or Messaging. To use your bot, you must connect it to a Chat implementation, a Messaging channel, or both!
1
Einstein Bots Developer Cookbook Set Up Your First Einstein Bot
• For Lightning Chat, use the “Get Started with Web Chat” unit in the Trailhead module Web Chat Basics.
• For Classic Chat, follow the instructions in Create a Basic Chat Implementation.
• For Messaging, go through our guided setup flow. To learn more, see Set Up Messaging with a Guided Setup Flow. Alternatively,
you can manually Set Up a Messaging Channel.
3. From Setup, use the Quick Find box to find Einstein Bots.
4. Enable Einstein Bots.
Set the Einstein Bots switch to On. If you’re enabling the bot for the first time, you are asked to accept the terms.
As part of setup, the permission set sfdc.chatbot.service.permset is added to your org. This permission set controls which objects
and Apex classes bots can access. To build a simple bot, you don’t have to change anything in the permission set. As you add more
features to the bot, edit the permission set to expand access. For instance, you can grant access to Apex classes from Apex Class
Access; you can grant access to Salesforce objects through Object Settings; you can enable access to flows from the Run Flows
checkbox in the System Permissions section.
2
Einstein Bots Developer Cookbook Set Up Your First Einstein Bot
3
Einstein Bots Developer Cookbook Set Up Your First Einstein Bot
When your new bot is ready, you’re taken to the Bot Builder Overview page. To get oriented, explore the Overview, Dialogs,
Entities, Variables, and Performance pages.
To learn more about each page within the Bot Builder, use the following Help articles:
• Overview: Create a Basic Bot
• Dialogs: Understand Einstein Bot Dialogs
• Entities: What’s an Entity?
• Variables: What’s a Variable?
• Performance: Monitor, Analyze, and Refine Bot Activity
4
Einstein Bots Developer Cookbook Set Up Your First Einstein Bot
5
Einstein Bots Developer Cookbook Greet the Customer
If you always want agents ready for transfer when the bot can’t answer an inquiry or the customer wants help from an agent, select
Require Agent Online. If your agents work limited hours and you want the bot working 24x7, don’t select this option.
For now, leave this setting deselected so that we can test the bot without setting up the agent side.
8. To preview the bot from within the Bot Builder, add an Embedded Chat deployment. .
For preview, Einstein Bots uses an Embedded Chat component. Even if you use Classic Live Agent for your customer chat interface,
create a chat deployment.
9. Preview your bot. If you created a chat deployment in the previous step, you can preview your bot by going to the Dialog page of
Bot Builder and clicking Preview. Alternatively, you can test your bot simply by using one of the channels you assigned to your bot.
.
Your Einstein Bot welcomes you with a greeting message and your two menu options. If you set up the bot using Embedded Chat,
you may also see a pre-chat form before the bot sends its first message.
After you’re able to test your bot, you can take on the other recipes in this cookbook.
6
Einstein Bots Developer Cookbook Greet the Customer
Prerequisites
• Set Up Your First Einstein Bot on page 1
In this recipe you learn how to:
• Use a pre-chat form to get data from the customer.
• Upload JavaScript to static resources to map fields in the Contact object with fields in the LiveChatTranscript object.
• Inspect fields in the LiveChatTranscript object.
• Access context variables with the Einstein Bot Builder.
• Use Apex code or the Metadata API to get data into a new variable.
1. Create custom fields on the LiveChatTranscript object to give the bot access to customer information.
In the Service Cloud Console, agents can view all chat fields on the Chat Details tab. Admins can use the Console Integration Toolkit
API to give agents even more information. Because bots don’t have a view of an agent’s console, the data must be committed to a
platform object. Commitment is necessary for giving the bot access to information programmatically. Bots can use the
LiveChatTranscript object to access pre-chat variables.
To capture the first name, last name, and email address data from the pre-chat form, create three fields on the
LiveChatTranscript object.
7
Einstein Bots Developer Cookbook Greet the Customer
From Setup, use the Quick Find box to find Embedded Service. Click View to access your Embedded Service deployment, then
click Edit next to Chat Settings. Enable the Pre-chat page if it has not been done already. By default, customer name and email
are included on the pre-chat form. If you have a Webmail field on the pre-chat form, click the X icon to remove it. and click Save.
window._snapinsSnippetSettingsFile = (function() {
embedded_svc.snippetSettingsFile.extraPrechatFormDetails = [{
"label":"First Name",
"transcriptFields": ["FirstName__c"]
},{
"label":"Last Name",
"transcriptFields": ["LastName__c"]
},{
8
Einstein Bots Developer Cookbook Greet the Customer
"label":"Email",
"transcriptFields": ["Email__c"]
}];
})();
Upload the JavaScript file to the org as a static resource. From Setup, use the Quick Find box to find Static Resources. Name
the resource CookbookBot_SnippetSettingsFile. Verify that the MIME Type is set to text/javascript and
that Cache Control is Public. Some text applications can add extra text which can cause problems down the road. To ensure
that your file matches the code sample, click View file.
Now, in Experience Builder, you can set the Snippet Settings File field in your chat window to your static resource.
In Experience Builder, add your static resource to Snippet Settings File.
9
Einstein Bots Developer Cookbook Greet the Customer
Important: Enter the static resource name (not the filename) in the Snippet Settings File field. For example, if your
JavaScript file is called CookbookBot_SnippetSettingsFile.js and you named it
CookbookBot_SnippetSettingsFile in your static resources, enter
CookbookBot_SnippetSettingsFile in the field.
Publish your Experience Cloud site after this change. If you run into other errors or messages from the site while publishing,
follow the instructions inside the site to resolve.
embedded_svc.settings.extraPrechatFormDetails sets the default value and adds information to the chat
transcript. The transcriptFields attribute specifies the field API name on the LiveChatTranscript object where
the data is saved.
10
Einstein Bots Developer Cookbook Greet the Customer
We can pass the pre-chat data to a variable, and use the variable to merge the customer name into the greeting message.
6. We now want to extract the value of the FirstName__c field from the LiveChatTranscript object, and get it into the
FirstName variable. You can get the FirstName__c value in two different ways, but first it's important to understand context
variables.
Let’s say you create a Rule in a bot flow and specify a Set Variable rule action. You can choose from a set of built-in variables to
access objects and fields related to the chat session.
11
Einstein Bots Developer Cookbook Greet the Customer
The values of these context variables depend on how you set up your bot.
12
Einstein Bots Developer Cookbook Greet the Customer
Context Variable Chat Using Omni-Channel Chat Using Live Agent Live Message Channel
Routing Routing
ChatKey LiveChatTranscript. LiveChatTranscript. N/A
ChatKey ChatKey
_LastCustomerInput Represents the most recent message that the customer entered.
You can use any of these context variables to access the fields behind them. But what if you want access to information that isn’t
available out of the box? Like how do you access the FirstName__c field that you created? You can tackle that problem in two
different ways.
a. Write Apex code to grab what you need and make the Apex method accessible to the Bot Builder using the
@InvocableMethod annotation. For instance, if you’re using Omni-Channel, you can use the RoutableId context
variable to get the LiveChatTranscript record, extract the custom field value, and then pass it back to your bot.
b. Use the Salesforce Metadata API to add context variables that aren’t available out of the box. For instance, you can create a
context variable to gain access to a LiveChatTranscript custom field.
This recipe includes both methods. Pick the one that best suits your situation.
7. (Option 1 of 2: Apex Code Solution) Extract the FirstName__c field from the LiveChatTranscript object using an
invocable Apex method.
Tip: For details about the power of Apex for your bot, see Call an Apex Action.
13
Einstein Bots Developer Cookbook Greet the Customer
return names;
}
}
14
Einstein Bots Developer Cookbook Greet the Customer
8. (Option 2 of 2: Metadata API Solution) Extract the FirstName__c field from the LiveChatTranscript object by creating
a new context variable with Metadata API.
Note: If you’re not familiar with the Metadata API, review the Metadata Developer Guide. To access the API features, you can
use the Salesforce Extensions for Visual Studio Code or the Ant Migration Tool.
a. Retrieve the metadata for your bot using the Metadata API.
The first step is to retrieve bot metadata using the Metadata API. To retrieve metadata, provide a zip package containing a
package.xml manifest file. You can use this sample code to get you started.
To retrieve metadata, provide a zip package containing a package.xml manifest file. You can use this sample code to get
you started. Replace MY_BOT_API_NAME with your bot’s API name. Also replace the version number with the latest API
version of your org.
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>MY_BOT_API_NAME</members>
<name>Bot</name>
</types>
<types>
15
Einstein Bots Developer Cookbook Greet the Customer
<members>*</members>
<name>MlDomain</name>
</types>
<version>45.0</version>
</Package>
b. Add the context variable to the retrieved metadata and deploy it back to your org.
Now you can add a context variable (to the content that you previously retrieved) and then deploy the package back to your
org. In the .bot file, search for the area that has the context variables, and add the following XML snippet. This snippet adds
the context variable using the FirstName__c field of the LiveChatTranscript object.
<contextVariables>
<contextVariableMappings>
<SObjectType>LiveChatTranscript</SObjectType>
<fieldName>LiveChatTranscript.FirstName__c</fieldName>
<messageType>WebChat</messageType>
</contextVariableMappings>
<dataType>Text</dataType>
<developerName>TranscriptFirstName</developerName>
<label>Transcript First Name</label>
</contextVariables>
After you deploy the package back to your org, you can access the new context variable.
c. Create a Set Variable rule in Bot Builder for accessing the new context variable.
In your bot’s “Welcome” dialog, add an action at the top of the flow using the Set Variable action type. For the source, select
the new Transcript First Name context variable. For the destination, select the FirstName variable.
16
Einstein Bots Developer Cookbook Greet the Customer
If the bot is not working as expected, we’ve found that most errors fall into one of two issues:
• If the bot goes directly to the agent and skips the greeting, the Apex may have failed and should be revisited.
• If the bot is unable to convert the variable and shows {!FirstName}, the Apex was unable to pass info along to the bot or the
Snippet Settings file is incorrect.
Note: It’s a common request for Embedded Chat to show different avatars when the customer is talking with a bot as opposed
to an agent. Although the Lightning component doesn’t support different avatars, you can use JavaScript code from
SnippetSettingsFile. The attribute name is
embedded_svc.snippetSettingsFile.chatbotAvatarImgURL for a bot avatar and
embedded_svc.snippetSettingsFile.avatarImgURL for an agent avatar. The same is true if you are configuring
from an external site, but add the embedded_svc.settings prefix. For more supported attributes in the
snippetSettingsFile, see the Embedded Service for Web Developer Guide.
17
Einstein Bots Developer Cookbook Greet the Customer
In the Service Cloud Console, agents can view all chat fields on the Chat Details tab. Admins can use the Console Integration Toolkit
API to give agents even more information. Because bots don’t have a view of an agent’s console, the data must be committed to a
platform object. Commitment is necessary for giving the bot access to information programmatically. Bots can use the
LiveChatTranscript object to access pre-chat variables.
To capture the first name, last name, and email address data from the pre-chat form, create three fields on the
LiveChatTranscript object.
<!-- This script takes the endpoint URL parameter passed from the deployment page and
makes it the action for the form -->
<script type='text/javascript'>
(function() {
function handlePageLoad() {
var endpointMatcher = new RegExp("[\\?\\&]endpoint=([^&#]*)");
document.getElementById('prechatForm').setAttribute('action',
decodeURIComponent(endpointMatcher.exec(document.location.search)[1].replace("javascript:",
"")));
} if (window.addEventListener) {
window.addEventListener('load', handlePageLoad, false);
} else { window.attachEvent('onload', handlePageLoad, false);
}})();
</script>
<!-- Form that gathers information from the chat visitor and sets the values to Live
Agent Custom Details used later in the example -->
<form method='post' id='prechatForm'>
First name: <input type='text' name='liveagent.prechat:FirstName' id='firstName'
/><br />
Last name: <input type='text' name='liveagent.prechat:LastName' id='lastName' /><br
/>
Email: <input type='text' name='liveagent.prechat:Email' id='email' /><br />
<!-- Used to set the visitor's name for the agent in the Console -->
<input type="hidden" name="liveagent.prechat.name" id="prechat_field_name" />
<!-- Set the visitor's name for the agent in the Console to first and last name provided
18
Einstein Bots Developer Cookbook Greet the Customer
<style type="text/css">
p {font-weight: bolder }
</style>
</form>
</apex:page>
The element name specified after liveagent.prechat.save: is the chat detail variable name. Set the value attribute of
the input tag to the API name of the LiveChatTranscript field to populate.
19
Einstein Bots Developer Cookbook Greet the Customer
We can pass the pre-chat data to a variable, and use the variable to merge the customer name into the greeting message.
6. We now want to extract the value of the FirstName__c field from the LiveChatTranscript object, and get it into the
FirstName variable. You can get the FirstName__c value in two different ways, but first it's important to understand context
variables.
Let’s say you create a Rule in a bot flow and specify a Set Variable rule action. You can choose from a set of built-in variables to
access objects and fields related to the chat session.
20
Einstein Bots Developer Cookbook Greet the Customer
The values of these context variables depend on how you set up your bot.
21
Einstein Bots Developer Cookbook Greet the Customer
Context Variable Chat Using Omni-Channel Chat Using Live Agent Live Message Channel
Routing Routing
ChatKey LiveChatTranscript. LiveChatTranscript. N/A
ChatKey ChatKey
_LastCustomerInput Represents the most recent message that the customer entered.
You can use any of these context variables to access the fields behind them. But what if you want access to information that isn’t
available out of the box? Like how do you access the FirstName__c field that you created? You can tackle that problem in two
different ways.
a. Write Apex code to grab what you need and make the Apex method accessible to the Bot Builder using the
@InvocableMethod annotation. For instance, if you’re using Omni-Channel, you can use the RoutableId context
variable to get the LiveChatTranscript record, extract the custom field value, and then pass it back to your bot.
b. Use the Salesforce Metadata API to add context variables that aren’t available out of the box. For instance, you can create a
context variable to gain access to a LiveChatTranscript custom field.
This recipe includes both methods. Pick the one that best suits your situation.
7. (Option 2 of 2: Metadata API Solution) Extract the FirstName__c field from the LiveChatTranscript object by creating
a new context variable with Metadata API.
Note: If you’re not familiar with the Metadata API, review the Metadata Developer Guide. To access the API features, you can
use the Salesforce Extensions for Visual Studio Code or the Ant Migration Tool.
a. Retrieve the metadata for your bot using the Metadata API.
The first step is to retrieve bot metadata using the Metadata API. To retrieve metadata, provide a zip package containing a
package.xml manifest file. You can use this sample code to get you started.
To retrieve metadata, provide a zip package containing a package.xml manifest file. You can use this sample code to get
you started. Replace MY_BOT_API_NAME with your bot’s API name. Also replace the version number with the latest API
version of your org.
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>MY_BOT_API_NAME</members>
<name>Bot</name>
</types>
<types>
<members>*</members>
<name>MlDomain</name>
</types>
<version>45.0</version>
</Package>
b. Add the context variable to the retrieved metadata and deploy it back to your org.
22
Einstein Bots Developer Cookbook Greet the Customer
Now you can add a context variable (to the content that you previously retrieved) and then deploy the package back to your
org. In the .bot file, search for the area that has the context variables, and add the following XML snippet. This snippet adds
the context variable using the FirstName__c field of the LiveChatTranscript object.
<contextVariables>
<contextVariableMappings>
<SObjectType>LiveChatTranscript</SObjectType>
<fieldName>LiveChatTranscript.FirstName__c</fieldName>
<messageType>WebChat</messageType>
</contextVariableMappings>
<dataType>Text</dataType>
<developerName>TranscriptFirstName</developerName>
<label>Transcript First Name</label>
</contextVariables>
After you deploy the package back to your org, you can access the new context variable.
c. Create a Set Variable rule in Bot Builder for accessing the new context variable.
In your bot’s “Welcome” dialog, add an action at the top of the flow using the Set Variable action type. For the source, select
the new Transcript First Name context variable. For the destination, select the FirstName variable.
8. (Option 1 of 2: Apex Code Solution) Extract the FirstName__c field from the LiveChatTranscript object using an
invocable Apex method.
Tip: For details about the power of Apex for your bot, see Call an Apex Action.
23
Einstein Bots Developer Cookbook Greet the Customer
Let’s use Apex code to extract information from the LiveChatTranscript record. This code takes the
LiveChatTranscript record ID as the input, queries for the record using SOQL, extracts the FirstName__c field
from the record, and returns the first name as an output.
From Setup, use the Quick Find box to find Apex Classes. Add a new class.
public with sharing class CookbookBot_GetTranscriptVariables {
return names;
}
}
24
Einstein Bots Developer Cookbook Greet the Customer
this variable maps to the ID of the LiveChatTranscript record. For the output, use the FirstName variable that you
created earlier.
25
Einstein Bots Developer Cookbook Greet the Customer
Using any method described in Set Up Your First Einstein Botto preview your bot and test out the new functionality.
Warning: Adding a custom pre-chat form to a Live Agent button configuration page breaks any Snap-ins deployments that are
built on top of this chat button. Snap-ins chat deployments have a pre-chat form built in, so it doesn't expect the underlying chat
button to have another Classic pre-chat page. Test with Snap-ins or use Preview in the Bot Builder to create another Live Agent
button with no pre-chat form.
Prerequisites
• Set Up Your First Einstein Bot on page 1
In this recipe you learn how to:
• Access context variables with the Einstein Bot Builder.
• Use Apex code to search for a contact based on a phone number.
• Greet the customer by name.
• Learn about intent detection and why it’s particularly valuable with bots and messaging.
The beginning of a messaging conversation is a little different than a chat session. For one, there isn’t any notion of a pre-chat form—you
can’t query customers in advance for information. However, you can still query your org using the information that you do have. For
some messaging channels (such as SMS), you have their phone number. For other channels (such as Facebook Messenger), you have a
username or an ID. With this information, you can use Apex or a flow to get contact information from your org, if it exists.
Also, unlike a chat session, the customer can initiate the conversation by asking a question. This flow is different than a chat session,
where your bot can start the conversation. However, you can use intent detection and other techniques to direct a customer to the
appropriate dialog within your bot flow.
In what follows, we outline the process to handle these issues. First, we discuss how to find information about a user without the benefit
of a pre-chat form.
26
Einstein Bots Developer Cookbook Greet the Customer
27
Einstein Bots Developer Cookbook Greet the Customer
The values of these context variables depend on how you set up your bot.
28
Einstein Bots Developer Cookbook Greet the Customer
Context Variable Chat Using Omni-Channel Chat Using Live Agent Live Message Channel
Routing Routing
ChatKey LiveChatTranscript. LiveChatTranscript. N/A
ChatKey ChatKey
_LastCustomerInput Represents the most recent message that the customer entered.
Note: With Messaging, the ContactId context variable, which is tied to the MessagingEndUser.ContactId
field, is only filled if an agent has previously linked the Messaging User to the Contact record. This link can be done when an
agent receives a link notification or through Channel-Object Linking. For this reason, the ContactId variable is null the
first time a Messaging user reaches out, or for the returning Messaging user who has only encountered a bot. The Apex code
in this recipe therefore uses the MessagingEndUser record in the EndUserId variable to more reliably access contact
information.
You can use any of these context variables to access the fields behind them. In the next few steps, we use the EndUserId, which
contains the ID of the MessagingEndUser. This object contains information depending on the particular messaging channel.
For a text message, the Name field contains the user’s phone number. For other channels, it can be the username.
3. Write Apex code to grab info from the MessagingEndUser record and then search for a contact based on that info.
Tip: For details about the power of Apex for your bot, see Call an Apex Action. If you’d rather perform this action with Flow
Builder, see Call a Flow Action on page 48.
Create an invocable Apex method to access the messaging end user. If the messaging user is a text messaging user, you can grab
the phone number from the Name field and use that number to look up a Contact record with the same number.
From Setup, use the Quick Find box to find Apex Classes. Add a new class.
public with sharing class CookbookBot_MessagingContact {
return scrubbedNumber;
}
29
Einstein Bots Developer Cookbook Greet the Customer
return outputs;
}
}
Important: As mentioned in Set Up Your First Einstein Bot, you must give the bot permission to access an Apex class. From
Setup, use the Quick Find box to find Permission Sets. Select the sfdc.chatbot.service.permset permission set. From the
permission set options, select Apex Class Access. Now you can edit the access settings so that your new class is accessible
to the bot. Always make sure that the bot has permission to access objects and classes as required.
30
Einstein Bots Developer Cookbook Greet the Customer
31
Einstein Bots Developer Cookbook Greet the Customer
After you add intent detection on page 78 to other dialogs, add this same rule to the beginning of those dialogs as well.
32
Einstein Bots Developer Cookbook Prompt Customer with Menu Options
This dialog is still a bit simplistic for an ideal greeting. For instance, if the Apex code doesn’t find a contact, it returns “messaging user”
as the name. Not the most elegant way to speak with a customer. As a follow-up exercise, you can change the flow so that the Apex
method returns an empty string if it can’t find a contact. Then, the dialog can check whether it got a contact back. If so, it can use the
contact’s name, as shown above. If not, it can display a different, more generic message.
To address scenarios where the user initiates a conversation before the bot gets in the action, you can use intent detection. With intent
detection, any of our dialogs can automatically detect a relevant input for a particular flow and then take control of the conversation.
This behavior involves turning on intent detection for a dialog, and then adding enough utterances for the natural language processing
to figure out when it’s time to kick in.
Once our other dialogs are more fleshed out, you’ll see the power of getting the customer to the right part of your bot flow as fast as
possible. To learn more about intent detection, see the Natural Language Processing on page 78 section.
Channels
• Chat
• Messaging
Prerequisites
• Set Up Your First Einstein Bot on page 1
33
Einstein Bots Developer Cookbook Prompt Customer with Menu Options
When our cookbook bot was first created, we entered Order Related and Appointment Related in the setup wizard as our initial main
menu options. The result was a couple of empty dialog placeholders that are listed from the main menu dialog. Let's add more options
to the main menu.
1. Add a few more dialogs.
Since every menu option points to a dialog, a dialog must be built for each of the menu options. Go to the Dialogs tab and confirm
that your bot is deactivated to edit your bot. Click the + button and select New Dialog. Let's create a dialog called “Search FAQ”.
In creating a dialog, there are two options that are optional but allow for better organization: Assign to Dialog Group and Show in
Bot Options Menu. The setting Assign to Dialog Group provides admins an easy way to group similar dialogs together in the Bot
Builder for easy navigation.
The setting Show in Bot Options menu gives customers a quick way to kick off this dialog from the shortcut menu at any time
during the chat conversation. To access this menu, look for the ... icon to the left of the chat input text box on the chat window.
34
Einstein Bots Developer Cookbook Prompt Customer with Menu Options
For the “Main Menu” dialog, the choice is obviously to Show a menu. To add the newly created “Search FAQ” dialog option to the
menu, click the magnifying glass . There are also a few pre-built dialogs such as Transfer to Agent or End Chat. Let's add the
Transfer to Agent option as well.
3. Add a submenu.
While you can add more options to the main menu to support different inquiry types, it's probably not a good idea to list them all
in one place when you have many menu options. It's likely going to overwhelm customers. The list could get longer than the height
of their phone so that they have to keep scrolling to see the menu options. It’s important to take into account your channel as you’re
creating menus and submenus. In Chat, when a bot has more than 5 menu options, it’s recommended to group them in different
categories and use submenus to add more options. In Messaging, the limit is 3 menu options.
Using the Next Step tool on the “Order Related” dialog, let’s create a submenu. In this submenu, we support “Order Status”, “Cancel
an Order” and “Return an Order” transactions. Similar to main menu options, each submenu option also maps to a dialog. Let's go
ahead and create these three dialogs. You don't have to add anything yet. We’ll create them as placeholders for now. Since these
dialogs are all related to customer orders, we can also create a dialog group named “Order” in Bot Builder to group them together.
To create a group, click the + button and select New Group. Then assign your new dialogs to this new group.
35
Einstein Bots Developer Cookbook Prompt Customer with Menu Options
4. Test!
OK. Let's test the new flow as a customer. Don't forget to Activate the bot first. Preview your bot in any of the ways described in Set
Up Your First Einstein Bot.
Voila, here is our new menu navigation.
36
Einstein Bots Developer Cookbook Beginner Bot Recipes
While it's not a best practice to have a long menu, it's also not a best practice to have so many levels of menus that the customer will
request a transfer to an agent. The more inquiry types the bot supports, the more we should leverage Natural Language Processing
(NLP) to help identify customer intent and jump to the topic right away.
37
Einstein Bots Developer Cookbook Gather Customer Information Using the Bot
Channels
• Chat
• Messaging
Prerequisites
• Set Up Your First Einstein Bot on page 1
In this recipe you learn how to:
• Create entities and variables to store formatted data.
So far we have created a few dialogs. But they are mostly empty. Let's build conversations in them. There are four types of elements you
can add to a dialog: Message, Question, Action, and Rules. We have already seen how a Message works from the welcome dialog.
It displays a message to your customer and you can merge variables in a message with this format: {!VariableAPIName}.
In this recipe, we'll talk about the Question element, where you configure the bot to ask a question and store the answer in a variable.
When we are building out our cookbook bot, guess what we need to know first to do any of the order-related inquiries? That's right, we
need to ask for the order number and store it somewhere.
1. Create a custom object to store customer order information.
Many use cases in this cookbook revolve around customer orders, so let’s create a custom object to store order data. We won’t use
this object yet, but it’ll be handy for future recipes.
Let’s create a custom object with the API name of Bot_Order__c and with these fields:
• Name (Text)
• Status__c (Picklist): New, Packaging, Shipped, Canceled, Returning, Returned
• OrderDate__c (Date)
• Contact__c (lookup to Contact)
The actual order number is stored in the Name field.
When you build this Bot_Order object in your org, it should look like this screenshot:
38
Einstein Bots Developer Cookbook Gather Customer Information Using the Bot
Important: As mentioned in Set Up Your First Einstein Bot, you need to give the bot permission to access this custom object
and these fields. From Setup, use the Quick Find box to find Permission Sets. Select the sfdc.chatbot.service.permset
permission set. From the permission set options, select Object Settings. Select your custom object and then make sure that
this permission set has read and edit permissions to the object and all the relevant fields.
While we’re at it, let’s create a few test records for this object. Make sure that you remember the order number for the record you
create so that you can use it later in this cookbook. Create at least one record with a name of O-00123456 for later use.
2. Create an entity.
We touched on this topic briefly in Greet the Customer when we created the first variable for customer FirstName and we used
the system entity Text. We can also create custom entities.
In any order management system, order numbers typically follow a certain format. Let's say in our system, it always starts with letter
O, then a dash, then 8 numbers. Something like: O-00123456. Knowing this format helps the bot recognize when customers
enter an order number in a conversation.
Let's create a new entity from the Entities tab. Name the entity OrderNumberString with an extraction type Pattern and
specify a RegEx Pattern of \bO\-\d{8}\b . For those of you who are not familiar with regular expressions, this expression
indicates that an order number must be one word, starting with a letter O, followed by a dash, then ending with 8 numbers.
39
Einstein Bots Developer Cookbook Gather Customer Information Using the Bot
3. Create a variable.
Now we can create a variable from the Variables tab. Name the variable OrderNumber. Let’s select Text as its data type. We’ll
apply the entity OrderNumberString to it when we ask the question, thus we need to make sure the base data types match
between the entity and variable.
40
Einstein Bots Developer Cookbook Gather Customer Information Using the Bot
Set the Entity Name to OrderNumberString entity and the Save Answer to Variable attribute to the OrderNumber
variable. This means that we’ll be looking for input from customers for the order number. We’ll apply the OrderNumberString
entity to identify the input and the result will be saved into the OrderNumber variable we just created.
41
Einstein Bots Developer Cookbook Call an Apex Action
6. Test!
Now, when a customer asks about order status, we ask for the order number so we can look it up for the customer later.
Try using an incorrect format for the order number and see what happens.
In Call an Apex Action and Call a Flow Action, we’ll actually look up these orders in our custom object.
Channels
• Chat
• Messaging
Prerequisites
• Set Up Your First Einstein Bot on page 1
42
Einstein Bots Developer Cookbook Call an Apex Action
Tip: Apex Action or Flow Action? We provide one recipe to introduce you to flow actions and another recipe to introduce you to
Apex actions. You’ll quickly see that you can do many of the same things with both solutions. Which one should you use? Think
about the flow option first for simple solutions. It's declarative and is easier to maintain. Apex, on the other hand, offers much
power and many more use cases not available with a simple flow. Another option is to use both. You could add Apex actions to
a flow. From within Flow Builder, just drag an Apex Action element onto the canvas. Or, you can invoke a flow from Apex. After
some experience with both flows and Apex, you’ll be able to determine how to most effectively use these tools together to get
the job done.
How does the bot get the status of a particular order? The Action element in dialogs supports different types of actions—such as an
Apex action or a Flow action—to trigger a transaction or process. Among all of the action types, Apex has the broadest use cases, so
we talk about Apex first. Since every company's order management system is different, you can store the order data in Salesforce in a
custom object, or externally somewhere in a data warehouse—so we don't expect the bot has every possible scenario built out for a
100% point-and-click configuration. Therefore, we leverage invocable Apex methods for the heavy lifting!
We use invocable Apex methods in other product areas, such as Process Builder. As long as the Apex method has a particular annotation
(@InvocableMethod) and formats its method signature properly, the Bot Builder is able to list this method as an available bot action
to call. The builder recognizes the method signature, so you can specify which variable you pass in as an input parameter and which
variable you use to store the return value. Then you can merge the returned variable to a message, call another action, or do anything
else you can do with a variable.
In a typical order status use case, you assign an OrderNumber variable as an input parameter of an Apex method and return the
status to another variable OrderStatus.
1. Before we write any code, make sure you’ve created a custom object with a few records, as described in the first step of Gather
Customer Information Using the Bot.
2. Now let’s build our invocable Apex class and method.
From Setup, use the Quick Find box to find Apex Classes. Add a new class.
public with sharing class CookbookBot_GetOrderStatus {
43
Einstein Bots Developer Cookbook Call an Apex Action
return orderOutputs;
}
}
Important: As mentioned in Set Up Your First Einstein Bot, you must give the bot permission to access an Apex class. From
Setup, use the Quick Find box to find Permission Sets. Select the sfdc.chatbot.service.permset permission set. From the
permission set options, select Apex Class Access. Now you can edit the access settings so that your new class is accessible
to the bot. Always make sure that the bot has permission to access objects and classes as required.
Some notes on the code:
• The public class OrderInput and OrderOutput are wrapper classes that include all the input and output variables. Each
input and output parameter in these two classes has the @InvocableVariable annotation.
• The getOrderStatus() method has the @InvocableMethod annotation. This method performs a SOQL query to
find the order records by order number, then returns the status. All the extra code using for loops is to make sure that this
method works for bulk invocations.
• The class is public in this sample code. Change the visibility to global if you plan on including this class in a package.
44
Einstein Bots Developer Cookbook Call an Apex Action
45
Einstein Bots Developer Cookbook Call an Apex Action
Create a message step to let the customer know the bot is working on finding the order.
Now let’s add a new Action type. Select the Apex action type. Click the magnifier next to Action Name field. You see all the Apex
methods with @InvocableMethod annotation listed. Select Get Order Status. The Bot Builder automatically parses the method
signature and populates additional fields for admins to map the variables to input and output invocable variables. If you go back to
our GetOrderStatus Apex class, you can see that we have one input invocable variable, sOrderNumber, and one output
46
Einstein Bots Developer Cookbook Call an Apex Action
invocable variable, sOrderStatus. They are exactly what the Bot Builder recognizes and lists as the parameters for this action.
Use OrderNumber as the input variable. Create a text variable called OrderStatus for the output variable.
Let’s create another message and include the {!OrderStatus} variable into the response back to the customer with this message: The
order number {!OrderNumber} has the following status: {!OrderStatus}.
4. Now we can successfully retrieve the customer order status from the Bot_Order__c object!
47
Einstein Bots Developer Cookbook Call a Flow Action
Our example is simple, but it opens the door to Apex code, from which you can leverage almost everything Apex has to offer for integration
tasks: External Object, Apex Callout, Salesforce Connect, Salesforce Integration... you name it!
Channels
• Chat
• Messaging
Prerequisites
• Set Up Your First Einstein Bot on page 1
• Greet the Customer on page 6
• Prompt Customer with Menu Options on page 33
In this recipe you learn how to:
• Create an autolaunched flow with Flow Builder.
48
Einstein Bots Developer Cookbook Call a Flow Action
Tip: Apex Action or Flow Action? We provide one recipe to introduce you to flow actions and another recipe to introduce you to
Apex actions. You’ll quickly see that you can do many of the same things with both solutions. Which one should you use? Think
about the flow option first for simple solutions. It's declarative and is easier to maintain. Apex, on the other hand, offers much
power and many more use cases not available with a simple flow. Another option is to use both. You could add Apex actions to
a flow. From within Flow Builder, just drag an Apex Action element onto the canvas. Or, you can invoke a flow from Apex. After
some experience with both flows and Apex, you’ll be able to determine how to most effectively use these tools together to get
the job done.
Since we are using a custom object on the platform (Bot_Order__c) to store the Order information, a CRUD (create, read, update,
and delete) operation such as a record update can be configured in an autolaunched flow.
1. Before we write any code, make sure you’ve created a custom object with a few records, as described in the first step of Gather
Customer Information Using the Bot.
2. Create an autolaunched flow.
Creating a flow is typically faster than writing Apex code. If you haven’t worked on a flow before, see Flows in Salesforce Help.
Note: As you work on this flow, we’ll explain in more detail how the interaction works between the Bot Builder and the Flow
Builder. At a high level, you need to make sure that all the flow variables that you want to set from Bot Builder are “available
for input”. And all flow variables that you want to pass back to Bot Builder are “available for output”.
From Setup, use the Quick Find box to find Flows. Create a new flow. The goal of this flow is to update a particular order based on
the order number provided by the customer and set its status to Canceled. So, we’ll start with an Update Records element.
49
Einstein Bots Developer Cookbook Call a Flow Action
In Flow Builder, drag the Update Records element from the Toolbox onto the canvas. To find a record, select Specify conditions
to identify records, and set fields individually. You can then search for all orders with the specified order number and set the
status field to Canceled.
50
Einstein Bots Developer Cookbook Call a Flow Action
The previous screenshot shows the desired values for the Update Records element.
To build the condition, create an OrderNumber variable in the Value field. After clicking the Value field, select New Resource
from the popup menu.
51
Einstein Bots Developer Cookbook Call a Flow Action
Now create a new Variable Resource Type and use the Text Data Type. Enter OrderNumber for the API name.
Note: Be sure to make this resource Available for input. This checkbox allows the Bot Builder to use this variable as an input
parameter to the flow.
Once you complete this step, the Value field should get set to {!OrderNumber}.
52
Einstein Bots Developer Cookbook Call a Flow Action
Now, you can go ahead and save the flow. Give it a unique label such as CookbookBot CancelOrder and specify the type
as Autolaunched Flow. Other types such as Screen Flow don’t apply here, because there is no UI element and this flow is triggered
by a bot as a server-side process.
53
Einstein Bots Developer Cookbook Call a Flow Action
We need to create another variable for this assignment. Create a Message variable from the Variable field and specify the Text
Data Type.
Note: Be sure to make this resource Available for output. This checkbox allows the Bot Builder to access this variable as an
output parameter from the flow.
54
Einstein Bots Developer Cookbook Call a Flow Action
The Manager subtab in the Toolbox lists all the constants and variables that are used in this flow. One thing to double-check—we
must have OrderNumber set as the Input variable and Message set as the Output variable.
Important: As mentioned in Set Up Your First Einstein Bot, you need to give the bot permission to access your flow. From
Setup, use the Quick Find box to find Permission Sets. Select the sfdc.chatbot.service.permset permission set. From the
permission set options, select System Permissions. Enable the Run Flows permission.
This flow is definitely not ready for prime time. It doesn’t check if the order exists, or if the order has been returned or canceled, in
which case we shouldn’t let the customer cancel again. But don’t worry, flow supports the necessary logic to make our flow more
robust.
If you only need to understand how to trigger a flow action from Bot, you can probably jump to the next step. But if you are new to
flow, now is a great time to learn about additional flow capabilities. You can design extremely powerful flows without even writing
a line of code. To learn more, see Flows in Salesforce Help.
55
Einstein Bots Developer Cookbook Call a Flow Action
56
Einstein Bots Developer Cookbook Call a Flow Action
In the action element, we need to first select Flow as the Action Type. With that, Bot Builder lists all the available flow actions. Select
the Cookbook Bot CancelOrder action. Notice that the input and output variable mapping are automatically expanded for the
OrderNumber and Message input variables with placeholders. We need to create a new bot variable for the output. Let’s
name it Transaction_Message.
57
Einstein Bots Developer Cookbook Call a Flow Action
Finally, in the message element, we use the {!Transaction_Message} variable as the message to the customer.
58
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Important: This feature only works when using your bot for Chat. It does not apply to Messaging.
Sometimes, if one piece of information is critical to help a customer with most inquiries, you may want to gather the information in a
pre-chat form before the customer even starts a conversation, such as the order number. From the Greet the Customer section, we
already know how to get a customer name through a pre-chat form. In this chapter, we'll take it one step further and show you how to
gather inquiry-related information from a pre-chat form and use this data to improve the user experience.
Prerequisites
59
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Before beginning this recipe, be sure you’ve completed the Greet the Customer recipe. These steps build on that previous section.
1. Create custom fields for the order number.
First of all, we need to create OrderNumber custom fields on both the LiveChatTranscript and the Case objects. As
explained in Greet the Customer, the bot pre-chat form action looks for fields on the LiveChatTranscript record to pull in
pre-chat information. As for the Case field, Embedded Chat's pre-chat configuration only uses Contact and Case fields to
build the form, thus we need the field on the Case object as well.
Go ahead and create two Text custom fields, one on Case and one on LiveChatTranscript. Both can be labeled as
OrderNumber with the API name OrderNumber__c.
60
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
embedded_svc.snippetSettingsFile.extraPrechatFormDetails = [{
"label":"First Name",
"transcriptFields": ["FirstName__c"]
},{
"label":"Last Name",
"transcriptFields": ["LastName__c"]
},{
"label":"Email",
"transcriptFields": ["Email__c"]
},{
"label":"OrderNumber",
"transcriptFields": ["OrderNumber__c"]
}];
})();
4. Get access to the OrderNumber custom field in the LiveChatTranscript record using either the Salesforce Metadata
API or an invocable Apex method.
Now just like how we discussed in the Greet the Customer with Embedded Service Chat section, there are two ways to get access
to this OrderNumber custom field.
61
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
a. Write Apex code to grab what you need and make the Apex method accessible to the Bot Builder using the
@InvocableMethod annotation. For instance, if you’re using Omni-Channel, you can use the RoutableId context
variable to get the LiveChatTranscript record, extract the custom field value, and then pass it back to your bot.
b. Use the Salesforce Metadata API to add context variables that aren’t available out of the box. For instance, you can create a
context variable to gain access to a LiveChatTranscript custom field.
We give you guidance on how to perform either method.
a. (Option 1 of 2: Apex Code Solution) If you want to extract the OrderNumber field from the LiveChatTranscript
object using an invocable Apex method, review the Apex Solution in the Greet the Customer section on page 13 and then
follow these additional instructions.
This time, you need to update your Apex code so that it grabs the order number from the LiveChatTranscript record.
Use this new code in place of the code you previously created. You see that it’s almost identical, except that it grabs the order
number and puts it in a new output variable (sOrderNumber).
public with sharing class CookbookBot_GetTranscriptVariables {
@InvocableVariable(required=true)
public String sOrderNumber;
}
FROM LiveChatTranscript
WHERE Id = :transcript.routableID
LIMIT 1];
62
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
return names;
}
}
To pass data from our Apex code to the bot, we'll call the Apex action to set the OrderNumber variable along with the
FirstName variable. We could call this action first thing in our “Welcome” dialog directly, similar to how we were able to set
the FirstName variable. However, in this exercise, let’s set up an initialization dialog. This way, we can wrap all the initialization
actions in this dialog while keeping our welcome dialog a little easier to read.
Create a “Bot Initialization” dialog that calls our Apex action.
63
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
b. (Option 2 of 2: Metadata API Solution) If you want to extract the OrderNumber field from the LiveChatTranscript
object using the Salesforce Metadata API, review the Metadata Solution in the Greet the Customer section on page 15 and then
follow these additional instructions.
This time, add the following XML snippet (in addition to the previously specified XML on page 15 which added the first name)
when deploying changes to your org.
<contextVariables>
<contextVariableMappings>
<SObjectType>LiveChatTranscript</SObjectType>
<fieldName>LiveChatTranscript.OrderNumber__c</fieldName>
<messageType>WebChat</messageType>
</contextVariableMappings>
<dataType>Text</dataType>
<developerName>TranscriptOrderNumber</developerName>
<label>Transcript Order Number</label>
</contextVariables>
To use this new context variable in our bot, we call another Set Variable rule using the new Transcript Order Number
context variable (in addition to the previous rule for the Transcript First Name context variable). We could call this
rule first thing in our “Welcome” dialog directly, similar to how we were able to set the FirstName variable. However, in this
exercise, let’s set up an initialization dialog. This way, we can wrap all the initialization actions in this dialog while keeping our
welcome dialog a little easier to read.
Create a “Bot Initialization” dialog that calls both of our Set Variable rules.
64
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Note the next step from this dialog should be set to the “Order Related” dialog to present the options from the “Order Related”
submenu.
65
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Tip: You can group your dialogs in Dialog Groups to make them easier to manage. In this example, we’ve grouped all the
initialization dialogs under one group. To create a group, use the same create button used when creating dialogs.
In the original “Welcome” dialog, let’s perform the following steps:
a. Use a Rule Action to call the “Bot Initialization” dialog we just created to grab the order number from the pre-chat field.
66
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
c. Use a Rule Action that redirects to the “Welcome with Order Number” dialog only if the OrderNumber variable has been set.
d. If the variable has not been set, then just ask the customer what they need help with.
67
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Notice that we split the original greeting message into two parts. We first greet the customer, then we have the rule action before
the next message. If the customer doesn’t provide an order number in the pre-chat form, we continue with the original question
“How can I help you today?” Otherwise, the customer is sent to the “Welcome with Order Number” dialog for order-specific questions.
6. Test!
Now let’s test our optimized user flow. If the customer enters an order number in the pre-chat form, the bot can use that information
to get right to the order-specific flow.
68
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
69
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Prerequisites
• Set Up Your First Einstein Bot on page 1
• Greet the Customer on page 6
• Prompt Customer with Menu Options on page 33
In this recipe you learn how to:
• Create a custom field on an existing object.
• Add information to the pre-chat form.
• Update your site’s code snippet so the bot can access this new information.
• Use Apex code or the Metadata API to access the custom field.
• Optimize the bot design.
3. Get access to the OrderNumber custom field in the LiveChatTranscript record using either the Salesforce Metadata
API or an invocable Apex method.
Now just like how we discussed in the Greet the Customer with Embedded Service Chat section, there are two ways to get access
to this OrderNumber custom field.
a. Write Apex code to grab what you need and make the Apex method accessible to the Bot Builder using the
@InvocableMethod annotation. For instance, if you’re using Omni-Channel, you can use the RoutableId context
variable to get the LiveChatTranscript record, extract the custom field value, and then pass it back to your bot.
b. Use the Salesforce Metadata API to add context variables that aren’t available out of the box. For instance, you can create a
context variable to gain access to a LiveChatTranscript custom field.
We give you guidance on how to perform either method.
70
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
a. (Option 1 of 2: Apex Code Solution) If you want to extract the OrderNumber field from the LiveChatTranscript
object using an invocable Apex method, review the Apex Solution in the Greet the Customer section on page 13 and then
follow these additional instructions.
This time, you need to update your Apex code so that it grabs the order number from the LiveChatTranscript record.
Use this new code in place of the code you previously created. You see that it’s almost identical, except that it grabs the order
number and puts it in a new output variable (sOrderNumber).
public with sharing class CookbookBot_GetTranscriptVariables {
@InvocableVariable(required=true)
public String sOrderNumber;
}
FROM LiveChatTranscript
WHERE Id = :transcript.routableID
LIMIT 1];
return names;
}
}
To pass data from our Apex code to the bot, we'll call the Apex action to set the OrderNumber variable along with the
FirstName variable. We could call this action first thing in our “Welcome” dialog directly, similar to how we were able to set
71
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
the FirstName variable. However, in this exercise, let’s set up an initialization dialog. This way, we can wrap all the initialization
actions in this dialog while keeping our welcome dialog a little easier to read.
Create a “Bot Initialization” dialog that calls our Apex action.
b. (Option 2 of 2: Metadata API Solution) If you want to extract the OrderNumber field from the LiveChatTranscript
object using the Salesforce Metadata API, review the Metadata Solution in the Greet the Customer section on page 15 and then
follow these additional instructions.
This time, add the following XML snippet (in addition to the previously specified XML on page 15 which added the first name)
when deploying changes to your org.
<contextVariables>
<contextVariableMappings>
72
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
<SObjectType>LiveChatTranscript</SObjectType>
<fieldName>LiveChatTranscript.OrderNumber__c</fieldName>
<messageType>WebChat</messageType>
</contextVariableMappings>
<dataType>Text</dataType>
<developerName>TranscriptOrderNumber</developerName>
<label>Transcript Order Number</label>
</contextVariables>
To use this new context variable in our bot, we call another Set Variable rule using the new Transcript Order Number
context variable (in addition to the previous rule for the Transcript First Name context variable). We could call this
rule first thing in our “Welcome” dialog directly, similar to how we were able to set the FirstName variable. However, in this
exercise, let’s set up an initialization dialog. This way, we can wrap all the initialization actions in this dialog while keeping our
welcome dialog a little easier to read.
Create a “Bot Initialization” dialog that calls both of our Set Variable rules.
73
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Note the next step from this dialog should be set to the “Order Related” dialog to present the options from the “Order Related”
submenu.
74
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Tip: You can group your dialogs in Dialog Groups to make them easier to manage. In this example, we’ve grouped all the
initialization dialogs under one group. To create a group, use the same create button used when creating dialogs.
In the original “Welcome” dialog, let’s perform the following steps:
a. Use a Rule Action to call the “Bot Initialization” dialog we just created to grab the order number from the pre-chat field.
75
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
c. Use a Rule Action that redirects to the “Welcome with Order Number” dialog only if the OrderNumber variable has been set.
d. If the variable has not been set, then just ask the customer what they need help with.
76
Einstein Bots Developer Cookbook Optimize Bot Flow with Pre-Chat Data
Notice that we split the original greeting message into two parts. We first greet the customer, then we have the rule action before
the next message. If the customer doesn’t provide an order number in the pre-chat form, we continue with the original question
“How can I help you today?” Otherwise, the customer is sent to the “Welcome with Order Number” dialog for order-specific questions.
5. Test!
Now let’s test our optimized user flow. If the customer enters an order number in the pre-chat form, the bot can use that information
to get right to the order-specific flow.
77
Einstein Bots Developer Cookbook Understand Customer Intent with Natural Language
Processing
Channels
• Chat
• Messaging
Prerequisites
• Set Up Your First Einstein Bot on page 1
78
Einstein Bots Developer Cookbook Understand Customer Intent with Natural Language
Processing
A good approach in bot solution design is to start with inquiry volume analysis. Understanding your typical customer inquiry types and
their volume gives us a good picture for the things we want to tackle first. Once you have the initial set of target inquiries defined, you
can start designing and building the dialogs. In general, each type of inquiry should be mapped to one dialog or a group of dialogs.
These dialogs are the building blocks of our bot. After we have these dialogs in place, all our bot needs to learn next is how to understand
the customer intent and kick off that particular conversation.
An interface with menus and buttons provides customers a basic-yet-effective navigation experience, especially during the early phase
of your bot development when the support for different inquiry types is limited. However, as our bot develops with more inquiry types
and dialogs, the navigation menus and submenus become longer and deeper, and less optimal. For a bot to support many types of
transactions or to make a bot more conversational, Natural Language Processing (NLP) provides a more natural approach to identifying
customer intent. Customers enter whatever they want to ask and the bot can ideally understand their intent and start the right dialog.
Although it takes iterations of training, learning, and refining to improve the accuracy of intent detection, the initial setup is easy. We
can get our bot up and running with NLP in no time.
1. Create an Einstein intent set.
The customer intent training dataset contains the many ways your customer may ask the bot about one particular thing, also known
as an “intent”. Intent Sets is where we can enter the training data—customer input or utterances.
From Setup, use the Quick Find box to find Einstein Intent Sets and create a new intent set called CookbookBot Intents.
After you’ve created the intent, edit this intent set.
From the Intents section, create at least two intents: Main Menu and Order Status.
79
Einstein Bots Developer Cookbook Understand Customer Intent with Natural Language
Processing
For each of the intents, enter at least 20 unique customer inputs. For example, for Order Status, you might enter:
• Can you check the order status for me?
• did I place the order successfully?
• order didn’t arrive yet
• when will it be shipped?
Important: If you have not yet enabled dialog intents for this bot, you’ll have to click the Enable Dialog Intent button beside
the dialog name before you can access the Dialog Intent subtab.
80
Einstein Bots Developer Cookbook Understand Customer Intent with Natural Language
Processing
In the Intent Extensions section, select the Add Intent button and select the “Order Status” intent we created from last step.
(Notice there’s also an AppExchange button that allows you to search pre-built intent libraries and install them into your org.)
81
Einstein Bots Developer Cookbook Understand Customer Intent with Natural Language
Processing
Once started, the model building process usually finishes in a few minutes given that our training dataset is small at this point.
4. Test!
After the Einstein Intent Management status shows it has succeeded, we can launch the bot again. Since we have customer intents
for the “Order Status” dialog, let's try that intent. After receiving the greeting message, instead of clicking one of the menu options,
let's enter something like “where is my package”. In our example, the bot correctly identified the intent and sends us to the “Order
Status” dialog. The bot now asks for our order number right away!
82
Einstein Bots Developer Cookbook Understand Customer Intent with Natural Language
Processing
83
Einstein Bots Developer Cookbook Understand Customer Intent with Natural Language
Processing
This recognition feature is probably one of the most often overlooked features that we should keep in mind when designing a
conversational bot. To learn why, test your bot again. This time instead of asking “where is my package”, ask “where is my package
O-00123456”. (Use whatever value is an actual order number in your org.)
84
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
The bot not only identified the intent of checking order status, but also correctly retrieved the subject (Order Number) of the question.
Thus it skipped the order number question and jumped directly into the action to check order status.
So how did it do it? Once the bot identified the intent was an order status inquiry, it looked at the questions in this dialog with the
Recognize checkbox enabled to see if there is any answer provided already in the original customer input. With the
OrderNumberString entity specified in a regular expression (as described in Gather Customer Information Using the Bot), the bot
easily found the order number.
• Not all dialogs need customer inputs. For example, our “Welcome” dialog shouldn't have to be trained. You wouldn't expect the
customer to be greeted again, right? Or if you have a group of dialogs to process one inquiry type, perhaps only the first dialog in
the group should be trained.
• Although the minimum size of the customer inputs for each dialog is 20 unique utterances, we recommend at least 150 customer
inputs for each dialog that requires training.
• If you’re using a bot for messaging and you created a “Messaging Initialization” dialog, as described in Greet the Customer with
Messaging on page 26, follow the instructions in that recipe to call your initialization logic from all dialogs that use intent detection.
85
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
Channels
• Chat
• Messaging
Prerequisites
• Set Up Your First Einstein Bot on page 1
• An org with Lightning Knowledge set up
• A bot assigned to a Custom Bot User which has access to Cases & Contacts
In this recipe you learn how to:
• Set up Object Search to quickly find articles related to a customer question.
• Use Conditional Messaging to provide targeted responses to the customer.
• Create a case using Flows to complete the bot conversation.
Because this recipe is channel agnostic so that the bot works on any channel, we skip using the pre-chat form. Instead we use flows to
look up the user via email. If your bot uses Messaging, it doesn’t have access to the pre-chat form, so you must bake the contact creation
into the bot dialogs. If your bot is only used for Chat, you can use the pre-chat form instead of the method that we show here. We
highlight great conversation design methods when we ask questions to keep the customer involved in the process every step of the
way.
To give a high-level idea of the bot is doing, here’s a flowchart:
1. We need a few dialogs for this recipe, so we create a dialog group called Knowledge Search to keep things organized. In this dialog
group we have four dialogs:
• Search Knowledge Base: the bot asks the customer what they’re looking for and performs a knowledge search
• Create a Case Question: the bot uses conditional messaging to ask the customer if the knowledge article solved their issue
• Case Flow: a dialog where the bot attempts to find a contact and creates a case
• More Case Info: a dialog where the bot asks for more information to create a contact, then creates a case
To create a dialog group in the Bot Builder, click the plus icon next to the search bar and select New Group. Name the group
Knowledge Search. Use the plus icon again and select New Dialog to create the four dialogs listed above. Make sure that
you select the Knowledge Search group in the Assign to Dialog Group field.
86
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
2. To make sure that we wire this dialog to the main bot, add the Search Knowledge Base dialog onto the Main Menu dialog.
3. Click the Search Knowledge Base dialog to build the introductory messages. Click the plus icon and start with a Question Dialog
Step. In the Bot Asks field, enter “Great. What would you like to know?” as the message.
We must store the customer input in a variable, so select [System] Text (Text) as the Entity Name to capture the text data. In the
Save Answer to Variable field, click to create the Text Variable Knowledge Question.
It’s a good conversational design practice to let the customer know the bot’s next step. To add a Message Dialog Step, click the plus
icon and enter Thanks! I'll search for that in the Knowledge Base for you.
4. Next, let’s add an action to use Object Search. Add an action dialog step and select Object Search as the Action Type. Select Knowledge
in the Object field. In the Input Variable to Search, select your Knowledge Question variable, and create a List Variable Knowledge
Results to serve as the Search Results variable.
87
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
Knowledge search let you deliver up to three results, so feel free to select up to three articles. Make sure that your input variable is
set to Knowledge Question, and create an Object List variable Knowledge Results.
Note: To create an Object List Variable, select Object as the Data Type and make sure that you check Contains a List.
5. Next we plan for two scenarios: the bot doesn’t find anything and the bot finds results. To start with the bot not finding anything,
add a rule element with conditions to check if the Knowledge Results variable is less than 1. To keep the customer informed, add a
Message dialog before you redirect them to ask whether they want to create a case anyway with Create a Case Question dialog.
We select Sorry, I couldn't find anything in the Knowledge Base that would be a good match., but you can use whatever
works for your company.
88
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
6. We handled the null use case, so let’s continue to the results. Add a question element, and enter the text Here are some
articles that I found: in the message. Click Choice Type to deliver the results to the end user. Change the Choice
Type to Dynamic, and then set Action Type to From List Variable. The input is the object list variable used in the knowledge search
completed in the Action dialog — in this example, Knowledge Results.
This is a dynamic choice, so we identify the field that is placed within the choice buttons. For knowledge, we recommend the {!Title}
field. To make sure that the selection is saved into a new variable, create an Object variable and name it Knowledge. Set the Entity
to Object. This setting delivers multiple fields within the selected article.
Because the Error Rule is required, let’s add a redirect to Create a Case Question.
89
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
7. Now let’s deliver the selected article to the customer. Add a Message dialog step to deliver the selected article summary, in this case,
{!Knowledge.Summary}. Since the Knowledge variable we created is an Object variable, we can call any field inside the object
by following the format: {!VariableName.FieldName}.
We're now going to check in with the customer to see if that article was helpful. Add a question dialog step with a new boolean
variable to ask if the article was helpful. We use Conditional Messaging built into the Rules dialog step to make sure that the customer
found what they wanted.
If it was helpful, then our bot’s job is done here and we return the customer to the Main Menu. It’s good practice to let the customer
know where you plan to transfer them before you do it, so add a conditional message as part of the Rule dialog step before you
redirect.
90
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
If the article wasn’t helpful, we want to give the customer the option to create a case, so we add a transfer to the Create a Case
dialog.
8. Next we build a flow to create a case for when a knowledge base article isn’t helpful to our customer.
Switch over to the Create a Case Question dialog. We use a similar flow with a question dialog step that leads to two rule dialog
steps. And we use conditional messages that depend on the answer. Create a boolean variable to store the answer. If true, the bot
redirects to the Case Flow dialog, and if not, then the bot moves back to the Main Menu dialog.
91
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
92
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
9. Now let’s add flows to our bot. To keep things simple for this flow, we ask the user for an email address. To enhance this flow, you
can ask the customer for either an email or a phone number. Here, we search for a contact based on their contact information. If the
flow is unable to find a match, the flow is complete. If the bot finds a match, then the flow should create a case attached to that
contact, and deliver the case number back to the bot.
On the flowchart, the next section refers to the second half of the chart:
Before we move to the Flow Builder, let’s open the Case Flow dialog and enter a new Question dialog step to ask the customer for
their preferred contact information:
93
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
10. We split the process into two autolaunched flows—one if there’s a contact match in the system and another to create a contact
and case at once. Because we need more information from the customer, it makes sense to move this process into a separate flow.
The dialog can launch one flow at a time, so calling two flows works with the conversation written in the dialog. We create this flow
with email only, but you can use this base as a launching point for other channels.
94
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
Let’s create the lookup part of the flow. We add a Get Records element to the workspace to look up a contact based on the email:
95
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
11. Next, we add a Decision element to check whether a match was found:
If found, then the flow moves to a Create Records element that defines the case record:
96
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
Note: We added Bot as a value on the Case Origin picklist to run reports on how many cases the bot created.
12. Next, we use Get Records and the Case ID to get the case number to pass along to the customer in the final message:
13. Now, let’s add a Decision element to define which output message is brought back to the bot. Whether it’s that a case was successful
or that we must create a contact, we can feed both results to the same variable back to the bot.
97
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
We finish with two Assignment elements that point to the same variables:
You can use variables such as the case number to personalize the message to the end user, for instance: Okay, your case
{!Get_Case_Number.CaseNumber} has been created.
Save the flow and activate it. To validate that the flow is working, use the Debug button to work through all the potential use cases.
14. Let’s head back to the Bot Builder to connect the bot to the flow. Select a new Action element and enter the flow details. If your flow
is missing, check to ensure that it is activated, and if variables are missing, return to the Flow builder and confirm that the variables
are set as available for input or output.
98
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
15. Finally, let’s build out the dialog steps to handle the output of the flow. If a contact does not exist in the system we want to move
the bot to the second flow, which asks the customer for more information and then creates both records. Otherwise, the flow includes
the success message with the case number and then sends them back to the main menu. Add two Rule dialog steps to act on the
boolean variable of whether a contact exists in the system: ContactExists. This information is passed through the flow back to the
bot.
99
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
Because we built the output message into the flow, we can use the same {!Flow_Output} variable in both situations.
16. Let’s move on to our final dialog step, which asks the customer for more information and then introduces a flow to create a contact
and a case at once.
In the Bot Builder, let’s add two question dialog steps to ask for the customer name followed by a Message dialog step to tell the
customer what happens on the backend:
100
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
Click Save.
17. Returning to the Flow Builder, we can build out an autolaunched flow to create a contact, then a case, and output a success message:
101
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
102
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
Then, we use the Get Records element to get the case number:
And finally, we set the output variable to the success message including the Case Number using the message Thanks
{!BotFirstName}, your case number is {!Get_Case_Number_Email.CaseNumber}.
Set up the flow to match the diagram shown at the beginning of this step. Make sure you save and activate this new flow.
18. Return to the Bot Builder to set up this second flow and deliver the flow output:
103
Einstein Bots Developer Cookbook Create a Self-Service Bot with Knowledge, Flows, and Cases
104
Einstein Bots Developer Cookbook Advanced Bot Recipes
It’s amazing how much you can automate with clicks! Bots built with flows paired with a well-considered conversation design can create
powerful, sustainable solutions for your business.
105
Einstein Bots Developer Cookbook Create Dynamic Menus
106
Einstein Bots Developer Cookbook Create Dynamic Menus
Important: As mentioned in Set Up Your First Einstein Bot, you need to give the bot permission to access this custom object
and these fields. From Setup, use the Quick Find box to find Permission Sets. Select the sfdc.chatbot.service.permset
permission set. From the permission set options, select Object Settings. Select your custom object and then make sure that
this permission set has read and edit permissions to the object and all the relevant fields.
Create a few test records in this object, including a few records with the Status value of New or Scheduled, so that we can
reschedule an appointment later on. Also note the email address for the contact associated with the appointments. That’s what
you’ll be using to test this functionality.
FROM Bot_Appointment__c
WHERE Contact__r.Email =:sEmail
AND Status__c IN ('New','Scheduled')];
107
Einstein Bots Developer Cookbook Create Dynamic Menus
return appointmentList;
}
}
• There is no @InvocableVariable declared in this class. Since we only have one input parameter and one output parameter,
we skipped that part.
• The return variable of the getOpenAppointments() method needs to be List<List<SObject>>. The inner List
has all the open appointment records associated with this email address. The outer List is required by the
@InvocableMethod annotation to allow this function to be bulk ready (in case you want to find open appointments for
multiple contacts). For our use case, we only need to operate on one contact record, so there’s only one element in the outer
List.
4. Call the “Get Open Appointments” Apex method and present dynamic options using a question.
Let’s build the “Reschedule an Appointment” dialog. First, we’ll ask for the email address used to book the appointment. We can
reuse the same variable Email to capture the customer answer. As we already learned, the bot skips this question if the customer
entered the email address previously, for example, in the pre-chat form, as long as the address is passed to the same variable (see
Optimize Bot Flow with Pre-Chat Data).
108
Einstein Bots Developer Cookbook Create Dynamic Menus
Next, we’ll add another Question element that presents the list of options. When we set the answer variable to an Object entity,
such as openAppointment, and select the Choices option as Dynamic, the Question element configuration area expands
with additional settings for a formula (1), an action (2), and an error handling mechanism (3).
109
Einstein Bots Developer Cookbook Create Dynamic Menus
The format formula gives administrators flexibility in determining the format of menu options. We can merge fields from the Salesforce
object using their field API names. In this case, set the formula to: {!JobType__c} on {!AppointmentDate__c}
{!AppointmentSlot__c}. You don’t have to prefix the variable names with the object type because this entry is scoped to
the Salesforce object itself. You can try different fields, but make sure they are included in the SOQL query in the
getOpenAppointments() Apex method. And make sure that the field level security is enabled in the
sfdc.chatbot.service.permset permission set.
Select Apex for the Action Type. In the Action Name field, set it to the new Apex class that we created (“Get Open Appointments”).
When you select the action name, the input and output parameter sections also expand based on the signature of the Apex method.
Set the Email variable as the input for this Apex action.
The Error Rule handles the situation when Apex returns no records. In that case, we redirect the customer to a new dialog named
“No Appointment Found”. We can leave the this new dialog empty for now.
110
Einstein Bots Developer Cookbook Create Dynamic Menus
After the customer selects an option from the menu, the variable is set to the selected record. You can use this info however you
want.
In our example, the bot acknowledges the customer selection in this response: Great, let's reschedule appointment
number {!openAppointment.Name} for that {!openAppointment.JobType__c}...
5. Test!
111
Einstein Bots Developer Cookbook Create Dynamic Menus
Let’s see how our dynamic menu looks now. Make sure you enter a valid email address that’s associated with one of the contacts
on a test appointment record in the org.
• Selecting an appointment to update from a list is only the first step of a rescheduling transaction. How many Apex actions do we
need to complete this inquiry type? There are roughly three potential actions: getOpenAppointments(),
getAvailableSlots(), and saveUpdatedAppointment(). Can you complete the other two Apex actions?
• Looking back at our user experience for the “Reschedule an Appointment” conversation, once the chat starts, the customer is greeted
and presented with the main menu. They can select Appointment Related and then Reschedule an Appointment in the submenu
to start this transaction. From this dialog, they select an open appointment, select an available time slot, and get a confirmation
message. Four taps on a mobile device. In a happy path scenario, they don't have to type anything at all. See how a bot can change
the way we interact with our customers through the traditional chat channel?
112
Einstein Bots Developer Cookbook Get Context Info from the Web
2. Modify the chat code snippet and add these new fields.
We created the extraPrechatFormDetails array in our JavaScript file in Optimize Bot Flow with Embedded Chat. Add the
variables ChatRequestPage and ShoppingCartValue to this array. For testing, to indicate that the customer is on the
payment page and the shopping cart has $600 worth of items, hard code the values of “Payment” and “600” in these variables.
Note the difference between these and other pre-chat fields, such as Name, Email, and OrderNumber. For the
ChatRequestPage and ShoppingCartValue variables, we are actually setting the value attribute in the array. Data for
113
Einstein Bots Developer Cookbook Get Context Info from the Web
other fields would actually come from whatever the customer entered on the pre-chat form. Also, specify the transcriptFields
attribute so that data is saved to the mapped field in the LiveChatTranscript record.
a. Code change for a customer site:
embedded_svc.settings.extraPrechatFormDetails = [{
"label":"First Name",
"transcriptFields": ["FirstName__c"]
},{
"label":"Last Name",
"transcriptFields": ["LastName__c"]
},{
"label":"Email",
"transcriptFields": ["Email__c"]
},{
"label":"OrderNumber",
"transcriptFields": ["OrderNumber__c"]
},{
"label": "ChatRequestPage",
"value": "Payment",
"displayToAgent": true,
"transcriptFields": ["ChatRequestPage__c"]
},{
"label": "ShoppingCartValue",
"value": "600",
"displayToAgent": true,
"transcriptFields": ["ShoppingCartValue__c"]
}];
114
Einstein Bots Developer Cookbook Get Context Info from the Web
b. (Option 1 of 2: Apex Code Solution) Use this code to get you going with the Apex solution. Notice that the data type for the
ShoppingCartValue variable is Decimal. If you need more help, revisit the Apex solution in Greet the Customer with
Snap-Ins Chat on page 13.
public with sharing class CookbookBot_GetTranscriptVariables {
@InvocableVariable(required=true)
public String sOrderNumber;
@InvocableVariable(required=true)
115
Einstein Bots Developer Cookbook Get Context Info from the Web
@InvocableVariable(required=true)
public Decimal nShoppingCartValue;
}
ChatRequestPage__c,
ShoppingCartValue__c
FROM LiveChatTranscript
WHERE Id = :transcript.routableID
LIMIT 1];
return outputList;
}
}
4. Verify that we correctly extracted the values from our new fields.
Temporarily add the following text to the welcome message: {!ShoppingCartValue} and {!ChatRequestPage}.
If the changes are correct, you see “600 and Payment” when you run the bot. If not, confirm that your bot has access to the new
LiveChatTranscript fields and any new Apex code. To learn more, review setting up permissions in Set Up Your First Einstein
Bot. Also, verify that the API field names are correct in all your code snippets.
Now let’s look at how we can use this context information to improve the user experience. Our goal is to transfer a customer that’s
stuck on the payment page to an agent.
116
Einstein Bots Developer Cookbook Get Context Info from the Web
117
Einstein Bots Developer Cookbook Get Context Info from the Web
By configuring the message within a variable, we can use an Apex action, for example, to populate message variables for different
situations.
Let’s write some Apex code to handle this logic. The code takes two input parameters (sChatRequestPage and
sShoppingCartValue), and returns two @InvocableVariables, bInitialTransferRequired and
sInitialTransferMessage, in the wrapper class. The code does two things.
118
Einstein Bots Developer Cookbook Get Context Info from the Web
@InvocableMethod(label='Initialize Bot')
public static List<InitializationOutput> initializeBot(List<InitializationInput>
inputParameters)
{
// Grab the input variables
String sChatRequestPage = inputParameters[0].sChatRequestPage;
Decimal nShoppingCartValue = inputParameters[0].nShoppingCartValue;
// Return result
outputParameters.add(outputParameter);
return outputParameters;
}
}
119
Einstein Bots Developer Cookbook Get Context Info from the Web
By now, you know how to add an Apex class and make sure that your bot has permission to access the class. If not, see Call an Apex
Action.
7. Call the “Initialize Bot” Apex action from the “Bot Initialization” dialog.
In the “Bot Initialization” dialog, after we set the ShoppingCartValue and ChatRequestPage variables with pre-chat
form actions, we can call the new Apex action that we built in the previous step. Create two new variables, Transfer_Required
and Transfer_Message, to take the output value of the Apex action, which drives the bot experience.
120
Einstein Bots Developer Cookbook Get Context Info from the Web
If you look at the available Rule Action options, there’s a Call Dialog action and a Redirect to Dialog action. Here’s the difference:
with Redirect to Dialog, the destination dialog takes over the conversation, while Call Dialog returns the conversation back to the
originating dialog. Hence, we use Call Dialog for “Bot Initialization” (because we want the flow to return back to this dialog), and
we use Redirect to Dialog for the “Transfer Required” dialog (where we want to hop over to the other dialog and not return). Note
that when we use Redirect to Dialog, whatever configuration we selected in the Next Dialog section of the originating dialog is
ignored.
9. Test!
Let’s do two rounds of testing. First, let’s use the original chat snippet that had the ShoppingCartValue set to 600.
121
Einstein Bots Developer Cookbook Get Context Info from the Web
Now let’s change the JavaScript that we wrote earlier so that the ShoppingCartValue is 300.
• Can a business user change the bot behavior or are admins responsible for all configuration? It may not be a good idea to have
everyone become an administrator and change the bot how they want. Instead, take advantage of custom settings or custom objects
that make the bot configuration more data-driven. You can then give access to users so that they can change configuration-related
data records. In this way, you give business users flexibility, but in a controlled manner.
122
Einstein Bots Developer Cookbook Get Context Info from the Web
liveagent.init('https://d.gla3-phx.MyDomainName.salesforce.com/chat', '572B0000000513C',
'00DB0000000LgOe');
</script>
The other thing to note is that the saveToTranscript() method maps the ChatRequestPage chat variable to the
custom field LiveChatTranscript.ChatRequestPage__c and the ShoppingCartValue chat variable to the
custom field LiveChatTranscript.ShoppingCartValue__c. This way, these two pieces of information are saved to
the LiveChatTranscript when the record is created.
123
Einstein Bots Developer Cookbook Get Context Info from the Web
The first two new lines of code indicate that we have two hidden chat variables with the name specified as
liveagent.prechat:ShoppingCartValue and liveagent.prechat:ChatRequestPage. The second two
lines of code map these two chat detail variables to the LiveChatTranscript fields by their API names.
Use the preChatInit callback function to populate these two hidden fields. Add the following section to the pre-chat page.
The values are coming from the input parameter details.customDetails array, which includes data passed from the
landing page where the customer initiated the chat.
<script type='text/javascript'
src='https://MyDomainName.my.salesforcescrt.com/content/g/js/32.0/prechat.js'></script>
<script type="text/javascript">
var detailCallback = function (details){
for (var i = 0; i < details.customDetails.length; i++) {
if(details.customDetails[i].label == 'ShoppingCartValue'){
document.getElementById('ShoppingCartValue').value =
details.customDetails[i].value;
}
if(details.customDetails[i].label == 'ChatRequestPage'){
document.getElementById('ChatRequestPage').value =
details.customDetails[i].value;
}
}
};
//First parameter is Chat URL. This is same as generated in Live Chat deployment code
and can be used here
liveagent.details.preChatInit('https://d.gla3-phx.MyDomainName.salesforce.com/chat','detailCallback');
</script>
There are two URLs in the above code. The first line references the prechat.js library. In your code, change the domain and
path to be the same as how the deployment.js file is referenced on the chat request page. One of the parameters for the
preChatInit() method is also a URL. You should set it the same as the first parameter in the liveagent.init() method
in the deployment code. It's generated from Deployments in Setup. While you are on the deployment configuration page, verify
that the Live Agent deployment has Allow Access to Pre-Chat API enabled.
124
Einstein Bots Developer Cookbook Get Context Info from the Web
In Bot Builder, create two variables, ChatRequestPage and ShoppingCartValue. Since the bot can properly cast a pre-chat form
field to the correct data type, we can use Text as the data type for the ChatRequestPage variable, and Number as the data type
for the ShoppingCartValue variable.
In the same “Bot Initialization” dialog where we set first name, last name, email, and order number variables (in Optimize Bot Flow
with Pre-Chat Data), we also want to populate the two new variables. As we discussed in Greet the Customer with Embedded Service
Chat (and then again in Optimize Bot Flow with Embedded Chat), you can access pre-chat fields using the Metadata API or by writing
some Apex code. Using the example in Greet the Customer with Embedded Service Chat, extend that functionality and include
these two variables. Use the following code snippets to check your work.
a. (Option 2 of 2: Metadata API Solution) Use this XML to get you going with the Metadata API approach. If you need more help,
revisit the metadata solution in Greet the Customer with Snap-Ins Chat on page 15.
<contextVariables>
<contextVariableMappings>
<SObjectType>LiveChatTranscript</SObjectType>
<fieldName>LiveChatTranscript.ChatRequestPage__c</fieldName>
<messageType>WebChat</messageType>
</contextVariableMappings>
<dataType>Text</dataType>
<developerName>ChatRequestPage</developerName>
<label>ChatRequestPage</label>
</contextVariables>
<contextVariables>
<contextVariableMappings>
<SObjectType>LiveChatTranscript</SObjectType>
<fieldName>LiveChatTranscript.ShoppingCartValue__c</fieldName>
<messageType>WebChat</messageType>
</contextVariableMappings>
<dataType>Number</dataType>
<developerName>ShoppingCartValue</developerName>
<label>ShoppingCartValue</label>
</contextVariables>
b. (Option 1 of 2: Apex Code Solution) Use this code to get you going with the Apex solution. Notice that the data type for the
ShoppingCartValue variable is Decimal. If you need more help, revisit the Apex solution in Greet the Customer with
Snap-Ins Chat on page 13.
public with sharing class CookbookBot_GetTranscriptVariables {
@InvocableVariable(required=true)
public String sOrderNumber;
@InvocableVariable(required=true)
public String sChatRequestPage;
125
Einstein Bots Developer Cookbook Get Context Info from the Web
@InvocableVariable(required=true)
public Decimal nShoppingCartValue;
}
ChatRequestPage__c,
ShoppingCartValue__c
FROM LiveChatTranscript
WHERE Id = :transcript.routableID
LIMIT 1];
return outputList;
}
}
5. Verify that we correctly extracted the values from our new fields.
Temporarily add the following text to the welcome message: {!ShoppingCartValue} and {!ChatRequestPage}.
If the changes are correct, you see “600 and Payment” when you run the bot. If not, confirm that your bot has access to the new
LiveChatTranscript fields and any new Apex code. To learn more, review setting up permissions in Set Up Your First Einstein
Bot. Also, verify that the API field names are correct in all your code snippets.
Now let’s look at how we can use this context information to improve the user experience. Our goal is to transfer a customer that’s
stuck on the payment page to an agent.
126
Einstein Bots Developer Cookbook Get Context Info from the Web
In Optimize Bot Flow with Pre-Chat Data, we optimized the conversation for customers that provided an order number on the
pre-chat form. Let’s do it again now that we have more context when a customer requests a chat.
Do we build another dialog called “Welcome customer with a high value shopping cart”? We can. But as we introduce more context
variables and rules, the number of dialogs can grow quickly for greeting the customer. Another approach is to build a utility or helper
dialog that uses variables to serve different situations and deliver different messages. This approach is more scalable. Let’s try it.
Add a “Transfer Required” dialog that handles when the bot recommends agent assistance.
a. Set the first message element to include just a new variable, “{!Transfer_Message}”.
b. Ask if the customer agrees to the transfer.
c. If they agree, redirect them to the “Transfer to Agent” dialog.
127
Einstein Bots Developer Cookbook Get Context Info from the Web
By configuring the message within a variable, we can use an Apex action, for example, to populate message variables for different
situations.
Let’s write some Apex code to handle this logic. The code takes two input parameters (sChatRequestPage and
sShoppingCartValue), and returns two @InvocableVariables, bInitialTransferRequired and
sInitialTransferMessage, in the wrapper class. The code does two things.
a. Sets boolean bInitialTransferRequired to true when sChatRequestPage='Payment' and
nShoppingCartNumber > 500.
b. Sets the message in the text variable sInitialTransferMessage.
public with sharing class CookbookBot_InitializeBot {
public class InitializationOutput{
@InvocableVariable(required=true)
public String sInitialTransferMessage;
@InvocableVariable(required=true)
public Boolean bInitialTransferRequired;
}
@InvocableMethod(label='Initialize Bot')
public static List<InitializationOutput> initializeBot(List<InitializationInput>
inputParameters)
{
// Grab the input variables
String sChatRequestPage = inputParameters[0].sChatRequestPage;
Decimal nShoppingCartValue = inputParameters[0].nShoppingCartValue;
128
Einstein Bots Developer Cookbook Get Context Info from the Web
// Return result
outputParameters.add(outputParameter);
return outputParameters;
}
}
By now, you know how to add an Apex class and make sure that your bot has permission to access the class. If not, see Call an Apex
Action.
8. Call the “Initialize Bot” Apex action from the “Bot Initialization” dialog.
In the “Bot Initialization” dialog, after we set the ShoppingCartValue and ChatRequestPage variables with pre-chat
form actions, we can call the new Apex action that we built in the previous step. Create two new variables, Transfer_Required
and Transfer_Message, to take the output value of the Apex action, which drives the bot experience.
129
Einstein Bots Developer Cookbook Get Context Info from the Web
If you look at the available Rule Action options, there’s a Call Dialog action and a Redirect to Dialog action. Here’s the difference:
with Redirect to Dialog, the destination dialog takes over the conversation, while Call Dialog returns the conversation back to the
originating dialog. Hence, we use Call Dialog for “Bot Initialization” (because we want the flow to return back to this dialog), and
we use Redirect to Dialog for the “Transfer Required” dialog (where we want to hop over to the other dialog and not return). Note
that when we use Redirect to Dialog, whatever configuration we selected in the Next Dialog section of the originating dialog is
ignored.
10. Test!
Let’s do two rounds of testing. First, let’s use the original chat snippet that had the ShoppingCartValue set to 600.
130
Einstein Bots Developer Cookbook Handle Intent Detection Failures
Now let’s change the JavaScript that we wrote earlier so that the ShoppingCartValue is 300.
• Can a business user change the bot behavior or are admins responsible for all configuration? It may not be a good idea to have
everyone become an administrator and change the bot how they want. Instead, take advantage of custom settings or custom objects
that make the bot configuration more data-driven. You can then give access to users so that they can change configuration-related
data records. In this way, you give business users flexibility, but in a controlled manner.
131
Einstein Bots Developer Cookbook Handle Intent Detection Failures
In addition, Apex code and system variables are available to improve the user experience. In this exercise, we explain two ways to improve
intent detection accuracy:
• Log the phrases that the customer enters but that the bot can’t identify. We can review these “missing phrase” logs to understand
what the customer is asking and add utterances to the bot that improve accuracy.
• If the customer tries several different phrases, we can propose speaking with an agent, and set the next dialog to “Transfer to Agent”.
However, we want to use advanced logic so that transfers occur only after there are multiple attempts.
2. Build an invocable Apex method to log any utterances that confuse us.
public with sharing class CookbookBot_LogUtterance {
public class LogInput{
@InvocableVariable(required=false)
public String sCurrentUtterance;
@InvocableVariable(required=true)
public String sLiveAgentTranscriptId;
}
@InvocableMethod(label='Log Utterance')
public static void logUtterance(List<LogInput> inputParameters)
{
String sCurrentUtterance = inputParameters[0].sCurrentUtterance;
String sLiveAgentTranscriptId = inputParameters[0].sLiveAgentTranscriptId;
132
Einstein Bots Developer Cookbook Handle Intent Detection Failures
logRecord.Live_Chat_Transcript__c = sLiveAgentTranscriptId;
This code takes input parameters—the system variables we pass from the “Confused” dialog—and saves them into a new
Utterance_Log__c record. With the Live_Chat_Transcript__c field, we can associate the utterance with the chat
transcript.
3. Build an invocable Apex class and method to handle the transfer required logic.
This method looks at how many logs we have in the same chat session, and decides whether the bot suggests a transfer. The code
uses two rules to determine whether we should redirect to an agent.
a. There are more than five intent detection failures in the entire session.
b. The last two failed attempts happened within twenty seconds.
The output parameters include a boolean value for when a transfer is recommended, and a text variable for the transfer message.
public with sharing class CookbookBot_HandleIntentDetectFailure {
133
Einstein Bots Developer Cookbook Handle Intent Detection Failures
WHERE Live_Chat_Transcript__c =
:sLiveChatTranscriptId
ORDER BY CreatedDate Desc];
{
// Then suggest a transfer...
outputParameter.bTransferRequired = true;
outputParameter.sTransferMessage =
'I\'m having troubles understanding what you need. Let me find a
specialist.';
}
}
}
outputParameters.add(outputParameter);
return outputParameters;
}
}
Important: As mentioned in Set Up Your First Einstein Bot, you need to give the bot permission to access these Apex classes.
From Setup, use the Quick Find box to find Permission Sets. Select the sfdc.chatbot.service.permset permission set. From
the permission set options, select Apex Class Access. Now you can edit the access settings so that your new class is accessible
to the bot. Always make sure that the bot has permission to access objects and classes as required.
Here are the steps for this dialog.
a. Keep the original message, such as Sorry, I didn’t understand that.
134
Einstein Bots Developer Cookbook Handle Intent Detection Failures
We use a built-in system variable called Last Customer Input, which passes in what the customer last typed. We also
use the context variable Routable Id to pass in the Live Chat Transcript ID. To review the list of context variables,
see the Context Variable Table on page 12 from Greet the Customer with Embedded Service Chat.
c. After logging the utterance, run our Handle Intent Detection Failure Apex method.
Again, we pass in Last Customer Input and Routable Id. As for the outputs, we store these values in Transfer
Required and Transfer Message. We’re using the same variables as in the Get Context Info from the Web recipe so
that we can leverage the transfer utility dialog that we already created.
d. After recording the output from the previous Apex method, create a rule to check the Transfer_Required variable. If
true, redirect to the “Transfer Required” dialog.
135
Einstein Bots Developer Cookbook Handle Intent Detection Failures
e. If the Transfer_Required variable is false, respond with a generic message, such as Can you try again?
5. Test!
OK, let’s see what the user experience looks like.
136
Einstein Bots Developer Cookbook Mobile App Bot Recipes
You can also inspect the Utterance_Log records to see what you captured from the failures.
137
Einstein Bots Developer Cookbook Get Config Info Before Building a Mobile App
Be sure not to include the protocol or the path. For instance, if your API Endpoint is:
https://d.gla5.gus.salesforce.com/chat/rest/
138
Einstein Bots Developer Cookbook Get Config Info Before Building a Mobile App
Be sure not to use the org ID value (which is also in this deployment code) for the deployment ID.
139
Einstein Bots Developer Cookbook Get Config Info Before Building a Mobile App
For instance, if your chat button code contains the following information:
<a id="liveagent_button_online_575C00000004h3m"
href="javascript://Chat"
style="display: none;"
onclick="liveagent.startChat('575C00000004h3m')">
<!-- Online Chat Content -->
</a>
<div id="liveagent_button_offline_575C00000004h3m"
style="display: none;">
<!-- Offline Chat Content -->
</div>
<script type="text/javascript">
if (!window._laq) { window._laq = []; }
window._laq.push(function() { liveagent.showWhenOnline('575C00000004h3m',
document.getElementById('liveagent_button_online_575C00000004h3m'));
liveagent.showWhenOffline('575C00000004h3m',
document.getElementById('liveagent_button_offline_575C00000004h3m'));
});
</script>
Be sure to omit the liveagent_button_online_ text from the ID when using it in the SDK.
OK. That’s it! You’re ready to build a mobile app. Which platform do you want to work on first?
• Add a Chatbot to Your iOS App
• Add a Chatbot to Your Android App
140
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
Give the app a name and an organization identifier. Specify Swift for the language and if you’re making a simple test app, you can
uncheck the boxes to use core data and to build test code.
141
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
b. From the Embedded Binaries section of your Xcode project settings, add these two framework files.
142
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
c. Because the chat experience with an agent could involve transferring an image, you need to provide descriptions for why the
app might access the device's camera and photo library.
Add string values for "Privacy - Camera Usage Description" and "Privacy - Photo Library Usage Description" in your Info.plist
file. To learn more about these properties, see Cocoa Keys in Apple's reference documentation.
Sample values for these keys:
<key>NSCameraUsageDescription</key>
<string>Used when sending an image to an agent.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Used when sending an image to an agent.</string>
Name the button Chat with an Expert. Align the button so that it shows on the view no matter how the device is oriented.
Once simple way to do this is by centering the button horizontally and vertically.
143
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
We may not have the most beautiful app in the world, but at least we have a working app with a button. If you try to run the app,
you’ll notice that the button doesn’t do anything yet.
This action displays a split screen with the storyboard on the left and the ViewController code on the right. We want to right
click (or “secondary click” in Apple parlance) the button in the storyboard. Then drag from the Touch Up Inside event into our
ViewController class on the right.
144
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
We have a chance to name our new action method. Let’s name it chatButtonTapped.
Great, we have wired up the method to the button. Go back to the standard editor.
Select the ViewController.swift class from the file browser and check out our new method.
145
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
import ServiceChat
At the top of the class, right after the class is defined, let’s add four constant values for our configuration information. If you don’t
have this information, go back to Get Config Info Before Building a Mobile App.
let POD = "YOUR_POD_NAME"
let ORG_ID = "YOUR_ORG_ID"
let DEPLOYMENT_ID = "YOUR_DEPLOYMENT_ID"
let BUTTON_ID = "YOUR_BUTTON_ID"
Below those values, let’s create a variable that we’ll use to specify configuration information.
var chatConfig: SCSChatConfiguration?
Let’s configure our SDK in the viewDidLoad method, which is stubbed out for you. In a more production-ready app, you probably
wouldn’t want to configure the SDK in the view controller (which can be instantiated and destroyed multiple times). Typically, you
only want to configure the SDK one time in the application’s lifecycle, but this will work fine for this example app.
override func viewDidLoad() {
super.viewDidLoad()
Great, we have our app configured. We’re almost ready to test it out.
146
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
The final step is to start a chat session, which we can do from the button handler we created earlier. Let’s call the showChat
method.
@IBAction func chatButtonTapped(_ sender: Any) {
ServiceCloud.shared().chatUI.showChat(with: chatConfig!)
}
Since we’re throwing a lot of new information your way, let’s break down exactly what’s going on:
ServiceCloud
This class is the entry point into the Service SDK.
shared()
This static method gets the singleton instance of the ServiceCloud class.
chatUI
This property gets the SCSChatInterface object, which is the entry point into the chat feature of the Service SDK.
showChat
This method shows the chat UI. This method has a few variants. We’re using the simplest method that only requires a chat
configuration object (SCSChatConfiguration). There is another variant that is used if you want to display a pre-chat
form.
If you’ve followed all these instructions, your ViewController.swift file looks like this:
import UIKit
import ServiceChat
8. Test!
Let’s see what happens when we build and run the app in the simulator.
147
Einstein Bots Developer Cookbook Add a Chatbot to Your iOS App
When the app launches, click the chat button. A thumbnail of the chatbot session appears on the right side of the screen.
When you tap that thumbnail, you can have a complete interaction with your chatbot, including menus and buttons and any other
smarts you’ve added to your bot along the way.
148
Einstein Bots Developer Cookbook Add a Chatbot to Your Android App
We’ve built the simplest possible chat app for iOS. Not a bad start. But there’s a lot we haven’t covered. For example:
Pre-chat Forms
As with the web, you can display a pre-chat form before starting a session.
State Changes and Error Handling
We haven’t discussed how to detect state changes and how to handle error conditions.
Branding and Customization
You can fully brand the look and feel of the chat UI and customize the colors, strings, and fonts.
Roll Your Own UI
You can even build your own UI and simply use the Chat Core API to communicate with the underlying chat functionality.
To get the full story on using this SDK, check out all the chat-related topics in the Service SDK developer guide: Using Chat with the
Service SDK for iOS.
149
Einstein Bots Developer Cookbook Add a Chatbot to Your Android App
1. Before adding a chatbot to our mobile app, we need to grab some configuration information from your org. If you haven’t done so,
follow the steps found in Get Config Info Before Building a Mobile App.
2. Build a basic app.
It’s time to launch Android Studio and create a new project. Give your application a name and then click Next.
For a target device, use Phone and Tablet, and pick a version of Android that is supported in Requirements for the Service SDK for
Android.
Let’s select the Basic Activity so that we already get a button we can use for chat.
150
Einstein Bots Developer Cookbook Add a Chatbot to Your Android App
Use the default values when configuring this activity and then select Finish.
allprojects {
repositories {
google()
jcenter()
maven {
url 'https://s3.amazonaws.com/salesforcesos.com/android/maven/release'
}
}
}
151
Einstein Bots Developer Cookbook Add a Chatbot to Your Android App
So, putting it all together, the entire onCreate method looks like this:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
152
Einstein Bots Developer Cookbook Add a Chatbot to Your Android App
7. Test!
Let’s see what happens when we build and run the app in the emulator.
When the app launches, click the chat button. A thumbnail of the chatbot session appears on the right side of the screen.
153
Einstein Bots Developer Cookbook Troubleshooting Your Bot
When you tap that thumbnail, you can have a complete interaction with your chatbot, including menus and buttons and any other
smarts you’ve added to your bot along the way.
As with the iOS recipe on page 141, we built an basic app here. There are many ways to fine-tune this experience. For example:
Pre-chat Forms
As with the web, you can display a pre-chat form before starting a session.
State Changes and Error Handling
We haven’t discussed how to detect state changes and how to handle error conditions.
Branding and Customization
You can fully brand the look and feel of the chat UI and customize the colors, strings, and fonts.
Roll Your Own UI
You can even build your own UI and simply use the Chat Core API to communicate with the underlying chat functionality.
To get the full story on using this SDK, check out all the chat-related topics in the Service SDK developer guide: Using Chat with the
Service SDK for Android.
154
Einstein Bots Developer Cookbook Troubleshooting Your Bot
Events Log
The first step in debugging a bot is to use the Events Log. You can get to the Events Log by selecting the Performance tab from the
Einstein Bot Builder.
After selecting the Performance tab, select the Events Log subtab.
From the Events Log subtab, you can view a history of all your bot conversations.
155
Einstein Bots Developer Cookbook Troubleshooting Your Bot
If you have too many conversations listed, you can filter the list using the filter button at the top right. The Errors column is useful when
looking for problematic conversations.
When you want to investigate a particular conversation, click the session ID to drill into an event log.
Note: It takes a few minutes after a conversation for the event log to populate with all recent events.
To get details about a specific event, click the disclosure triangle on the right side of a row and select DETAIL.
The detailed information gives you more insight into the event.
156
Einstein Bots Developer Cookbook Troubleshooting Your Bot
In this case, the error was caused because the bot didn’t have permissions to the Apex class it was trying to access. This error can easily
be resolved based on the guidance found in the Call an Apex Action section: From Setup, use the Quick Find box to find Permission
Sets. Select the sfdc.chatbot.service.permset permission set. From the permission set options, select Apex Class Access. Now you
can edit the access settings so that your new class is accessible to the bot. Always make sure that the bot has permission to access objects
and classes as required.
Debug Logs
If you didn’t get any insight from the Events Log, you can also look into the org’s debug log. From Setup, search for Debug Logs. Create
a User Trace Flag and specify Platform Integration as the Trace Entity Type.
157
Einstein Bots Developer Cookbook Troubleshooting Your Bot
You can now inspect logging information from your bots. To learn more about Salesforce debug logs, see Monitor Debug Logs from
Salesforce Help.
158