47 Oracle Web

The Digital Assistant Client SDK for Oracle Web provides you with a widget that enables you to run a skill in a web page. Using the SDK, you can customize the look and behavior of this widget.

The SDK connects to the Oracle Chat Server, the intermediary between the Oracle Web channel configured in Oracle Digital Assistant and the client. The chat server then passes messages to the skill for processing and delivers the skill's response to the client.

Note:

The Oracle Web Channel doesn't store messages when the client has disconnected from the server. It only delivers messages to connected clients. The SDK does not support multi-device login; it supports only one client per user.

What Do You Need?

  • An Oracle Web Channel. Creating the channel generates the Channel ID and the Secret Key that you need to initialize the chat app.
  • The URL of the Oracle Chat Server.
  • The Oracle Web SDK (located under Oracle Native Client SDKs for OCI Native Environments) from Oracle Technology Network’s ODA and OMC download page. Download this ZIP and extract it to your local system. This ZIP includes a user guide that describes the SDK's classes and a sample app that demonstrates many of its features.

Configure the Oracle Web Channel

You can configure the channel to connect to the ODA speech, text, or attachment server in two modes: authenticated (to protect access to the channel) or unauthenticated.
  • Authentication is enforced using JSON Web Tokens (JWT). The customer's backend server generates the JWT token, which is then passed to the Oracle Web SDK. This token is used for each request to an ODA speech, text, or attachment server.

    Note:

    To protect access to the channel, the token must always be generated by a remote server. It must never be generated within the client browser.
    When the web app needs to connect to an ODA server, it first requests the token from the backend server and then adds it to the Authorization header. The ODA server validates the token, evaluates the claims, and then either opens the socket or rejects the connection.

    Tip:

    This article steps you through running the SDK with an authenticated channel.
  • Unauthenticated mode – Use the unauthenticated mode when the client can't generate signed JWT tokens, when no authentication mechanism is in place, or when the client widget is already secured and visible to authenticated users.
To configure the Oracle Web channel:
  1. Choose Development, then Channels from the menu.
  2. Choose Users.
  3. Click Add Channel and then Oracle Web as the channel type.
  4. Complete the dialog:
    • Enter the channel name.
    • For authenticated connections:
      • Switch on the Client Authentication Enabled toggle to determine whether the SDK is connecting to a client authentication-enabled channel.
      • The channel will only communicate with the sites from the domains that you add as a comma-separated list. For example, *.corp.example.com, *.hdr.example.com. Entering a single asterisk (*) allows unrestricted access to the channel from any domain. Typically, you'd only enter a single asterisk during development. For production, you would add an allowlist of domains.
      • In the Max. Token Expiration (Minutes) field, set the maximum amount of time for the JWT token.
    • For unauthenticated connections:
      • Switch off Client Authentication Enable toggle.
      • Enter a comma-separated list of domains that can access the channel. If the domains in this allowlist includes asterisks (*.hdr.example.com) or if the allowlist is not completely known, then you might consider an authenticated connection.
    • Set the Session expiration time.
    • Click Create. Oracle Digital Assistant will generate the Channel ID and the Secret Key that you need to initialize the SDK. Keep these close at hand because you'll need them when configuring the HTML page to host the chat widget.
  5. Route the channel to your skill or digital assistant.
  6. Switch Channel Enabled to On.

Tutorial: Secure Your Oracle Web SDK Chat

You can get a hands-on look at securing the Web chat widget through this tutorial: Secure Your Oracle Web SDK Chat.

Install the SDK

  1. In the extracted ZIP file of the downloaded Oracle Web SDK, locate the web-sdk.js file (located in the native-client-sdk-js directory).
  2. Save web-sdk.js (located in the native-client-sdk-js directory of the extracted ZIP) in your project directory. Note the file location, because you'll need it to define the <WebSDK URL> property in the <script> tag's code.
  3. Create a JavaScript file with the following function that initializes the SDK. We call this file settings.js in the sample that ships with the SDK.
    // settings.js
    var chatSettings = {
        URI: '<Server URI>',
        channelId: '<Channel ID>',
        userId: '<User ID>'
    };
    
    function initSDK(name) {
        // If WebSDK is not available, reattempt later
        if (!document || !WebSDK) {
            setTimeout(function() {
                initSDK(name);
            }, 2000);
            return;
        }
    
        // Default name is Bots
        if (!name) {
            name = 'Bots';
        }
    
        setTimeout(function() {
            var Bots = new WebSDK(chatSettings);    // Initiate library with configuration
    
            var isFirstConnection = true;
            Bots.on(WebSDK.EVENT.WIDGET_OPENED, function() {
                if (isFirstConnection) {
                    Bots.connect()                          // Connect to server
                        .then(function() {
                            console.log('Connection Successful');
                        })
                        .catch(function(reason) {
                            console.log('Connection failed');
                            console.log(reason);
                        });
                       isFirstConnection = false;
                }
            });
    
            window[name] = Bots;
        }, 0);
    }
  4. Define the following properties:
    • URI - The URI of the Oracle Chat Server. This is a required property.
    • channelId - The Channel ID that's generated when you create the Oracle Web channel. This property is required because connects the widget to the underlying skill.
    • userId - A user ID. You can provide this value, but the SDK will generate this value if you haven't already provided it. This property is optional for unauthenticated connections.
  5. In your HTML page, reference the locations of both the your JS file (setting.js in the following example) the web-sdk.js library and the Web SDK namespace, which is typically Bots. Use this namespace to invoke the public APIs. For example, if you set the namespace to Bots, then you invoke the APIs as Bots.<API>(). To find out more about the various functions and events, refer to the user guide (available as both a readme and HTML doc) that's included in the Oracle Web SDK ZIP file.
       <script src="scripts/settings.js"></script>
        <script src="scripts/web-sdk.js" onload="initSdk('Bots')"></script>    

Import the Library Using the Asynchronous Module Definition API

You can import the library using implementations of the Asychronous Module Definition (AMD) API such as RequireJS with Oracle JET, and SystemJS.
requirejs(['<path of the web-sdk>'], function(WebSDK) {
var settings = {
    URI: '<Server URI>',
    channelId: '<Channel ID>',
    userId: '<User ID>'
};
Bots = new WebSDK(settings);

Bots.connect();
});

Import the Library Dynamically with JavaScript

Use the following Mozilla Development Network (MDN)-based utility function to import the library dynamically with JavaScript:
function fetchSDK(src, onloadFunction, name) {
var script = document.createElement('script');
script.type = 'application/javascript';
script.async = true;    // load the script asynchronously
script.defer = true;    // fallback support for browsers that does not support async
script.onload = function() {
    onloadFunction(name);
};
document.head.appendChild(script);
script.src = src;
}

fetchSDK('<path of the web-sdk>', initSDK, '<WebSDK namespace>');

Configure Client Authentication

In addition to using lists of allowed domains, client authentication is enforced by signed JWT tokens.

The token generation and signing must be done by the client in the backend server ( preferably after user/client authentication) which is capable of maintaining the keyId and keySecret safe.

When the SDK needs to establish a connection with the ODA server, it first requests a JWT token from the client and then sends it along with the connection request. The ODA server validates the token signature and obtains the claim set from the JWT payload to verify the token to establish the connection.

To enable this mode, these two fields are required during SDK initialization: clientAuthEnabled: true must be passed in the SDK settings parameter, and a token generator function must be passed as the second parameter. The function must return a Promise, which is resolved to return a signed JWT token string.
// settings.js
var chatSettings = {
    URI: '<Server URI>',
    clientAuthEnabled: true
};

function generateToken() {
    return new Promise(function(resolve) {
        fetch('https://yourbackend.com/endpointToGenerateJWTToken')
            .then(function(token) {
               resolve(token);
            })
            .catch(function(error) {
                console.log('Token generation error:', error);
            });
    });
}

function initSDK(name) {
    // If WebSDK is not available, reattempt later
    if (!document || !WebSDK) {
        setTimeout(function() {
            initSDK(name);
        }, 2000);
        return;
    }

    // Default name is Bots
    if (!name) {
        name = 'Bots';
    }

    setTimeout(function() {
        var Bots = new WebSDK(chatSettings, generateToken);    // Initiate library with configuration

        var isFirstConnection = true;
        Bots.on(WebSDK.EVENT.WIDGET_OPENED, function() {
            if (isFirstConnection) {
                Bots.connect()                          // Connect to server
                    .then(function() {
                        console.log('Connection Successful');
                    })
                    .catch(function(reason) {
                        console.log('Connection failed');
                        console.log(reason);
                    });
                   isFirstConnection = false;
            }
        });

        window[name] = Bots;
    }, 0);
}

The JWT Token

The client app is responsible for the JWT token generation. Some of the token payload fields are mandatory and are validated by the ODA server. Clients must use the HS256 signing algorithm to sign the tokens. The body of the token must have the following claims:
  • iat - issued at time
  • exp - expiry time
  • channelId - channel ID
  • userId - user ID
The tokens themselves must be signed by the secret key of the client auth-enabled channel to which the connection is made. Here’s a sample signed JWT token:
Encoded:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzY3NDcyMDUsImV4cCI6MTU3Njc1MTExNywiY2hhbm5lbElkIjoiNDkyMDU5NWMtZWM3OS00NjE3LWFmOWYtNTk1MGQ2MDNmOGJiIiwidXNlcklkIjoiSm9obiIsImp0aSI6ImQzMjFjZDA2LTNhYTYtNGZlZS05NTBlLTYzZGNiNGVjODJhZCJ9.lwomlrI6XYR4nPQk0cIvyU_YMf4gYvfVpUiBjYihbUQ
Decoded:
  • Header:
    {
        "typ": "JWT",
        "alg": "HS256"
    }
  • Payload:
    {
        "iat": 1576747205,
        "exp": 1576748406,
        "channelId": "4920595c-ec79-4617-af9f-5950d603f8bb",
        "userId": "John"
    }
If any claim in the token is missing or has incorrect format for its value, then an error message is thrown by the SDK describing the cause. The connection is not attempted. The error message can be used to fix the issue with the JWT token. Any additional claims passed in the payload do not affect the client authentication mechanism.

Customize the Chat Widget

You can customize various aspects of the chat widget, such as its layout and icons, colors, and text.

Tip:

This article gets you acquainted with the various customization properties.

Network Configuration

You intiate the SDK using these connection properties. The sample app that ships with the SDK provides an example of how to set them in its scripts/settings.js file.
Property Name Description Required? Default Value
URI The URL of the Oracle Chat Server Yes N/A
channelId The Channel ID of the Oracle Web Channel Yes N/A
userId A unique identifier for the user. If you don't provide this, Oracle Digital Asssistant generates one. No A randomly generated value
clientAuthEnabled Determines whether the SDK connectes to a channel where client authentication has been enabled. As described in Configure Client Authentication, you set this to true to connect to channel with authentication enabled and use the JWT token. Yes false

Feature Flags

Use the Feature Flag properties for:
  • Secure connections
  • Pill-shaped action buttons
  • Audio narration of skill responses.
  • Attachment sharing
  • Disabling clicks on previous (out of focus) messages
  • Autocomplete user input
For example:

    <script>
        var chatWidgetSettings = {
            enableTimestamp: true,
            showConnectionStatus: true,
            conversationBeginPosition: 'bottom',
            openChatOnLoad: true,
            position: {bottom: '2px', right: '2px'},
            displayActionAsPills: true,
            initUserHiddenMessage: 'Hello',
            embedded: true,
            targetElement: 'chat-container',    
            embedTopScrollId: 'top-text',
            customHeaderElementId: 'custom-header',
            botButtonIcon: 'images/bot-button.png', 
            logoIcon: 'images/bot-white.png', 
            botIcon: 'images/bot-green.png',        
            personIcon: 'images/user-icon.png',
            URI: YOUR_URI,
            channelId: YOUR_CHANNELID,

         };

...
    </script>
Property Name Description Required? Default Value
defaultGreetingTimeout The default timeout, in seconds, after which a default greeting message displays. No 5
defaultWaitMessageInterval The default interval, in seconds, that the default wait message displays. No 5
disablePastActions Disables interactions (button clicks) with the messages that users have already interacted with. The allowed values are all, none, or postback. The behavior enabled by this property is independent of the digital assistant-level configuration for disabling the selection of past actions. You need to set the two separately. No all
displayActionsAsPills Displays pill-shaped action buttons. No false
enableAttachment Configures attachment sharing. No true
enableAttachmentSecurity When set to true, extra headers are passed to the attachment upload requests to ensure that they can't be downloaded without passing a valid signed JWT token as an authorization header.

Do not enable this setting if the skill connects to an ODA instance that's Version 20.08 or runs on any version prior to 20.08. This property only applies to client auth-enabled connections to Versions 20.12 and higher of the ODA platform.

