Overview

The 8x8 Embedded Chat API is composed of a set of topics that can be subscribed to or published to a message bus. The tenant can use these topics to send commands to the embedded chat, as well as listen to events triggered by it.

How to access the message bus

In order to communicate with the embedded chat, the tenant must have a reference to the message bus object used to publish messages and subscribe to chat events. This reference can only be accessed inside the onInit callback function, as its first parameter.

The onInit callback function must be defined and assigned to the configuration object present in the embedded chat code snippet. This function (if defined) is automatically called once the chat has been initialized, i.e. ready to publish and subscribe to events in the message bus:

  /**
       * Callback function called after the chat has been initialized.
       *
       * @param bus The message bus used to publish and subscribe to topics
       */
       onInit: function(bus) {
          // Message bus created and ready to be used,
                                window.bus = bus;
                     }            
       };

How to publish to a topic

As soon as the tenant has access to the message bus, they can control some embedded chat behaviors by publishing messages to it. The messages are sent through this bus using the publish method, which requires a topic and an optional data object, passed to subscribers to that same topic.

Example:

  // Publish to other-topic, sending some data
  bus.publish("other-topic", {
      message: "Hello world!"
  });

How to subscribe to a topic

The tenant can also subscribe to topics using the subscribe method in order to listen to messages published by the embedded chat. This method requires a topic to subscribe to and a handler function that will be called when a message is published to the message bus using such topic. The handler function gets passed some data as its first parameter (which can be null if the sender did not publish any data).

Example:

  // Subscribe to some-topic, and log the event data
  var subscription = bus.subscribe("some-topic", function(data) {
      console.log(data);
  });

How to unsubscribe from a topic

The subscribe method also returns a subscription object with a single remove method, which can be used to unsubscribe from that topic.

Example:

  // Unsubscribe from a previously created subscription
  subscription.remove();

Customer Information

Introduction

A tenant may have relevant information about a customer currently using the embedded chat. For example, if a customer is using the embedded chat while viewing a product inside an ecommerce website, the tenant could, in principle, already know the customer name, age and other personal details, as well as which product is being viewed by him.

If the tenant could send this information to the agent, through the embedded chat, the customer would be freed from having to enter this very same information by himself. To solve this problem, the API allows the tenant to set and reset the customer information at any time after the embedded chat has been initialized. The passed data is submitted to the server when the customer is assigned to a queue or sends an offline form, and the tenant can choose to be notified about the customer information submission event.

Usage

The following messages are used to set and reset the customer information:

  • customer:set-infoSets the customer information, passing an object containing the desired properties. These properties are merged to any previously set customer information, overwriting properties with the same name.Example:
      bus.publish("customer:set-info", {
          "First name": "John",
          "Last name":  "Doe",
          "Age":        25,
          "Premium":    true
      });
    
  • customer:reset-infoResets the customer information, erasing any properties previously set.Example:
      bus.publish("customer:reset-info");
    

The embedded chat publishes the following messages related to the customer information:

  • customer:info-sentPublished as soon as the customer information is sent to the server, passing the information just submitted as well as the current chat phase.Example:
      bus.subscribe("customer:info-sent", function(data) {
          // data.info contains the customer information just sent
          // to the server, and data.phase the current chat phase
      });
    

Implementation Example

The following code exemplifies the complete implementation of an onInit callback function body, and the results when the customer information is successfully submitted to the server after being added to a chat queue:

  // Set the customer info
  bus.publish("customer:set-info", {
      "First name": "John",
      "Last name":  "Doe",
      "Age":        25,
      "Premium":    true
  });

  // Remove the customer's first name, keeping all other
  // previously set values
  bus.publish("customer:set-info", {
      "First name": null
  });

  // Listen to the customer info sent event, triggered when
  // the customer info has been sent to the server
  bus.subscribe("customer:info-sent", function(data) {
      console.log(data);
      // -> {
      //      info: {"Last name": "Doe", "Age": 25, "Premium": true}
      //      phase: "chatWindow"
      //    }
  });

