To install the widget without writing code, start from Installing the widget.
#What stays stable across versions
These elements don't change name or meaning from one version to the next:
- The
chatbot.jsfile, included as a classic script, withid="supportfast-script"(orid="chatbot-script") and thedata-chatbot-idattribute. - The
window.SupportFastobject, withinit()andversion. window.ChatbotConfig.langandwindow.chatbotUserData.- The
chatbot_openevent in thedataLayer. - The
#chat-widget-containercontainer, which the CSS variables apply to. - The CSS variables
--sf-offset-bottom,--sf-offset-sideand--sf-z-index.
Everything else, including the widget's internal classes, can change: don't use it in your website's code.
#The tag
HTML · the widget tag (sample agent code)
<script defer id="supportfast-script" src="https://cdn.supportfast.ai/chatbot.js" data-chatbot-id="bot-a1b2c3d4e5"></script>
| Attribute | Value | Notes |
|---|---|---|
id | supportfast-script or chatbot-script | Required. Keep the one in the code the console gives you. |
src | The address of chatbot.js | Required. Don't host the file on your own server: the widget loads its parts from the same folder. |
data-chatbot-id | The agent's code | Required. Without it, the widget doesn't start. |
defer | — | Recommended, and already in the console's code. The widget also works with async or with neither, but your code must wait for it as explained further down. |
- The tag must stay a classic script: don't add
type="module". - Include it once per page. A second inclusion does nothing.
- The widget mounts when the document is ready. If the tag arrives later, for example from Google Tag Manager, it mounts right away.
#The window.SupportFast object
The widget creates window.SupportFast as soon as chatbot.js runs, before the chat is ready.
| Member | What it does |
|---|---|
version | The version of the widget running on the page. |
init() | Mounts the widget, if it isn't mounted already. It runs on its own when the document is ready; calling it again doesn't create duplicates. If your framework removed the container, it mounts it again. |
open(), close(), toggle() | Open, close or toggle the chat. |
identify(data) | Replaces the signed-in customer's data. Without arguments, it reads window.chatbotUserData again. |
on(event, handler), off(event, handler) | Start or stop listening to the ready, open and close events. |
- Calls made after
chatbot.jsruns, but before the chat is ready, are queued and run in the order they arrive. readyfires when the agent is loaded and active; a handler registered later runs right away. If the agent isn't available, it doesn't fire.
HTML · a website button that opens the chat
<button type="button" onclick="window.SupportFast && window.SupportFast.open()">Contact us</button>
#Making your code wait
Before chatbot.js runs, window.SupportFast doesn't exist and there's no queue to leave calls in. So your code must wait for the object.
- With the tag in
defer, as in the console's code, theDOMContentLoadedevent is enough: it fires afterdeferscripts have run. - With
async, with Google Tag Manager or with a plugin that delays scripts,chatbot.jscan arrive afterDOMContentLoaded. Use the function below, which works in every case.
JavaScript · waiting for the widget, however it's loaded
function conSupportFast(azione) {
var tentativi = 0;
(function prova() {
if (window.SupportFast && typeof window.SupportFast.on === "function") {
azione(window.SupportFast);
} else if (tentativi < 100) {
tentativi += 1;
setTimeout(prova, 100); // retries every tenth of a second, for 10 seconds
}
})();
}
conSupportFast(function (chat) {
chat.on("ready", function () {
// the chat is loaded and the agent is active
});
});
If chatbot.js can arrive later, for example because a plugin waits for the visitor's first interaction, raise the number of attempts.
#Forcing the language: window.ChatbotConfig.lang
Normally the widget picks the language from the visitor's browser, among the workspace languages. To force it, set window.ChatbotConfig before the widget code.
HTML · chat always in English
<script>window.ChatbotConfig = { lang: "en" };</script>
<script defer id="supportfast-script" src="https://cdn.supportfast.ai/chatbot.js" data-chatbot-id="bot-a1b2c3d4e5"></script>
- Possible codes, in lowercase:
it,en,de,fr,es,nl,pl,tr,pt,pt-br,sr.it-ITorITaren't valid. - The language must be one of the workspace languages. Otherwise the widget ignores it and picks as usual.
- The language is set at startup: to change it, the page must be reloaded.
- It applies only to the widget installed with the code on the website, not to the link and the iframe.
#The signed-in customer's data: window.chatbotUserData
With window.chatbotUserData you pass the widget the data of a customer signed in to your website. The fields are firstName, lastName, fullName, company, email, phone and metadata, for the workspace variables. Limits and examples are in Passing user data.
#Events for Google Analytics and Tag Manager
Every time the chat opens, the widget runs window.dataLayer.push({ event: "chatbot_open" }). If dataLayer doesn't exist, it creates it. The event has no other parameters.
With Google Tag Manager, create a trigger of type Custom Event, with event name chatbot_open. Connect it to a Google Analytics 4 event tag, for example with the same name. Publish the container, open the chat and look for the event in the Analytics Realtime report.
With gtag.js, without Tag Manager, an entry in the dataLayer doesn't become an Analytics event. Use the widget's open event:
JavaScript · GA4 event when the chat opens
// conSupportFast is the function from "Making your code wait", above
conSupportFast(function (chat) {
chat.on("open", function () {
gtag("event", "chatbot_open");
});
});
The chat inside an iframe communicates with the page that contains it through postMessage messages, listed in Passing user data.
#Moving the button: the CSS variables
The widget container reads three CSS variables, which you can set from the website's stylesheet:
| Variable | Default | What it changes |
|---|---|---|
--sf-offset-bottom | 30px | The button's distance from the bottom of the screen. |
--sf-offset-side | 25px | The distance from the side, right or left depending on the Button position. |
--sf-z-index | 2147483647 | The stacking level: the default value is the highest possible. |
CSS · button higher up, so it doesn't cover a cookie banner
#chat-widget-container {
--sf-offset-bottom: 100px; /* the button moves above the banner, about 80 pixels tall */
--sf-offset-side: 20px;
--sf-z-index: 1000; /* lower than the default: the banner, if it has a higher level, stays above the chat */
}
- You can set them on
#chat-widget-containeror on an element that contains it, such as:root. - The open window and the bubble move with the button. Below 600 pixels wide, the open window fills the whole screen anyway.
- Lower
--sf-z-indexif an element of the website, such as a menu or the cookie banner, must stay above the chat: every element with a level higher than the value you choose goes on top. - To hide the widget on a page, apply the rule
#chat-widget-container { display: none; }on that page only. You need it, for example, on the page where you put the chat with the iframe.
#Isolation from the website's CSS
The chat is isolated from the rest of the page: the website's CSS doesn't get into the chat and the chat's CSS doesn't get out. From the website you control only the container and the three CSS variables.
#Content Security Policy
If the website sends a Content Security Policy (CSP), the policy must allow the addresses the widget loads its parts from and communicates with. Otherwise the button doesn't appear, or the chat opens but doesn't answer. Add these origins to the directives the website already uses:
| Directive | Origins to add | What it's for |
|---|---|---|
script-src | https://cdn.supportfast.ai | chatbot.js and the widget's parts, which come from the same folder. |
font-src | https://cdn.supportfast.ai | The chat's font. |
connect-src | https://server.supportfast.ai and wss://server.supportfast.ai | The agent, the messages, attachment uploads and real-time updates, for example operators' replies. |
img-src | https: and blob: | The agent's photo or logo, images in answers, attachments and the preview of a photo before it's sent. Images come from several addresses, temporary ones too: that's why https: is needed. |
media-src | https: | Playing voice messages in the chat. |
frame-src | https://app.supportfast.ai | Only if you put the chat on a page with the iframe: it's the address you find in the iframe code. |
HTTP · example header with only the widget's directives
Content-Security-Policy:
script-src 'self' https://cdn.supportfast.ai;
font-src 'self' https://cdn.supportfast.ai;
connect-src 'self' https://server.supportfast.ai wss://server.supportfast.ai;
img-src 'self' https: blob:;
media-src 'self' https:;
frame-src 'self' https://app.supportfast.ai
- The widget needs neither
'unsafe-inline'nor'unsafe-eval'. The scripts you write in the page yourself, such aswindow.chatbotUserDataorwindow.ChatbotConfig, are inline scripts instead: with a policy without'unsafe-inline', give them anonceor move them to a file. - For voice messages, the browser must grant the page access to the microphone. If the website sends the
Permissions-Policyheader, it must containmicrophone=(self). In the iframe, the console's code already hasallow="microphone". - On a reseller's portal the addresses can be different: for
script-src,font-srcandframe-src, use the domains you find in the code copied from the console.
How to check. Open the website, then the browser console (F12), and open the chat. If the policy blocks something, the console shows an error naming the directive and the blocked address: add it and try again.
#What it saves in the browser
The widget uses only localStorage: no cookies, no sessionStorage or IndexedDB. With the button, the data is stored on your website's domain; with the link and the iframe, on the chat's domain.
- The privacy consent given by the visitor is valid until the same day of the following month. A conversation idle for more than 31 days doesn't reopen on its own.
- The widget's keys start with
sf:. If a cookie manager clearslocalStorage, exclude them: otherwise the chat starts from scratch at every visit. - If the browser denies
localStorage, the widget works without memory.
#Messages in the browser console
During normal operation the widget doesn't write to the console. When something goes wrong, it writes a message in English that starts with [SupportFast]:
| Message | What it means |
|---|---|
script tag not found: it needs id="supportfast-script" or id="chatbot-script" and a src. | The tag doesn't have the right id or the src. Also check that a plugin hasn't removed the id. |
data-chatbot-id is missing on the script tag. | The agent's code is missing. |
the widget could not be loaded. | The widget's parts didn't arrive: network, Content Security Policy, or chatbot.js copied to your own server. |
Some cases produce no message: agent paused, code that doesn't exist, domain not authorized, browser too old. The causes and fixes are in Website widget.
#Supported browsers
The widget works on Chrome and Edge from version 85, on Firefox from 101 and on Safari from 16.4. On iPhone and iPad it needs iOS or iPadOS 16.4 or later. On older browsers the button doesn't appear, with no effect on the rest of the page.
Voice messages also need a browser that can record audio, and access to the microphone. Where they're missing, the microphone doesn't appear.
#Versions and updates
The tag always points to the same chatbot.js: new versions arrive on their own, without touching the website. To find out which version is running, type window.SupportFast.version in the browser console.