No false
enableAutocomplete Set to true to enable the skill to autocomplete the user request using the idealized user requests entered as Autocomplete Suggestions in the Create Intent page. The skill ouputs these suggestions when the user enters three or more characters. It also sets off the words in the user input that match the suggested phrases in bold. No false
enableBotAudioResponse Configures the skill responses. The skill responses are read aloud by the Web API. To select the voice for reading messages from a skill or digital assistant aloud, set this proprety to true and then define the skillVoices array. No false
enableClearMessage Enables the clear message button in the chat widget header. No false
enableDraggableButton Enables users to drag the launch button out of the way when it's blocking content on the web page. This feature also works for Android and iOS Safari browsers. No false
enableHeadless Enables you to use the Oracle Web SDK without its UI so that you can develop your own chat UI. No false
enableLocalConversationHistory Enables the previous conversation that's associated with a given userId to be loaded in the browser when the widget has been initialized. No false
enableLongPolling Use HTTP requests when the websocket fails to connect. No false
enableSecureConnection Configures secure communication (https v. http and wss v. ws). No true
enableSpeech When set to true, this property enables the microphone for voice recognition. For example:
chatWidgetSettings = {
    URI: 'idcs-oda-example.com',
    channelId: '9999b1-f99a-9999-999ee-df9d99999d',
    enableSpeech: true
};
No false
enableSpeechAutoSend When set to true (the default), the user's speech response is automatically sent to the chat server (and displays as a sent message in the chat widget). When set to false, the user's speech response is rendered in the message text field before it's sent to the chat server so that the user can modify it before sending it manually, or delete the message. No true
enableTimestamp Enables the timestamp for messages and the "read" symbol, which is a tick mark ('✓'). Use readMark to change this symbol. This feature is deprecated in Release 22.02. No true
focusOnNewMessage Sets the focus on either the user input field, or on the first action button in a message when a new message is received.
  • action – When a message is received, the focus is the first action button (if the message has action buttons). If the message has no buttons, then the focus is the user input field.
  • input – The user input field remains as the focus when new messages are received.
No input
multiLangChat Enables the chat widget to both detect a user’s language and allow the user to select a preferred language from a dropdown menu in the header. You define the menu with an object that defines the primary language and an array of two or more language tags (the supportedLangs array, described in Multi-Lingual Chat). No N/A
name The name for the instance. Provides a namespace to the instance and is used as prefix for the CSS classnames and element IDs. No oda-chat
openChatOnLoad Expands the chat widget when the page is loaded. No false
openLinksInNewWindow Overrides the user's browser preference by opening links in a new window. This setting applies to all links present in the conversation, including action buttons, fallback links for attachments, and card links. No false
showConnectionStatus Enables the connection status to display in the chat widget header. No false
showPrevConvStatus Displays status messages at the end of older messages from previous conversations. No true
showTypingIndicator Displays a chat bubble when waiting for a response. No true

Functionality

Use the Functionality properties to:
  • Imitate a skill-initiated conversation.
  • Embed content to the top and bottom of the chat window that either scrolls, or is stationary (sticky).
  • Set the locale.
  • Set debug mode.
  • Set the locale and voice for speech synthesis.
Property Name Description Required? Default Value
customHeaderElementId Names the ID of the <div> element that's added to the header of the chat widget. No N/A
delegate An object that sets a delegate to receive callbacks before certain events occur in a conversation. The delegate object allows code to interact with both user messages and skill responses before messages are sent and responses get displayed. No N/A
embedBottomScrollId The ID of the element that's added as the scrolling content at the bottom of the chat. Use this property to add custom content in the chat widget's conversation view. No N/A
embedBottomStickyId The ID of the element used for the sticky content that appears at the bottom of the chat. Use this property to add custom content in the chat widget's conversation view. No N/A
embedded Setting this to true, activates the embedded mode for the chat widget. In addition to setting this property, you need to name the div element that houses the widget in the targetElement property. No false
embeddedVideo Enables the embedding of a YouTube video link in a text message. No false
embedTopscrollId The ID of the div element that's added as a scrolling content at the top of the chat widget. No N/A
embedTopStickyId The ID of the div element that's used for the sticky content that appears at the top of the chat widget. Use this property to add custom content in the chat widget's conversation view. For example, the top-text div element in the following snippet is referenced as embedTopStickyId: 'top-text':

<div id="top-text" style="padding: 0; text-align: initial">
<p>Talk to Pizzabot to order your pizza.</p>
</div>
The Web SDK tutorial describes how to configure this property and set scrolling and non-scrolling for chat widget elements.
No N/A
enableAutocompleteClientCache Enables client side caching to minimize server calls when the autocomplete feature is in use. No false
enableDefaultClientResponse When set to true, the client displays default responses when the skill response has been delayed, or when there's no response from the skill. No false
enableEndConversation Enables the user to end the conversation and reset the chat session. It also clears the local conversation history, disconnects from the chat server and minimizes the widget No true
enableHeaderActionCollapse Collapses the header actions into a menu button if the icon count is more than two. No true
enableTabsSync Synchronizes conversation messages across different tabs for a given userId and channelId. No true
i18n An object that contains locale fields. Each locale maintains i18n key-value pairs for the text strings used in the widget. No {'en-us':{…}}
For example:
"i18n": {
                "en-us": {
                    "chatTitle": "Pizza King"
                }
            } 
initBotAudioMuted Initializes the skill message utterance in muted mode. This feature can only be activated when you set enableBotAudioResponse to true. No true
initMessageOptions Whereas initUserHiddenMessage sends the initial "hidden" message only after the client has connected to the skill and the chat widget has been expanded, you can use this setting to send messages as soon as the client has connected to the skill, regardless of whether the widget is expanded or not. This setting accepts an object that has a sendAt property. The sendAt property can have one of the two values: 'init', or 'expand'. If you set 'init', then the init messages are sent as soon as connection is made. If you set 'expand', then the init messages are sent only when the widget is expanded. In the following snippet, the message is set when the connection is established because of sendAt: 'init':
var settings = {
    URI: '...',
    channelId: '...',
    initUserHiddenMessage: 'Hello',
    initMessageOptions: {
        sendAt: 'init'
    }
}
Bots = new WebSDK(settings);
Bots.connect();
Bear in mind that billing starts when the init message has been sent, even if the widget is still closed (as would be the case with sendAt: 'init').
   
initUserHiddenMessage A message that's used to initiate a conversation. This message, can be a text string or a message payload. For example: initUserHiddenMessage: 'Hi'. These messages are not dependent on the user history. This message is sent in every session after the client has connected to the skill and the chat widget has been expanded. To send the first message only when the conversation history is empty, you must bind event listeners using the Bots.on() method. For example, you can accomplish this by binding the WIDGET_OPENED and NETWORK events, which are described in the SDK docs. No N/A
initUserProfile Updates the user profile before the start of a conversation. The format of the profile payload must be { profile: {...} }. For example:
initUserProfile : {
    profile:{
    givenName: 'First',
    surname: 'Last',
    email: 'first.last@example.com',
    properties: {
        lastOrderedItems: '1 medium pepperoni'
    }
}
This function updates the user context after the client is connected to the skill and the chat widget has been expanded. As a result, the user profile can be reflected in the first response message to the user. For example, the skill can greet the user with a message like "Welcome back, John Smith! Your last order was a medium pepperoni pizza." These messages are sent after the client has connected to the skill and the chat widget is expanded.These user profile messages are sent after the client has connected to the skill and the chat widget is expanded. A user profile message is still sent before the initial "hidden" message if initUserHiddenMessage is also passed.

You can only pass the profile property in the payload. If you need to pass another property such as messagePayload. If the initial message needs both the profile and the messagePayload properties, then use initUserHiddenMessage instead.

No N/A
isDebugMode Enables debug mode. No false
linkHandler An object that overrides the configuration for handling the clicks on the links that are embedded in the skill's responses. There are two ways that this object handles links: target, which accepts a string, and onclick, which accepts a function. You can set either target or onclick, but not both. When you want all links to open in a WebView, pass linkHandler: { target: 'oda-chat-webview' }. No
{ onclick: <function>, target: 'string' }
locale The default locale for the widget's text strings. The locale passed during initialization has a higher preference over users’ browser locales. If there isn’t an exact match, then the SDK attempts to match the closest language. For example, if the locale is 'da-dk', but i18n translations are provided only for 'da', then the 'da' translation is used. In absence of translations for passed locale, translations are searched for and applied for the browser locales. In absence of translations for any of them, the default locale, 'en' is used for translations. No en-us
messageCacheSizeLimit The maximum number of messages that get save in localStorage at a time. No 2000
readMark Sets the symbol that denotes that a skill's messages have been read. By default, this is indicated by a tick mark ('✓') when enableTimestamp is set to true, but you can substitute another symbol by defining this property. This symbol, whether the default or custom, can only accompany the timestamp, so it is hidden when enableTimestamp is set to false. The read mark does not display for absolute timestamps. No A tick mark (
'✓'
)
shareMenuItems The menu items in the share popup menu. This property accepts an array with string values that are mapped to menu items:
  • 'visual' for image and videos
  • 'audio' for audio
  • 'file' for files
  • 'location' for location
You can specify which items are available in the menu (['audio', 'file'], for example). All of the menu items are available when the array is empty, when the items in the array are incorrect (['audio', 'visuil'], or when shareMenuItems has not been defined.
No
['audio', 'file', 'location', 'visual']
skillVoices An array containing the preferred voices that used for narrating responses. Each item in the array should be an object with two fields: lang, and name. name is optional. The first item that matches a voice that’s available in the system will be used for the narration. No System language
speechLocale The expected locale of the user's speech that's used for voice recognition. US English ('en-US') is the default locale. The other supported locales are: Australian English ('en-au'), UK English ('en-uk'), French ('fr-fr'), German ('de-de'), Italian ('it-it'), Indian-Hindi (hi-in), Indian-English (en-in), Brazilian Portuguese ('pt-br'), and Spanish ('es-es'). The speech locale can be set dynamically by calling the setSpeechLocale('<locale>') API. Voice recognition will not work if an unsupported locale has been passed. No 'en-us'
storageType The web storage mechanism that's used to store the conversation history for users whose userId is passed by the host app. The supported values are 'localStorage' and 'sessionStorage'. Anonymous users’ conversations are always stored in sessionStorage and are deleted automatically after the browser session has ended. No 'localStorage'
targetElement Names the div element where the chat widget gets embedded in the web page. The chat-container div element in the following snippet is referenced as targetElement: 'chat-container':
        <div id="chat-container" class="chatbox" 
            style="height: 600px; width: 400px; padding: 0;
            text-align: initial">
        </div>
Check out the Web SDK tutorial to find out how to add and style the div element.
No N/A
theme The primary layout theme. Three themes are available: 'default', 'redwood-dark', and 'classic'. No default
timestampFormat Formats the delivery timestamp that accompanies messages. Accepts values in a DateTimeFormat options object or as a pattern string as described in Customize the Timestamp. No
{
weekday:'long',
year:'numeric',
month: 'long',
day: 'numeric'

}
timestampMode Selects the timestamp display mode as either absolute timestamps that appear on each message, or as a relative timestamp that appears only on the latest message.
  • default – Sets an relative timestamp on each message.
  • relative (default) – The timestamp displays before the first message of the day as an absolute timestamp in a header, and then as a relative timestamp for the new messages as an updating timestamp indicating the time passed since the message was added in the conversation. The relative timestamp updates at set intervals until a new message is received.
  • absolute – Sets an absolute timestamp on each message.
  • none – Disables the time stamp.
No default (for absolute timestamps), or relative.
ttsService Injects a custom speech synthesis service for uttering the skill responses. No The text-to-speech (TTS) service on the user device.
typingIndicatorTimeout Sets the number of seconds after which the typing indicator is automatically removed if the chat widget has not yet received the response. No 20
webViewConfig Customizes the in-widget WebView. No { referrerPolicy: 'no-referrer-when-downgrade', closeButtonType: 'icon', size: 'tall' }

Read More and Read Less Buttons for Multi-Paragraph Skill Responses

You can optimize the user experience for multi-paragraph skill messages by adding Read More and Read Less buttons.
Description of readmore.png follows
Description of the illustration readmore.png

You can add the client-side code for these buttons, which hide and show paragraphs, using the delegate object and custom functions.

  1. In settings.js, define a delegate object with a beforeDisplay callback function in the var chatWidgetSettings declaration:
    delegate: {
                beforeDisplay: function (message) {
                    var messagePayload = message && message.messagePayload;
                    if (messagePayload.type === 'text') {
                        messagePayload.text = splitParagraph(messagePayload.text);
                    }
                    return message;
                }
            }
    If the message is of type text, beforeDisplay calls the custom splitParagraph function to split the text by the first paragraph.
  2. Declare the variables for the custom splitParagraph and toggleParagraph view functions:
    var PREFIX_DOTS = 'dots_';
    var PREFIX_MORE = 'more_';
    var PREFIX_TOGGLE = 'toggle_button';
  3. Add the splitParagraph function expression and the toggleParagraphView function.
    splitParagraph is an IIFE (Immediately Invoked Function Expression) that isolates the globalIDCounter variable so that it can only be accessed by the splitParagraph function. The code identifies a paragraph ("\n\n") and splits the text accordingly. It then adds three dots (…) to indicate that there is more text to display and a Read More button to unhide the remaining text.

    var splitParagraph = (function () {
        var globalIDCounter = 0;
    
        return function splitParagraph(text) {
            var paragraphs = text.split('\n\n');
    
            if (paragraphs.length > 1) {
                var HTMLText = '<p>' + paragraphs[0] +
                    '<span id="' + PREFIX_DOTS + globalIDCounter + '">...</span></p>' +
                    '<span id="' + PREFIX_MORE + globalIDCounter + '" class="more">';
    
                for (var i = 1; i < paragraphs.length; i++) {
                    HTMLText += '<p>' + paragraphs[i] + '</p>';
                }
    
                HTMLText += '</span><button id="' + PREFIX_TOGGLE + globalIDCounter + '" class="readMore" onclick="toggleParagraphView(' + globalIDCounter + ')">Read More</button>';
    
                globalIDCounter++;
                return HTMLText;
            } else {
                return text;
            }
        }
    })();
    
    function toggleParagraphView(elemID) {
        var dots = document.getElementById(PREFIX_DOTS + elemID);
        var textMore = document.getElementById(PREFIX_MORE + elemID);
        var buttonToggle = document.getElementById(PREFIX_TOGGLE + elemID);
    
        if (!dots || !textMore || !buttonToggle) {
            return;
        }
    
        if (dots.style.display === 'none') {
            dots.style.display = 'inline';
            buttonToggle.innerText = 'Read More';
            textMore.style.display = 'none';
        } else {
            dots.style.display = 'none';
            buttonToggle.innerText = 'Read Less';
            textMore.style.display = 'inline';
        }
    }
  4. You can optionally style the Read More and Read Less buttons. The CSS includes a display:none style to show or hide buttons according to the state of the long text display.
    <style>
    .readMore {
      color: #fff !important;
      background-color: red;
      font-size: 12pt;
      padding: 4px;
      outline: 0;
      -moz-outline: 0;
      border: 0;
    }
    
    .readMore:hover {
      color: #fff !important;
      background-color: #606060 !important;
    }
    .more {
      display: none;
    }
    </style>

Layout

Use the layout properties to:
  • Set the position of the widget within the web page.
  • Set chat widget's dimensions, colors, and font style.
  • Set the padding for the messages within the widget.
  • Set the position of the notification badge icon with respect to bot button.
  • Set the starting position for the conversation within the widget.
For example:
     <script>
        var chatWidgetSettings = {
            URI: YOUR_URI,
            channelId: YOUR_CHANNELID,
            font: '14px "Helvetica Neue", Helvetica, Arial, sans-serif', //layout modification property
            height: '60vh', //layout modification property
            width: '20vw',  //layout modification property
             "colors": {    //custom colors property  
                "branding": "#01538A",
                "text": "#B20637"
            },
         }
                
...
    </script>
Property Description Required? Default Value
badgePosition The position of the badge icon with respect to the icon button. No {"top": "0", "right": "0"}
colors The colors used in the chat widget. No {"branding": "#1B8FD2", "text": "#212121", "textLight": "#737373"}
conversationBeginPosition The starting position for conversation in the widget. If set to top, the first messages appear at the top of the widget. If set to bottom, then the conversation starts at the bottom. No bottom
font The font used in the chat widget. No 16px "Helvetica Neue", Helvetica, Arial, sans-serif
height The height of a chat width as set by one of the <length> data type values. No 70vh
messagePadding The padding around messages in the chat widget. No 15px
position The placement of the chat widget in the browser window. This should be passed as a JSON object. No {bottom: '20px', right: '20px'}
theme The primary layout theme. The valid values are 'default', 'redwood-dark', and 'classic'. No 'default'
width The width of the chat widget as set to one of the <length> data type values. No 30vw

Custom Header Button Icons

You can customize the header's clear message This is am image of the clear messages icon., audio response toggle button This is an image of the Audio Response icon., and the close button This is an image of the Close icon. in two ways: by passing the source URL of the image, or by passing a raw SVG string. For raw SVG strings, the fill color of the SVG can be customized by CSS classes, as well as by passing a color value in the colors.headerButtonFill property in the initial settings.

Note:

The color customization may not work for all SVGs, as they can be multi-colored or have their own stroke and fill colors.
Icon Function Feature Flag Customization
Clear Message Clears both the current and older messages in the conversation. enableClearMessage: true '<image URL | SVG string>'
Audio response Toggles the audio of skill responses as they are received. Because this a toggle button, it has two states, utterance on, where responses are spoken, and utterance off, where responses are not spoken. enableBotAudioResponse: true
  • Response on: audioResponseOnIcon: '<image URL | SVG string>'
  • Response off: audioResponseOffIcon: '<image URL | SVG string>
Close Collapses the widget and displays the launch button This is an image of the launch icon.. This button cannot be disabled. None: This icon is always enabled in the chat widget. It's not displayed in the embedded mode. closeIcon : '<image URL | SVG string>'

Custom Colors

You can customize the widget by modifying its colors. There are two approaches to color customization:
  • You can pass the colors config:
    colors: {
        "branding": "#e00",
        "text": "#545454"
    },
    
  • Or you can use CSS variables defined on the chat wrapper (.oda-chat-wrapper):
    .oda-chat-wrapper {
        --color-branding: '#e00';
        --color-text: '#545454';
    }
    }
