Docs
Install OpenMate
One script tag adds the assistant to your website. It works on any stack — pick your platform below and copy the snippet.
<script src="https://api.openmate.bond/widget.js" data-bot-id="YOUR_BOT_ID" defer></script>Paste your own data-bot-id where it says YOUR_BOT_ID.
In four steps
- 1
Create your assistant
Sign up and copy your bot id — the public identifier you paste into the tag.
- 2
Register your website origin
Add your exact site origin (for example https://acme.com) in the dashboard’s Origins page. Without it, the widget refuses to load.
- 3
Paste the script tag
Add the tag to your site using the guide for your stack below. One tag, once.
- 4
Check it loads
Open your site, look for the chat button bottom-right, and ask it a question.
Choose your platform
The install is the same tag in every case — only the file changes.
Plain HTML / CSS / JavaScript
Paste the tag before the closing </body> tag on every page (or in your shared layout/footer).
<!DOCTYPE html><html> <body> <!-- your page content --> <script src="https://api.openmate.bond/widget.js" data-bot-id="YOUR_BOT_ID" defer ></script> </body></html>No build step, no framework. If your site has a shared footer file, add it there once and every page gets it.
React (Vite / CRA / plain)
Add it once to the public index.html — Vite and CRA both serve this file unchanged.
<!-- index.html (Vite) or public/index.html (CRA) --><body> <div id="root"></div> <script src="https://api.openmate.bond/widget.js" data-bot-id="YOUR_BOT_ID" defer ></script></body>Keep it outside <div id="root">: React only manages its own root, so the widget is never touched by re-renders.
React — inject at runtime
No HTML file to edit? Load the script from a top-level component with an effect.
import { useEffect } from 'react';export default function OpenMateWidget() { useEffect(() => { const s = document.createElement('script'); s.src = 'https://api.openmate.bond/widget.js'; s.setAttribute('data-bot-id', 'YOUR_BOT_ID'); s.defer = true; document.body.appendChild(s); return () => s.remove(); }, []); return null;}Render <OpenMateWidget /> once in App. The cleanup removes the tag on unmount so a hot reload cannot mount two.
Next.js (App Router)
Use next/script in the root layout so it loads once for the whole app.
// app/layout.jsimport Script from 'next/script';export default function RootLayout({ children }) { return ( <html lang="en"> <body> {children} <Script src="https://api.openmate.bond/widget.js" data-bot-id="YOUR_BOT_ID" strategy="afterInteractive" /> </body> </html> );}strategy="afterInteractive" keeps the site fast: the widget loads after the page is usable.
Next.js (Pages Router)
Put it in _app.js so it appears on every route.
// pages/_app.jsimport Script from 'next/script';export default function App({ Component, pageProps }) { return ( <> <Component {...pageProps} /> <Script src="https://api.openmate.bond/widget.js" data-bot-id="YOUR_BOT_ID" strategy="afterInteractive" /> </> );}Vue (Vite / Vue CLI)
Add it to index.html — the Vue app mounts into #app, so the tag sits alongside it.
<!-- index.html --><body> <div id="app"></div> <script src="https://api.openmate.bond/widget.js" data-bot-id="YOUR_BOT_ID" defer ></script> <script type="module" src="/src/main.js"></script></body>For Nuxt, put the same tag in nuxt.config or app.html.
Angular
Add the tag to src/index.html. Angular only manages <app-root>.
<!-- src/index.html --><body> <app-root></app-root> <script src="https://api.openmate.bond/widget.js" data-bot-id="YOUR_BOT_ID" defer ></script></body>The widget needs no Angular module. If your CSP is strict, allow the script origin (see the checklist below).
Troubleshooting
- Nothing appears on the page
- Check the browser console. “ORIGIN_NOT_ALLOWED” means your site’s origin is not registered — add it in the dashboard’s Origins page. The origin must match exactly (scheme + host + optional port, no trailing slash).
- Blocked by a Content-Security-Policy
- Allow your OpenMate host in
script-srcandframe-src. The widget mounts a sandboxed iframe, so the frame origin must be allowed too. - It loaded once but disappeared
- A single-page-app re-render replaced the DOM. Load the script once from an HTML file or a root layout (as the guides above do), not inside a component that unmounts.
Ready to add your bot id?
Create an assistant to get your bot id, then register the site you will embed it on.
Create your assistant