Screenshots

The customer information is available in the following locations, depending on how it was submitted:

Figure 1: Customer information in agent transcript

customer-info-case-details

Figure 2: Customer information in case details

customer-info-offline-email

Figure 3: Customer information in offline form email

Important Notes

  • The customer information can be set and/or reset at any time using the message bus and the respective customer:set-info and customer:reset-info topics, but it will only be actually sent to the server when the customer is added to a queue and/or has submitted an offline form.
  • Whenever the customer information is submitted to the server, a message containing the data that was just sent will be immediately published to the message bus using the customer:info-senttopic. The tenant has no control over when the data is submitted to the server.
  • Only primitive data types (strings, numbers and booleans) are allowed as values. Trying to set the customer information with non-primitive data types (e.g. objects, arrays and functions) will result in console warnings, and their values will be discarded.
  • Setting a customer information already previously set will overwrite that information, unless the new value is undefined. If the new value is null, that information will be removed from the customer information and will not be sent to the server from that moment on, unless it is set again with a non-null, defined value.
  • The customer information key:value pair is limited in 100 characters for the key and 500 character for the value. Any key:pair bigger than the specified value will be ignored.

Troubleshooting

  • Make sure that, when trying to remove properties from the customer information without resetting all its properties (i.e. by using the customer:set-info topic), the passed properties have null values (and not undefined), as setting undefined values to properties do not have any effect on the final customer information.
  • If the message Customer info <info> is not of a primitive type and will be discarded is shown in the browser console when trying to set the customer information, it means that the logged property value is of a data type unsupported by the embedded chat. Only primitive data types (strings, numbers and booleans) are currently allowed.
  • If the message Customer info <info> key is too big and will be discarded is shown in the browser console when trying to set the customer information, it means that the key string length is too big. Only strings with length less than 100 characters are allowed.
  • If the message Customer info <info> value is too big and will be discarded is shown in the browser console when trying to set the customer information, it means that the value string length is too big. Only strings with length less than 500 characters are allowed.

Chat Language

Introduction

A tenant may want to set the chat language manually instead of using a question in the Pre-Chat. For example, the tenant may already have this information and don’t want to ask for the customer again.

The API allows the tenant to set the chat language by sending a message through the bus with the language code.

The list of available languages is the following:

  • English: en
  • Russian: ru
  • German: de
  • Japanese: ja
  • Spanish: es
  • French: fr
  • Chinese: zh
  • Portuguese: pt
  • Italian: it
  • Polish: pl

Usage

The following messages is used to set the chat language:

  • chat:set-languageSet the chat languageExample:
      bus.publish("chat:set-language", "pt");
    

Important Notes

  • The chat language can be set on any time before starting a chat (customer enter a queue) and you can change it as many time as you want, only the last value will be considered.
  • Only system messages and the chat transcription will be localized to the configured language.
  • This event should be published in the same bus as when setting the customer information.

Troubleshooting

  • If the message Chat language <language> is not valid and will be discarded is shown in the browser console when trying to set the chat language, it means that the language code is not valid. Only language codes specified in the list of available languages above are valid.

Invitation window trigger

Introduction

A tenant may want to trigger the Invitation window manually instead of waiting for a fixed time. For example, the tenant may have additional information from the customer and may want to trigger the Invitation window after a specific customer action.

The API allows the tenant to configure the page to send a message through the bus indication when to trigger the Invitation window.

Usage

The following messages is used to trigger the Invitation window:

  • chat:trigger-invitationTrigger the Invitation window.Example:
      bus.publish("chat:trigger-invitation");
    

