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
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.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).
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.
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
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.
next
: [function]If the next() statement is executed, the sideWindow will be closed.
The classback passed to this event listener is executed each time the createTicket
action is called.
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.
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.
next
: [function]If the next() statement is executed, the callback is passed on the next subscription if there is one.
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.
messageData
:object chatBotMessageDatanext
: [function]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);
}
});
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.
The callback passed to this event listener executes each time the onDisplaySystemMessage()
action is called.
When next()
is executed, it calls the displaysystemMessage action.
messageData
:object messageDatanext
: [function]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;
});
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.
messageData
:object messageDatanext
: [function]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.
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:
messageData
: object messageDatanext
: [function]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:
The callback passed to this subscription method is executed each time the downloadMedia
action is called.
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
});
The callback passed to this event listener is executed each time the EscalateToAgent()
action is called.
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();
});
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);
});
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);
});
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.
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();
});
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
});
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);
});
});
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
})
});
The callback passed to this subscription method is executed after rendering DOM HTML elements.
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.
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
});
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'}
]
})
});
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
optionchatbot.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);
})
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.
displayChatbotMessage
action with the API response.messageData
:object messageDatanext
: [function]Example
The example below replaces a string on the messageData.message
with the replaceWith
var. 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);
}
);
The callback passed to this event listener is executed each time the setExternalInfo()
action is called.
data
: objectnext
: [function]chatbot.subscriptions.onSetExternalInfo(function(data, next) {
console.log(data); //Do something with the given data
return next(data);
});
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.
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();
});
The callback passed to this subscription method is executed every time the sideWindow action is called.
sideWindowData
: SideWindownext
: [function] chatbot.subscriptions.onShowSideWindow(function(sideWindowData, next) {
sideWindowData.sideWindowContent = "test modified content";
return next(sideWindowData);
});
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:
message:label
and userActivityOptions:value
.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.
});
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.
This is a special subscription. Because the next()
statement does not interrupt nor execute the callbacks, you may simply choose to ignore it.
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;
});
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
});