One script tag puts an AI support chat on any website. It answers from the knowledge base of the AI project you point it at, matches your brand colour, and opens a ticket when it cannot help.
The widget answers only from its project's knowledge base. Add documents in AI Voice Agent → Knowledge Base, or import your site with the web crawler, and set them Live. An empty knowledge base means an agent that can only say it doesn't know.
In AI Voice Agent → Chat Widget, pick the accent colour, wording and corner, then turn the widget on. The preview beside the settings is what visitors get.
Copy the snippet from that page and put it before the closing </body> tag of every page you want the widget on. It loads asynchronously and blocks nothing.
The snippet is one line. data-portal is your account's public embed key, and data-agent is the AI project that answers.
<script async src="https://aiclosr.ai/chat.js"
data-portal="clsr_your_portal_key"
data-agent="support"></script>Leave data-agent off and the tag talks to your default project. Name a project's slug and it talks to that one — which is how one account runs a different widget, with a different knowledge base and a different colour, on each site it looks after.
The portal key is public by design: it identifies the account, never authenticates it. If it ends up somewhere you would rather it hadn't, rotate it from Embed & Tracking and re-paste the snippet.
| Attribute | What it does |
|---|---|
| data-portal | Required. Your account's public embed key (clsr_…). |
| data-agent | The AI project's slug. Omit it to use your default project. |
| data-color | Overrides the accent colour for this page only, e.g. #bc6c25. Normally set it in Closr instead so every site stays in sync. |
| data-position | "bottom-right" (default) or "bottom-left". Useful when a cookie bar already owns one corner. |
| data-mount | A CSS selector, e.g. "#support-chat". Renders the panel inside that element instead of as a floating bubble — for a dedicated support page. |
| data-open | Set to "true" to open the panel automatically on page load. |
Paste the snippet immediately before </body> in your template. If your site uses a shared footer include, put it there once rather than on each page.
Without a plugin: Appearance → Theme File Editor → footer.php, and paste before </body>. Use a child theme, or a theme update will overwrite it.
With a plugin (recommended): install WPCode or Insert Headers and Footers, then paste the snippet into the “Footer” box and save. It survives theme updates.
Elementor: Site Settings → Custom Code → Add New, location “Body — End”.
Online Store → Themes → ⋯ → Edit code. Open layout/theme.liquid and paste the snippet just before </body>. Save; it applies to every page including checkout-adjacent ones.
Project Settings → Custom Code → Footer Code, paste, then Publish. Custom code only runs on the published site, not in the Designer preview — so test on your live or staging domain.
Settings → Developer Tools → Code Injection → Footer. Paste and save. On Business plans and above; on Personal, add it per page via a Code Block instead.
Settings → Custom Code → Add Custom Code. Paste the snippet, apply it to “All pages”, and choose “Body — end”.
New Tag → Custom HTML, paste the snippet, trigger “All Pages”, then publish the container. Leave “Support document.write” unchecked — the tag is async and does not need it.
If you fire it on consent, use your consent trigger instead of All Pages: the widget does not set cookies itself, but it does read the Closr visitor cookie if your tracking snippet has already set one.
The widget is framework-agnostic — it appends itself to document.body and lives outside your app's render tree, so a re-render never disturbs it. In Next.js (App Router), add it to app/layout.tsx:
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Script
src="https://aiclosr.ai/chat.js"
data-portal="clsr_your_portal_key"
data-agent="support"
strategy="afterInteractive"
/>
</body>
</html>
);
}Load it once, at the root. Mounting it inside a page component would add a second widget on every navigation.
To put the chat inside your own layout — a support page, a sidebar, a help centre — give it an element to fill:
<div id="support-chat" style="height: 560px; max-width: 420px"></div>
<script async src="https://aiclosr.ai/chat.js"
data-portal="clsr_your_portal_key"
data-agent="support"
data-mount="#support-chat"></script>In this mode there is no launcher bubble; the panel is always open and fills the element you named. Give that element a height — the panel fills its container, and a container with no height is a panel with no height.
By default, any site with your portal key can show the widget. Once you list allowed origins, only those domains can — everywhere else the script quietly renders nothing.
Set them per widget in AI Voice Agent → Chat Widget (one domain per line, with the scheme: https://yourdomain.com). Leave that blank and the widget inherits your account-wide list from Embed & Tracking. A per-widget list is what keeps an agency's client sites separated: each client's widget answers only on that client's domain.
Include every domain the widget must work on — www and non-www are different origins, as are staging subdomains.
Every factual answer comes from documents you marked Live on that project. When retrieval finds nothing relevant, the agent says it doesn't have that detail rather than inventing one.
Account-specific questions, billing disputes, upset visitors and anything the knowledge base doesn't cover open a ticket in your inbox, tagged with an AI category and priority. You can switch this off to make the widget purely informational.
The email prompt appears once the visitor is already talking, never before their first question. Give it and the conversation attaches to a contact record in the CRM.
Reply to the conversation from the inbox and it appears in the visitor's panel while they are still on the page.
The widget keeps the conversation in sessionStorage, so a reload continues the thread and a closed tab ends it. It reads the Closr visitor cookie only if your tracking snippet already set one.
Each widget has a daily message cap, and its AI usage is counted against its own project — so an account running several widgets can see what each one costs.
The widget never throws errors onto your page: an unknown key, a disallowed origin, and a switched-off widget all look identical from the outside — nothing renders. Work down this list.
| Check | What to do |
|---|---|
| Is it on? | AI Voice Agent → Chat Widget, for the project the tag names. A widget is off until you turn it on. |
| Is chat on for the account? | Embed & Tracking has a master chat switch. Off there silences every widget. |
| Right project? | data-agent must match the project's slug exactly. A wrong slug means no widget at all, rather than the default one — silently answering from the wrong knowledge base would be worse. |
| Origin allowed? | The domain in the browser's address bar must be on the widget's list (or the account list) — www and non-www included. |
| Plan? | Support chat is a paid feature. On the free plan the widget loads and then declines to answer. |
| Tag actually on the page? | View source and search for chat.js. Some builders strip <script> tags from rich-text or content blocks — use the platform's custom-code field instead. |
| Knowledge base empty? | The widget renders, but every answer is “I don't have that detail.” Add Live documents to the project. |
Send us the URL you pasted it on and we will tell you exactly what is stopping it.
Replies within one business day.