Important Notes

  • When triggering the Invitation, it will only be open if the customer is not in a Pre-chat, Chat window or Offline form. So, it will show the Invitation window if the chat is closed or if it is displaying another Invitation. In this last case, the Invitation will be replaced by the new one.
  • Calling this message will trigger the Invitation window to be displayed only if an Invitation window is available to be displayed in the Chat Script.
  • If you don’t want your Invitation window to be automatically displayed (only by callingchat:trigger-invitation), set all your Invitations nodes in the Chat Script as Invitation to chat pops up after (seconds): Custom.
  • This message must be called in the same bus as the Customer Information.

Troubleshooting

  • Triggering the Invitation window is not a guarantee that a Invitation will be shown. The request will be sent to the server in order to check for an Invitation window in the Chat Script. So, if in that moment there isn’t any Invitation window available, none will be displayed.

Message Manipulation

Introduction

A tenant may want to be notified about the exchanged chat messages, or modify the message contents before they are consumed by the costumer or the agent. For example, the tenant may want to externally log the message contents, or translate them before they are consumed by their recipient.

The API allows the tenant to intercept and manipulate the embedded chat messages, prior to their submission to their counterpart, by enabling a proxy at any time after the embedded chat has been initialized. When the proxy is enabled, the tenant has total control over the messages exchanged between the customer and the agent, which means he can read and modify their contents.

Configuration

The __8x8Chat configuration should be like this:

    <script type="text/javascript">
        var __8x8Chat = {
            // Other chat parameters (uuid, tenant, channel, domain...)
            
            busHandlerURL: "https://path.to/external-bus-handler.js",

            /**
             * Callback function called after the chat has been initialized.
             *
             * @param bus The message bus used to publish and subscribe to topics
             */
            onInit: function(bus) {
              // user info manipulation goes here
            }
        };
    </script>

Notice the busHandlerURL configuration parameter. This should be a path to a script which will be embedded in the chat window to allow message manipulation even when the main window is closed.

Attention: the busHandlerURL parameter MUST be a script running over SSL (HTTPS protocol).

How to access the message bus for Message Manipulation API

The access to the Message Manipulation API is made through another script that will be available to the embedded chat both when running on the same window or in popup. This script CAN be hosted in another domain.

The following code is an example of how the busHandlerURL script should be like:

    // external-bus-handler.js
    (function(root) {
        root.__8x8Chat = {
            onInit: function(bus) {
                // message manipulation goes here
            }
        };
    })(this);

Usage

The following messages are used to enable and disable the chat proxy:

  • chat:enable-proxyEnables the embedded chat message proxy. After publishing this message, the tenant is able to modify new messages sent from the customer to the agent and vice-versa (as long as the waiting timeout is not exceeded; see Important Notes) by using the customer:send-messageand agent:send-message topics, respectively.Example:
      bus.publish("chat:enable-proxy");
    
  • chat:disable-proxyDisables the embedded chat message proxy. After publishing this message, the tenant is unable to modify new messages sent from the customer to the agent and vice-versa, returning the chat to its default behavior. The tenant will still be able to manipulate previously unhandled messages (see Important Notes) and access the newer messages’ contents if subscribed to the customer:message-received and agent:message-received topics.Example:
      bus.publish("chat:disable-proxy");
    

Regardless of the chat proxy status, the tenant can subscribe to the following topics in order to access the contents of messages exchanged between the customer and the agent:

  • customer:message-receivedNotifies the tenant of a message sent by the customer. If the embedded chat message proxy is disabled, the message is immediately sent to the server, and the tenant cannot modify its contents prior to the submission. If the message proxy is enabled, the customer message is locally shown in their chat transcript, but the actual message is not sent to the agent until the tenant publishes the final message (using the customer:send-message topic), or the tenant takes too long to respond and the waiting times out (in which case the original message is sent).Example:
      bus.subscribe("customer:message-received", function(data) {
          // data.message contains the customer message, and data.id
          // the message ID to be sent back when proxying
      });
    
  • agent:message-receivedNotifies the tenant of a message sent by the agent. If the embedded chat message proxy is disabled, the message is immediately added to the customer chat transcript, and the tenant cannot modify its contents prior to the display. If the message proxy is enabled, the agent message is not shown to the customer until the tenant publishes the final message (using theagent:send-message topic), or the tenant takes too long to respond and the waiting times out (in which case the original message is shown).Example:
      bus.subscribe("agent:message-received", function(data) {
          // data.message contains the agent message, and data.id
          // the message ID to be sent back when proxying
      });
    

