Teneo Web Chat

Teneo Web Chat is a chat interface that can be embedded in websites. It is built using the Vue.js javascript framework and it is based on Vue Beautiful Chat by Matteo Merola.

Support for various components like buttons, quick replies, images, audio, videos and cards is built-in and additional components can easily be added.

Teneo Web Chat works on common browsers, like Chrome, Edge, Firefox, Internet Explorer 11, Opera and Safari. You can find the source code for this project on Github.

Prerequisites

  • Your bot needs to be published and you need to know the engine URL.
  • When extending the chat widget, a basic understanding of Vue.js is required.

Setup options

Adding the web chat UI to your site

To add the web chat UI to your site, proceed as follows:

Download main.js

Download the file main.js from the latest release of teneo-web-chat on Github and add it to your site.

Update pages

Add the following code before the closing </body> tag to each page where you want the web chat window to appear.

<script type="text/javascript" src="/path/to/webchat/main.js"></script>
<div id="teneo-web-chat"></div>
<script>
  window.onload = function () {
      if (
          window.TeneoWebChat &&
          typeof window.TeneoWebChat.initialize === 'function'
      ) {
          var element = document.getElementById('teneo-web-chat')
          var teneoEngineUrl = 'https://some.teneo/engine-instance/'
          var closeEngineSessionOnExit = 'no'
          var headerTitle = ''
          var headerIconUrl = ''
          var extraEngineInputParams = {}

          window.TeneoWebChat.initialize(
              element,
              headerTitle,
              teneoEngineUrl,
              closeEngineSessionOnExit,
              headerIconUrl,
              extraEngineInputParams
          );
      }
  }
</script>

When adding the script to your site, note the following:

  • Make sure /path/to/webchat/main.js in the first line is replaced with the correct path.
  • The value of the variable 'teneoEngineUrl' should be updated to match the url of your engine.
  • The variable 'closeEngineSessionOnExit' specifies if the Teneo Engine session should be ended when the chat UI is closed. It is advised to keep this value as is, to prevent your bot from losing the conversation history when the user closes the chat UI.
  • The value of 'headerTitle' specifies the title shown in the header of the chat window. If empty, 'Teneo Web Chat' is used.
  • The variable 'headerIconUrl' can be used to specify a custom icon (with a size of 24x24 pixels) shown in the header.
  • The variable 'extraEngineInputParams' can be populated with additional input parameters that need to be included in each Teneo Engine request. Note that both the keys and the values in the map should be strings.

Deploy to Heroku

If you are looking for a quick way to interact with your bot using this web chat UI but you don't have a website to host it yet, you can deploy it to Heroku. Click the button below to create a new Heroku app that hosts the web chat:

Deploy

  1. Give the app a name (lowercase, no spaces)
  2. In the 'Config Vars' section, add the following:
    • TENEO_ENGINE_URL: The engine url.
    • CLOSE_TIE_SESSION_ON_EXIT: Optional. If set to 'yes', the Teneo engine session will be killed when the chat UI is closed.
    • HEADER_TITLE: Optional. Title shown in the header of the chat window.
    • HEADER_ICON_URL: Optional. Can be used to specify a custom icon (with a size of 24x24 pixels) shown in the header.
  3. Click 'Deploy app'.

When Heroku has finished deploying, click 'View app'. You should now be able to use the web chat ui to talk to your bot.

Local development

If you want to run the code locally, proceed as follows:

  1. Clone the project:
    git clone https://github.com/artificialsolutions/teneo-web-chat && cd teneo-web-chat
  2. Install dependencies:
    npm install

    Note: if you're using Windows and get an error "'NODE_ENV' is not recognized as an internal or external command, operable program or batch file.", you may want to install a module called win-node-env and run npm install again.

  3. Create a .env file in the teneo-web-chat folder with the following (replace the dummy url with Teneo Engine url of your bot):
    TENEO_ENGINE_URL=https://some.engine/instance/
    CLOSE_TIE_SESSION_ON_EXIT="no"
    HEADER_TITLE=
    HEADER_ICON_URL=
  4. Start the application:
    npm run start:dev

The page is now available on http://localhost:9000.

Building main.js

If you've made modifications to the code and you want to build the bundle, run:

npm run-script build

This will add a file main.js in the /dist folder of the project. You can use this main.js to add to your site.

Components

Teneo Web Chat offers various components that can be 'attached' to the bot's answer text. This is achieved by adding an output parameter teneowebclient with component specific JSON. For more details on how to populate output parameters, see: Populate output parameters in the 'Build your bot' section.

The following components are supported:

Image

Engine JSON

To add an image, the JSON that should be included in the teneowebclient output parameter looks as follows:

{
    "type": "image",
    "image_url": "https://url.to/an/image.png",
    "alt": "This is an image"
}

Videos

Example of a youtube video in the conversation

Teneo Web Chat supports the following video platforms:

  • YouTube
  • Vimeo
  • Mp4 videos
Engine JSON

In general, the JSON to add a video looks like this:

{
    "type": "[videotype]",
    "video_url": "[url]"
}

The type and URL differ depending on the platform that is used to host the video.

YouTube video

{
    "type": "youtubevideo",
    "video_url": "https://www.youtube.com/embed/123456789"
}

Note that the URL of a YouTube video should start with https://www.youtube.com/embed/.

Vimeo video

{
    "type": "vimeovideo",
    "video_url": "https://player.vimeo.com/video/12345678"
}

Note that the URL of a Vimeo video should start with https://player.vimeo.com/video/.

mp4 video

{
    "type": "filevideo",
    "video_url": "https://url.to/a/video.mp4"
}

Note that the type is filevideo.

Audio

To display an audio player, the JSON that should be included in the teneowebclient output parameter looks as follows:

{
    "type": "audio",
    "audio_url": "https://url.to/audio.mp3"
}

Buttons

Example of buttons in Teneo Web Chat

The title above the buttons is optional. The style attribute in the JSON detemines the colors of the buttons. When clicked, a 'postback' value is sent to engine.

Engine JSON

The JSON that should be included in the teneowebclient output parameter should look as follows:

{
    "type": "buttons",
    "title": "Optional title",
    "button_items": [
        {
            "style": "primary",
            "title": "Primary",
            "postback": "Primary"
        },
        {
            "style": "secondary",
            "title": "Secondary",
            "postback": "Secondary"
        },
        {
            "style": "success",
            "title": "Success",
            "postback": "Success"
        },
        {
            "style": "danger",
            "title": "Danger",
            "postback": "Danger"
        },
        {
            "style": "warning",
            "title": "Warning",
            "postback": "Warning"
        },
        {
            "style": "info",
            "title": "Info",
            "postback": "Info"
        }
    ]
}

If the 'style' of a button is omitted, the primary color is used.

Quick replies

Example of quick replies

Quick replies behave the same as buttons, but are pill-shaped. Quick replies don't have a title. The style attribute in the JSON determines the colors of the quick replies. When clicked, a 'postback' value is sent to engine.

Engine JSON

The JSON that should be included in the teneowebclient output parameter should look as follows:

{
    "type": "quickreply",
    "quick_replies": [
        {
            "style": "primary",
            "title": "Primary",
            "postback": "Primary"
        },
        {
            "style": "secondary",
            "title": "Secondary",
            "postback": "Secondary"
        },
        {
            "style": "success",
            "title": "Success",
            "postback": "Success"
        },
        {
            "style": "danger",
            "title": "Danger",
            "postback": "Danger"
        },
        {
            "style": "warning",
            "title": "Warning",
            "postback": "Warning"
        },
        {
            "style": "info",
            "title": "Info",
            "postback": "Info"
        }
    ]
}

If the 'style' of a quick reply is omitted, the primary color is used.

Clickable list

Clickable list example

The title above the list of clickable items is optional. When clicked, a 'postback' value is sent to engine. Clickable lists don't have a style attribute.

Engine JSON

The JSON that should be included in the teneowebclient output parameter should look as follows:

{
    "type": "clickablelist",
    "title": "Optional title",
    "list_items": [
        {
            "title": "One",
            "postback": "One"
        },
        {
            "title": "Two",
            "postback": "Two"
        },
        {
            "title": "Three",
            "postback": "Three"
        },
        {
            "title": "Four",
            "postback": "Four"
        },
        {
            "title": "Five",
            "postback": "Five"
        },
        {
            "title": "Six",
            "postback": "Six"
        }
    ]
}

Cards

Card

The main elements of a card are an image, title, subtitle and body. All elements are optional, but you should at least include one of them.

Engine JSON

The JSON that should be included in the teneowebclient output parameter looks as follows:

{
    "type": "card",
    "image": {
        "image_url": "https://url.to/an/image.png",
        "alt": "This is an image"
    },
    "title": "This is the title",
    "subtitle": "This is the subtitle",
    "text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt."
}

In addition to the above, cards can contain a section with links, buttons or a clickable list.

Card with links:

Card with links

{
    "type": "card",
    "image": {
        "image_url": "https://url.to/an/image.png",
        "alt": "This is an image"
    },
    "title": "This is the title",
    "subtitle": "This is the subtitle",
    "text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt.",
    "link_items": [
        {
            "title": "Card link",
            "url": "https://url.to/a/page"
        },
        {
            "title": "Another link",
            "url": "https://url.to/another/page"
        }
    ]
}