The color must be a hexadecimal color. If you don't provide a color, then a default color is used instead. These snippets illustrates how to modify the branding and text colors. The default color will be used for the secondary text color.

Tip:

We recommend changing colors using CSS variables.
CSS Variable Key Description
N/A recognitionViewBackground The background color for the view where the recognized text displays when users activate the voice mode. If you don't define this color, then the color defined for headerBackground is used instead.
N/A recognitionViewButtonFill The SVG fill color for the voice-text mode toggle when users switch to the voice mode.
N/A shareMenuText The color used for the share menu items. This color overrides the value set for the text key, if passed.
N/A userMessageBackgound The background color of the bubble used for user messages.
--color-actions-background actionsBackground The background color for the action buttons
--color-actions-background-focus actionsBackgroundHover The background color of the action buttons on hover
--color-actions-background-hover actionsBackgroundFocus The background color for the action buttons when they're in focus.
--color-actions-border actionsBorder The border color for the action buttons
--color-actions-text actionsText The text color for the action buttons
--color-actions-text actionsTextFocus The text color for the action buttons on focus
--color-actions-text-focus actionsTextHover The text color for the action buttons on hover
--color-bot-text botText The color for the text in a message sent by the skill
--color-branding branding The primary color for the widget branding. This color is used as the header background and as the hover color on footer buttons.
--color-card-background cardBackground The background color used for a card.
--color-conversation-background conversationBackground The color used for the background of the conversation pane.
--color-error-border N/A The border color of an error message bubble
--color-error-message-background N/A The background color of an error message bubble
--color-error-text N/A The description color of an error message content
--color-error-title N/A The title color of an error message content
--color-footer-background footerBackground The color used for the backgound of the footer.
--color-footer-button-background-hover N/A The background color of the footer buttons on hover
--color-footer-button-fill footerButtonFill The fill color of an SVG icon used in the buttons that are located in the chat footer.
--color-footer-button-fill-hover N/A The fill color of the header footer on hover
--color-global-actions-background globalActionsBackground The background color of the global action buttons
--color-global-actions-background-focus globalActionsBackgroundFocus The background color of the global action buttons when they're in focus.
--color-global-actions-background-hover globalActionsBackgroundHover The background color for the hover over the global action buttons.
--color-global-actions-border globalActionsBorder The border color of the global action buttons
--color-global-actions-text globalActionsText The text color of the global action buttons
--color-global-actions-text-focus globalActionsTextFocus The color of the text in the global action buttons when they're in focus.
--color-global-actions-text-hover globalActionsTextHover The color of the text in the global action buttons when users hover over them.
--color-header-background headerBackground The background color of the chat widget’s header
--color-header-button-background-hover N/A The background color of the header buttons on hover
--color-header-button-fill headerButtonFill The fill color of the SVG icons used for the buttons in the chat header
--color-header-button-fill-hover N/A The fill color of the header buttons on hover
--color-header-text headerText The color of the chat header title
--color-input-background inputBackground The message input field background color in the chat footer
--color-input-border N/A The border color of the input field
--color-input-text inputText The message input text color in the chat footer
--color-links links The color for links in messages
--color-notification-badge-background notificationBadgeBackground The background color for the message notification badge
--color-notification-badge-text notificationBadgeText The text color for the message count in the notification badge
--color-popup-background N/A The background color of prompts and popups
--color-popup-button-background N/A The background color of popup buttons
--color-popup-button-text N/A The text color of popup buttons
--color-popup-horizontal-rule N/A The horizonatal rule color for separator for multi-lang chat menu action
--color-popup-item-background-hover N/A The background color on hover of popup list items
--color-popup-text N/A The text and icon color of prompts and popups
--color-rating-star ratingStar The color that's applied to the rating stars in a feedback message when users hover over them or select them. If you do not specify a color, the branding color is used instead.
--color-recognition-view-text recognitionViewText The color used for the text that's recognized from the user's voice input. If you don't define this color, then color defined for text is used instead.
--color-table-background N/A The background color of tables
--color-table-header-background N/A The background color of table headers
--color-table-separator N/A The separator color of table rows
--color-table-text N/A The text color of tables
--color-text text The text color for messages in the chat widget.
-color-text-light textLight The text color of the secondary text in the messages, such as the card descriptions in the chat widget.
--color-timestamp timestamp The color for the relative timestamp.
--color-typing-indicator typingIndicator The background fill color used for the typing indicator.
--color-user-message-background botMessageBackground The color for the background of the skill's response message bubble
--color-user-text userText The color for the text in a message sent by the user.
--color-visualizer visualizer The color used for the bars in the visualizer graph. If you don't define this color, then the color defined for branding is used instead.
--color-visualizer-container-background visualizerContainerBackground The background color for the container of the voice visualizer that displays when users toggle to the voice mode. If you don't define this color, then the color defined for userMessageBackgound is used instead.

Note:

You can set an image for conversationBackground, headerBackground, and footerBackground. These fields can accept any parameters that can be passed to the CSS background background property. For example:
colors: {conversationBackground: 'no-repeat url("https://images.unsplash.com/photo-1582580470647-e3be5274d6a0?ixlib=rb-1.2.1&auto=format&fit=crop&w=668&q=80")'},

Custom Icons

You can customizes the icons, including the ones for the skill icon, the chat logo icon, and the avatar icons for the skill and user.

You can pass the URL of the image asset for these icons. For some icons, you can either use the URL or pass a Scalable Vector Graphics (SVG) string. You can pass the raw SVG data for icons that support SVG strings. The chat view renders these as an inline SVG.

Tip:

