API Reference
The ChatCops singleton is exposed on window.ChatCops by the script tag build (chatcops.min.js or chatcops.full.min.js), or importable from the ESM bundle.
Methods
Section titled “Methods”ChatCops.init(config)
Section titled “ChatCops.init(config)”Initialize the widget with a configuration object. Must be called before any other method if not using script tag auto-init.
// Popup mode (default)ChatCops.init({ apiUrl: 'https://your-api.com/chat', theme: { accent: '#6366f1' }, branding: { name: 'My Bot' }, welcomeMessage: 'Hello! How can I help?',});
// Inline modeChatCops.init({ apiUrl: 'https://your-api.com/chat', mode: 'inline', container: '#chat-container', branding: { name: 'My Bot' },});Calling init() again will destroy the previous instance and create a new one.
In the ESM and single-file builds, init() returns the Widget instance. In the script tag loader (chatcops.min.js) it returns nothing, since the chat itself loads later. Use the ChatCops methods there, which work before and after the chat has loaded.
ChatCops.open()
Section titled “ChatCops.open()”Programmatically open the chat panel.
- Popup mode: Shows the panel and updates the FAB icon.
- Inline mode: Shows the panel (useful if you’ve previously called
close()).
document.querySelector('#help-btn')?.addEventListener('click', () => { ChatCops.open();});ChatCops.close()
Section titled “ChatCops.close()”Close the chat panel.
- Popup mode: Hides the panel and resets the FAB icon.
- Inline mode: Hides the panel. Call
open()to show it again.
ChatCops.close();ChatCops.toggle()
Section titled “ChatCops.toggle()”Open the chat if it’s closed, and close it if it’s open. With the script tag build, the first call loads the chat.
document.querySelector('#help-btn')?.addEventListener('click', () => ChatCops.toggle());ChatCops.sendMessage(text, options?)
Section titled “ChatCops.sendMessage(text, options?)”Send a message as if the visitor typed it, for example from a “Ask about pricing” button on your page. The chat opens first, unless you pass { open: false }. The promise resolves when the reply has finished. While a reply is still coming, another message is ignored, as it is in the input.
document.querySelector('#pricing-question')?.addEventListener('click', () => { void ChatCops.sendMessage('How much is the Team plan?');});ChatCops.newConversation()
Section titled “ChatCops.newConversation()”Start a fresh conversation: a new conversation id, and the chat back to the welcome message. A reply that’s still coming is stopped. Pre-chat answers are kept, so the visitor isn’t asked again.
ChatCops.newConversation();ChatCops.clear()
Section titled “ChatCops.clear()”Like newConversation(), and also removes what the widget saved in this browser: the transcript and the pre-chat answers, so the form shows again. Use it when a visitor signs out.
ChatCops.clear();ChatCops.destroy()
Section titled “ChatCops.destroy()”Completely remove the widget from the DOM and clean up all event listeners.
- Popup mode: Removes FAB, panel, and welcome bubble from the page.
- Inline mode: Removes the widget from the container element.
ChatCops.destroy();ChatCops.on(event, callback)
Section titled “ChatCops.on(event, callback)”Subscribe to widget events. Returns an unsubscribe function.
Handlers can be registered before init() (including from inline scripts before DOMContentLoaded), and are preserved across repeated init() calls.
const unsub = ChatCops.on('message', (data) => { console.log('New message:', data);});
// Later, remove the listener:unsub();ChatCops.off(event, callback)
Section titled “ChatCops.off(event, callback)”Remove a specific event listener from both the persistent registry and the active widget instance.
function onOpen() { console.log('Widget opened');}
ChatCops.on('open', onOpen);ChatCops.off('open', onOpen);ChatCops.setUser(user)
Section titled “ChatCops.setUser(user)”Tell the widget who the signed-in visitor is.
tokenis the identity token for signed-in visitors, which your server signs.nameandemailare sent to the bot as visitor details with the first message of a conversation, and the name greets them.
Switching to another user, or setUser(null) when the visitor signs out, clears the chat, so one person’s conversation never shows for the next. With the script tag build, a call before the chat has loaded is kept until it does.
declare const session: { name: string; email: string; chatToken: string };
ChatCops.setUser({ name: session.name, email: session.email, token: session.chatToken });
// When the visitor signs out:ChatCops.setUser(null);ChatCops.setContext(data)
Section titled “ChatCops.setContext(data)”Details the bot should know for the next messages, such as the visitor’s plan or what’s in their cart. They’re sent with each message as page context: at most 20 fields, keys up to 40 characters, values up to 500. The bot sees them as details the page added, not as verified facts. setContext(null) removes them. Nothing is sent when pageContext: false.
ChatCops.setContext({ plan: 'Team', seats: '12' });ChatCops.update(changes)
Section titled “ChatCops.update(changes)”Change how the running chat looks or what it says, without loading it again. It takes these options from init():
theme, exceptposition: moving the chat needsinit()branding,placeholderandstringsdisclosurewelcomeMessageandsuggestions
What you leave out stays as it is, and that goes for each field inside theme, branding and strings too. A chat with only the welcome message shows the new one right away. Once the visitor has written, the new welcome message and suggestions wait for the next conversation. With the script tag build, a call before the chat has loaded is kept until it does, and the launcher button takes the new theme straight away.
// A single-page app moving to its pricing page:ChatCops.update({ branding: { name: 'Sales', subtitle: 'Usually replies in a minute' }, welcomeMessage: 'Questions about plans? Ask here.', suggestions: ['Compare plans', 'Is there a free trial?'],});
// Following the site's own dark mode toggle:ChatCops.update({ theme: { mode: 'dark' } });ChatCops.registerLocale(code, strings, options?)
Section titled “ChatCops.registerLocale(code, strings, options?)”Add a language the widget doesn’t ship, or replace one of its own. Strings you leave out stay in English. Pass { dir: 'rtl' } for a right-to-left language. Register before init(), then use the code as locale.
ChatCops.registerLocale('sv', { welcomeMessage: 'Hur kan jag hjälpa dig?', inputPlaceholder: 'Skriv ett meddelande…', sendButton: 'Skicka',});ChatCops.init({ apiUrl: '/api/chat', locale: 'sv' });See Internationalization for every string.
ChatCops.version
Section titled “ChatCops.version”The widget’s version, such as "0.7.0".
Auto-Initialization
Section titled “Auto-Initialization”When using the CDN script tag, the widget auto-initializes by reading data-* attributes:
Popup (default)
Section titled “Popup (default)”<script src="https://cdn.jsdelivr.net/npm/@chatcops/widget/dist/chatcops.min.js" data-api-url="https://your-api.com/chat" data-accent="#6366f1"></script>Inline
Section titled “Inline”<div id="my-chat" style="width: 400px; height: 500px;"></div><script src="https://cdn.jsdelivr.net/npm/@chatcops/widget/dist/chatcops.min.js" data-api-url="https://your-api.com/chat" data-mode="inline" data-container="#my-chat"></script>The script tag approach is equivalent to calling ChatCops.init() with the corresponding config. You can still use the programmatic API after auto-init (e.g., ChatCops.open()).
ESM Usage
Section titled “ESM Usage”import ChatCops from '@chatcops/widget';
// PopupChatCops.init({ apiUrl: '/api/chat' });
// Inline with element referenceconst el = document.getElementById('chat');if (!el) throw new Error('Chat container not found');ChatCops.init({ apiUrl: '/api/chat', mode: 'inline', container: el,});
// Use methods as neededChatCops.on('message', (msg) => console.log(msg));React / Framework Usage
Section titled “React / Framework Usage”For inline mode in React or other frameworks, pass the container element directly:
import { useEffect, useRef } from 'react';import ChatCops from '@chatcops/widget';
function Chat() { const ref = useRef(null);
useEffect(() => { if (!ref.current) return; ChatCops.init({ apiUrl: '/api/chat', mode: 'inline', container: ref.current, }); return () => ChatCops.destroy(); }, []);
return <div ref={ref} style={{ width: 400, height: 500 }} />;}