Card with buttons:

{
    "type": "card",
    "image": {
        "image_url": "https://url.to/an/image.png",
        "alt": "This is an image"
    },
    "title": "This is the title",
    "subtitle": "This is the subtitle",
    "text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt.",
    "button_items": [
        {
            "style": "primary",
            "title": "Primary",
            "postback": "Primary"
        },
        {
            "style": "secondary",
            "title": "Secondary",
            "postback": "Secondary"
        },
        {
            "style": "success",
            "title": "Success",
            "postback": "Success"
        }
    ]
}

Card with a clickable list

Card with a clickable list

{
    "type": "card",
    "image": {
        "image_url": "https://url.to/an/image.png",
        "alt": "This is an image"
    },
    "title": "This is the title",
    "subtitle": "This is the subtitle",
    "text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt.",
    "list_items": [
        {
            "title": "One",
            "postback": "One"
        },
        {
            "title": "Two",
            "postback": "Two"
        },
        {
            "title": "Three",
            "postback": "Three"
        }
    ]
}

Combo message

You can combine multiple components in a single bot response by using a 'combo' message.

Combo message showing a card, a text message and buttons

The following components can be included in a combo message:

  • Buttons
  • Cards
  • Clickable lists
  • Images
  • Quick replies
  • Text messages
  • Videos
  • Audio players

You can include as many of these components as you need in the order you like. Obviously one should take into account that the height of the chat window is limited; when too many components are added, some components may scroll out of view.

Engine JSON

The JSON used to create the combo message in the screenshot looks as follows:

{
    "type": "combo",
    "components": [
        {
            "type": "card",
            "image": {
                "image_url": "https://url.to/an/image.png",
                "alt": "This is an image"
            },
            "title": "This is the title",
            "subtitle": "This is the subtitle",
            "text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt."
        },
        {
            "type": "text",
            "text": "This is an additional speech bubble shown below the card."
        },
        {
            "type": "buttons",
            "title": "Are you sure?",
            "button_items": [
                {
                    "style": "danger",
                    "title": "Yes",
                    "postback": "Yes"
                },
                {
                    "style": "success",
                    "title": "No",
                    "postback": "No"
                }
            ]
        }
    ]
}

Splitting answers into 'bubbles'

Sometimes you may wish to provide an answer using multiple text bubbles.

Example of multiple answer text bubbles

This can be achieved by including an output parameter called outputTextSegmentIndexes. This output parameter should contain a list of index pairs, to indicate where the output text can be split into separate bubbles. The value of the outputTextSegmentIndexes should be structured like this (linebreaks are added for readability):

[
    [startIndexOfFirstBubble,endIndexOfFirstBubble],
    [startIndexOfSecondBubble,endIndexOfSecondBubble],
    ...
]

For the screenshot above, the following values were used:

Output Text outputTextSegmentIndexes Bubbles
This should appear in the first bubble. This appears in the middle. And this in the last bubble. [[0, 41], [41, 72], [72, 100]] This should appear in the first bubble.
This appears in the middle.
And this in the last bubble.

Post-processing script

There are different ways to generate the value of outputTextSegmentIndexes. The Groovy script below, is a global post-processing script that looks for two consecutive pipe symbols || in an output text, uses those to generate the value for outputTextSegmentIndexes, removes the pipe symbols from the answer text and adds the outputTextSegmentIndexes output parameter.

def outputTextSegmentIndexes = []
def outputTextSegments = _.getOutputText().split(/\|\|/)
if (outputTextSegments.size() > 1) {
    def startIndex = 0
    def cleanedOutputText = ""

    outputTextSegments.each { textSegment ->
        def endIndex = startIndex + textSegment.size()
        if (textSegment) {
                outputTextSegmentIndexes << [startIndex, endIndex]
        }
        startIndex = endIndex
        cleanedOutputText += textSegment
    }
    _.setOutputText(cleanedOutputText)
}

if (outputTextSegmentIndexes) {
    _.putOutputParameter("outputTextSegmentIndexes", "${outputTextSegmentIndexes}")
}

To use the script, proceed as follows:

  1. Copy the script above.
  2. In Teneo Studio, open the 'SOLUTION' tab in the solution's window (if you're not there already).
  3. Select 'Globals' in the purple bar on the left hand side, and then select 'Scripts'.
  4. Select 'Post-processing' and choose 'Edit'.
  5. Paste the script above.
  6. Click 'Save'.