SVG strings load faster than image assets. They also let you animate the image and change its color. The layout defined for the theme property is applied to SVG strings for attachment, send, and mic buttons, but not for the other image assets.
Starting with Version 21.10, you can use the icons property to group all of the custom icons into a single field. The pre-21.10 icons are still supported, but the values passed with the icons object take precedence. All fields within the icons object support both image resource paths and raw SVG strings.
var settings = {
    URI: '<URI>',
    channelId: '<channel ID>',
    icons: {
        rating: '<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><path d="M15.994 3.006a5.7 5.7 0 00-3.795 1.707L12 4.916l-.199-.202a5.676 5.676 0 00-8.128 0c-2.231 2.275-2.231 5.953 0 8.228L12 21.428l8.326-8.486A5.873 5.873 0 0022 8.828a5.873 5.873 0 00-1.675-4.115A5.693 5.693 0 0016.262 3z"/></svg>'
    },
Property (21.10 Release) Property (Prior Releases) Description SVG String Compatible?
avatarAgent agentAvatar For skills integrated with live agents, this icon displays alongside messages from the live agent. The avatarBot (or agentAvatar) appears if this property is not defined. Yes
avatarbot botIcon The icon that displays alongside the skill's reponse message. This skill icon only displays if you provide this icon. Otherwise, no icon displays. Yes
avatarUser personIcon The icon that displays alongside user messages. This icon does not display by default: it only displays if you define it. Yes
clearHistory clearMessageIcon The clear message button icon that's located in the widget header Yes
close N/A The icon that's displayed for the close button in error message banners, expanded image previews, and the in-widget WebView. Yes
collapse closeIcon The icon for the button, located in the chat view header, that minimizes the chat view. Yes
download downloadIcon The icon used for the attachment download button that appears on each attachment message sent by the skill. download – Yes
error errorIcon The URL for the image used for the error icon.
  • errorIcon – No
  • error – Yes
No
expandImage expandImageIcon The icon used for the image expand control that appears on each image attachment message sent by the skill. expandImage – Yes
fileAudio audioIcon The audio attachment icon, displayed when attachment source URL is not reachable.
  • audioIcon – No
  • fileAudio – Yes
fileGeneric fileIcon The file attachment icon.
  • fileIcon – No
  • fileGeneric – Yes
fileImage imageIcon The image attachment icon, which is displayed when the attachment source cannot be reached.
  • fileImage – No

    imageIcon – Yes

fileVideo videoIcon The video attachment icon, which is displayed when the attachment source URL cannot be reached.
  • videoIcon – No
  • fileVideo – Yes
keyboard keyboardIcon The keyboard icon, displayed in button that switches the mode from voice to keyboard mode. Yes
launch botButtonIcon The skill bot button, displayed when the chat widget is minimized.
  • botButtonIcon – No

    launch – Yes

logo logoIcon The chat logo icon which is displayed in the header of the chat widget.
  • logoIcon – No
  • logo – Yes
mic micIcon The mic button icon in the footer of the chat widget that appears when Yes
rating N/A The icon displayed for the feedback action buttons in the ratings component. For the best user experience for the hover action, pass a filled SVG icon string. rating – Yes
send sendIcon The send message button icon Yes
shareMenu attachmentIcon The attachment upload icon Yes
shareMenuAudio N/A The icon for the audio menu item in the share menu popup. Yes
shareMenuFile N/A The icon for the file menu item in the share menu popup. Yes
shareMenuLocation N/A The icon for the share menu button in the share menu popup. Yes
shareMenuVisual N/A The icon for the image/video menu item in the share menu popup Yes
ttsOff audioResponseOffIcon The icon for the toggle button when audio responses are turned off. Yes
ttsOn audioResponseOnIcon The icon for the toggle button when audio responses are turned on. Yes
typingIndicator chatBubbleIcon The animated icon in conversation pane that indicates a response being sent from skill. Yes
You can also resize the icon for the loading chat bubble icon (enabled with chatBubbleIcon).
Property Name Description Required? Default Value
chatBubbleIconHeight The height of the loading chat bubble icon. No 42px
chatBubbleIconWidth The width of the loading chat bubble icon. No 56px

Custom Strings

You can customize the following strings and provide them as localized text. As illustrated by the following object, localization requires you to provide a valid locale for each entry. You need to update all keys for locales other than en-us. If you don't, then en-us translations are displayed for the missing values.
"i18n": {
    "fr": {
        "chatTitle": "Soutien"
    },
    "en-us": {
        "chatTitle": "Support"
    },
    "es": {
        "chatTitle": "Apoyo"
    },
    "zh-cn": {
        "chatTitle": "支持"
    }
}
Key Description Default Value
attachment_audio The text that's used for the TTS utterance of an audio attachment. 'Audio attachment'
attachment_file The text that's used for the TTS utterance of a file attachment. 'File attachment'
attachment_image The text that's used for the TTS utterance of an image attachment. 'Image attachment'
attachment_video The text that's used for the TTS utterance of a video attachment. 'Video attachment'
attachmentAudioFallback The fallback message that is displayed in place of an audio attachment if the audio can not be rendered by the client. The text between {0} and {/0} is set to a link to download the file. Your browser does not support embedded audio. However you can {0}download it{/0}.
attachmentVideoFallback The fallback message that is displayed in place of an video attachment if the video can not be rendered by the client. The text between {0} and {/0} is set to a link to download the file. Your browser does not support embedded video. However you can {0}download it{/0}.
audioResponseOn The tooltip that appears when the user hovers over the audio utterance "off" button in header. Turn audio response on
card The identifier for the card. 'Card {0}'. You can localize the string by placing the ordinal placeholder ({0}) before or after the word. We will continue to support the 'Card' string used in prior releases that does not include the ordinal placeholder. For this string, the ordinal is placed after the word. If you want to mute the utterance, pass an empty string (card: '').
cardImagePlaceholder The placeholder text that displays while the card image is fetched and loaded. Loading image
cardImagePlaceholder The placeholder text that displays while the card image is fetched and loaded. Loading image
cardNavNext The label for the card navigation button for displaying the next card in a horizontal layout. Next card
cardNavPrevious The label for the card navigation button for displaying the previoust card in a horizontal layout. Previous card
chatSubtitle Sets the subtitle of the chat view, which is displayed below the title on the chat view header. If the subtitle flag is set and either (or both) the showConnectionStatus and showTypingIndicator flags are set to true, then the subtitle is displayed instead of either the connection status or the typing indicator. N/A
chatTitle The title of the chat widget that is displayed in the header. Ask
clear The tooltip that appears when the user hovers over the Clear Messages button in the header. Clear
close The tooltip that appears when the user hovers over the close widget button in the header. Close
closing The status text that displays while the connection between chat widget and server is closing. Closing
connected The status text that displays while the connection between chat widget and server is established. Connected
connecting The status text that displays when the chat widget connects to the chat server. Connecting
defaultGreetingMessage The default client greeting response displayed when the skill response has not been received within the number of seconds set by defaultGreetingTimeout.. Hey, Nice to meet you! Allow me a moment to get back to you.
defaultSorryMessage The default client response when the skill response has not been received the number of seconds set by typingIndicatorTimeout. Unfortunately, I am not able to get you the right content. Please try again.
defaultWaitMessage The default response that displays at the interval when an actual skill response has not been received. This interval is set, in seconds, by defaultWaitMessageInterval I\'m still working on your request. Thank you for your patience!
disconnected The status text that displays when the connection between chat widget and server has closed. Disconnected
download The accessibility text for the download button that appears on each attachment message sent by the skill. Download
endConversation The tooltip that appears when hovering over the end conversation header button. End Conversation
endConversationConfirmMessage The confirmation message that displays when a user clicks the end conversation button. Are you sure you want to end the conversation?
endConversationDescription The description message that displays along with the confirm message in the end conversation prompt. This will also clear your conversation history.
errorSpeechInvalidUrl The error message that's displayed when the speech server URL is not set. ODA URL for connection is not set. Please pass \'URI\' parameter during SDK initialization.
errorSpeechMultipleConnection The error message that's displayed when multiple speech connections are attempted wihtin a short interval. Another voice recognition is ongoing. Can\'t start a new one.'
errorSpeechTooMuchTimeout The error message that's displayed when a user provides voice message that's too long to be recognized. Too much voice input to recognize. Can not generate recognized text.
errorSpeechUnsupportedLocale The error message that's displayed when a recording is attempted and an unsupported locale has been configured for voice recognition. The set speech locale is not supported. Cannot start recording.
imageViewerClose The accessibility text for the button that closes the expanded image. Close image viewer
imageViewOpen The accessibility text for the button that expands the image. Open image viewer
inputPlaceholder The placeholder text that appears in the user input field. Type a message
itemIterator Item identifier in a list of items in a Table, Form, or Table-Form message. The text ({0}) is replaced by the item index. Item {0}
linkField The replacement utterance text for a link field in a Table, Form, or Table-Form message. The placeholder ({0}) is replaced with the linkLabel of the field. Click on the highlighted text to open Link for {0}
noSpeechTimeout The status text that's displayed when the Chat Server is unable to recognize the voice. Could not detect the voice, no message sent.
noText The label for the No confirmation button. No
openMap The label for the action button that's used to open a location map. Open Map
previousChats The status text that displays at the end of older messages. Previous conversations
ratingStar The tooltip text that's displayed for each rating star in a feedback message. The placeholder `{0}` is replaced by number of stars that the user has selected. Rate {0} star
recognitionTextPlaceholder When voice mode is activated, this is the placeholder text that's displayed in the recognition text field. Speak your message
relTimeDay The relative timestamp that displays every day since the previous message was received. {0} is replaced by the number of days that have passed. {0}d ago
relTimeHr The relative timestamp that displays every hour for the first 24 hours after the previous message was received. {0} is replaced by the number of hours that have passed. {0}hr ago
relTimeMin The relative timestamp that displays every minute since the last message was received. {0} is replaced by the number of minutes that have passed. {0}min ago
relTimeMoment The relative timestamp that displays ten seconds after the message has been received and before 60 seconds has elapsed since the last message was received. A few seconds ago
relTimeMon The relative timestamp that displays every month since the previous message was received. {0} is replaced by the number of months that have passed. {0}mth ago
relTimeNow The relative timestamp that displays for a new message. Now
relTimeYr The relative timestamp that displays each year after the previous message was received. {0} is replaced by the number of years that have passed. {0}yr ago
requestLocation The text that displays while the user location is requested. Requesting location
requestLocationDeniedPermission The error message that's displayed when the permission to access location is denied. Location permission denied. Please allow access to share your location, or else type in your location.
requestLocationDeniedTimeout The error message that's displayed when the location request is not resolved because of a timeout. Taking too long to get your current location. Please try again, or else type in your location.
requestLocationDeniedUnavailable The error message displayed when the location request is denied because the current location of the client device is unavailable. Your current location is unavailable. Please try again, or else type in your location.
requestLocationString The error text that displays when the user denies the location request. Cannot access your location. Please allow access to proceed further.
retryMessage The text that displays when the user message has not been sent to the server. Try again
send The tooltip appears when the user hovers over the send button in the footer. Send
shareAudio The menu item text in the share the popup for sharing an audio file Share Audio
shareFailureMessage The error message that's displayed when the share action button in a message is clicked, but the share API is unavailable in the client device, or the share request has been rejected. Sorry, sharing is not available on this device.
shareFile The menu item text in the share popup for sharing a generic file Share File
shareLocation The menu item text for sharing a location in the popup Share Location
shareVisual The menu item text in the share popup for sharing an image or video file Share Image/Video
skillMessage A skill message indicator for screen readers. It's spoken by the screen readers before the skill responses. Skill says
speak The tooltip that appears when the user hovers over the speak button in the footer. Speak
typingIndicator The accessibility text for the typing indicator. It is spoken by the screen readers. Waiting for response
upload The tooltip that appears when the user hovers over the upload button in the footer. Share popup
uploadFailed The error text that displays when an upload fails. Upload Failed.
uploadFileSizeLimitExceeded The error text that displays when the size of the upload file exceeds the limit. Upload Failed. File size should not be more than 25MB.
uploadFileSizeZeroByte The error text that displays when upload file size is 0 bytes. Upload Failed. Files of size zero bytes cannot be uploaded.
uploadUnsupportedFileType The error text that displays when an upload is attempted for an unsupported file type. Upload Failed. Unsupported file type.
userMessage A user message indicator for screen readers. It's spoken by the screen readers before the user messages. I say
utteranceGeneric The fallback description for the response message that's used in utterance. Message from skill.
webViewAccessibilityTitle The default accessibility title for webview that's read aloud by screen readers. In-widget WebView to display links
webViewClose The default label/tooltip title for webview close button. Done
webViewErrorInfoDismiss The tooltip for the dismiss button that's used to close the fallback link inside the webview. 'Dismiss'
webViewErrorInfoText The informational text displayed in the webview when the clicked link can't be opened within it. The text between {0} and {/0} is set to the original link that opens in a new tab or window. Sorry, we can\'t open this page in the chat window. Click {0}here{/0} to open it in your browser.
yesText The label for the Yes confirmation button. Yes

Configure Share Menu Options

By default, the share menu displays options for the following file types:
  • visual media files (images and videos)
  • audio files
  • general files like documents, PDFs, and spreadsheets
  • location


The shareMenuItems setting allows you to restrict the items that display in the share menu. The setting accepts a string array with keys that are mapped to the share menu items: 'visual' for the Share Image/Video item, 'audio' for the Share Audio item, 'file' for the Share File item, and 'location' for the Share Location item. You can use these keys, which are not case-sensitive, to specify which items are available in the menu (['visual', 'location'], for example). All of the menu items are available when the array is empty, or when an invalid value is passed.

Note:

You can disable the attachment functionality by setting enableAttachment to false.


Using attachment functionality often requires updating the network security policy of the host site. The attachments, which are uploaded to Oracle Digitial Assistant object storage using HTTP calls, may get blocked by the site's CORS policies. With the site blocking the uploads, an error can display in the browser console indicating that the client has blocked the request because of a CORS policy. To fix such issues, the network security policy of the host site should be updated to allow the Oracle Digital Assistant domain. This allows the upload requests to go through. Since the CORS policy does not apply to WebSockets, the conversations between the SDK and the skills are not impacted by such restrictions.

Note:

Do not enable this setting if the skill connects to an ODA instance that's Version 20.08 or runs on any version prior to 20.08. This property only applies to client auth-enabled connections to Versions 20.12 and higher of the ODA platform.
Custom Share Menu Items
You can customize the share menu item to display specific file types. To create this customized menu, pass each menu item as an object of the shareMenuItems array:
{
type: string,       // Space separated list of file formats, pass '*' to allow all supported file types

label: string,      // OPTIONAL, label for the share menu item, should preferably be configured through i18n strings

icon?: string,      // OPTIONAL, Icon image source path or SVG source string, the file icon is displayed as fallback

maxSize?: number    // OPTIONAL, Maximum file size allowed for upload in KiloBytes, the maximum and fallback value is 25 MB (25600 KB)
}
The menu item can be passed with or without the string category.

Tip:

To support labels in multiple languages, we recommend using i18n instead of the label tag.
The following code snippet illustrates how to pass the shareMenuItems array in the settings variable. You set the labels by passing them with share_ keys, which are illustrated in this snippet as well. You can set the label for a wild card (*) using the share_all i18n key.
var settings = {
shareMenuItems: [ {
    type: 'pdf',
    label: 'Upload PDF',
}, {
    type: 'pdf'
}, {
    type: 'jpg png jpeg',
    icon: 'https://image-source-site/imageicon'
}, {
    type: 'doc docx xls',
    maxSize: 4096
}],
i18n: {
    en: {
        share_pdf: 'Upload PDF',
        share_jpg_png_jpeg: 'Upload Image',
        share_doc_docx_xls: 'Upload document'
    }
}
}

Customize CSS Classes

You can override the widget's CSS classes with custom style rules to further customize the look and feel.
Class Component
oda-chat-button The collapsed chat component button
oda-chat-button-clear The clear messages button
oda-chat-button-close The close widget button
oda-chat-button-narration The skill's audio response toggle button
oda-chat-button-send The send message button
oda-chat-button-upload The upload file button
oda-chat-card The card message
oda-chat-closing Applied as a sibling to oda-chat-connection-status when the widget is disconnecting from server
oda-chat-connected Applied as a sibling to oda-chat-connection-status when the widget is connected to server
oda-chat-connecting Applied as a sibling to oda-chat-connection-status when the widget is connecting to server
oda-chat-connection-status The connection status. Each connection value has its own class as well, such as oda-chat-connected, oda-chat-disconnected, or oda-chat-connecting.
oda-chat-conversation The container for the conversation
oda-chat-disconnected Applied as a sibling to oda-chat-connection-status when the widget is disconnected from server
oda-chat-footer The chat widget footer
oda-chat-footer-button The common class for all footer buttons
oda-chat-header The chat widget header
oda-chat-header-button The common class for all header buttons
oda-chat-icon-wrapper The wrapper for the skill or for a person that's displayed alongside the message.
oda-chat-left The wrapper for the skill message
oda-chat-logo The logo on the widget header
oda-chat-message The common wrapper class for all chat messages
oda-chat-message-action-location The location request action button
oda-chat-message-action-postback The postback action button
oda-chat-message-actions The action buttons wrapper
oda-chat-message-bubble The message bubble
oda-chat-message-global-actions The global action buttons wrapper
oda-chat-message-icon The image for the skill or for a person that's displayed alongside the message.
oda-chat-notification-badge The notification badge for messages that haven't been viewed.
oda-chat-rating-star The rating star button in a feedback message
oda-chat-rating-star-icon The SVG icon for the rating star button
oda-chat-right The wrapper for the user message
oda-chat-title The title on the widget header
oda-chat-user-input The user input text area
oda-chat-widget The expanded chat component, which wraps the widget header, conversation, and footer.
oda-chat-wrapper The wrapper for entire chat component

Customize the Timestamp

By default, the timestamp that displays in the header when enableTimestampdates is set to true displays the format as the locale's day of the week, month, date, year, and time (am and pm). For example, Thursday, August 13, 2020, 9:52:22 AM. You can configure this timestamp by passing formatting options in the timestampFormat setting. You can format the timestamp by either passing a pattern string of formatting tokens, or by passing an object containing Intl.DateTimeFormat options.

Format the Date-Time with Pattern Strings
The pattern strings used for formatting the timestamp are made up of format tokens. For example, passing timestampFormat: 'hh:mm:ss a' sets the timestamp as 09:30:14 pm.

Note:

These tokens are case-sensitive, so for example, passing yyyy instead of YYYY would prevent the year from displaying.
Component Token Output
Day of the month
  • D
  • Do
  • DD
  • 1 2 ... 30 31
  • 1st 2nd ... 30th 31st
  • 01 02 ... 30 31
Day of the week
  • d
  • dd
  • dddd
  • 0 1 ... 5 6
  • Sun Mon ... Fri Sat
  • Sunday Monday ... Friday Saturday
Month
  • M
  • MM
  • MMM
  • MMMM
  • 1 2 ... 11 12
  • 01 02 ... 11 12
  • Jan Feb ... Nov Dec
  • January February ... November December
Year
  • YY
  • YYYY
  • 70 71 ... 29 30
  • 1970 1971 ... 2029 2030
Hour
  • H
  • HH
  • h
  • hh
  • 0 1 ... 22 23
  • 00 01 ... 22 23
  • 1 2 ... 11 12
  • 01 02 ... 11 12
Minute
  • m
  • mm
  • 0 1 ... 58 59
  • 00 01 ... 58 59
Second
  • s
  • ss
  • 0 1 ... 58 59
  • 00 01 ... 58 59
Fractional Second
  • S
  • SS
  • SSS
  • 0 1 ... 8 9
  • 0 1 ... 98 99
  • 0 1 ... 998 999
AM/PM
  • A
  • a
  • AM PM
  • am pm
Timezone
  • Z
  • ZZ
  • -07:00 -06:00 ... +06:00 +07:00
  • -0700 -0600 ... +0600 +0700li
Format the Timestamp with Intl.DateTimeFormat Objects
The timestamp can also be formatted using the options defined for Intl.DateTimeFormat object. The properties that are passed with the object include:
Property Values
dateStyle 'full' | 'long' | 'medium' | 'short'
timeStyle 'full' | 'long' | 'medium' | 'short'
weekday
  • 'long' (for example, Thursday)
  • 'short' (for example, Thu)
  • 'narrow' (for example, T)
day
  • 'numeric'
  • '2-digit'
month
  • 'numeric' (for example, 2)
  • '2-digit' (for example, 02)
  • 'long' (for example, March)
  • 'short' (for example, Mar)
  • 'narrow' (for example, M)
year
  • 'numeric'
  • '2-digit'
era
  • 'long' (for example, Anno Domini)
  • 'short' (for example, AD)
  • 'narrow' (for example, A)
hour
  • 'numeric'
  • '2-digit'
minute
  • 'numeric'
  • '2-digit'
second
  • 'numeric'
  • '2-digit'
timeZoneName
  • 'long' (for example, British Summer Time)
  • 'short' (for example, GMT+1)
timeZone The time zone. All implementations must recognize UTC. The default value is the runtime's default time zone. Implementations may also recognize the time zone names of the IANA time zone database, such as Asia/Shanghai, Asia/Kolkata, America/New_York.
hour12 Whether to use 12-hour time (as opposed to 24-hour time). Values are true and false.

Customize the Feedback Message Rating Gauge

The feedback component message enables you to collect user feedback. If you're using the 21.10 SDK, the default presentation of the feedback component is a star rating system, a horizontal row of stars that are highlighted as users hover over and select them. You can change the behavior of the component using the System.Feedback component, but you can customize the components' appearance using the SDK settings.

You can change the icon for the component's rating selection buttons by passing the icon of your choice by defining the rating icon in the icons field.

Tip:

For the best user experience, use a solid SVG string without a fill color, as it allows for a recognizable highlighting on hover.
new WebSDK({
    URI: '<Server URI>',
    //...,
    icons: {
        rating: '<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.994 3.006a5.7 5.7 0 00-3.795 1.707L12 4.916l-.199-.202a5.676 5.676 0 00-8.128 0c-2.231 2.275-2.231 5.953 0 8.228L12 21.428l8.326-8.486A5.873 5.873 0 0022 8.828a5.873 5.873 0 00-1.675-4.115A5.693 5.693 0 0016.262 3z"/></svg>'    // A heart icon
    }
})
The color of the icon in the two states, unselected and hovered/selected, can be configured with the ratingStar and ratingStarFill color fields in colors setting respectively.
new WebSDK({
    URI: '<Server URI>',
    //...,
    icons: {
        rating: '<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.994 3.006a5.7 5.7 0 00-3.795 1.707L12 4.916l-.199-.202a5.676 5.676 0 00-8.128 0c-2.231 2.275-2.231 5.953 0 8.228L12 21.428l8.326-8.486A5.873 5.873 0 0022 8.828a5.873 5.873 0 00-1.675-4.115A5.693 5.693 0 0016.262 3z"/></svg>'    // A heart icon
    },
    colors: {
        ratingStar: '#ffebee',
        ratingStarFill: '#d32f2f'
    }
})

Tip:

You can customize the prompts output by the System.Feedback component by the editing the Feedback-related resource bundles accessed through the Resource Bundle Configuration page or by editing the systemComponent_Feedback_ keys in an exported resource bundle CSV file.

Send the Initial Message when the Conversation History is Empty

The initUserHiddenMessage messages are sent regardless of the user's conversation history; they are sent the first time the chat widget is opened for every session. To send the initial message when the conversation history is empty, you need to bind an event listener to the Bots.on() method. For example:
Bots = new WebSDK(chatWidgetSettings);

var isHandled = false;
var message = ;

Bots.on(WebSDK.EVENT.WIDGET_OPENED, function() {
    if (!isHandled && Bots.isConnected() && !Bots.getConversationHistory().messagesCount) {
        Bots.sendMessage(message, { hidden: true });
        isHandled = true;
    }
});

Bots.on(WebSDK.EVENT.NETWORK, function(state) {
    if (!isHandled && Bots.isConnected() && Bots.isChatOpened() && !Bots.getConversationHistory().messagesCount) {
        Bots.sendMessage(message, { hidden: true });
        isHandled = true;
    }
});

Bots.connect();

Speech Synthesis Service Injection

By utilizing the device's native text-to-speech service, the SDK's text-to-speech (TTS) synthesis uses the device's service allows the skill's responses to be uttered as soon as they're received by the Web SDK instance. This is the out-of-the box approach, and while it's reliable, it does have a few drawbacks:
  • You're often limited to unnatural, generic-sounding voices that can undermine your branding.
  • A user's device may not support gender-specific voices.
  • Some native frameworks (Cordova and ReactNative among them) require third-party libraries for TTS services because their webviews do not expose the native speech synthesis APIs that are required by the Web SDK.
To address these challenges, you can set the voice used for the skill's responses by injecting a TTS service into the SDK instance by initiating the SDK with the ttService feature flag or by calling the setTTSService method (described in the documentation that accompanies the SDK). You can use your own TTS, or one provided by a third party.
Speech Synthesis Service Interface
You need to implement the SpeechSynthesisService interface for the TTS service instance that you're going to inject.
/**
 * Interface for the speech synthesis service; this can be used to define a service that can be
 * injected into the SDK to perform speech synthesis on behalf of the skill or assistant
 */
interface SpeechSynthesisService {
    /**
     * Adds a phrase to the utterance queue to be spoken
     * @param phrase string
     */
    speak(phrase: string): void;

    /**
     * Cancels any ongoing speech synthesis utterance
     */
    cancel(): void;

    /**
     * Returns a Promise that resolves into a list of SpeechSynthesisServiceVoice objects representing
     * the available voices
     *
     * @return {*}  {Promise<SpeechSynthesisServiceVoice[]>}
     */
    getVoices(): Promise<SpeechSynthesisServiceVoice[]>;

    /**
     * Sets the voice to be used for speaking the utterances. It accepts an array of candidate voices
     * sorted in their preference order, and sets one of them according to its matching criteria.
     * It returns a Promise that gets resolved when the voice is set.
     *
     * @param {SpeechSynthesisServiceVoice[]} voice
     * @return {*}  {Promise<void>}
     */
    setVoice(voices: SpeechSynthesisServiceVoice[]): Promise<void>;

    /**
     * Returns the voice that is used for speaking the utterances
     */
    getVoice(): SpeechSynthesisServiceVoice;
}
You must implement or extend the SpeechSynthesisServiceVoice interface for the voices used in the speech synthesis service:
/**
 * Represents a voice that the SpeechSynthesisService supports. Every SpeechSynthesisServiceVoice has
 * its own relative speech service including information about language, name and optionally more.
 */
interface SpeechSynthesisServiceVoice {
    /**
     * Returns a BCP 47 language tag indicating the language of the voice
     */
    readonly lang: string;

    /**
     * Returns a human-readable name that represents the voice
     */
    readonly name: string;

    /**
     * Pitch of the voice, can range between 0 and 2, default is 1
     * Optional
     */
    pitch?: number;

    /**
     * Speed at which the utterance is spoken at, can range between 0.1 and 10, default is 1
     * Optional
     */
    rate?: number;

    /**
     * Volume at which the utterance is spoken at, can range between 0 and 1, default is 1
     * Optional
     */
    volume?: number;
}
Once your TTS service is mapped to an object that implements the Speech Synthesis API, it can be passed to the SDK for injection of the TTS service. The service can be injected when this object is passed to the ttsService field during initialization, or it can be injected dynamically by passing the object to the setTTSService(service) method.

After the TTS service has been injected, the SDK handles the calls to the service methods for uttering the messages. However, you can call these methods directly, or you can use the TTS methods exposed by the SDK for any requirement. In headless mode, for example, you can call the Bots.speakTTS(message) method to pass a message as it is received from the skill. The SDK handles both the parsing of the utterable text from the message and the passing of this text to the TTS service so that it can be uttered.

Features

Absolute and Relative Timestamps

You can enable absolute or relative timestamps for chat messages. Absolute timestamps display the exact time for each message. Relative timestamps display only on the latest message and express the time in terms of the seconds, days, hours, months, or years ago relative to the previous message.
Description of relative_v_absolute_timestamps.png follows
Description of the illustration relative_v_absolute_timestamps.png

The precision afforded by absolute timestamps make them ideal for archival tasks, but within the limited context of a chat session, this precision detracts from the user experience because users must compare timestamps to find out the passage of time between messages. Relative timestamps allow users to track the conversation easily through terms like Just Now and A few moments ago that can be immediately understood. Relative timestamps improve the user experience in another way while also simplifying your development tasks: because relative timestamps mark the messages in terms of seconds, days, hours, months, or years ago, you don't need to convert them for timezones.

How Relative Timestamps Behave
As previously mentioned, a relative timestamp appears only on the latest message. Here's that behavior in a little more detail. When you configure the timestamp (timestampMode: 'relative' or timestampMode: 'default'), an absolute timestamp displays before the first message of the day as a header. This header displays when the conversation has not been cleared and older messages are still available in the history.

A relative timestamp then displays on each new message.
Description of most_recent_message_timestamp.png follows
Description of the illustration most_recent_message_timestamp.png
This timestamp is updated at following regular intervals (seconds, minutes, etc.) until a new message is received.
  • For first 10s
  • Between 10s-60s
  • Every minute between 1m-60m
  • Every hour between 1hr-24hr
  • Every day between 1d-30d
  • Every month between 1m-12m
  • Every year after first year
When a new message is loaded into the chat, the relative timestamp on the previous message is removed and a new timestamp appears on the new message displaying the time relative to the previous message. At that point, the relative timestamp updates until the next messages arrives.
Add a Relative Timestamp
To add a relative timestamp:
  • Enable timestamps – enableTimestamp: true

    Note:

    This feature flag has been deprecated in Release 22.02 in favor of timestampFormat: 'none'.
  • Enable relative timestamps – timestampMode: 'relative'
  • Optional steps:
    • Set the color for the relative timestamp – timestamp: '<a hexadecimal color value>'
    • For multi-lingual skills, localize the timestamp text using these keys:
      Key Default Text Description
      relTimeNow Now The initial timestamp, which displays for the first 9 seconds. This timestamp also displays when the conversation is reset.
      relTimeMoment a few moments ago Displays for 10 to 60 seconds.
      relTimeMin {0}min ago Updates every minute
      relTimeHr {0}hr ago Updates every hour
      relTimeDay {0}d ago Updates every day for the first month.
      relTimeMon {0}mth ago Updates every month for the first twelve months.
      relTimeYr {0}yr ago Updates every year.
    • Use the timeStampFormat settings to change the format of the absolute timestamp that displays before the first message of each day.
Autocomplete

Autocomplete minimizes user error by providing effective phrases that can be used as both direct input and as suggestions. To enable this feature, update the widget settings with enableAutocomplete: true and add a set of optimized user messages to the Create Intent page. Once enabled, a popup displays these messages after users enter three or more characters. The words in the suggested messages that match the user input are set off in bold. From there, users can enter their own input, or opt for one of the autocomplete messages instead.
Description of autocomplete_phrase_list.png follows
Description of the illustration autocomplete_phrase_list.png

When a digital assistant is associated with the Oracle Web channel, all of the sample utterances configured for any of the skills registered to that digital assistant can be used as autocomplete suggestions.

Automatic RTL Layout

When the host page's base direction is set with <html dir="rtl"> to accomodate right-to-left (RTL) languages, the chat widget automatically renders on the left side. Because the widget is left-aligned for RTL langauges, its icons and text elements are likewise repositioned. The icons are in the opposite positions from where they would be in a left-to-right (LTR) rendering. For example, the send, mic and attachment icons are flipped so that the mic and send icons occupy the left side of the input field (with the directional send icon pointing left) while the attachment icon is on the right side of the input field. The alignment of the text elements, such as inputPlaceholder and chatTitle, is based on whether the text language is LTR or RTL. For RTL languages, the inputPlaceHolder text and chatTitle appear on the right side of the input field.

Avatars
By default, none of the messages in the chat are accompanied with avatars. Using the following parameters, however, you can configure avatars for the skill, the user, and an agent avatar when the skill is integrated with live agent support.
  • avatarBot - The URL of the image source, or the source string of the SVG image that's displayed alongside the skill messages.
  • avatarUser - The URL of the image source, or the source string of the SVG image that's displayed alongside the user messages. Additionally, if the skill has a live agent integration, the SDK can be configured to show a different icon for agent messages.
  • avatarAgent - The URL of the image source, or the source string of the SVG image that's isplayed alongside the agent messages. If this value is not provided, but avatarBot is set, then the avatarBot icon is used instead.

Note:

These settings can only be passed in the initialization settings. They cannot be modified dynamically.
new WebSDK({
URI: '<URI>',
//...,
icons: {
    avatarBot: '../assets/images/avatar-bot.png',
    avatarUser: '../assets/images/avatar-user.jpg',
    avatarAgent: '<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M12 6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2m0 9c2.7 0 5.8 1.29 6 2v1H6v-.99c.2-.72 3.3-2.01 6-2.01m0-11C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"/></svg>'
}
})
Cross-Tab Conversation Synchronization

Users may need to open the website in multiple tabs for various reasons. With enableTabsSync: true, you can synchronize and continue the user's conversation from any tab, as long as the connections parameters (URI, channelId, and userId) are the same across all tabs. This feature ensures that users can view messages from the skill on any tab and respond from the same tab or any other one. Additionally, if the user clears the conversation history in one tab, then it's deleted from the other tabs as well. If the user updates the chat language on one tab, then the chat language gets synchronized to the other tabs.

There are some limitations:
  • A new tab synchronizes with existing tab(s) for the new messages between the user and the skill on opening. If you have not configured the SDK to display messages from the conversation history, the initial chat widget on the new tab will appear empty when opened.
  • If you have configured the SDK to display conversation history, the messages from the current chat on existing tabs will appear as part of conversation history on a new tab. Setting disablePastActions to all or postback, may prevent interaction with the actions for messages in the new tab.
  • The Safari browser currently does not support this feature.
Focus on the First Action in a Message

For users who prefer keyboard-based navigation (which includes power users), you can shift the focus from the user input field to the first (or left most), action button in a message. By default, the chat widget sets the focus back to the user input field with each new message (focusOnNewMessage: 'input'). This works well for dialog flows that expect a lot of textual input from the user, but when the dialog flow contains a number of messages with actions, users can only select these actions through mousing or reverse tab navigation. For this use case, you can change the focus to the first action button in the skill message as it's received by setting focusOnNewMessage: 'action'. If the message does not contain any actions, the focus is set to the user input field.

Default Client Responses

Use enableDefaultClientResponse: true to provide default client-side responses accompanied by a typing indicator when the skill response has been delayed, or when there's no skill response at all. If the user sends out the first message/query, but the skill does not respond with the number of seconds set by defaultGreetingTimeout, the skill can display a greeting message that's configured using the defaultGreetingMessage translation string. Next, the client checks again for the skill's response. The client displays the skill's response if it has been received, but if it hasn't, then the client displays a wait message (configured with the defaultWaitMessage translation string) at intervals set by the defaultWaitMessageInterval flag. When the wait for the skill response exceeds the threshold set by the typingIndicatorTimeout flag, the client displays a sorry response to the user and stops the typing indicator. You can configure the sorry response using the defaultSorryMessage translation string.

Delegation
The delegation feature sets a delegate to receive callbacks before certain events in the conversation. To set a delegate, pass the delegate parameter, or use the setDelegate method. The delegate object may optionally contain the beforeDisplay, beforeSend, beforePostbackSend, and beforeEndConversation delegate functions.
var delegate = {
    beforeDisplay: function(message) {
        return message;
    },
    beforeSend: function(message) {
        return message;
    },
    beforePostbackSend: function(postback) {
        return postback;
    },
    beforeEndConversation: function(message) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(message);
            }, 2000);
        });
    }
}

