Messaging for in-app and web

Configure the Salesforce integration for chat interactions.

Salesforce's Messaging for In-App and Web feature allows you to embed chat sessions into your website or application. These interactions and transcripts can be included in the Agent Connect integration, but additional configuration is required.

In order to send the necessary information to Agent Connect, you will need to configure field mappings for messaging sessions in the Agent Connect Lightning Configuration tab using the instructions in this guide.

Request field mapping

The Request Field Mapping tab maps data from Salesforce onto the required attributes for Agent Connect surveys. The fields on this tab will be used to create Request records in Salesforce and populate important parameters in the API requests from Salesforce to Agent Connect.

Within the Request Field Mapping tab, you will need to add a second sub-tab that contains field mappings for Messaging for In-App and Web interactions. Configuring these field mappings is similar to the Case sub-tab, with several differences to note.

image of messaging field mapping

Use the steps below to create and configure field mappings:

  1. In the Request Field Mapping tab, click the + button next to the initial field mapping sub-tab to create a second sub-tab.

  2. In the new sub-tab, select the API key to use for this map.

  3. Set the Requests Auto-triggering switch to "Test" to use your Test API Key if you are not ready to move to production, or switch it to "Production" to use the Production API Key.

  4. Select the object that contains information about Messaging for In-App and Web interactions.

    This will be the "Messaging Session" object most of the time, unless you use a different object to contain interaction details.

  5. Select the relevant fields from the object selected in the previous step to map onto Agent Connect requests.

    All of the necessary items to map are listed on the tab, with some providing additional guidance to help you select the relevant fields. Most of these fields should be present in the object you specified in the previous step, with the exception of the Transcript Text field (see below for details).

    For more information on the fields in this tab, see Field mappings and custom properties.

  6. (Optional) Add any custom properties you would like near the bottom of the tab, and map each custom property to a relevant field in the designated Salesforce object.

Channel (or Case Origin) field

In the Channel (or Case Origin) field, we recommend selecting "Channel Type". This should result in Agent Connect receiving a channel value of embeddedmessaging, but the value can differ in your environment.

image of the channel field

If your Salesforce instance will be sending a new channel type other than email, phone, or chat, share the channel name with the Medallia Support team so they can ensure it is recognized by Agent Connect.

Transcript Text field

The Transcript Text field allows you to specify the location of the chat transcript from a Messaging for In-App and Web interaction.

image of the transcript text field

By default, Salesforce does not store the transcript in the Messaging Session object, so you will need a way to obtain the transcript and map it to a field that can be selected here. This will ensure that Agent Connect can import the transcript for use in QA reviews and coaching.

We have developed an example Apex class and Flow to accomplish this, but your Salesforce administrator may choose to map the transcript in a different way. See the section below to review our example.

Example Apex class and Flow

As mentioned in the previous section, Salesforce does not store the transcript in the Messaging Session object, so you will need to way to obtain the transcript and map it to a field that can be selected in the Transcript Text field in order to use QA features in Agent Connect.

The following example shows how this can be done using an Apex class invoked by a Flow.

Important: The following Flow and Apex class are intended to be examples for demonstration. Your Salesforce administrator may wish to use a different approach to map the transcript to a field in a Salesforce record. What matters is that you have a way to attach the chat transcript to the base object (such as Messaging Session) designated in the Messaging Session field mapping tab, so that it can be sent to Agent Connect.

Example Apex class

The following example Apex class retrieves the chat transcript from a chat session, formats it chronologically, and saves it to the corresponding Messaging Session record in Salesforce.

You can download the script and upload it into Salesforce as a starting point, or copy the code below:

public with sharing class TranscriptGenerator { @InvocableMethod(label='Generate Transcript' description='Generates the chat transcript for the specified MessagingSession ID.') public static void generateChatTranscript(List<FlowInputs> inputs) { String messagingSessionId = inputs[0].messagingSessionId; performCallout(messagingSessionId); } @future(callout=true) public static void performCallout(String messagingSessionId) { List<MessagingSession> messageSessionList = [SELECT Id, Conversation.ConversationIdentifier, Transcript__c FROM MessagingSession WHERE Id = :messagingSessionId]; if(!messageSessionList.isEmpty() && messageSessionList[0].Conversation.ConversationIdentifier != null) { String endpoint = URL.getOrgDomainURL().toExternalForm() + '/services/data/v61.0/connect/conversation/' + messageSessionList[0].Conversation.ConversationIdentifier + '/entries?queryDirection=FromStart&recordLimit=1000'; // Send HTTP request Http h = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint(endpoint); req.setMethod('GET'); req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId()); HttpResponse res = h.send(req); String payload = res.getBody(); System.debug('STATUS CODE : ' + res.getStatusCode()); System.debug('STATUS : ' + res.getStatus()); System.debug('PAYLOAD : ' + payload); if (res.getStatusCode() == 200) { ConversationWrapper conversation = ConversationWrapper.parse(payload); ConversationEntriesCompare convCompare = new ConversationEntriesCompare(); conversation.conversationEntries.sort(convCompare); List<String> formattedConversationEntries = new List<String>(); for(ConversationEntries convEntry : conversation.conversationEntries) { formattedConversationEntries.add( '[' + Datetime.newInstance(convEntry.serverReceivedTimestamp) + '] ' + '[' + convEntry.sender.role + ']\t: ' + convEntry.messageText ); } String formattedConversation = String.join(formattedConversationEntries, '\n'); System.debug('\n' + formattedConversation); // Formatted conversation from formattedConversation can be stored in any field and then mapped in the field mapping. messageSessionList[0].Transcript__c = formattedConversation; update messageSessionList; } } } public class FlowInputs { @InvocableVariable(label='MessagingSession Id' description='Record id of the MessagingSession' required=true) public String messagingSessionId; } // Wrapper classes public class Sender { public String appType; public String role; public String subject; } public class ConversationEntries { public Integer clientDuration; public Long clientTimestamp; public String identifier; public String messageText; public List<String> relatedRecords; public Sender sender; public Long serverReceivedTimestamp; } public class ConversationWrapper { public List<ConversationEntries> conversationEntries; } // Method to deserialize the payload as ConversationWrapper type public static ConversationWrapper parse(String json) { return (ConversationWrapper) System.JSON.deserialize(json, ConversationWrapper.class); } // Comparator class to sort the ConversationEntries public class ConversationEntriesCompare implements Comparator<ConversationEntries> { // Sort the ConversationEntries based on serverReceivedTimestamp public Integer compare(ConversationEntries e1, ConversationEntries e2) { Integer result; if(e1?.serverReceivedTimestamp == null && e2?.serverReceivedTimestamp == null) { result = 0; } else if(e1?.serverReceivedTimestamp == null) { result = -1; } else if(e2?.serverReceivedTimestamp == null) { result = 1; } else if (e1.serverReceivedTimestamp < e2.serverReceivedTimestamp) { result = -1; } else if (e1.serverReceivedTimestamp > e2.serverReceivedTimestamp) { result = 1; } else { result = 0; } return result; } } }

Example Flow

The Flow that invokes the Apex class should be triggered when a Messaging Session has been marked "ended". The example Flow can be built via the steps below:

  1. On the Flows page, click New.

  2. When the Flow Builder loads, click Start From Scratch.

  3. Select "Record-Triggered Flow", then click Create.

  4. Configure the Flow as detailed below:

    Start block

    The Start block will determine when this Flow will be triggered.

    example start block
    • Object — Select "Messaging Session" or the base object you specified in the field mapping.

    • Trigger the Flow When — Select "A record is updated".

    • Condition Requirements — Select "All Conditions are Met (AND)".

    • Conditions — Configure the conditions that will trigger this Flow. Your conditions and use case may vary based on your strategy, but in our example, we set one condition:

      • Status = Ended

      With this condition, the Flow will run any time a messaging session is updated to an "ended" status. This means that after an interaction has ended, the Apex class script will be executed.

    • When to Run... — Select the second option, "Only when a record is updated to meet..."

    • Optimize the Flow for — Select "Actions and Related Records".

    Create Records block

    The next block will create a Request record containing information about the request sent from Salesforce to Agent Connect.

    example create records block
    • Label — Enter a descriptive name for this block.

    • API Name — This field will be automatically populated based on the Label.

    • How to set record field values — Select "Manually".

    • Object — Select "Agent Connect Request"

    • Set Field Values — Assign the following field values:

      • Field Mapping to be Used — Enter the name of the Request Field Mapping to be used (our example uses "Mapping2")

      • Originating Record Id — Triggering Messaging Session > Messaging Session ID

      • Processing Status — Not Processed

      • Request Type — Initial Feedback

    • Check for Matching Records — Leave this disabled.

    Apex Action block

    The final block will invoke the Apex class created earlier. When adding the block, select the name of the Apex class, such as "Generate Transcript" in our example.

    image of the generate transcript block
    • Label — Enter a descriptive name for this block.

    • API Name — This field will be automatically populated based on the Label.

    • Set Input Values for the Selected Action — Triggering Messaging Session > Messaging Session ID

  5. Save the Flow when finished.

When you are finished with the steps in this guide, return to the main Salesforce integration guide to continue configuring the integration.