If the tenant is listening to the chat messages and the chat proxy is enabled, he should publish the new messages’ contents to the following topics:

  • customer:send-messageSends a customer message, overwriting the original message by a new one (which could be the same as the original message). The customer always sees their original message in the chat transcript, even though the message itself might have been modified by the tenant prior to being sent to the agent. The original message ID received in the customer:message-receivedevent must also be passed in to indicate which message it refers to.Example:
      bus.publish("customer:send-message", {
          message: "Hello World",  // The modified customer message
          id: 1                    // The original message ID
      });
    
  • agent:send-messageSends an agent message, overwriting the original message by a new one (which could be the same as the original message). The agent always sees their original message in the chat transcript, even though the message itself might have been modified by the tenant prior to being shown to the customer. The original message ID received in the agent:message-receivedevent must also be passed in to indicate which message it refers to.Example:
      bus.publish("agent:send-message", {
          message: "Hello World",  // The modified agent message
          id: 2                    // The original message ID
      });
    

Implementation Example

The following code exemplifies the complete implementation of an onInit callback function body, appending “(modified)” to every new message:

  // Enable the chat proxy
  bus.publish("chat:enable-proxy");

  // Subscribe to the customer's messages
  bus.subscribe("customer:message-received", function(data) {
      // Modify and publish customer message
      data.message += " (modified)";
      bus.publish("customer:send-message", data);
  });

  // Subscribe to the agent's messages
  bus.subscribe("agent:message-received", function(data) {
      // Modify and publish agent message
      data.message += " (modified)";
      bus.publish("agent:send-message", data);
  });

Screenshots

The manipulated customer and agent messages are shown like the following:

 

msg-manipulation-transcripts

Figure 4: Manipulated messages in chat transcripts

Important Notes

  • The chat proxy only allows the tenant to manipulate messages already sent by the customer or the agent, which means that no new message can be sent unless it refers to a specific proxied message.
  • If the tenant proxies a customer message with more characters than the currently maximum allowed, the message will be shortened and a warning will be shown in the chat transcript, even if the original message did meet the length requirement.
  • If a proxied message is not handled in under 10 seconds by the tenant while the chat proxy is enabled, the original message will be consumed as if the chat proxy was disabled. Any handling of that same message by the tenant will be silently discarded after the timeout has been reached.
  • If the chat proxy is disabled, the tenant still has the opportunity to manipulate any queued message sent while the chat proxy was enabled, unless it has already been previously handled or its timeout has been reached. Disabling the chat proxy merely means that newer messages will not be added to the proxied message queue and, therefore, will not accept changes from the tenant until the chat proxy is enabled again.
  • The embedded chat currently does not guarantee the correct chat transcript message ordering while the chat proxy is enabled, which means the tenant is responsible for publishing back the proxied messages in the same order as they came if message ordering is desired. Also, the ID present in the message data is incremental, which can help the tenant determine what message to return at any given time.
  • The behavior when using invalid or self-signed SSL certificates is undefined and most of the time will not work.

Troubleshooting

  • If the Malformed message data <data> message is logged to the browser console when trying to publish a proxied message, it means that either the message data is not an object, or it does not have the required message and/or id properties.
  • If the Proxied message data <data> from sender <sender> not found message is logged to the browser console when trying to publish a proxied message, it means that the respective message could not be found in the proxied message queue, either because it was never added to such queue, or because its waiting timeout has been reached and the original content has been used.
  • If the busHandlerURL script is not being loaded, verify the validity of the SSL certificate from where it is being hosted. If there is no valid certificate and you are in a test environment, you can add the self-signed certificate (with extension .crt) from the host to the Trusted Root Certification Authorities in the client.

