Zammo Bot UI Kit Extension Documentation

Table of content

Abstract

A UI Kit extension allows any website to extend the UI Kit's out-of-the-box capabilities to customize the chatbot experience.

Intro

UI Kit extensions are classes with a designated contract described below.

An admin must add the extension by instantiating and adding it to an array of extensions instances window.ZammoBotUIKit.Extensions.

The array of extensions is available in the windows object at runtime.

Usage

The admin needs to add the script for the extension after the Zammo UI Kit script tag on the HTML page.

<script
  id="ZammoBotUIKitScript"
  src="https://cdn.zammo.ai/zammo-bot-ui-kit/zammo-bot-ui-kit-latest.min.js"
  cssUrl="https://cdn.zammo.ai/zammo-bot-ui-kit/zammo-bot-ui-kit-latest.min.css"
  zammoApiBaseUrl="https://app.zammo.ai"
  webChatId="af666a31-8fce-4da9-9875-153f6941d7b8"
></script>

<script
  type="text/javascript"
  src="https://some-hosting-place-to-update.yourdomain.com/you-zammo-ui-kit-extension.js"
></script>

In the extension script, the admin needs to register an instance of the extension inside the array of extensions. window.ZammoBotUIKit.onDocumentReady is available to use to guarantee all the elements have successfully loaded on the page.

// register extensions
window.ZammoBotUIKit.onDocumentReady(function () {
  window.ZammoBotUIKit.Extensions.push(new YourZammoUIKitExtension());
});

If the extension needs dependencies, the admin can either:

  • import them into the HTML
<script
  id="ZammoBotUIKitScript"
  src="https://cdn.zammo.ai/zammo-bot-ui-kit/zammo-bot-ui-kit-latest.min.js"
  cssUrl="https://cdn.zammo.ai/zammo-bot-ui-kit/zammo-bot-ui-kit-latest.min.css"
  charset="UTF-8"
  zammoApiBaseUrl="https://app.zammo.ai"
  webChatId="af666a31-8fce-4da9-9875-153f6941d7b8"
></script>

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- the extension can use window.axios -->

<script
  type="text/javascript"
  src="https://some-hosting-place-to-update.yourdomain.com/you-zammo-ui-kit-extension.js"
></script>
  • use window.ZammoBotUIKit.loadScript(scriptUrl: string, cb: Callback) => void, which is a helper method in ZammoBotUiKit that will download the script. Admin can use the call back function to act when the loading is completed. The callback has the following signature (loadedWithRequired: any|null) => void where loadedWithRequired will be set when the website that the page is on uses RequireJS. loadedWithRequired will be the global namespace of the loaded library.
window.ZammoBotUIKit.onDocumentReady(function () {
  window.ZammoBotUIKit.loadScript(
    "https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js",
    function () {
      window.ZammoBotUIKit.Extensions.push(new YourZammoUIKitExtension());
    }
  );
});

API

In all the methods after

  • the parameter the activity is an object of the type bot framework activity (see https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest) for a full description.
  • the parameter the zammoBotUIKitInstance is an instance of the zammoBotUIKitInstance class. The class handles the behavior of the bot.

It will contain the following methods:

  • canHandleInbound(activity: Activity, zammoBotUIKitInstance: ZammoBotUIKitInstance) => boolean: Zammo Bot UI Kit will call this extension's method upon receiving a message from the bot. It will return true if the extension can handle the message. The Zammo Bot UI Kit will call this extension's handleInbound(activity, zammoBotUIKitInstance, logger) method.

  • canHandleOutbound(activity: Activity, zammoBotUIKitInstance: ZammoBotUIKitInstance) => boolean: Zammo Bot UI Kit will call this method when the widget sends a message to the bot. The method should return true if the admin wants to perform post processing actions when the user enters or speak a message. The Zammo Bot UI Kit will call this extension's handleOutbound(activity, zammoBotUIKitInstance, logger) method when canHandleOutbound returns true.

  • handleInbound(activity: Activity, zammoBotUIKitInstance: ZammoBotUIKitInstance, logger: Logger) => void: Zammo Bot UI Kit will call this method if the extension returns true for canHandleInbound. An admin can perform any additional activity processing and use the ZammoBotUiKitInstance to interact with the chat widget (using appendMessage) or the bot (using sendActivity). The extension must act when returning true to canHandleInbound otherwise, the activity will not be processed.

  • handleOutbound(activity: Activity, zammoBotUIKitInstance: ZammoBotUIKitInstance, logger: Logger) => void: Zammo Bot UI Kit will call this method if the extension returns true for canHandleOutbound. An admin can perform any additional activity processing that ZammoBotUiKitInstance will send to the bot. the extension must use sendActivity or appendMessage or any other capabilities (such as calling the proactive URL) to keep the conversation moving.

  • canHandleHook(hookName: string) => boolean: Zammo Bot UI Kit will call this method when emitting events to allow an extension to gain additional control on the bot execution flow. extension can return true if they would like to perform an acction when the event occurs.

  • handleHook(hookName: string, zammoBotUIKitInstance: ZammoBotUIKitInstance, data: object) => void: Zammo Bot UI Kit will call this method when emitting events to allow an extension to perform any chosen action. This method runs synchronously. The third parameter is the data sent by the hook which is contextual. Each hook defines the data that it passes.

  • shouldContinueAfterHandlingHook(hookName: string) => boolean: Zammo Bot UI Kit will call this method when emitting events to let the extension decides if the processing should continue. This method is used to enable chaining of extension or to let the Zammo default processing happen. By default, this method returns false, meaning the default processing will stop after executing this method.