Once added, whenever you add || to an answer text in Teneo Studio, the script will add the output parameter 'outputTextSegmentIndexes' with the proper index values and Teneo Web Chat will divide the text into multiple bubbles.

Note that this script works for both Teneo Web Chat and Microsoft Bot Framework. If this script was already added to post processing, you don't need to add it again.

Extending

The web chat UI can be extended by adding additional .vue files in the /src/components/messages/ folder. These files should parse the JSON that is included in an output parameter called teneowebclient in the engine response. The .vue files should display the data accordingly.

Let's look at two extensions included in the web chat ui.

Example: Image

As we have seen above, to display an image, the JSON that should be included in the teneowebclient output parameter should look as follows:

{
    "type": "image",
    "image_url": "https://url.to/an/image.png",
    "alt": "This is an image"
}

The type parameter is linked to the .vue file for this extension. Allowed characters for the type name are a-z and - where - cannot be the first character. Based on the type, the Web Chat code will look for a matching Vue component in the /src/components/messages/ folder. The assumed file name is derived by taking the type field, turn it into upper CamelCase and append Message to the resulting string. E.g image becomes ImageMessage and image-list would become ImageListMessage.

Vue file

Because the type is image, the web chat code looks for a file called ImageMessage.vue in the /src/components/messages/ folder and it will execute that file. This is what the ImageMessage.vue file looks like:

<template>
  <div class="image-message">
    <img :src="imageUrl" :alt="altText"/>
  </div>
</template>

<script>
export default {
  name: 'ImageMessage',
  props: {
    message: {
      type: Object,
      required: true,
      validator: (message) => {
        return (
          message &&
          message.type === 'image' &&
          message.data &&
          message.data.image_url
        );
      },
    },
  },
  computed: {
    imageUrl() {
      return this.message.data.image_url;
    },
    altText() {
      return this.message.data.alt;
    },
  },
};
</script>

<style>
.image-message {
  width: 100%;
  margin-right: 40px;
}
.image-message img {
  max-width: 100%;
  max-height: 200px;
}
</style>

As you can see the file contains three sections:

  • template: contains the html used to display the image
  • script: contains the javascript to parse the engine JSON and return the image url and the alt text
  • style: contains the css styles to format and position the image

Example: Quick replies

To display three quick reply buttons (Small, Medium and Large), the JSON that needs to be included in the teneowebclient output parameter should look as follows:

{
    "type": "quickreply",
    "quick_replies": [
        {
            "title": "Small",
            "postback": "small"
        },
        {
            "title": "Medium",
            "postback": "medium"
        },
        {
            "title": "Large",
            "postback": "large"
        }
    ]
}

The title is displayed in the button and the postback value is sent back to engine when the button is clicked.

Vue file

Because the type is quickreply, the web chat code looks for a component defined in a file called QuickreplyMessage.vue in the /src/components/messages/ folder and renders it.

Again, everything needed to handle this type of exension is contained in the single .vue file. It contains a template section to specify the html, a script section to parse the JSON but to also handle what happens when a user clicks one of the buttons. It also contains the styles needed to style the buttons.

The Teneo API is available as this.$teneoApi if you need to send messages back to the bot. Look at the QuickreplyMessage.vue for an example of how to use it.

Creating custom extensions

To create custom extensions, these are the steps to take:

  1. Define the JSON that specifies the message type and any additional data.
  2. Create an example flow in studio that includes the JSON in the output parameter teneowebclient and publish your solution.
  3. Create a .vue file for the message type.
  4. Add the template, scripts and applicable styles to the .vue file.
  5. Test the result by connecting your Web Chat UI to the engine with the example flow.

Engine input parameters

channel

In addition to the input entered by the user, requests to the Teneo Engine also contain an input parameter 'channel' with value 'teneo-webchat'. This allows you to change the behavior of your bot, depending on the channel used. For information on how to retrieve the value of an input parameter in Teneo Studio, see Store input parameters in the 'Build your bot' section.

Extra parameters

An optional map of parameters can be included when Teneo Web Chat is initialized. The keys in this map (and their values) will be included as individual input parameters in all requests to the Teneo Engine.

Cross-Origin Resource Sharing (CORS)

In many cases, the website that is hosting the web chat UI uses a different domain than the domain used by the Teneo Engine. Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.

By default the Teneo Engine includes CORS headers in the responses to browser requests coming from any domain. This means any site can add the web chat ui and interact with a Teneo Engine. If you want to restrict your solution to only include CORS headers for specific domains, you can add a file called tieapi_cors_origins.txt to the Teneo Resource Manager in the views folder. The file should contain the list of allowed origin domains (one domain per line, domains should include port numbers if applicable).

Was this page helpful?