Developers

Subscriptions

Overview

Subscribe callbacks to specific actions. The purpose of subscriptions is to define the Chat behaviour, by dispatching actions when a particular action occurs or by modifying the data that is sent within the action.

Every subscription has the following argument as an entry parameter: callback. The function of a callback is to act as a middleware for the action subscribed.

The subscriptions are available inside the subscription property of the Chat instance. chatbot.subscriptions.onSendMessage

Note

To see a code sample that uses the Chat app variable and a subscription, see the Promotional Message adapter page and click on "Click here to see the adapter code" under Adapter code and public Github repository.

Glossary:

  • []: Optional parameter.
  • example1|example2: The parameter must have one of this values.
  • example String: The parameter is String type.

How it works

Subscription to actions

During the User-Chat app interaction, different actions happen. When a subscribed action occurs, the Chat instance triggers the callback. The subscription gives information about the action it triggers and gives data related to this action.

Subscriptions execute custom js functions, so you can modify the data that this action created, and delay or cancel any further function subscribed to this action.

The actions subscription only accepts one parameter, which must be a function (the callback). This function is executed when the action is triggered. The callback receives parameters in the form of the data generated in the action (as described in the Actions section).

Middleware composition

To allow for the full customization of the Chat SDK, it must be possible to modify or remove the Inbenta Chat app behavior. A callback subscribed to an action acts as a middleware: It is executed between the call for an action and the function that performs the action.

Inbenta allows you to perform several subscriptions on the same action. This builds a middleware chain. The chain follows a FIFO (First In, First Out) paradigm, which means the first subscribed action is the first that is executed.

Each callback is responsible for calling the next callback with the action data. If only one callback has been subscribed, the next callback executes the original action.

Example In the following example, we add the string "Custom Chat message" to any answer the Chat app displays, unless the message displayed is a "no answer" response. To do this, we execute a return and we do not send the next() premise. In any other case, we will modify the displayed message and execute the next(), which allow the execution of the displayChatbotMessage action.

chatbot.subscriptions.onDisplayChatbotMessage(function(messageData, next) {
    // BEFORE DisplayChatbotMessage action execution
    if (messageData.message == "Sorry, we couldn't find any answers to your question."){
      console.log("hidden message")
      return
    } else {
      messageData.message = 'Custom chatbot message! ' + messageData.message;
      return next(messageData);
    }
});

See below the result of the subscription: The first and third message were modified, and the second message was not displayed, because the message matched the string. Finally, the displayChatbotMessage action was not executed since there was a return and the next() callback was not called.

subscription_example

Available subscriptions

Here is the list of all the actions available to you grouped by use:

Defining the Chat app windows and their elements

Manipulating the displayed Chatbot message

Handling user actions with the Chat app

Interaction with the Chat app state

Escalating to Assist

Others

onCloseSideWindow

The callback passed on this event listener is executed every time the action closeSideWindow is triggered, which happens on every chatbotMessage before showing a new sideWindow, and on closing the conversationWindow.

  • Callback arguments:
    • next: [function]

If the next() statement is executed, the sideWindow will be closed.

onCreateTicket

The classback passed to this event listener is executed each time the createTicket action is called.

  • Callback arguments:
    • ticketData: [object]
    • next: [function]

This subscription is used by the Inbenta "Create ticket" adapter to create a ticket in the Assist module when the createTicket action is called.

onCustomTrigger

The callback passed on this event listener is executed every time the action customTrigger is triggered. This never happens by default, only when other adapters called the customTrigger action. This can be used for custom implementations.

  • Callback arguments:
    • next: [function]

If the next() statement is executed, the callback is passed on the next subscription if there is one.

onDisplayChatbotMessage

The callback passed to this event listener is executed each time the Chat app receives an answer from the Inbenta API but before it processes this answer and displays any new message in the Chat SDK.

When next() is executed, this message shows as displayChatbotMessage.