System Message Localization

Introduction

A tenant may want to localize or customize some/all chat system messages. For example, s/he can customize the message that is shown when the chat session is established.

Configuration

The __8x8Chat configuration should be like this:

Note that the configuration is the same as when using the Message Manipulation, so you don’t need to configure it again if you already have an external bus handler script configured. You just need to implement the System Message Localization in the external script.

  <script type="text/javascript">
      var __8x8Chat = {
          // Other chat parameters (uuid, tenant, channel, domain...)
          
          busHandlerURL: "https://path.to/external-bus-handler.js",

          /**
           * Callback function called after the chat has been initialized.
           *
           * @param bus The message bus used to publish and subscribe to topics
           */
          onInit: function(bus) {
            // user info manipulation goes here
          }
      };
  </script>

Notice the busHandlerURL configuration parameter. This should be a path to a script which will be embedded in the chat window to allow message manipulation even when the main window is closed.

Attention: the busHandlerURL parameter MUST be a script running over SSL (HTTPS protocol).

How to access the message bus for System Message Localization API

The access to the System Message Localization API is made through the same script used in the Message Manipulation API that will be available to the embedded chat both when running on the same window or in popup. This script CAN be hosted in another domain.

The following code is an example of how the busHandlerURL script should be like:

  // external-bus-handler.js
  (function(root) {
      root.__8x8Chat = {
          onInit: function(bus) {
              // system message localization goes here
          }
      };
  })(this);

Usage

The following messages are used to set the system messages

  • chat:set-system-messagesSets the system messages, passing an object containing the desired properties. These properties are merged to any previously set system messages, overwriting properties with the same name.Example:
      bus.publish("chat:set-system-messages", {
          // Localized/Customized messages goes here
      });
    

Available system messages that can be customized

  • endChatButton: “End chat”
  • closeChatButton: “Close”
  • errorServerUnavailable: “Server is unavailable. Please, try again later.”
  • chatEstablished: “Your chat session has been established.”
  • chatQueued: “Please stand by. We will be with you shortly.”
  • chatForwarded: “Your chat is being forwarded. Please wait.”
  • chatMsgTooLong: “Your last message was shortened because it exceeded maximum length.”
  • chatDisconnected: “You have been disconnected from your chat session. Please check your network connection and try again.”
  • chatEnded: “You have ended your chat session.”
  • agentTyping: “Agent is typing…”
  • agentDisconnected: “The agent has disconnected from this chat session.”
  • errorInvalidLogin: “We have encountered an error trying to start a new chat. Please try again later.”
  • endChatNotification: “Chat session has been ended.”
  • endChatConfirmation: “Are you sure you want to end this chat session?”
  • chatLogTitle: “Chat Log”
  • chatLogDescription: “Below is a complete log of the chat session.”
  • yesButton: “Yes”
  • noButton: “No”
  • saveButton: “Save”
  • clearButton: “Clear”
  • pullDownInfo: “Swipe to see more options”
  • errorGenericMessage: “Sorry, something went wrong. Please try again later.”
  • errorRequiredMessage: “Please verify the mandatory fields”
  • errorCrmFieldInvalidMessage: “Sorry, we couldn’t find your information using the value you provided.”
  • errorInvalidNumber: “The field is a numeric field.”
  • errorInvalidEmail: “The field only accept the valid e-mail format.”
  • preChatFormData: “Pre-Chat form data”
  • offChatFormData: “Offline form data”
  • skipQueueFormData: “Skip Queue form data”
  • chatTranslationOn: “Automatic chat translation has been turned on.”
  • chatTranslationOff: “Automatic chat translation has been turned off.”
  • chatTranslationServiceError: “Translation service error.”
  • sessionDisconnected: “Your chat session has ended.”