Hook

The Zammo UI Kit widget emits events when performing some operations.

The exhaustive list of events is as follows:

  • START_OPENING_CHATBOT: the widget emits this event when the user clicks on the chat icon. When it's the first time the user clicks on the icon, after the event, the widget will initiate the connection with the bot.
  • END_OPENING_CHATBOT: the widget emits this event after completing the initialization of the connection with the bot when the user clicks on the chat icon. If the user has already clicked on the icon before, START_OPENING_CHATBOT and END_OPENING_CHATBOT are happening one after the other.
  • START_CLOSING_CHATBOT: the widget emits this event when the user clicks on the close icon.
  • END_CLOSING_CHATBOT: the widget emits this event after the chatbot has finished closing.
  • START_PROCESSING_CHATBOT_ACTIVITY: the widget emits this event when the bot starts processing an activity (a message sent or received). This hook will replace handleInbound which was preventing the processing from continuing. It will allow more focused extension that can handle a single task. This hook will pass the activity as a data.
  • END_PROCESSING_CHATBOT_ACTIVITY: the widget emits this event after the chatbot ends the processing of an activity. This hook will pass the activity as a data.

Note: You can use these values as plain strings, but you can also retrieve them from window.ZammoBotUIKit.ChatWidgetHooks.

Sample extension

Extension using a proactive URL and sending the user agent back to the bot

The extension below intercepts a custom activity to get the user browser and returns it to the proactive URL for processing.

/**
 * This custom Zammo extension captures a from the bot for the location and
 */
var ZammoUIKitGetBrowserAgentExtension = function () {
  this.canHandleInbound = function (activity, zammoBotUIKitInstance) {
    return activity.type === "get-browser-agent";
  };

  this.handleInbound = function (activity, zammoBotUIKitInstance, logger) {
    console.log("handleInbound", "activity", activity); // for debugging purposes

    var activityInfo = JSON.parse(activity.text); // in the bot, we have built an object with the shape { "proactiveUrl": "https://bot.zammo.ai/conversation/12345/proactive?verificationToken="abc" }

    var proactiveUrl = activityInfo.proactiveUrl;

    var userBrowserUserAgent = navigator.userAgent;

    axios.post(proactiveUrl, { userAgent: userBrowserUserAgent }).then(() => {
      console.log(
        "handleInbound",
        "data succesfuly sent to the bot proactive URL"
      ); // for debugging purposes
    });
  };

  this.canHandleOutbound = function (activity, zammoBotUIKitInstance, logger) {
    return false;
  };
};

window.ZammoBotUIKit.onDocumentReady(function () {
  window.ZammoBotUIKit.loadScript(
    "https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js",
    function () {
      window.ZammoBotUIKit.Extensions.push(
        new ZammoUIKitGetBrowserAgentExtension()
      );
    }
  );
});

Some highlights:

  • This sample extension doesn't have any impact on the UI. The processing and the action will not be visible to the user.
  • Vanilla Javascript is used in this example but depending on the targeted browser support using Framework or more recent ECMAScript versions is compatible.

Extension logging the time in the console when the user opens the chatbot

<script>
  if (!window.ZammoBotUIKit) {
    console.error(
      "zammo-log",
      "extension does not have access to Zammo Bot UI kit namespace.",
      "it is sometimes due to an invalid script inclusion, verify that the script tags have been included."
    );
  } else {
    // mini extension that will:
    // - log the time after the user opens the chatbot
    window.ZammoBotUIKit.onDocumentReady(function () {
      var LogTimeInConsoleAfterUserOpensChatExtension = function () {
        var extension = this;

        extension.canHandleInbound = function (activity, zammoBotUIInstance) {
          return false;
        };

        extension.canHandleOutbound = function (activity, zammoBotUIInstance) {
          return false;
        };

        extension.handleOutbound = function (
          activity,
          zammoBotUIInstance,
          logger
        ) {};

        extension.handleInbound = async function (
          activity,
          zammoBotUIInstance,
          logger
        ) {};

        extension.canHandleHook = function (
          hookName,
          zammoBotUIInstance,
          logger
        ) {
          return (
            hookName ===
            window.ZammoBotUIKit.ChatWidgetHooks.START_OPENING_CHATBOT
          );
        };

        extension.handleHook = function (hookName, zammoBotUIInstance, logger) {
          console.log(new Date());
        };

        return extension;
      };

      window.ZammoBotUIKit.onDocumentReady(function () {
        window.ZammoBotUIKit.Extensions.push(
          new LogTimeInConsoleAfterUserOpensChatExtension()
        );
      });
    });
  }
</script>