Bots.setDelegate(delegate);
beforeDisplay

The beforeDisplay delegate allows a skill's message to be modified before it is displayed in the conversation. The message returned by the delegate is used as the display message. If it returns a falsy value, like null, undefined, or false, then no message is sent. Use the beforeDisplay delegate to selectively apply the in-widget WebView linking behavior.

beforeSend

The beforeSend delegate allows a user message to be modified before it is sent to the Oracle Chat Server. The message returned by the delegate is sent to the skill. If it returns a falsy value, like null, undefined, or false, then no message is sent.

beforePostbackSend

The beforePostbackSend delegate is similar to beforeSend, just applied to postback messages from the user. The postback returned by the delegate is sent to the skill. If it returns a falsy value, like null, undefined, or false, then no message is sent.

beforeEndConversation
The beforeEndConversation delegate allows an interception at the end of a conversation flow if some pre-exit activity must be performed. The function receives the exit message as its input parameter and it must return a Promise. If this Promise resolves with the exit message, then the CloseSession exit message is sent to the chat server. Otherwise, the exit message is prevented from being sent.
...

 beforeEndConversation: function(message) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(message);
            }, 2000);
        });
    }
Draggable Launch Button

Sometimes, particularly on mobile devices where the screen size is limited, the chat widget's launch button can block content in a web page. By setting enableDraggableButton: true, you can enable users to drag the launch button out of the way when it's blocking the view. This flag only affects the location of the launch button, not the chat widget: the widget will still open from its original location.