Implementation Example

The following code exemplifies the complete implementation of an onInit callback function body, appending “(modified)” to every system message:

  bus.publish("chat:set-system-messages", {
      endChatButton:               "(modified) End chat",
      closeChatButton:             "(modified) Close",
      errorServerUnavailable:      "(modified) Server is unavailable. Please, try again later.",

      chatEstablished:             "(modified) Your chat session has been established.",
      chatQueued:                  "(modified) Please stand by. We will be with you shortly.",
      chatForwarded:               "(modified) Your chat is being forwarded. Please wait.",
      chatMsgTooLong:              "(modified) Your last message was shortened because it exceeded maximum length.",
      chatDisconnected:            "(modified) You have been disconnected from your chat session. Please check your network connection and try again.",
      chatEnded:                   "(modified) You have ended your chat session.",
      agentTyping:                 "(modified) Agent is typing...",
      agentDisconnected:           "(modified) The agent has disconnected from this chat session.",
      errorInvalidLogin:           "(modified) We have encountered an error trying to start a new chat. Please try again later.",
      endChatNotification:         "(modified) Chat session has been ended.",
      endChatConfirmation:         "(modified) Are you sure you want to end this chat session?",
      chatLogTitle:                "(modified) Chat Log",
      chatLogDescription:          "(modified) Below is a complete log of the chat session.",
      yesButton:                   "(modified) Yes",
      noButton:                    "(modified) No",
      saveButton:                  "(modified) Save",
      clearButton:                 "(modified) Clear",
      pullDownInfo:                "(modified) Swipe to see more options",

      errorGenericMessage:         "(modified) Sorry, something went wrong. Please try again later.",
      errorRequiredMessage:        "(modified) Please verify the mandatory fields",
      errorCrmFieldInvalidMessage: "(modified) Sorry, we couldn't find your information using the value you provided.",
      errorInvalidNumber:          "(modified) The field is a numeric field.",
      errorInvalidEmail:           "(modified) The field only accept the valid e-mail format.",
      preChatFormData:             "(modified) Pre-Chat form data",
      offChatFormData:             "(modified) Offline form data",
      skipQueueFormData:           "(modified) Skip Queue form data"
  });

Important Notes

  • The message localization is only available in the Message Manipulation bus, so this should be configured in the external bus handler script.

Custom Stylesheet

Introduction

A tenant may want to customize embedded chat elements that are currently not available in the Chat Design page. For this reason it is possible to set a custom CSS file to be loaded before the chat is started, letting the tenant change the chat look and feel to a more fitting style.

Configuration

The __8x8Chat configuration should be like this:

  <script type="text/javascript">
      var __8x8Chat = {
          // Other chat parameters (uuid, tenant, channel, domain...)
          
          stylesheetURL: "https://path.to/external-stylesheet.css"
      };
  </script>

Notice the stylesheetURL configuration parameter. This should indicate the path to the CSS file that should be loaded by the chat window to apply the desired custom styles.

custom-stylesheet-example

Click here to open an example style sheet.

You can use this text to help getting started authoring a new chat theme. The results of this stylesheet can be seen above.