If no next() statement is executed, the message does not show.

Example

Let's add the string "Custom chat message" to any answer that the Chat app displays, unless the message displayed is the "no answer" response. To do this, execute a return and do not send the next() premise. For all other cases, modify the displayed message and execute next(). This allows the execution of the displayChatbotMessage action.

chatbot.subscriptions.onDisplayChatbotMessage(function(messageData, next) {
    // BEFORE DisplayChatbotMessage action execution
    if (messageData.message=="Sorry, we could not find any answers to your question."){
      console.log("hidden message")
      return
    }else{
      messageData.message = 'Custom chat message! ' + messageData.message;
      return next(messageData);
    }

});

onDisplayRating

The callback passed to this event listener is executed each time the DOM elements of the ratings are created.

Since this is not triggered by an action, the next() statement will not stop the ratings of being shown.

In this example, we are using JQuery library, and have the following configuration in the ratingOptions:

ratingOptions : [
        {
            id: 1,
            comment: false,
        },
        {
            id: 2,
            comment: false,
        },
        {
            id: 3,
            comment: false,
            label:"test",
            customClass:'inbenta-contact'
        }
      ],
chatbot.subscriptions.onDisplayRating(function(next) {
    $('.inbenta-contact').empty();
    $('.inbenta-contact').append("<span class='contact-class'>"+'<img src=<mail-icon-example>' + "</span>");
});

Using the displayRating subscription, we modify its HTML component to display an email icon instead of the usual icon.

onDisplaySystemMessage

The callback passed to this event listener executes each time the onDisplaySystemMessage() action is called.

When next() is executed, it calls the displaysystemMessage action.

  • Callback arguments:

Example

This subscription allows you to modify the systemMessage displayed. In the example below, it saves the internal ID of all the generated systemMessages:

chatbot.subscriptions.onDisplaySystemMessage(function(data, next) {
    // Display message
    const messageId = next(data);

    // AFTER display system message code here
    console.log('system message id: ' + messageId);

    return messageId;
});

onDisplayUserMessage

The callback passed to this event listener is executed each time the displayUserMessage() is called.

When the next() is executed, this message shows as displayUserMessage. If the next() callback is not executed, the user message won't be displayed.

  • Callback arguments:

Example

Suppose that you have a tool called hidePrivateInfo(). This tool hides account numbers when users enter it in the input, so that other people cannot see it in the displayed user question:

chatbot.subscriptions.onDisplayUserMessage(function(messageData, next) {
    messageData.message = hidePrivateInfo(messageData.message);
    return next(messageData);
});

Since you execute next(messageData), the message will be displayed but the account numbers are hidden.

onClickAIDisclaimerButton

This subscription allows you to customize the behavior of the disclaimer Info icon displayed through the Generative AI configuration.

The callback passed to this event listener is executed each time the user clicks on the Generative AI disclaimer Info icon.

Callback arguments:

chatbot.subscriptions.onClickAIDisclaimerButton(function(messageData, next) {
  // Custom behavior in which a sidebubble is displayed when a user clicks on the disclaimer icon
  chatbot.actions.showSideWindow({
    sideWindowTitle: "Answer Generated by AI",
    sideWindowContent: "This answer has been generated with AI"
  });
  next(messageData);
});

The appearance of this icon changes depending on the configured skin. This is what the icon looks like when the SDK is configured with the tatooine-sunset skin:

onDownloadMedia

The callback passed to this subscription method is executed each time the downloadMedia action is called.

  • Callback arguments:
    • media: media (with the messageExternalId property)
    • next: [function]

When you develop a chat integration with the Inbenta Chat app, and you allow attachments, you must use the downloadMedia subscription, so that when a user clicks on an attachment, you can define how to download the attachment, if it shows any message, or any other action needed.