Dynamic Typing Indicator

A typing indicator tells users to hold off on sending a message because the skill is preparing a response. By default, skills display the typing indicator only for their first response when you initialize the SDK with showTypingIndicator: 'true'. For an optimal user experience, the skill should have a dynamic typing indicator, which is a typing indicator that displays after each skill response. Besides making users aware the skill has not timed out but is still actively working on a response, displaying the typing indicator after each skill response ensures that users won’t attempt to send messages prematurely, as might be the case when the keepTurn property directs the skill to reply with a series of separate messages that don’t allow user to interject a response.

To enable a typing indicator after each skill response:
  • Initialize the SDK with showTypingIndicator set to true.
  • Call the showTypingIndicator API
The showTypingIndicator can only enable the display of the dynamic typing indicator when:
  • The widget is connected to the Oracle Chat Server. The dynamic typing indicator will not appear when the connection is closed.
  • The SDK has been initialized with showTypingIndicator set to true.

    Note:

    This API cannot work when the SDK is used in headless mode.
The typing indicator displays for the duration set by the optional property, typingIndicatorTimeout, that has default setting of 20 seconds. If the API is called while a typing indicator is already displaying, then the timer is reset and the indicator is hidden.

The typing indicator disappears as soon as the user receives the skill’s messages. The typing indicator moves to the bottom of the chat window if a user enters a message, or uploads an attachment, or sends a location, while it’s displaying.

Control Embedded Link Behavior

