Documentation

Embed the AI chat widget.

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.

Install

Three steps

01

Give the project something to say

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.

02

Style it and switch it on

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.

03

Paste the tag on your site

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 tag

What the snippet says

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.

AttributeWhat it does
data-portalRequired. Your account's public embed key (clsr_…).
data-agentThe AI project's slug. Omit it to use your default project.
data-colorOverrides 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-mountA CSS selector, e.g. "#support-chat". Renders the panel inside that element instead of as a floating bubble — for a dedicated support page.
data-openSet to "true" to open the panel automatically on page load.
Platforms

Where to paste it

Plain HTML, PHP, or a static site

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.

WordPress

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”.

Shopify

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.

Webflow

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.

Squarespace

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.

Wix

Settings → Custom Code → Add Custom Code. Paste the snippet, apply it to “All pages”, and choose “Body — end”.

Google Tag Manager

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.

React, Next.js, Vue, and other SPAs

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.

Inside a page, not floating

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.

Restrict it

Who is allowed to load your widget

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.

Behaviour

What visitors experience

Answers

Grounded in your knowledge base

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.

Escalation

A ticket, not a dead end

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.

Contacts

Email captured after the fact

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.

Handover

Your reply reaches them live

Reply to the conversation from the inbox and it appears in the visitor's panel while they are still on the page.

Privacy

No cookies of its own

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.

Spend

Capped, and attributed per project

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.

Troubleshooting

If nothing appears

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.

CheckWhat 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.

Need a hand with the install?

Send us the URL you pasted it on and we will tell you exactly what is stopping it.

Replies within one business day.