chatbot.subscriptions.onDownloadMedia(function(media, next) {
    // do something with the media object
    // for example, open the attachment in a new window if the file object passed in the `uploadMedia` function contains an URL property
    window.open(media.file.url, media.file.name);

    // if you do not want more adapters to receive your media information, do not call next
});

onEscalateToAgent

The callback passed to this event listener is executed each time the EscalateToAgent() action is called.

  • Callback arguments:
    • next: [function]

Example

You can place a button on our website to contact a human agent. When a user clicks on this button, it triggers the EscalateToAgent.

Inbenta also built an adapter to create a subscription in the SendMessage action without executing the next(), to send the userMessage to an external human-human API.

Inside the sendMessage subscription, there is a connectToHuman flag. When it is set to true, it sends the message to your human-to-human external API instead of the Inbenta API. (The flag must be set to true.)

With this flag, the next query that the user sends is sent to this external API. It also sends the conversation history to the human agent for context.

chatbot.subscriptions.onEscalateToAgent(function(next) {

    const connectToHuman = true;
    const conversation = chatbot.actions.getConversationTranscript();
    return next();
});
Note

When using both of Inbenta escalation adapters, the escalateToAgent action also has the data relevant to the escalation. This data is also sent to the subscription. If you need to modify any of the escalationData properties, remember to trigger the return statement with the escalationData like the following example:

chatbot.subscriptions.onEscalateToAgent(function(escalationData, next) {
    escalationData['FIRST_NAME'] = "John Doe"
    return next(escalationData);
});

onEscalationStart

The callback passed to this event listener is executed each time the escalationStart() action is called.

chatbot.subscriptions.onEscalationStart(function(data, next) {
    return next(data);
});

onHideConversationWindow

The callback passed to this event listener is executed each time the HideConversationWindow() action is called.

When next() is executed, it calls the hideConversationWindow action.

  • Callback arguments:
    • next: [function]

Example

Suppose that you need to store all the Chat app-human interactions in an external system. You use an external sendChatbotConversation functions to send the conversation after you use the HideConversationWindow action to minimize the window.

chatbot.subscriptions.onHideConversationWindow(function(next) {

    const conversation = chatbot.actions.getConversationTranscript();
    sendChatbotConversation(conversation);
    return next();
});

onRateContent

The callback passed to this event listener is executed each time the user clicks on a rating.

If the next() is executed, the ratecontent action sends the trackingData to the Inbenta API using the ratecontent js-client method.

This is the subscription the Chat SDK uses to send the rate to the Inbenta API:

 chatbot.subscriptions.onRateContent(function(rateData, next) {
    if(!rateData.hasOwnProperty('trackingCode')){
        console.warn("trackingCode property, canceling rateContent");
        return;
    }
    if(!rateData.hasOwnProperty('value')){
        console.warn("value property, canceling rateContent");
        return;
    }
    //Custom code can be used here to track how many negatives rates the user has already clicked,
    return next(rateData); //return next to allow the SDK to send the rate to the API
  });

onReady

The callback passed to this subscription method is executed before rendering the view of the SDK. It is possible to return a promise in this subscription. When a promise is returned, the SDK automatically detects it and holds the render until the promise is fulfilled. If no promise is returned, it will automatically render the view.

  • Callback arguments:

    • next: [function]

You can use it to detect when the SDK has finished the build, which allows the execution of actions before the user clicks on the launcher.

chatbot.subscriptions.onReady(function(next) {
//if you want to open the `conversationWindow` when the SDK has been build:
    chatbot.actions.showConversationWindow();
});

Example

In this example, the bot returns a promise (an AppData API call) so the SDK is not rendered until the promise is fulfilled:

chatbot.subscriptions.onReady(function(next) {
 var newLabels={};
 var newKey="";
 return bot.api.getAppData(appData).then(({data})=>{
  var labelsExtraData = data.results[0].value;
  for (var property in labelsExtraData) {
    newKey = property.replace(/_/g, "-");
    newLabels[newKey] = labelsExtraData[property];
  }
  botConfig.labels = newLabels;
  botConfig.launcher = launcher;
  chatbot.actions.updateConfiguration(botConfig);
 });
});
Caution