In addition to opening links within a new window by setting openLinksInNewWindow: true, or the default behavior of opening links in a new tab when this option is set to false, you can also open links which overlay the widget’s web page. To enable this and other overrides to the linking behavior, initialize the SDK with
linkHandler: {
    target: '_blank',   // open link in a new page
    onclick: (event) => { // some operation }
}
Use linkHander to:
  • Control iframe navigation so that it can continue to overlay the page without having to include the widget in every page, reopening it upon navigation, and maintaining the same user ID.

  • Open some links in a new window, while opening others in the same tab.
  • Performing an action when a link is clicked.
  • Preventing a link from opening.
  • Opening a link in a webview.
To override the linking behavior set by the openLinksInNewWindow setting, you must define one, or both, of these attributes:
  • target – Names the browsing location context, such as tab, a window, or an iFrame. Define the iFrame location as the target attribute of an anchor element (<a>). You can define the target’s _self, _blank, _parent and _top attributes.
  • onclick - Accepts a callback function that is called when the link is clicked. The callback is passed the MouseEvent that's received on the click, and can be used to perform an action, or even prevent the link from opening.
Embedded Mode
In addition to the other settings that customize the look and feel of the widget that runs the chat, you can embed the widget itself in the Web page by:
  • Adding embedded: true.
  • Defining the targetElement property with the ID of the DOM element (an HTML component) that's used as the widget's container (such as 'container-div' in the following snippet).
<head>
    <meta charset="utf-8">
    <title>Oracle Web SDK Sample</title>
    <script src="scripts/settings.js"></script>
     <script>
        var chatWidgetSettings = {
            URI: YOUR_URI,
            channelId: YOUR_CHANNELID,
            embedded: true,
            targetElement: 'container-div'
...

    </script> 
</head>
<body>
    <h3 align="center">The Widget Is Embedded Here!</h3>
</body>
           <div id="container-div" 
                style="height: 600px; width: 380px; padding: 0; text-align: initial">
            </div>

Note:

The widget occupies the full width and height of the container. If it can't be accommodated by the container, then the widget won't display in the page.
End the Conversation Session

Starting with Version 21.12, the SDK adds a close button to the chat widget header by default (enableEndConversation: true) that enables users to end the current session.
This is an image of the close button in the chat widget header.

After users click this button, the SDK presents them with a confirmation prompt whose text ("Are you sure you want to end the conversation? This will also clear your conversation history.") you can customize with the endConversationConfirmMessage and endConversationDescription keys. When a user dismisses the prompt by clicking Yes, the SDK sends the skill an event message that marks the current conversation session as ended. The instance then disconnects from the skill, collapses the chat widget, and erases the current user's conversation history. It also raises a chatend event that you can register for:
Bots.on('chatend', function() {
    console.log('The conversation is ended.');
});
Opening the chat widget afterward starts a new conversation session.

Note:

You can also end a session by calling the Bots.endChat() method (described in the reference that accompanies the Oracle Web SDK that's available from the Downloads page). Calling this method may be useful when the SDK is initialized in headless mode.
Headless SDK
Similar to headless browsers, the SDK can also be used without its UI. The SDK maintains the connection to the server and provides APIs to send messages, receive messages, and get updates on the network status. You can use these APIs to interact with the SDK and to update the UI. To enable this feature, pass enableHeadless: true in the initial settings. The communication can be implemented as follows:
  • Sending messages - Calls Bots.sendMessage(message) to pass any payload to server.
  • Receiving messages - Responses can be listened for using Bots.on('message:received', <messageReceivedCallbackFunction>).
  • Get connection status update - Listens for updates on the status of the connection using Bots.on('networkstatuschange', <networkStatusCallbackFunction>). The callback has a status parameter that is updated with values from 0 to 3, each of which maps to WebSocket states:
    • 0 : WebSocket.CONNECTING
    • 1: WebSocket.OPEN
    • 2: WebSocket.CLOSING
    • 3: WebSocket.CLOSED
    • Return suggestions for a query – Returns a Promise that resolves to the suggestions for the given query string. The Promise is rejected if it takes too long (which is approximately 10 seconds) to fetch the suggestion.
      Bots.getSuggestions(utterance)
          .then((suggestions) => {
              const suggestionString = suggestions.toString();
              console.log('The suggestions are: ', suggestionString);
          })
          .catch((reason) => {
              console.log('Suggestion request failed', reason);
          });

    Note:

    To use this API, you need to enable autocomplete (
    enableAutocomplete: true
    ) and configure autocomplete for the intents.
Multi-Lingual Chat

The Web SDK's native language support enables the chat widget to detect a user's language or allow users to select the conversation language. Users can switch between languages, but only in between conversations, not during a conversation because the conversation gets reset whenever a user selects a new language.

Enable the Language Menu
You can enable a menu that allows users to select a preferred language from a dropdown menu by defining the multiLangChat property with an object containing the supportedLangs array, which is comprised of language tags (lang) and optional display labels (label). Outside of this array, you can optionally set the default language with the primary key (primary: 'en' in the following snippet).
multiLangChat: {
    supportedLangs: [{
        lang: 'en'
    }, {
        lang: 'es',
        label: 'Español'
    }, {
        lang: 'fr',
        label: 'Français'
    }, {
        lang: 'hi',
        label: 'हिंदी'
    }],
    primary: 'en'
}
The chat widget displays the passed-in supported languages in a dropdown menu that's located in the header. In addition to the available languages, the menu also includes a Detect Language option. When a user selects a language from this menu, the current conversation is reset, and a new conversation is started with the selected language. The language selected by the user persists across sessions in the same browser, so the user's previous language is automatically selected when the user revisits the skill through the page containing the chat widget.

Tip:

You can add an event listener for the chatlanguagechange event (described in the reference that accompanies the Oracle Web SDK that's available from the Downloads page), which is triggered when a chat language has been selected from the dropdown menu or has been changed.
Bots.on('chatlanguagechange', function(language) {
    console.log('The selected chat language is', language);
});
Here are some things to keep in mind when configuring language dropdown menu:
  • You need to define a minimum of two languages to enable the dropdown menu to display.
  • The label key is optional for the natively supported languages: fr displays as French in the menu, es displays as Spanish, and so on.
  • Labels for the languages can be set dynamically by passing the labels with the i18n setting. You can set the label for any language by passing it to its language_<languageTag> key. This pattern allows setting labels for any language, supported or unsupported, and also allows translations of the label itself in different locales. For example:
    i18n: {
        en: {
            langauge_de: 'German',
            language_en: 'English',
            language_sw: 'Swahili',
            language_tr: 'Turkish'
        },
        de: {
            langauge_de: 'Deutsche',
            language_en: 'Englisch',
            language_sw: 'Swahili',
            language_tr: 'Türkisch'
        }
    }
    If the i18n property includes translation strings for the selected language, then the text for fields like the input placeholder, the chat title, the hover text for buttons, and the tooltip titles automatically switch to the selected language. The field text can only be switched to a different language when there are translation strings for the selected language. If no such strings exist, then the language for the field text remains unchanged.
  • The widget automatically detects the language in the user profile and activates the Detect Language option if you omit the primary key.
  • While label is optional, if you've added a language that's not one of the natively supported languages, then you should add a label to identify the tag, especially when there is no i18n string for the language. For example, if you don't define label: 'हिंदी', for the lang: hi, then the dropdown displays hi instead, contributing to a suboptimal user experience.
Disable Language Menu

Starting with Version 21.12, you can also configure and update the chat language without also having to configure the language selection dropdown menu by passing multiLangChat.primary in the initial configuration without also passing a multiLangChat.supportedLangs array. The value passed in the primary variable is set as the chat language for the conversation.

Language Detection
In addition to the passed-in languages, the chat widget displays a Detect Language option in the dropdown. Selecting this option tells the skill to automatically detect the conversation language from the user's message and, when possible, to respond in the same language.

Note:

If you omit the primary key, the widget automatically detects the language in the user profile and activates the Detect Language option in the menu.

You can dynamically update the selected language by calling the setPrimaryChatLanguage(lang) API. If the passed lang matches one of the supported languages, then that language is selected. When no match can be found, Detect Language is activated. You can also activate the Detected Language option by calling setPrimaryChatLanguage('und') API, where 'und' indicates undetermined or by passing either multiLangChat: {primary: null} or multiLangChat: {primary: 'und'}.

You can update the chat language dynamically using the setPrimaryChatLanguage(lang) API even when the dropdown menu has not been configured. For example:
Bots.setPrimaryChatLanguage('fr')
You can dynamically update the language irrespective of whether the chat language is initially configured or not.

Note:

Response narration and voice recognition, when configured, are available when users select a supported language. They are not available when the Detect Language option is set. Selecting a language that is not supported by voice recognition disables the recognition functionality until a supported language has been selected.
Multi-Lingual Chat Quick Reference
To do this... ...Do this
Display the language selection dropdown to end users. Pass multiLangChat.supportedLangs.
Set the chat language without displaying the language selection dropdown menu to end users. Pass multiLangChat.primary.
Set a default language. Pass multiLangChat.primary with multiLangChat.supportedLangs. The primary value must be one of the supported languages included the array.
Enable language detection. Pass primary: null or primary: 'und' with multiLangChat.
Dynamically update the chat language. Call the setPrimaryChatLanguage(lang) API.
In-Widget Webview

You can configure the link behavior in chat messages to allow users to access web pages from within the chat widget. Instead of having to switch from the conversation to view a page in a tab or separate browser window, a user can remain in the chat because the chat widget opens the link within a Webview.

Configure the Linking Behavior to the Webview
You can apply the webview to all links, or in a more typical use case, to just select links. You can also customize the webview itself.
  • To open all links in the webview, pass linkHandler: { target: 'oda-chat-webview' } in the settings. This sets the target of all links to oda-chat-webview, which is the name of the iframe in the webview.
  • To open only certain links in the webview while ensuring that other links open normally in other tabs or windows, use the beforeDisplay delegate. To open a specific message URL action in the webview, replace the action.type field’s 'url' value with 'webview'. When the action type is 'webview' in the beforeDisplay function, the action button will open the link in the webview when clicked.
Open Links from Within the Webview

Links that are embedded within a page that displays within the WebView can only be opened within the WebView when they are converted into an anchor element (<a>), with a target attribute defined as target="oda-chat-webview".

Customize the WebView
You can can customize the WebView with the webViewConfig setting which accepts an object. For example:
{ referrerPolicy: 'no-referrer-when-downgrade', closeButtonType: 'icon', size: 'tall' 
The fields within this object are optional.

Note:

The configuration can also by updated dynamically by passing a webViewConfig object in the setWebViewConfig method. Every property in the object is optional.
Field Value Description
accessibilityTitle String The name of the WebView frame element for Web Accessibility.
closeButtonIcon String The image URL/SVG string that is used to display the close button icon.
closeButtonLabel String Text label/tooltip title for the close button.
closeButtonType
  • 'icon'
  • 'label'
  • 'iconWithLabel'
Sets how the close button is displayed in the WebView.
referrerPolicy ReferrerPolicy Indicates which referrer to send when fetching the frame's resource. The referrerPolicy policy value must be a valid directive. The default policy applied is 'no-referrer-when-downgrade'.
sandbox A String array An array of of valid restriction strings that allows for the exclusion of certain actions inside the frame. The restrictions that can be passed to this field are included in the description of the sandbox attribute in MDN Web Docs.
size
  • 'tall'
  • 'full'
The height of the WebView compared to the height of the chat widget. When set to 'tall', it is set as 80% of the widget's height, when set to 'full' it equals the widget's height.
title String The title that's displayed in the header of the WebView container.
Not all links may be able to open inside the WebView. Here are some reasons why:
  • Pages which provide response header X-frame-options: deny or X-frame-options: sameorigin may not open in the WebView due to server-side restrictions that prevent the page from being opened inside iframes. In such cases, the WebView presents the link back to the user so that they can open it in a new window or tab.
  • Due to server-side restrictions, authorization pages like IDCS, Google Login, and FaceBook Login cannot opened inside the WebViews, as authorization pages always return X-frame-options: deny to prevent a clickjacking attack.
  • External links, which can't open correctly within the WebView. Only links embedded in the conversation messages can be opened in the WebView.

    Note:

    Because external messages are incompatible with the WebView, do not target any external link to be opened in the WebView.
When a link can't open in the WebView, the widget presents the user with some informational text and a link to the WebView, which opens the page in a new tab when clicked. You can customize this text using the webViewErrorInfoText i18n translation string:
settings = {
    URI: 'instance',
    //...,
    i18n: {
        en: {
            webViewErrorInfoText: 'This link can not be opened here. You can open it in a new page by clicking {0}here{/0}.'
        }
    }
}
Long Polling

The SDK uses WebSockets to connect to the server and converse with skills. If for some reason the WebSocket is disabled over the network, traditional HTTP calls can be used to chat with the skill. This feature is known as long polling because the SDK must continuously call, or poll, the server to fetch the latest messages from skill. This fallback feature can be enabled by passing enableLongPolling: true in the initial settings.

Response Narration
The SDK enables narration of the chat server's responses by leveraging the device’s speech synthesis APIs. You can define the voice that reads the skill or digital assistant messages aloud by setting enableBotAudioResponse to true and then by defining the skillVoices array, which prioritizes the voice preferences. The objects in this array use a lang field and an optional name field to describe the voices that the device can use for spoken content. The following example illustrates a skillVoices array for iPhone voices.
const settings = {
    ...,
    enableBotAudioResponse: true,
    skillVoices: [{
        lang: 'en-US',
        name: 'Samantha'
    }, {
        lang: 'en-US',
        name: 'Alex'
    }, {
        lang: 'en-UK'
    }]
}

The SDK searches for these voices in the order that they are passed. It then selects the first complete match to be the voice of the narrator. If the SDK can't find an exact match, then it selects the first match based on the lang value alone. If there's no matching lang value, then the SDK uses the device’s default language.

Voice Recognition

Setting enableSpeech: true enables the microphone button to display in place of the send button whenever the user input field is empty.

Your skill can also utilize voice recognition with the startVoiceRecording(onSpeechRecognition, onSpeechNetworkChange) method to start recording and the stopVoiceRecording method to stop recording. (These methods are described in the User's Guide that's included with the SDK.)

Using the enableSpeechAutoSend flag, you can configure whether or not to send the text that’s recognized from the user’s voice directly to the chat server with no manual input from the user. By setting this property to true (the default), you allow the user’s speech response to be automatically sent to the chat server. By setting it to false, you allow the user to edit the message before it's sent to the chat server, or delete it.

Voice Visualizer

The chat widget displays a voice visualizer when users click the voice icon This is an image of the Voice Visualizer's Speak icon., the chat widget displays a voice visualizer. It's an indicator of whether the audio level is sufficiently high enough for the SDK to capture the user’s voice. The user’s message, as it is recognized as text, displays below the visualizer.

Note:

Voice mode is indicated when the keyboard This is an image of the keyboard icon. icon appears.
Description of voice_visualizer.png follows
Description of the illustration voice_visualizer.png
Because of the default setting for enableSpeachAutosend is true (enableSpeechAutoSend: true), messages are sent automatically after they're recognized. Setting enableSpeechAutoSend: false switches the input mode to text after the voice message is recognized, allowing users to edit or complete their messages using text before sending them manually. Alternatively, users can complete their message with voice through a subsequent click of the voice icon before sending them manually.

Note:

The voice visualizer is created using AnalyserNode. You can implement the voice visualizer in headless mode using the startVoiceRecording method. Refer to the SDK to find out more about AnalyserNode and frequency levels.

Message Model

To use features like headless mode and delegate, you need to understand both user and skill messages. Everything that's received or sent from the Oracle Chat Server is represented as a message, one that's sent from the user to the skill, or from the skill to the user.

Base Types
These are the base types used in all messages sent from the user to the skill and vice versa. They are the building blocks of all messages.
Attachment
Represents an attachment that's sent by the user.
Name Description Type Required?
title The attachment title string No
type The attachment type string (valid values: audio, file, image, video) Yes
url The download URL for the attachment string Yes
For example:
{
    "title": "Oracle Open World Promotion",
    "type": "image",
    "url": "https://www.oracle.com/us/assets/hp07-oow17-promo-02-3737849.jpg"
}
Location
Represents a location object.
Name Description Type Required?
title The location title string No
url The URL for displaying the location on a map string No
latitude The GPS coordinate's longitude value double Yes
longitude The GPS coordinate's latitude value double Yes
For example:
{
    "title": "Oracle Headquarters",
    "url": "https://www.google.com.au/maps/place/37°31'47.3%22N+122°15'57.6%22W",
    "longitude": -122.265987,
    "latitude": 37.529818
}
Action
An action represents something that the user can select.
Name Description Type Required?
type The action type string Yes
label The descriptive label text for the action. string At least one of label or imageUrl will be present.
imageUrl The image for the action string At least one of label or imageUrl will be present.
PostbackAction
Sends a predefined postback back to the skill when the user selects an action.
Name Description Type Required?
type The action type "postback" Yes
postback The postback that's returned when the user selects an action. A string or JSON object Yes
For example:
{
    "type": "postback",
    "label": "Large Pizza",
    "imageUrl": "https://example.com/images/gallery/locations/11.jpg",
    "postback": {
        "state": "askSize",
        "action": "getCrust"
    }
}
CallAction
Requests the client to call a specified phone number on behalf of the user.
Name Description Type Required?
type The action type "call" Yes
phoneNumber The phone number to call string Yes
For example:
{
    "type": "call",
    "label": "Call Support",
    "imageUrl": "http://example.com.ar/files/2016/05/cuidado.jpg",
    "phoneNumber": "18005555555"
}
urlAction

Requests the client to open a website in a new tab or in an in-app browser.

Name Description Type Required?
type The action type "call" Yes
url The URL of the website that's displayed. string Yes
ShareAction
Requests the client to open a sharing dialog for the user.
Name Description Type Required?
type The action type "share" Yes
LocationAction
Requests the client to ask for the user's location.
Name Description Type Required?
type The action type "location" Yes
For example:
{
    "type": "location",
    "label": "Share location",
    "imageUrl": "http://images.example.com/location-clipart-location-pin-clipart-1.jpg"
}
Conversation Message
All of the messages that are part of a conversation have the following structure:
Name Description Type Required?
messagePayload The message payload Message Yes
userId The user ID string Yes
For example:
{
    "messagePayload": {
        "text": "show menu",
        "type": "text"
    },
    "userId": "guest"
}
Message
Message is an abstract base type for all other messages. All messages extend it to provide some information.
Name Description Type Required?
type The message type string Yes
User Message

Represents a message sent from the user to the skill.

User Text Message
The simple text message that's sent to the server.
Name Description Type Required?
type The message type "text" Yes
text The message text string Yes
For example:
{
    "messagePayload": {
        "text": "Order Pizza",
        "type": "text"
    },
    "userId": "guest"
}
User Postback Message
The postback response message that's sent to the server.
Name Description Type Required?
type The message type "postback" Yes
text The postback text string No
postback The postback of the selected action A string or JSON object Yes
For example:
{
    "messagePayload": {
        "postback": {
            "variables": {
                "pizza": "Small"
            },
            "system.botId": "69BBBBB-35BB-4BB-82BB-BBBB88B21",
            "system.state": "orderPizza"
        },
        "text": "Small",
        "type": "postback"
    },
    "userId": "guest"
}
User Attachment Message
The attachment response message that's sent to the server.
Name Description Type Required?
type The message type "attachment" Yes
attachment The attachment metadata Attachment Yes
For example:
{
    "messagePayload": {
        "attachment": {
            "type": "image",
            "url": "http://oda-instance.com/attachment/v1/attachments/d43fd051-02cf-4c62-a422-313979eb9d55"
        },
        "type": "attachment"
    },
    "userId": "guest"
}
User Location Message
The location response message that's sent to the server.
Name Description Type Required?
type The message type "location" Yes
location The user location information Location Yes
For example:
{
    "messagePayload": {
        "location": {
            "latitude": 45.9285271,
            "longitude": 132.6101925
        },
        "type": "location"
    },
    "userId": "guest"
}
Skill Message

Represents the message sent from the skill to the user.

Bot Text Message
Represents a text message.
Name Description Type Required?
type The message type "text" Yes
text The message text string Yes
actions An array of actions related to the text. array No
globalActions An array of global actions related to the text. array No
For example:
{
    "messagePayload": {
        "type": "text",
        "text": "What do you want to do?",
        "actions": [
            {
                "type": "postback",
                "label": "Order Pizza",
                "postback": {
                    "state": "askAction",
                    "action": "orderPizza"
                }
            },
            {
                "type": "postback",
                "label": "Cancel A Previous Order",
                "postback": {
                    "state": "askAction",
                    "action": "cancelOrder"
                }
            }
        ]
    },
    "userId": "guest"
}
Skill Location Message
Represents a location message.
Name Description Type Required?
type The message type "location" Yes
location The location Location Yes
actions An array of actions related to the text. array No
globalActions An array of global actions related to the text. array No
Skill Attachment Message
Represents an attachment message.
Name Description Type Required?
type The message type "attachment" Yes
attachment The attachment sent Attachment Yes
actions An array of actions related to the text. array No
globalActions An array of global actions related to the text. array No

Note:

File uploads from the host site may fail and throw a console error similar to the following:
https://<oda-instance>/chat/v1/attachments from origin <client site> has been blocked by CORS policy: No Access-Control-Allow-Origin header is present on the requested resource
This is because the host site's CORS (Cross-Origin Resource Sharing) settings, which block all cross-origin HTTP requests, may also block upload requests from the client instance to the Oracle Digital Assistant attachment server. If you run into this problem, update the host site's security policy to allow the domain for the Digital Assistant instance. Because the conversation uses WebSocket connections, CORS does not impact the conversation.
Passing File Names
Use the following headers to retrieve the name of a file (including video, audio, or image files) that's uploaded to the ODA file server:
  • x-oda-meta-file-name
  • x-oda-meta-file-type
You can return these headers with GET or HEAD requests. Use HEAD if a custom component doesn't need the file's contents.
Feedback Messages
This represents a feedback rating component, which takes a user’s feedback using a rating gauge (typically a star rating system). Its payload is similar to a text message, but it has an additional channelExtensions object field that is set as { "displayType": "stars" }.
Name Description Type Required?
type The message type "text" Yes
text The message text string Yes
actions An array of actions representing the postback information for each rating. array<action> Yes
globalActions An array of global actions related to the text array<action> No
channelExtensions An object depicting specific extension to the payload. { “displayType”: “stars” } Yes
For example:
{
    "messagePayload":{
        "text":"How would you like to rate us?",
        "type":"text",
        "actions":[
            {
                "postback":{
                    "variables":{
                        "rating":"1"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"1",
                    "system.state":"giveFeedback"
                },
                "label":"1",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"2"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"2",
                    "system.state":"giveFeedback"
                },
                "label":"2",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"3"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"3",
                    "system.state":"giveFeedback"
                },
                "label":"3",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"4"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"4",
                    "system.state":"giveFeedback"
                },
                "label":"4",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"5"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"5",
                    "system.state":"giveFeedback"
                },
                "label":"5",
                "type":"postback"
            }
        ],
        "channelExtensions":{
            "displayType":"stars"
        }
    },
    "source":"BOT",
    "userId":"<userID>"
}
Skill Card Message
Represents a set of choices that are displayed for the user, either horizontally as carousels or vertically as lists.
Name Description Type Required?
type The message type "card" Yes
layout Whether to display the messages horizontally or vertically. string (values: horizontal, vertical) Yes
cards An array of cards to be rendered. array Yes
headerText The cards' header text string No
actions An array of actions related to the text. array No
globalActions An array of global actions related to the text. array No
Card
Represents a single card in the message payload.
Name Description Type Required?
title The title of the card, displayed as the first line on the card. string Yes
description The description of the card string No
imageUrl The URL of the image that is displayed. string No
url The website URL that's opened by a tap. string No
actions An array of actions related to the text array No
Here's an example:
{
    "messagePayload": {
        "type": "card",
        "layout": "horiztonal",
        "cards": [
            {
                "title": "Hawaiian Pizza",
                "description": "Ham and pineapple on thin crust",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Order Small",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "hawaiian",
                                "pizzaCrust": "thin",
                                "pizzaSize": "small"
                            }
                        }
                    },
                    {
                        "type": "postback",
                        "label": "Order Large",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "hawaiian",
                                "pizzaCrust": "thin",
                                "pizzaSize": "large"
                            }
                        }
                    }
                ]
            },
            {
                "title": "Cheese Pizza",
                "description": "Cheese pizza (i.e. pizza with NO toppings) on thick crust",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Order Small",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "cheese",
                                "pizzaCrust": "thick",
                                "pizzaSize": "small"
                            }
                        }
                    },
                    {
                        "type": "postback",
                        "label": "Order Large",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "cheese",
                                "pizzaCrust": "thick",
                                "pizzaSize": "large"
                            }
                        }
                    }
                ]
            }
        ],
        "globalActions": [
            {
                "type": "call",
                "label": "Call for Help",
                "phoneNumber": "123456789"
            }
        ]
    },
    "userId": "guest"
}
Skill Postback Message
Represents a postback.
Name Description Type Required?
type The message type "postback" Yes
text The message text string No
postback The postback A string or a JSON object Yes
actions An array of actions that are related to the text array No
globalActions An array of global actions related to the text array No
Skill Form Message
Represents a message that returns the results of a query in a form that's read only. The message consists of an array of form results. Each form result contains a fields array with key-value pairs that represent a field.