{\rtf1\ansi\ansicpg1252\cocoartf1344\cocoasubrtf720
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural

\f0\fs24 \cf0 /*****************************************************************************\
 * General\
 *****************************************************************************/\
body, input[type="text"], textarea, button, select \{\
    font-family: "Segoe UI", "Myriad Pro", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;\
\}\
\
/*****************************************************************************\
 * Container\
 *****************************************************************************/\
.container, .inner-container, button \{\
    border-radius: 0;\
\}\
\
.inner-container \{\
    -ms-filter: "none";\
    background: none;\
    padding: 0;\
\}\
\
/*****************************************************************************\
 * Controls\
 *****************************************************************************/\
.control \{\
    background: none !important;\
    border: 0 !important;\
    line-height: 1.1;\
    text-decoration: none !important;\
    opacity: 0.8 !important;\
\}\
\
.control:hover \{\
    opacity: 1 !important;\
\}\
\
.control.close:before, .control.end:before \{\
    color: #fff;\
    content: "\\00D7";\
\}\
\
/*****************************************************************************\
 * Header\
 *****************************************************************************/\
.header .logo \{\
    display: none !important;\
\}\
\
.header .title \{\
    background: rgba(0, 0, 0, 0.6);\
    font-size: 14px;\
    color: #fff;\
    padding: 5px 8px;\
\}\
\
/*****************************************************************************\
 * Form\
 *****************************************************************************/\
input[type="text"], textarea, .message-history, select \{\
    box-shadow: none;\
\}\
\
button, button:active \{\
    -ms-filter: "none";\
    background-image: none;\
    box-shadow: none;\
\}\
\
/*****************************************************************************\
 * Introduction\
 *****************************************************************************/\
.intro \{\
    padding: 0 20px;\
\}\
\
/*****************************************************************************\
 * Window\
 *****************************************************************************/\
.translation-header \{\
    border-left: 0;\
    border-right: 0;\
\}\
\
/*****************************************************************************\
 * Message\
 *****************************************************************************/\
#message-field \{\
    border: 0 !important;\
\}\
\
.message-history \{\
    border-left: 0;\
    border-right: 0;\
\}\
\
.message-actions \{\
    z-index: 1;\
\}\
\
.message-wrapper \{\
    padding: 15px;\
\}\
\
.message-content \{\
    display: inline-block;\
    width: 100%;\
\}\
\
.chat-outgoing-msg, .chat-incoming-msg \{\
    background: #fafafa;\
    border: 1px solid #ddd;\
    color: #333;\
    position: relative;\
\}\
\
.chat-outgoing-msg:before, .chat-incoming-msg:before,\
.chat-outgoing-msg:after, .chat-incoming-msg:after \{\
    content: "";\
    position:absolute;\
    border-style: solid;\
    display: block;\
    width: 0;\
\}\
\
.chat-outgoing-msg:before, .chat-incoming-msg:before \{\
    top: auto;\
    bottom: 8px;\
    right: -6px;\
    border-width: 6px 0 6px 6px;\
    border-color: transparent #ddd;\
\}\
\
.chat-outgoing-msg:after, .chat-incoming-msg:after \{\
    top: auto;\
    bottom: 10px;\
    right: -4px;\
    border-width: 4px 0 4px 4px;\
    border-color: transparent #fff;\
    clear: both;\
\}\
\
.chat-incoming-msg:before \{\
    top: 8px;\
    bottom: auto;\
    left: -6px;\
    border-width: 6px 6px 6px 0;\
\}\
\
.chat-incoming-msg:after \{\
    top: 10px;\
    bottom: auto;\
    left: -4px;\
    border-width: 4px 4px 4px 0;\
\}\
\
.chat-outgoing-msg \{\
    margin-left: 20%;\
    text-align: left;\
\}\
\
.chat-incoming-msg \{\
    margin-right: 20%;\
\}\
\
.chat-log-msg, .chat-info-msg, .chat-error-msg, .chat-link-msg \{\
    text-align: center;\
\}\
\
/*****************************************************************************\
 * Acknowledge/Close messages\
 *****************************************************************************/\
.acknowledge-text, .confirm-close \{\
    padding: 0;\
\}}

Figure 5: Embedded chat using a custom stylesheet

Attention: the stylesheetURL parameter MUST be a CSS file served over SSL (HTTPS protocol).

Important Notes

  • A functional stylesheet should be written by inspecting the current chat window HTML structure. This can be done using a web inspector, a tool shipped with most web browsers today.
  • As the chat window HTML structure may change between versions, the tenant should test their customizations when upgrading to make sure they are working as expected.