Skip to main contentWatson Assistant web chat

Creating a custom response

Learn how to use user-defined templates to render your own custom response types in your web chat.

Overview

With web chat, you can render your own dynamic content directly within the chat widget. This capability makes it easy to create experiences for complex data input or display of information, while still taking advantage of all of the benefits of web chat.

See it in action

Add an instance of web chat configured to behave like this tutorial to this page.

Instructions

This tutorial uses an example dialog skill that responds with a user_defined response type. (The user_defined response type is an upcoming feature of dialog skills, which we will simulate by using the pre:receive event to manipulate the responses sent from your assistant. For more information about web chat events, see Events.)

Before you can use web chat to interact with this skill, you must create an assistant that uses it:

  1. Download and save the user-defined-response-types.json file below.
  2. In the Watson Assistant UI, create a new skill by importing the user-defined-response-types.json file.
  3. Add the new skill to an assistant.
  4. Create a new web chat integration for the assistant. Make note of the HTML code snippet that is provided when you create the web chat.

For more information about creating assistants and skills, see the Watson Assistant documentation.

Also download the dialog skill below; it will return the right response type to render.

Downloadable Files

user-defined-response-types.json

A dialog skill configured to send responses to display an element that displays a random background color.

Adding basic embed code

Now embed the web chat code into your website HTML. The embed code should look something like the code snippet below. Remember to change the integrationID and region values to the values you were given when you created your web chat.

Basic Embed Code

<!doctype html>
<html>
<body>
<script>
  window.watsonAssistantChatOptions = {
    // A UUID like '1d7e34d5-3952-4b86-90eb-7c7232b9b540' included in the embed code provided in Watson Assistant.
    integrationID: 'YOUR_INTEGRATION_ID',
    // Your assistants region e.g. 'us-south', 'us-east', 'jp-tok' 'au-syd', 'eu-gb', 'eu-de', etc.
    region: 'YOUR_REGION',
    // The callback function that is called after the widget instance has been created.
    onLoad: function(instance) {
      instance.render();
    }
  };
  setTimeout(function(){const t=document.createElement('script');t.src='https://web-chat.global.assistant.watson.appdomain.cloud/loadWatsonAssistantChat.js';document.head.appendChild(t);});
</script>
</body>
</html>

Simulating the user_defined response type

Watson Assistant does not currently support the user_defined response type. To simulate this behavior, we will add data to the output.user_defined object available in the current version of the API, and then use the pre:receive event to manipulate the content processed by web chat so that it conforms to the planned user_defined response type.

Converting a response to the user_defined response type

<!doctype html>
<html lang="en">
<body>
<script>
  /**
   * IMPORTANT: The TEMPORARY_convertToUserDefinedResponse function is a temporary workaround until
   * user_defined is a supported response type in Watson Assistant.
   *
   * If "output.user_defined.template_name" has a value, we convert the response to follow the
   * planned "user_defined" response type. We will replace the "text" response type with
   * "replace with user_defined" as its value.
   *
   * @param event The event passed from Watson Assistant
   * @param event.type The type of event, in this case "pre:receive".
   * @param event.data.message The original message.
   */
  function TEMPORARY_convertToUserDefinedResponse(event) {
    if (event.data.output.user_defined && event.data.output.user_defined.template_name) {
  
      // Map over all items in the output array.
      event.data.output.generic = event.data.output.generic.map(function(item) {
  
        // If we find one that matches our convention to transform to user_defined response type, make the transformation.
        if (item.response_type === 'text' && item.text === 'replace with user_defined') {
          item.response_type = 'user_defined';
          item.user_defined = event.data.output.user_defined;
          delete item.text;
        }
  
        /* 
          * When we are done, the user_defined output should be in the shape below.
          * {
          *   "output": {
          *     "generic": [
          *       {
          *         "response_type": "user_defined",
          *         // You can add whatever custom variables you like inside the user_defined object.
          *         "user_defined": {
          *           // By convention, include the name of the template you want to display.
          *           "template_name": "foo"
          *         }
          *       }
          *     ]
          *   }
          * }
          */
  
        return item;
      });
    }
  }

  window.watsonAssistantChatOptions = {
    integrationID: "YOUR_INTEGRATION_ID",
    region: "YOUR_REGION",
    serviceInstanceID: "YOUR_SERVICE_INSTANCE_ID",

    onLoad: function(instance) {
      // Temporary: Subscribe to the "pre:receive" event to convert to the user_defined response type.
      instance.on({ type: 'pre:receive', handler: TEMPORARY_convertToUserDefinedResponse });
    
      instance.render();
    }
  };

  setTimeout(function(){const t=document.createElement('script');t.src='https://web-chat.global.assistant.watson.appdomain.cloud/loadWatsonAssistantChat.js';document.head.appendChild(t);});
</script>
</body>
</html>

Handling the customResponse event

When web chat receives a response with a user_defined response type, it fires a customResponse event. The event passes an object that includes the original message and the element to which the custom view should be rendered.

