Zendesk: Handover Webchat Conversations to Agent Workspace

zendesk-chat-handover-agent-workspace-webchat-header.png

Modified from https://web-assets.zendesk.com/images/p-self-guided-tour/intro.png 

When it comes to Zendesk handover scenarios in Cognigy.AI, one has two different options. On the one hand, the Sunshine Conversations Endpoint could be used. On the other hand, the entire handover and live chat conversation can be handled through the Cognigy Webchat. This tutorial explains how to add the Zendesk Agent Workspace as a live chat tool to a Cognigy.AI conversation -- using the Webchat.


Table of Contents

  1. Overview
  2. Technical Components
  3. Download the Zendesk Web SDK
  4. Trigger the Handover event
  5. How to embed the required Webchat
    1. Forward user messages to Zendesk Agent Workspace
    2. Display Zendesk Agent messages in the Webchat
    3. Try to start the live chat session
    4. Notify Cognigy.AI about the available live agent
    5. Listen to agent messages and display them inside of the Webchat window
      1. If a new agent joined the chat session
      2. If the agent left or ended the chat session
  6. The final source code

Overview

Before implementing everything in Cognigy.AI and an example Webchat, the architecture of this integration needs to be explained. Please have a look at the figure below:

zendeskAgentWorkspaceWebchatHandoverArchitecture__1_.png

Generally speaking, the Cognigy.AI Virtual Agent is handling the entire conversation between the user and itself through the Webchat Endpoint. As soon as this user wants to talk with a human agent, the handover process will be executed. This means, that the Flow sends a so-called DATA_ONLY message to the Webchat in order to inform the client-side about the requested handover. Last but not least, the whole live chat conversation is controlled and established through the Cognigy Webchat.

Technical Components

The reason for this client-side implementation is the Zendesk Chat Web SDK which provides multiple, easy-to-use functions for the expected behavior. However,  in order to use the Cognigy Webchat as a logical live chat handler, the standard Webchat Embedding must be extended to include the Webchat Analytics API. This Application Programming Interface (API) checks all incoming and outgoing messages for specific, pre-configured, data. On the one hand, it forwards messages to the Zendesk Agent Workspace and, on the other hand, it displays the agents' answers in the Webchat window.

Therefore, one needs to use

  1. A Cognigy.AI Flow,
  2. the Cognigy Webchat Endpoint
  3. and the Zendesk Chat Web SDK

for this handover scenario.

Download the Zendesk Web SDK

Before implementing the live chat logic, the Zendesk Web SDK must be added to the directory of the target website:

  1. Navigate to https://api.zopim.com/web-sdk/#downloads and download the latest SDK version
  2. Navigate to your website's root folder and add the web-sdk.js file
  3. Add the following <script> block to the website's index.html file:
<script src="web-sdk.js"></script>

Trigger the Handover event

In order to start the integration from a logical point of view, the Cognigy.AI Flow has to hand over the control to the Webchat (Analytics Service):

  1. As soon as the user wants to talk to an agent, the Webchat needs to be informed and "configured". Therefore, the Zendesk Extension is recommended.
    1. Please follow this article to learn how to install the Zendesk Extension: Zendesk: Maintain Support Tickets and search for Help Center Articles
    2. Afterward, the Start Live Chat Flow Node can be added to the Flow:

      zendesk-chat-start-live-chat-flow-node.PNG

  2. The Start Live Chat Node sends the data information to the Webchat client while the text message will be displayed to the user:
    zendesk-chat-start-live-chat-flow-node-edit-menu.PNG
  3. From now on, the Webchat is ready to handle all upcoming messages.

How to embed the required Webchat

Info

Please read the comments included in the code blocks below for more information. A comment starts with // or <!--

On the Webchat side, the minimal required JavaScript code for embedding the Webchat to a website is the following:

<!-- 1. Load the webchat.js bundle via a script tag -->
<script src="webchat.js"></script>

