Widget API
The Widget API enables you to interact with the Kindly Chat embedded on your website.
Kindly Chat is a feature-rich and customizable chat client for the web. New versions packing features and updates are made available continuously. You can read more on supported versions below.
Get the HTML snippet
Start by navigating to your bot in the Kindly platform.
Select Connect from the left-hand menu, then click Kindly Chat - Publish your chatbot.
Under the heading Get HTML code go ahead and copy it by hitting Copy to clipboard. You'll need this code to embed Kindly Chat on your site.
The HTML snippet should look something like this:
<script
id="kindly-chat"
src="https://chat.kindlycdn.com/kindly-chat.js"
data-bot-key="{{your-bot-key}}"
data-shadow-dom="1"
data-market="{{market-slug}}"
defer
></script>A pure build is also available.
Deploying Kindly Chat
Once you have copied the snippet, you're ready to add Kindly Chat to your site. This should be a simple process that involves updating an HTML template. Put the snippet in your HTML template, between the <head> or <body> tags.
If this sounds strange, foreign, or scary, we recommend you contact your website administrator or a developer in your organization for further assistance.
Using Google Tag Manager?
When using Google Tag Manager (GTM), the script needs to be added programmatically. This means the HTML snippet won't work, as GTM won't be able to load its attributes like data-bot-key. When adding a new tag, choose the "custom HTML" option and paste the following snippet into the editor:
<script>
var script = document.createElement("script");
script.src = "https://chat.kindlycdn.com/kindly-chat.js";
script.defer = true;
script.id = "kindly-chat";
script.setAttribute("data-shadow-dom", "1");
script.setAttribute("data-bot-key", "{{your-bot-key}}");
script.setAttribute("data-market","{{market-slug}}");
document.body.appendChild(script);
</script>One thing worth noting when implementing with GTM, is that the chat bubble can be hidden for some users using an ad blocker extension. Therefore we do recommend implementing the chat bubble directly into the source code, or via a CMS if possible.
Customizing
There are two options available for configuring Kindly Chat appearance and behaviour:
- Set default settings directly through the Kindly platform.
- Override the default settings using options in your site HTML (window.kindlyOptions). This allows for per-page customization. See the section options reference for a list of supported options.
Set default behaviour and appearance
Start by navigating to your bot in the Kindly platform.
From the left-hand menu, open Settings, then go to Kindly Chat.
Configure the bot behaviour and appearance according to your needs.
Override behaviour or appearance per page
Sometimes Kindly Chat needs slightly different behaviour or appearance depending on the page the user is visiting. This can be accomplished by adding options to the original HTML snippet. Use the following HTML snippet for overriding the settings. Remember to replace the part that says 'YOUR-BOT-KEY' with the value from your original HTML snippet.
NOTE: In this example, available options have been commented out. To activate an option, uncomment the line by removing "//" from the start of the line.
<script>
window.kindlyOptions = {
// chatbubble: {
// autopopup: false,
// autopopup_time: 10000, // ms
// },
// name: 'Your bot name',
// bubbleHidden: true,
// context: { /* your own context */ },
// getAuthToken: async function(chatId) { /* return token code */ },
};
</script>
<script
id="kindly-chat"
src="https://chat.kindlycdn.com/kindly-chat.js"
data-bot-key="{{your-bot-key}}"
defer
></script>Set initial language
If you need to pre-configure which language the bot should use to greet the user, just set window.kindlyOptions.language to a supported language code. The language must have been activated in the Kindly Platform before. See example below.
<script>
window.kindlyOptions = {
language: "nb", // Norwegian (Bokmål)
};
</script>
<script
id="kindly-chat"
src="https://chat.kindlycdn.com/kindly-chat.js"
data-bot-key="{{your-bot-key}}"
defer
></script>Chat options - window.kindlyOptions
You can control your Kindly Chat settings by setting some options through the global window.kindlyOptions or with the data attributes on the Kindly Chat <script> tag.
Property reference
Property, type | Data attribute | Default | Description |
|---|---|---|---|
bubbleAvatar string | - | "" | Accepts a single string, which should be the location for the image file. The image will be displayed inside the bubble. |
bubbleHidden bool | data-bubble-hidden | false | Hides the bubble initially |
chatbubble.autopopup bool | - | - | Automatically popup chat window |
chatbubble.autopopup_time number | - | - | Milliseconds to wait before popup of chat window |
context object | - | undefined | Initial chat memory / context. |
customFont | - | - | Set a different font-family, for example: window.kindlyOptions = { customFont: '"Comic Sans MS", cursive, sans-serif' }. |
focusTrapOnFullView bool | | false | If true, this option activates a focus trap when the chat covers the entire screen. This ensures that keyboard and screen reader navigation remains within the chat interface, improving accessibility for users relying on VoiceOver and keyboard controls. This setting may default to true in future updates, but for now, it must be explicitly enabled. |
fullscreenMode bool | - | - | Makes the chat window take up the entire screen. |
hideHeader bool | - | - | hides the header component of the chat window |
language string, | data-language | - | Initial bot and interface language |
market | data-market | Random Bot market slug | The market slug you want your chat to be mounted in. It can only be set once at the start. |
position.bottom string, | - | 20px | Offset position of the chat icon, relative to bottom of window. |
position.right string, | - | 20px | Offset position of the chat icon, relative to right of window. Keep in mind that elements will keep their place relative to the chat icon, and that elements will always appear to the left. |
shadowDom | data-shadow-dom | false | Render Kindly Chat HTML in a |
styles | data-styles | "" | NB: Use at own risk, we do not guarantee stable class names. CSS injected into Shadow DOM to override styles. |
zIndex number | - | 5000 | Control the z-index of the chat container if it's hidden behind other elements |
Chat properties - window.kindlyChat
Kindly Chat comes with some useful methods and data properties.
Property reference
Property | Description |
|---|---|
isBrowserCompatible bool | Whether Kindly Chat officially supports the current browser or not. |
open bool | If true, it means the Chat window is open. |
showBubble() | Shows the bubble icon, which affects bubbleHidden. |
hideBubble() | Hides the bubble icon, which affects bubbleHidden. |
openChat() | Opens the chat window. |
closeChat() | Closes the chat window. |
restartChat(options) | Restarts the chat.
|
cancelHandover() | It terminates the ongoing handover, whether the user is in the queue or already engaged in the process. |
sendMessage(message, options) | Send a message into the chat.
|
triggerDialogue("[DIALOGUE_ID]", options) | Trigger selected dialogue in chat, using ID or slug. options is an optional object. It may include languageCode to specify language and openChat to open the chat window. |
identifyUser({ full_name: "John Doe" }) | Add a user identity to the current chat session. Allowed fields: , user_id, avatar_url, full_name, email and phone_number. |
async getContext() | Get the current chat context. |
setNewContext({"key": "value"}) | Add some additional context to the current conversation. The context can e.g be used in webhooks or by bot builders. |
setNewLabel("newLabel") | Add an additional label to the current conversation. If the chat hasn't started yet when you invoke this function, an empty labelled chat will be created in Insights, without the customer knowing it. |
setNewBannerMessage({content: "Banner message text here", buttonHref: "https://example.com", buttonText: "Example"}, "23234") | The last parameter is an ID. It is optional, and is used to make sure the same banner message is not shown twice to the same user. |
Nudge property reference
You also have some properties to handle Nudges. These are usable independently of the nudge type you want to use them with. Read more about nudges here.
Property | Description |
|---|---|
showNudge({ slug: 'string', nudgeLayout }); | showNudge is used to trigger a specific nudge, either from the platform or from a given layout. |
showCustomNudge({ content, slug, onRendered, onRendered }) | showCustomNudge is used to trigger a nudge with a fully custom layout. |
closeNudge(); | closeNudge will close any active nudge. If there is no one open, the function won't do anything. |
Examples
Opening the chat from a button on your webpage
Add en event listener to your button that calls openChat().
<button id="open-kindly-chat-button" type="button">
Chat with us
</button>
<script>
document
.getElementById('open-kindly-chat-button')
.addEventListener('click', function () {
window.kindlyChat.openchat();
});
</script>Displaying the chat bubble only if the browser is officially supported.
Keep in my mind that Kindly Chat could still work fine for more browsers than the officially supported ones, so we suggest the approach below only if really necessary.
<!-- Make the chat start hidden by default -->
<script>
window.kindlyOptions = {
bubbleHidden: true,
}
</script>
<!-- Load the chat -->
<script id="kindly-chat" src="kindly-chat.js" data-bot-key="<bot_key>">
</script>
<!-- Only display the chat if browser is compatible -->
<!-- N.B. to safely use kindlyChat properties, always listen for kindly:load
that will ensure the chat to be loaded and ready to use.
-->
<script>
document.addEventListener('kindly:load', (event) => {
if (window.kindlyChat.isBrowserCompatible) {
window.kindlyChat.showBubble();
}
});
</script>Send a message in Kindly Chat on behalf of the user.
This could be useful, for example, if you have a support form on your website: before submitting the customer's inquiry to your backend, you could ask directly in the Chat and only if the Chat goes to fallback then submit it to your backend or an agent.
window.kindlyChat.sendMessage("Hi, do you sell computers as well?", {sender: "user"})Restart the widget in another market
Use restartChat() to end the current conversation and start a new one in another market without reloading the page:
window.kindlyChat.restartChat({market: '<market-slug>'});The market change applies immediately to the mounted widget. However, after a page refresh, the widget is initialized again using window.kindlyOptions.market or the data-market attribute.
To preserve the selected market across page refreshes, store it in durable application state—such as the page URL—and use that value when initializing the widget. For example:
<script>
const DEFAULT_MARKET = 'general';
const pageUrl = new URL(window.location.href);
const initialMarket =
pageUrl.searchParams.get('market') || DEFAULT_MARKET;
// Configure the initial market before loading the widget.
window.kindlyOptions = {
...(window.kindlyOptions || {}),
market: initialMarket,
};
function changeKindlyMarket(market) {
// Persist the market in the URL without reloading the page.
const nextUrl = new URL(window.location.href);
nextUrl.searchParams.set('market', market);
window.history.replaceState(null, '', nextUrl);
// Keep the page configuration and mounted widget in sync.
window.kindlyOptions.market = market;
window.kindlyChat.restartChat({ market });
}
</script>
<script
id="kindly-chat"
src="https://chat.kindlycdn.com/kindly-chat.js"
data-bot-key="{{your-bot-key}}"
data-shadow-dom="1"
defer
></script>This ensures that:
- The widget changes market without reloading the page.
- A fresh conversation starts in the selected market.
- The selected market is restored after a page refresh.
Use restartChat() only after the kindly:load event has fired.
When using window.kindlyOptions.market as the source of truth, do not also provide a fixed data-market value. If you use data-market, render it from the same persistent application state.
Chat events
You can attach event listeners for the following events emitted by the Kindly Chat client.
Event reference
event | event.detail | Description |
|---|---|---|
kindly:load |
| Triggered once after Kindly Chat has loaded server side settings. It receives the complete settings object. Functions like openChat and closeChat should be called after this. |
kindly:message |
| Triggered on every message, including user, agent and system messages. It receives the last message and the complete chat transcript. |
kindly:buttonclick |
| Triggered on every button click. It receives the button details, button type, last message and the complete chat transcript. To prevent running the default actions of that button type, you can call event.preventDefault() on the DOM event in the event listener. |
kindly:ui |
| Triggered when some actions are performed in Kindly Chat. The type property will say which particular action was performed. Currently, we support:
The source property will say if the action was somehow initiated by the user or not. The chatId is provided as well, when available in the event triggered. The value property will carry any meaningful info (if any) in relation to the action performed. Currently, we expose a value for feedback, language and open-chatbubble events. |
kindly:globalicon |
| Triggered when certain actions are performed in relation to Global Icons. The type property indicates which particular action was performed. Currently, we support only trigger-globalicon. The icon.action corresponds to the action the icon will trigger. It can be a URL, a dialogue slug/ID, or a nudge slug. |
Nudge callbacks
These are callbacks used along with nudges. Read more about them here.
We don't have yet an event emitter API for these events so it's currently working with callbacks that you can set on window.kindlyOptions.
Function | Supported nudge types | Description |
|---|---|---|
onNudgeDismiss: () => { ... }, | All | onNudgeDismiss is triggered whenever a nudge is closed. |
onNudgeFormSubmit: (e, values) => { ... }, | Form nudge | onNudgeFormSubmit is triggered whenever a form nudge is submitted. It contains the submit event along with the input value. |
onNudgeProductClick: (e, product) => { ... }, | Product nudge | onNudgeProductClick is triggered when a specific product on a product nudge is clicked. However, it is only triggered if linkUrl is not sent as a property in the items array |
Examples
Logging the payload and randomly displaying the chat bubble on kindly:load
document.addEventListener('kindly:load', (event) => {
console.log('💖💖', event.detail);
if(Math.random() >= 0.5) {
kindlyChat.showBubble();
}
});Logging and sending to analytics the button data on kindly:buttonclick
window.addEventListener('kindly:buttonclick', (event) => {
console.log('This is the event payload:', event.detail);
const buttonData = event.detail.button;
trackGoogleAnalytics(buttonData);
});Tracking every time the user manually switches language
window.addEventListener(`kindly:ui`, (event) => {
const { detail } = event;
const eventType = detail.type;
// In general, for tracking user behaviour, it's good practice to also
// check that `source` is `user`, since perhaps you wouldn't want to track
// if the action was somehow initiated/performed by the Chat itself
if (eventType === 'change-language' && detail.source === 'user') {
const payload = {
incrementCount: eventType,
targetLanguage: detail.value.languageName
}
sendToGoogleAnalytics(payload)
}
}⚰️ Callback reference (deprecated)
Property and callback signature | Description |
|---|---|
onLoad: () => {} | Deprecated: use kindly:load event listener instead. onLoad is called once after Kindly Chat has loaded server-side settings. Functions like openChat and closeChat should be called inside this callback |
onMessage: (newMessage, chatLog) => {} | Deprecated: use kindly:message event listener instead. onMessage is called on every message, including user, agent, and system messages. It receives the last message and the complete chat transcript. |
buttonHandlers: {[BUTTON_TYPE]: (event, button, lastMessage, chatLog) => {}} | Deprecated: use kindly:buttonclick event listener instead. Each type of button takes a callback and buttonHandlers[BUTTON_TYPE] is called on click for that BUTTON_TYPE. It receives the DOM event, button definition, last message, and the complete chat transcript. Valid BUTTON_TYPE's are quick_reply, takeover_request, link, email, phone, dialogue_trigger, privacy_export, privacy_delete. If you return true from a button handler the default actions of that button type are not run (similar to event.preventDefault()). |
getAuthToken: (chatId) => {} | getAuthToken is called once the chat is started to authenticate the user. It must return a signed JWT token. |
Authentication
Kindly supports authenticating your users. When your users are authenticated, it's easier to identify them in the Kindly Insights and you can create more personalized and powerful webhook integrations.
To set this up you need to do a few things:
- Add a callback to Kindly Chat initialization code.
- Create a private/public key pair.
- Create an authentication endpoint that returns a JWT in a specific format.
After the initial implementation and setup, you are able to:
- See user details in Kindly Insights.
- Identify users in webhooks (via the forwarded JWT).
Read more about authenticating your users in the full Kindly Chat authentication guide.
Supported versions
Major versions are released on a six month cycle and there will be no breaking changes outside of a major release.
We follow semantic versioning when naming versions of Kindly Chat.
Browser support for Kindly Chat widget is based on the following logic:
- >0.2% in alt-eu - We support browsers that have more than 0.2% of the market share in Europe (alternative data source).
- >0.2% in US - We support browsers that have more than 0.2% of the market share in the United States.
- last 3 years - We support all browsers that have been released in the last 3 years.
- not dead - We do not support browsers that are no longer maintained.
- not OperaMini all - We do not support any versions of Opera Mini.
- not Edge < 20 - We do not support Microsoft Edge versions older than version 20.
- not opera < 63 - We do not support Opera versions older than version 63.
- not safari < 13 - We do not support Safari versions older than version 13.