If the promise given is a request to the Chat API, you are performing this API request for every user that enters the website, not only the ones who interact with the Chat app. To avoid this, Inbenta recommends that you create an HTML element that builds the Chat app when a user clicks on it. Make sure that you add the showConversationWindow action at the end of the onReady subscription.

<button class="ExampleHtml" type="button" onclick="buildUI()"></button>
window.buildUI = function () {
    InbentaChatbotSDK.buildWithDomainCredentials(authorization,{
        adapters:[
            showConversationOnready()
        ]
    })
};

It is not mandatory to return the next() function in the callback, but if no next() is returned, all the onReady subscription callbacks added after the current adapter will not be executed.

Example The following subscription will make the bot render after 1 second but it won’t execute any other callback subscribed to the onReady and added after this one.

chatbot.subscriptions.onReady(function (next) {
    return new Promise((resolve, reject) => {
        setTimeout(function() {
            resolve();
        },1000)
    }).then(() => {
        console.log('promise resolved');
    })
});

If you want to continue with all the other callback executions, the next() function should be returned. We update the previous example to return the next() function:

chatbot.subscriptions.onReady(function (next) {
    return new Promise((resolve, reject) => {
        setTimeout(function() {
            resolve();
        },1000)
    }).then(() => {
        console.log('promise resolved');
        return next(); // return next to continue executing callbacks
    })
});

onDomReady

The callback passed to this subscription method is executed after rendering DOM HTML elements.

Note

Inbenta recommends that you manipulate the Chat app HTML using both customHTML feature, and helpers functionality.

  • Callback arguments:

    • next: [function]

You can use it to detect when the DOM HTML elements of the Chat app have been rendered.

Caution

Whether you call next statement or not does not stop the Chat SDK from showing. This is a subscription that identifies the moment when the HTML is rendered, which cannot be interrupted.

chatbot.subscriptions.onDomReady(function(next) {
    //Detect HTML DOM elements rendered
});

onResetSession

The callback passed to this subscription method is executed when the resetSession action will be called. You can use this subscription to avoid the reset of session (e.g. to show an alert that the session is about to close) or to do something (e.g. send logs or remove the Chat instance).

  • Callback arguments:

    • next: [function]
chatbot.subscriptions.onResetSession(function(next) {
    // You must define `hasUserConfirmedReset` and `confirmResetMessageId` in your adapter.
    // Subscribe to `onSelectSystemMessageOption`. In this subscription, you can change `hasUserConfirmedReset` if the user clicks 'Yes' and dispatch 'resetSession' again
    if (hasUserConfirmedReset) {
      hasUserConfirmedReset = false;
      return next();
    }

    confirmResetMessageId = chatbot.actions.displaySystemMessage({
      message: 'Do you want to reset your session? You will lose all your messages',
      options: [
        {label: 'Yes'},
        {label: 'No'}
      ]
    })
});

onSelectSystemMessageOption

The callback passed to this subscription method is executed each time the selectSystemMessageOption action is called.

  • Callback arguments:

    • id String: The id of the selected option's message.
    • option option
chatbot.subscriptions.onSelectSystemMessageOption(function(optionData, next) {
  if (optionData.id == myStartChatMessageId) {
    if (optionData.option.label == 'yes') {
      startChat();
    }
    // Prevent any other callback subscribed to onSelectSystemMessageOption from doing anything with a message from the adapter.
    return;
  }

  return next(optionData);
})

onSendMessage

The callback passed to this event listener is executed each time the user writes a message in the widget input and send it.

If the next() is executed, the sendMessage action sends the message to the Inbenta API. the Chat app then builds an answer and displays it with the displayChatbotMessage action.