Note:

This message type is used for Conversation to SQL (C2SQL), which is a limited availability feature.
Name Description Type Required?
type The message type "form" Yes
forms An array of form results. Each result contains a fields array that represents the form fields. Array<Row> Yes
formColumns A number suggesting the number of columns in which the fields of the form should be grouped. 1, 2 Yes
paginationInfo The paging information for the results in the form PaginationInfo No
actions An array of actions related to the form Array<Action> No
globalActions An array of global actions Array<Action> No
{
    "type":"form",
    "headerText":"A-Team",
    "forms":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/aaron-adams-4862752"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Bobbrown"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Bob is a member of the cloud architects team which is specialized in enterprise mobility and cloud development. Bob has been directly involved with Oracle middleware since 2005 during which he held different roles in managing highly specialized teams."
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Charlie-chase-97a418"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Charlie is a member of the enterprise mobility team. Charlie has 20+ years experience with custom development. Charlie is an expert on mobile cloud services and development tools. He is the creator of productivity tools. His latest passion is building chatbots with a minimum amount of custom code."
                }
            ]
        }
    ],
    "formColumns":2,
    "paginationInfo":{
        "currentRangeSize":3,
        "rangeStart":0,
        "nextRangeSize":2,
        "hasPrevious":false,
        "hasNext":true,
        "totalCount":5,
        "rangeSize":3,
        "status":"Showing 1-3 of 5 items"
    },
    "globalActions":[
        {
            "postback":{
                "variables":{},
                "action":"system.showMore"
            },
            "label":"Show More",
            "type":"postback"
        }
    ]
}
Skill Table Message
Represents a message that returns the results of a query in table form The message consists of an array of headings and an array of rows. The rows themselves contain a fields array that represents individual cells.

Note:

This message type is used for Conversation to SQL (C2SQL), which is a limited availability feature.
Name Description Type Required?
type The message type "table" Yes
headings An array of table headings Array<Heading> Yes
rows An array of table rows. Each row contains a fields array that represents the table cells. Array<Row> Yes
paginationInfo The paging information for the results in the table PaginationInfo No
actions An array of actions related to the table Array<Action> No
globalActions An array of global actions Array<Action> No
{
    "type":"table",
    "headerText":"A-Team",
    "headings":[
        {
            "width":20,
            "label":"First Name",
            "alignment":"left"
        },
        {
            "width":20,
            "label":"Last Name",
            "alignment":"left"
        },
        {
            "width":35,
            "label":"Title",
            "alignment":"left"
        },
        {
            "width":25,
            "label":"Phone",
            "alignment":"right"
        }
    ],
    "rows":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"David"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Davidson"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Machine Learning Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Eric"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Eastman Junior"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Docker Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        }
    ],
    "paginationInfo":{
        "currentRangeSize":5,
        "rangeStart":0,
        "nextRangeSize":-3,
        "hasPrevious":false,
        "hasNext":false,
        "totalCount":5,
        "rangeSize":8,
        "status":"Showing 1-5 of 5 items"
    }
}
Skill Table-Form Message
This message combines the Table and Form message types. It represents a message that returns the results of a query in the form of a table. Each each row of the table has a read-only form in addition to the row information.

Note:

This message type is used for Conversation to SQL (C2SQL), which is a limited availability feature.
Name Description Type Required?
type The message type "tableForm" Yes
headings An array of table headings Array<Heading> Yes
rows An array of table rows. Each row contains an array of fields that represent the table cells. Array<Row> Yes
forms An array of form results that correspond to each table row. Each form contains a fields array that represents the form fields. Array<Form> Yes
formColumns The number suggesting the number of columns in which the fields of the form should be grouped. 1, 2 Yes
paginationInfo An array of global actions related to the text Array<Action> No
actions An array of actions related to the table form Array<Action> No
globalActions An array of global actions Array<Action> No
{
    "type":"tableForm",
    "headerText":"A-Team",
    "headings":[
        {
            "width":47,
            "label":"First Name",
            "alignment":"left"
        },
        {
            "width":47,
            "label":"Last Name",
            "alignment":"left"
        }
    ],
    "rows":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                }
            ]
        }
    ],
    "forms":[
        {
            "title":"View details Aaron Adams",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Aaron-adams-4862572"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left"
                }
            ]
        },
        {
            "title":"View details Bob Brown",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Bobbrown"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Bob is a member of the cloud architects team which is specialized in enterprise mobility and cloud development. Bob has been directly involved with Oracle middleware since 2005 during which he held different roles in managing highly specialized teams."
                }
            ]
        },
        {
            "title":"View details Charlie Chase",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder Fanatic"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Charlie-chase-97a418"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Charlie is a member of the enterprise mobility team. Charlie has 20+ years experience with custom development. Charlie is an expert on mobile cloud services and development tools. He is the creator of productivity tools. His latest passion is building chatbots with a minimum amount of custom code."
                }
            ]
        }
    ],
    "formColumns":2,
    "paginationInfo":{
        "currentRangeSize":3,
        "rangeStart":0,
        "nextRangeSize":2,
        "hasPrevious":false,
        "hasNext":true,
        "totalCount":5,
        "rangeSize":3,
        "status":"Showing 1-3 of 5 items"
    },
    "actions":[
        {
            "postback":{
                "variables":{

                },
                "action":"system.showMore"
            },
            "label":"Show More",
            "type":"postback"
        }
    ],
    "footerText":"Tap on a row to see personal details"
}
Skill Raw Message
Used when a component creates the channel-specific payload itself.
Name Description Type Required?
type The message type "raw" Yes
payload The channel-specific payload A JSON object Yes

Embed Chat in Visual Builder Apps

Using the <oj-oda-chat> Web Component, you can embed chat in Oracle Visual Builder apps. This component, which is available from the Component Exchange that's associated with your instance, provides the following:
  • Support for System.CommonResponse component-based conversations
  • Speech integration
  • Attachment sharing
  • Connection to authentication-enabled channels
  • Audio response for skill messages
  • Delegate
  • Theming
Refer to the Oracle Visual Builder Documentation for information on adding components from the Component Exchange.

Tutorial: Access a Skill from Your Website

You can get a hands-on look at setting up the Oracle Web Channel, embedding the widget in a web page, customizing the widget's look and feel, and enabling autocomplete through this tutorial: Access a Skill from Your Website.

Oracle Web Channel Extensions

For Oracle Web channels, you can extend the functionality of System.CommonResponse components with capabilities that are specific to the JavaScript SDK.

You access the extensions by using the channelCustomProperties element in the System.CommonResponse component and setting the appropriate properties. The code has the following format:

...
            channelCustomProperties:
            - channel: "websdk"
              properties:
                PROPERTY_NAME: "PROPERTY_VALUE"
...

Here are the available custom properties for Oracle Web channels:

Name Allowed Values Applies To... Description
mediaType
  • A valid media type
  • Response items with the following attributes:
    • type: "attachment"
    • attachmentType: "file"or attachmentType: "image"
  • Cards with imageUrl specified
The media type of the attachment. For example, image/jpeg. If not specified, the media type will be resolved from the attachment URL.

For more general information on channelCustomProperties, see Channel-Specific Extensions.