In this section, we will add the external files that render the user_defined response type, as well as the handler for the customResponse event.

Handling the customResponse event

<!doctype html>
<html lang="en">
<body>
<script>
  function handleColorBoxTemplate(event) {
    // Defined in next section
  }

  function TEMPORARY_convertToUserDefinedResponse(event) {
    // Defined above.
  }

  /**
   * Watch for the customResponse event and forward incoming data to the correct handler.
   *
   * @param event The event passed from Watson Assistant
   * @param event.type The type of event, in this case "customResponse".
   * @param event.data.message The individual message from output.generic[].
   * @param event.data.element An HTML element that is rendered in web chat for you to manipulate.
   */
  function customResponseHandler(event) {
    const { message } = event.data;
  
    // Add a switch so you can watch for different custom responses.
    // By convention, have a "template_name" property inside your user_defined object.
    switch (message.user_defined.template_name) {
      case 'color_box':
        handleColorBoxTemplate(event);
        break;
      default:
        console.error('Unhandled response type.');
    }
  }

  window.watsonAssistantChatOptions = {
    integrationID: "YOUR_INTEGRATION_ID",
    region: "YOUR_REGION",
    onLoad: function(instance) {
      // Temporary: Subscribe to the "pre:receive" event to convert to the user_defined response_type.
      instance.on({ type: 'pre:receive', handler: TEMPORARY_convertToUserDefinedResponse });
      
      // Watch for the customResponse event to handle the user defined response type.
      instance.on({ type: 'customResponse', handler: customResponseHandler });
    
      instance.render();
    }
  };

  setTimeout(function(){const t=document.createElement('script');t.src='https://web-chat.global.assistant.watson.appdomain.cloud/loadWatsonAssistantChat.js';document.head.appendChild(t);});
</script>
</body>
</html>

Writing your user_defined response handler

The handleColorBoxTemplate() function receives the event for a customResponse and uses it to render the color box template.


/**
 * Handler for the color box template. Writes a <div> to the element provided by web chat and changes its
 * background color when you push a button.
 *
 * @param event The event passed from Watson Assistant.
 * @param event.type The type of event, in this case "customResponse".
 * @param event.data.message The original message.
 * @param event.data.message.response_type "user_defined"
 * @param event.data.message.user_defined A free object for you to pass whatever you want into.
 * @param event.data.element An HTML element that is rendered in web chat for you to add your content to.
 */
function handleColorBoxTemplate(event) {
  const colorsSubSet = ["AliceBlue","RebeccaPurple","RosyBrown","Sienna"];

  const element = document.createElement('div');
  element.setAttribute('style', 'width:100%; height:100%; background-color: red; padding: 24px; text-align: center;');
  element.innerHTML = '<button>Make random background color!</button>';
  element.querySelector('button').addEventListener('click', function addBackgroundColor(e) {
    element.style.setProperty('background-color', colorsSubSet[Math.floor(Math.random() * colorsSubSet.length)], 'important');
  });

  // Append your element to the provided element.
  event.data.element.appendChild(element);
}

Styling your user_defined response handler

By default, buttons, tables, lists, and text have styling attached to them that matches other web chat content. Web chat also provides some helper classes you can use for other nonstandard content. In this case, we need to wrap our content in a card like the ones that web chat uses for some built-in response types. (For more information about the helper classes, see the documentation.)


/**
 * Handler for the color box template. Writes a <div> to the element provided by web chat, and changes its
 * background color when you push a button.
 *
 * @param event The event passed from Watson Assistant.
 * @param event.type The type of event, in this case "customResponse".
 * @param event.data.message The original message.
 * @param event.data.message.response_type "user_defined"
 * @param event.data.message.user_defined A free object for you to pass whatever you want into.
 * @param event.data.element An HTML element that is rendered in web chat for you to add your content to.
 */
function handleColorBoxTemplate(event) {
  const colorsSubSet = ["AliceBlue","RebeccaPurple","RosyBrown","Sienna"];

  const parent = document.createElement('div');

  // Create a element with the 'ibm-web-chat-card' class we will add our content to.
  // This class makes the element look like one of the cards used in web chat.
  const card = document.createElement('div');
  card.classList.add('ibm-web-chat-card');

  const element = document.createElement('div');
  element.setAttribute('style', 'width:100%; height:100%; background-color: red; padding: 24px; text-align: center;');
  element.innerHTML = '<button>Make random background color!</button>';
  element.querySelector('button').addEventListener('click', function addBackgroundColor(e) {
    element.style.setProperty('background-color', colorsSubSet[Math.floor(Math.random() * colorsSubSet.length)], 'important');
  });

  // Add our color picker inside the card.
  card.innerHTML = '<p style="margin-top:0;"><strong>My Color Changing Card</strong></p>';
  card.appendChild(element);

  parent.appendChild(card);
  event.data.element.appendChild(parent);
}