Pull supplemental data from LivePerson
After receiving and processing a survey for a LivePerson interaction, Medallia Experience Cloud can retrieve supplemental information about the respondent from LivePerson by using OmniExporter as a webhook. OmniExporter is a service that uses HTTP to send and receive data from external systems.
Typically OmniExporter is used to send new or updated survey data to an external system, and then optionally process the response, possibly by updating the same survey record with new data. However, in this configuration OmniExporter is triggered when a new LivePerson survey result is available. It then sends information about the respondent to specific endpoint in LivePerson that treats the data as a request, and it then sends the supplemental information back to Medallia Experience Cloud as part of the response. OmniExporter then updates the survey record with the supplemental data.
To setup the webhook to send data to LivePerson, create an OmniExporter specification in Medallia Experience Cloud setup. You will need
LivePerson account ID
-
LivePerson login OAuth URL and credentials
-
Names of the survey fields to send to LivePerson, and the matching names of the LivePerson fields to receive the data
Trigger
The trigger identifies the condition that causes OmniExporter to make the request. In this case, the trigger happens when there is a new and complete LivePerson survey record.
| Trigger property | Value |
|---|---|
| Trigger by | Field value changes |
| Data object | Survey |
| Trigger an event on record UPDATE | On |
| Triggering fields | e_status |
| Matching condition |
|
Login settings
These setting identify the OmniExporter request to LivePerson by passing the LivePerson account authentication information.
| Login property | Value |
|---|---|
| Login Method | OAuth |
| Login URL Type | Static |
| Login URL |
|
| Login Headers Type | Static |
| Login Headers |
|
HTTP Request Assembly
This is the request that is sent to LivePerson. The URL (endpoint) is specific the company's LivePerson instance and includes the company's account ID, ID of the Lambda function to process the request, and ID of the admin account to run the request. The body of the request contains the the survey responses field values that identify the respondent.
| HTTP Request Assembly property | Value |
|---|---|
| HTTP Method | POST |
| URL Type | Static |
| URL |
|
| Headers Type | Static |
| Headers |
|
| Fields used in the action | e_bp_customer_id_txt |
| Body Type | JavaScript |
| Body | JavaScript code to build a JSON payload to send to LivePerson. |
The JavaScript in the request body needs to return a JSON payload that maps the survey field values to their corresponding LivePerson fields, similar to this:
// Stringify the final json to send it
write(JSON.stringify((function(){
/* Adjust the payload object below to match the structure you need */
// This function return the JSON to send
var generatePayload=function(record){
var payload={
// Conversation ID as already received.
"payload": {
"conversationId":record.e_bp_cc_liveperson_conversation_id_txt
},
// Timestamp just needs to be provided - it doesn't have any purpose.
"timestamp":"1621874976"
};
// Return the payload
return payload;
};
/* Parsing and Helper functions - No need to change */
/* Helper functions */
// Function to return a date in a predefined format
var returnDate=function(myDate){
if(myDate){
return formatDate(myDate, "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
}else{
return null;
}
};
/* Parsing function to construct request */
// Get fields for the record to be sent
var entities=data.changedEntities;
// Set entity for readability
var entity = entities[0];
// Store the payload in a temporary object to screen null values
var tempRecordJson=generatePayload(entity);
// Define and clear out the final json body to be sent
var body={};
// For each "element" in the temporary json...
for(var key in tempRecordJson){
// ... if the "element" is not null then add it to the final json
if(tempRecordJson[key]!==null){body[key]=tempRecordJson[key];}
}
return body;
})()));HTTP Response
After receiving the request, LivePerson returns a JSON payload that contains the supplemental data to include in the Medallia Experience Cloud survey record. OmniExporter uses JavaScript to parse the received JSON object, extract the fields, and map them to corresponding fields in the importer specification that updates the survey record.
| HTTP Response Processing properties | Vale |
|---|---|
| Response Body Processing | JavaScript |
| Result Assembly | JavaScript code to parse the JSON payload received from LivePerson. See below. |
| Auto Importer Spec | CONTACT CENTER: LivePerson Append Data Import |
| Pre-processor Spec | None |
| Content Type | APPLICATION_JSON |
The JSON payload result that maps the LivePerson field values to their corresponding fields in importer specification, similar to this:
/*
Create a JSON object that can be read by the importer to update the existing
survey record.
*/
write(JSON.stringify(function () {
// Helper function to parse and format the chat transcript
var getChatTranscript = function(messagesList) {
// Filter out messages that don't pertain to the actual conversation (i.e. the survey)
messagesList = messagesList.filter(function(message) {
return message.dialogId == conversationId;
});
var outputList = [];
for (i = 0; i < messagesList.length; i++) {
var message = messagesList[i];
var messageSender = message.sentBy.toUpperCase();
messageSender = messageSender == "CONSUMER" ? "CUSTOMER" : "AGENT";
var messageText = message.messageData.msg ? message.messageData.msg.text : null;
if (messageText != null){
messageText = messageText.replace(/\n|\r/g,' ');
outputList.push(messageSender + ": " + messageText);
}
}
return outputList.join('\n');
};
// Convert the request sent into a JavaScript object
var req = {
"data" : data.changedEntities[0] /* Gather the fields from the exported survey record(s) */
};
// Convert the response received into a JavaScript object
var res = {
"status" : JSON.parse(http.getResponseStatusCode()),
"body" : JSON.parse(http.getResponseBodyUtf8())
};
/* In case of SUCCESS */
if( res.status == "200" || res.status == "201" || res.status == "202" || res.status == "204") {
var recordsToProcess = [];
var record = res.body.conversationHistoryRecords[0];
var conversationId = req.data.e_liveperson_conversation_id_txt;
/* Parse function to prevent missing fields from breaking the code. It takes one parameter:
- field : label of the field to parse
*/
record.parse = function(section,field){
if (section == "consumerParticipants") {
return this[section][0][field] ? this[section][0][field] : null;
}
else
return this[section][field] ? this[section][field] : null;
};
var parsedRecord = {
"medalliaId": req.data.a_surveyid,
"consumerId": record.parse("consumerParticipants","participantId"),
"firstName": record.parse("consumerParticipants","firstName"),
"lastName": record.parse("consumerParticipants","lastName"),
"latestAgentNickname": record.parse("info","latestAgentNickname"),
"email": record.parse("info","email"),
"phone": record.parse("info","phone"),
"country": record.parse("info","country"),
"timeZone": record.parse("info","timeZone"),
"brandId": record.parse("info","brandId"),
"conversationId": record.parse("info","conversationId"),
"startTime": record.parse("info","startTime"),
"endTime": record.parse("info","endTime"),
"duration": record.parse("info","duration"),
"closeReason": record.parse("info","closeReason"),
"source": record.parse("info","source"),
"device": record.parse("info","device"),
"latestSkillId": record.parse("info","latestSkillId"),
"latestSkillName": record.parse("info","latestSkillName"),
"latestAgentFullName": record.parse("info","latestAgentFullName"),
"latestAgentId": record.parse("info","latestAgentId"),
"latestAgentLoginName": record.parse("info","latestAgentLoginName"),
"language": record.parse("info","language"),
"agentGroupId": record.parse("info","agentGroupId"),
"agentGroupName": record.parse("info","agentGroupName"),
"chatTranscript": getChatTranscript(record.messageRecords)
};
recordsToProcess.push(parsedRecord);
return recordsToProcess;
/* In case of FAILURE */
}else{
return {
"medalliaId" : req.data.a_surveyid, /* This exporter processes only one record at a time, so just look at first record in the record set */
"success" : "false"
};
}
}()));