If no next() statement is executed (e.g. to consult an external API), you must call the displayChatbotMessage action manually when you get the answer so that you can display it.

  • default behaviour: Send the user query to the Inbenta Chat API and perform displayChatbotMessage action with the API response.
  • Callback arguments: custom

Example

The example below replaces a string on the messageData.message with the replaceWithvar. When it returns the next(), it sends the message to the Inbenta API and displays the answer.

chatbot.subscriptions.onSendMessage( function(messageData, next) {
   messageData.message = messageData.message.replace(regex, replaceWith);
   return next(messageData);
 }
);

onSetExternalInfo

The callback passed to this event listener is executed each time the setExternalInfo() action is called.

  • Callback arguments:
    • data: object
    • next: [function]
chatbot.subscriptions.onSetExternalInfo(function(data, next) {
    console.log(data); //Do something with the given data
    return next(data);
});

onShowConversationWindow

The callback passed to this event listener is executed each time the showConversationWindow() action is called.

When the next() is executed, it calls the showConversationWindow action.

  • Callback arguments:
    • next: [function]

Example

A store has this new amazing offer for their new product, and they want to show their users how amazing it is. They will use the sideWindow to show the offer when users click on the launcher, so they do not miss this opportunity.

chatbot.subscriptions.onShowConversationWindow(function(next) {
    const SideWindow = {
      sideWindowContent: "<p>Hi! check out this amazing article </p><a href="https://www.fakeLinkTo.com/amazingArticle/">Article</a>",
      sideWindowTitle: "Special promotion",
    }
    chatbot.actions.showSideWindow(SideWindow);
    return next();
});

onShowSideWindow

The callback passed to this subscription method is executed every time the sideWindow action is called.

  • Callback arguments:
  chatbot.subscriptions.onShowSideWindow(function(sideWindowData, next) {
    sideWindowData.sideWindowContent = "test modified content";
    return next(sideWindowData);
  });

onSelectActionFieldOption

The callback passed to this subscription method is executed each time the selectActionFieldOption action is called.

Callback arguments:

  • method[sendMessage|addVariable]: This parameter defines what action to take with this data:

    • sendMessage: The label parameter displays as a userMessage, and a sendMessage action will be done with message:label and userActivityOptions:value.
    • addVariable: The variableName parameter and value are used in the addVariable API method and a systemMessage displays with the label selected-option.
  • variableName [String] This is only mandatory when selecting the addVariable method.

  • value String: This is the value sent to the API either as the value in the addVariable endpoint, or as userActivityOptions in the messageData object in the sendMessage action

  • label [String]: Displays as a userMessage when sendMessage method is selected. It is also send as a message in the messageData object in the sendMessage action

chatbot.subscriptions.onSelectActionFieldOption(function(actionData, next) {
    //Modify actionData properties to change the method, value or label.
});

onStartConversation

The callback passed to this subscription method is executed at the beginning of the session after the conversation request is done. The callback Data is the the response to the conversation request.

Note

This is a special subscription. Because the next() statement does not interrupt nor execute the callbacks, you may simply choose to ignore it.

  • Callback arguments:
    • sessionToken: [String]: SessionToken assigned for this conversation.
    • sessionId: [String]: SessionId assigned for this conversation.
    • next: [function]
chatbot.subscriptions.onStartConversation(function(conversationData, next) {
    var sessionToken = conversationData.sessionToken;
});

onUploadMedia

The callback passed to this subscription method is executed each time the uploadMedia action is called.

  • Callback arguments:

    • media: media

    • next: [function]

When you develop a chat integration with the Inbenta Chat solution, and you allow attachments, you must use the uploadMedia subscription, so that when a user clicks on the media-button, you can define how to upload the attachment or any other action needed.

chatbot.subscriptions.onUploadMedia(function(media, next) {
    // do something with the media object to send it to your service

    // if you do not want more adapters to receive your media information, do not call next
});