<!-- Initialize the Webchat towards a Cogngiy Endpoint via initWebchat() -->

<script>
initWebchat("https://endpoint-trial.cognigy.ai/");
</script>

Now, the mentioned Analytics API needs to be added, while it consists of two different parts -- in this case:

  1. Forward user messages to Zendesk Agent Workspace
  2. Display Zendesk Agent messages in the Webchat

Forward user messages to Zendesk Agent Workspace

For this functionality, only the second <script> block of the code above needs to be extended. First, the available webchat object has to be extracted from the initWebchat() callback:

initWebchat("https://endpoint-trial.cognigy.ai/").then(webchat => {

// TODO: Use the Webchat API
}

Then, the Analytics service can be registered in order to process incoming and outgoing chat messages:

initWebchat("https://endpoint-trial.cognigy.ai/").then(webchat => {

// Register the Analyics Service
webchat.registerAnalyticsService(event => {

// Check the event types
if (event.type === "webchat/outgoing-message") { }

if (event.type === "webchat/incoming-message") { }
}
}

Now, all outgoing messages (the user sends a message in the Webchat window) can be processed:

initWebchat("https://endpoint-trial.cognigy.ai/").then(webchat => {

// Register the Analyics Service
webchat.registerAnalyticsService(webchatEvent => {

const { payload, type } = webchatEvent;

// Whether to forward all messages to Zendesk Chat or not
let zendeskChatInitialized = false;
let zendeskEventInitialized = false;

// Check if the current event is a user message
if (type === "webchat/outgoing-message") {

// Every event consists of the message text and data stored in the payload object
const { text } = payload;

// Check if all Webchat user messages should be forwarded to Zendesk Chat
if (zendeskChatInitialized) {

// Check if the current event contains a text message
if (text) {

// Use the SDK to send a chat message to the Zendesk agent
// including the user's text
zChat.sendChatMsg(text);
}
}
}
}
}

If the current event, e.g. a user message, contains a text, this text will be forwarded to the Zendesk Agent Workspace.

Important

All upcoming text messages will be forwarded to Zendesk directly and not processed by Cognigy.AI anymore. This client-side "Is Handover" state is controlled by the boolean variable called zendeskChatInitialized that is used in the code above as well.

Display Zendesk Agent messages in the Webchat

Instead of processing all outgoing user messages, all incoming events need to be checked -- in order to display agent messages. However, the first step is to start the live chat session while the previously sent DATA_ONLY message must be extracted for further use:

initWebchat("https://endpoint-trial.cognigy.ai/").then(webchat => {

// Register the Analyics Service
webchat.registerAnalyticsService(event => {

// Check all "bot" messages that are incoming from Cognigy.AI
if (type === "webchat/incoming-message") {

// Extract the text and data again from the payload object
const { payload } = event;
const { text, data } = payload;

// In this case, the DATA_ONLY message needs to be extracted from the data object as well
const { handover, transcript, account_key, visitor } = data;
}
}
}

The following code block is separated into two main parts again:

  1. Try to start the live chat session
  2. Listen to agent messages and display them inside of the Webchat window

Try to start the live chat session

initWebchat("https://endpoint-trial.cognigy.ai/").then(webchat => {

// Register the Analyics Service
webchat.registerAnalyticsService(event => {

// Check all "bot" messages that are incoming from Cognigy.AI if (
type === "webchat/incoming-message") {
const { data } = payload;
  const { handover, transcript, account_key, visitor } = data;

  if (handover && account_key) {
  if (!zendeskChatInitialized) {

// Only initialize zChat once
if (zChat.getConnectionStatus() !== "connected") {
  // Initialize the Zendesk Chat
    // Source: https://api.zopim.com/web-sdk/#introduction
      zChat.init({
      account_key,
        suppress_console_error: false,
      });
}

      // Set Visitor information of current Cognigy Webchat user
      const { display_name, email, phone } = visitor;
      zChat.setVisitorInfo({
      display_name,
        email,
        phone
      });

// Configure that all upcoming user messages will be forwarded to Zendesk and not Cognigy.AI
      zendeskChatInitialized = true;
    }

    // Check Live Agent Availability
    // 'online', 'offline', 'away'
    const status = zChat.getAccountStatus();
    if (["offline", "away"].includes(status)) {
    webchat.sendMessage("", {
      type: `agent.${status}`
      });
    } else {

    if (transcript && zendeskChatInitialized) {
    // Send the Transcript of the previous bot conversation to the Zendesk agent
      zChat.sendChatMsg(transcript);
    }

// Only start one listening thread for one conversation
if (!zendeskEventInitialized) {
    zChat.on("chat", (zendeskChatEvent) => {
      if (zendeskChatEvent.type === "chat.msg" && zendeskChatEvent.type !== "typing") {
      webchat.store.dispatch({
        type: "ADD_MESSAGE",
          message: {
          source: "agent",
            text: zendeskChatEvent.msg,
          },
        });

// Send the chat.memberleave event to Cognigy.AI and end the Zendesk Chat
} else if (zendeskChatEvent.type === "chat.memberleave" && zendeskChatInitialized) {
zendeskChatInitialized = false;
// Send event to Cognigy.AI
webchat.sendMessage("", zendeskChatEvent);
// End the Zendesk Chat
zChat.endChat();

// Send Zendesk event to Cognigy.AI Flow
      } else if (zendeskChatEvent.nick?.includes("agent") && zendeskChatEvent.type !== "typing") {
      webchat.sendMessage("", zendeskChatEvent);
      }
    });
}
}
});
});

As soon as the Webchat received a message from Cognigy.AI, it checks if it contains the required data information:

  1. Whether to handover
    1. "handover":  true
  2. The display name for the current user in the live chat session
    1. "display_name": "Laura Wilson"
  3. The transcript of the virtual agent conversation
    1. "transcript": "..."
  4. The Zendesk account key for authentication
    1. "account_key": "..."

Therefore, the logic can check as well if the user wants to hand over the conversation and, afterward, try to establish the connection by looking for available agents. If there is no live agent available at the moment, the Cognigy.AI Flow will be informed in order to pass over the control to the virtual agent again.

Notify Cognigy.AI about the available live agent

Without thinking about upcoming code in the next section, one missing thing can be added already to the, yet empty, else {} code block:

if (transcript && zendeskChatInitialized) {
// Send the Transcript of the previous bot conversation to the Zendesk agent
zChat.sendChatMsg(transcript);
}

It checks if Cognigy.AI sent a transcript of the previous chat conversation between the user and the virtual agent.

Listen to agent messages and display them inside of the Webchat window

The Webchat needs to listen to upcoming Zendesk events. Inside of the else {} block, the following code should be added:

zChat.on("chat", (zendeskChatEvent) => {
if (zendeskChatEvent.type === "chat.msg" && zendeskChatEvent.type !== "typing") {
webchat.store.dispatch({
    type: "ADD_MESSAGE",
     message: {
      source: "agent",
       text: zendeskChatEvent.msg,
     },
   });

// Send Zendesk event to Cognigy.AI Flow
 } else if (zendeskChatEvent.nick?.includes("agent") && zendeskChatEvent.type !== "typing") {
webchat.sendMessage("", zendeskChatEvent);
 }
});

After initializing the Zendesk Chat session, another event listener is started, namely the Zendesk Chat Messages Event Listener. It checks and processes the following three events:

  1. Incoming agent messages
    1. Type: "chat.msg"
  2. If a new agent joined the chat session
    1. Type: "chat.memberjoin"
  3. If the agent left or ended the chat session
    1. Type: "chat.memberleave"
  4. If the agent is away
    1. Type: "agent.away"
  5. If the agent is offline
    1. Type: "agent.offline"

If a new agent joined the chat session

In this case, the "chat.memberjoin" event and the agent's display name are sent in the following format:

{
"type: "chat.memberjoin",
"display_name": "Peter Parker"
}

Inside of Cognigy.AI, one can use CognigyScript in order to extract the name in a Say Node -- for example:

{{input.data.display_name}}

and inside of a Say Node text:

"You are now talking to {{input.data.display_name}}"

which results in

"You are now talking to Peter Parker"

If the agent left or ended the chat session

In the case of leaving or ending the chat, the Webchat sends a "handover is false" message to the Cognigy.AI Flow:

{
"handover": false
}

Inside of Cognigy.AI, one could now use a Lookup Node, for example, and handle this escalation

zendesk-chat-handover-example-flow.PNG

The final source code

initWebchat("https://endpoint-trial.cognigy.ai/").then((webchat) => {

// Whether to forward all messages to Zendesk Chat or not
            let zendeskChatInitialized = false;
            let zendeskEventInitialized = false;

            webchat.registerAnalyticsService((webchatEvent) => {
                const { payload, type } = webchatEvent;
                if (type === "webchat/outgoing-message") {
                    const { text } = payload;
                    // Forward all Webchat user messages to Zendesk Chat
                    if (zendeskChatInitialized) {
                        if (text) {
                            zChat.sendChatMsg(text);
                      }
                  }
                }

                if (type === "webchat/incoming-message") {
                    const { data } = payload;
                    const { handover, transcript, account_key, visitor } = data;

                    if (handover && account_key) {
                        if (!zendeskChatInitialized) {

                            // Only initialize zChat instance one
                          if (zChat.getConnectionStatus() !== "connected") {

                                // Initialize the Zendesk Chat
                                // Source: https://api.zopim.com/web-sdk/#introduction
                                zChat.init({
                                    account_key,
                                    suppress_console_error: false,
                              });
                            }

                            // Set Visitor information of current Cognigy Webchat user
                            const { display_name, email, phone } = visitor;
                            zChat.setVisitorInfo({
                                display_name,
                                email,
                                phone
                            });

                            zendeskChatInitialized = true;
                        }

                        // Check Live Agent Availability
                        // 'online', 'offline', 'away'
                        const status = zChat.getAccountStatus();

                        if (["offline", "away"].includes(status)) {
                            webchat.sendMessage("", {
                                type: `agent.${status}`
                          });
                        } else {

                            if (transcript && zendeskChatInitialized) {
                                // Send the Transcript of the previous bot conversation to the Zendesk agent
                                zChat.sendChatMsg(transcript);
                            }

                            // Only start one listening thread for one conversation
                            if (!zendeskEventInitialized) {

                                // Listener initialized
                                zendeskEventInitialized = true;

                                zChat.on("chat", (zendeskChatEvent) => {
                                    if (zendeskChatEvent.type === "chat.msg" && zendeskChatEvent.type !== "typing") {
                                        webchat.store.dispatch({
                                            type: "ADD_MESSAGE",
                                          message: {
                                                source: "agent",
                                                text: zendeskChatEvent.msg,
                                          },
                                      });
                                    }

                                    else if (zendeskChatEvent.type === "chat.memberleave" && zendeskChatInitialized) {

                                        // Close the current chat session
                                        zendeskChatInitialized = false;

                                        // Send chat.memberleave event to Cognigy.AI
                                        webchat.sendMessage("", zendeskChatEvent);

                                        // End the Zendesk Chat
                                        zChat.endChat();

                                    }

                                    else if (zendeskChatEvent.nick?.includes("agent") && zendeskChatEvent.type !== "typing") {
                                        webchat.sendMessage("", zendeskChatEvent);
                                  }
                              });
                          }
                      }
                  }
              }
          });
        });
 

 

 


Comments

0 comments

Article is closed for comments.

Was this article helpful?
0 out of 0 found this helpful