Websites
Add it to your site
Paste this before the closing body tag. Find your staff ID in Staff, On your website, where you also list the web addresses allowed to show it.
<script src="https://custardai.dev/widget.js"
data-agent="YOUR_STAFF_ID" async></script>Works on any site: WordPress, Shopify, Webflow, Squarespace, React, Next.js. Shape and colour you pick in the dashboard update by themselves.
Using React?
Use the component instead. It loads the same script, passes visitor details and keeps them in sync, and is safe with server rendering.
npm install @custardai/react
import { CustardWidget } from "@custardai/react";
<CustardWidget
agentId="YOUR_STAFF_ID"
user={{ userId: user.id, email: user.email, fullName: user.name }}
onAction={(a) => { if (a.action === "open_page") { router.push(a.url); return true; } }}
/>Websites
Tell it who the visitor is
If the visitor is signed in, pass their details. Your staff knows them at once, and the same values come back to you after the conversation.
<script>
// Call any time, before or after the chat opens.
window.CustardWidget?.setContext({
userId: "u_123",
email: "ana@example.com",
fullName: "Ana Silva",
plan: "pro"
});
</script>Flat values only (text, numbers, true/false), up to 20 keys, text up to 500 characters.
Websites
Let it show people around
List the pages your staff may open and the things it may point at. It only ever picks one of your labels, so it can never send a visitor somewhere you did not allow.
window.CustardWidget?.setGuide({
pages: [
{ label: "Pricing", url: "/pricing" },
{ label: "Create account", url: "/signup" }
],
spots: [
{ label: "Sign up button", selector: "#signup" },
{ label: "Plan picker", selector: "[data-plans]" }
]
});Or skip the list and mark your own buttons, the same way Custard AI guides owners around its own dashboard. Every element with data-guide becomes a spot, named by data-guide-label (or its text). When a visitor asks "where do I export my invoices?", your staff scroll there, open the tab or panel it sits in and ring it. When the visitor taps the ringed spot or a data-guide-copy button, the AI hears it and moves on. Call CustardWidget.refreshGuide() after a big screen change.
<!-- Mark the things your staff may point at. No setup code needed. -->
<button data-guide="export" data-guide-label="Export invoices">Export</button>
<!-- A tab is chosen first, then the spot inside it gets the ring -->
<button data-guide="billing-tab" data-guide-select data-guide-then="card-form">Billing</button>
<!-- A folded panel opens by itself when a spot inside it is shown -->
<details data-guide-open>
<summary>Advanced</summary>
<input data-guide="api-key" data-guide-label="API key box" />
<button data-guide-copy="API key">Copy</button>
</details>Opening a page loads it on the same site. Pointing scrolls to the element and draws a soft ring around it for a few seconds. Links to other websites are ignored.
When a new page loads, the chat opens again by itself with the conversation so far; a voice call pauses until the visitor taps the mic. On single page apps, handle the move yourself so a voice call never pauses:
// Single page apps: move with your own router so the voice call keeps going.
window.CustardWidget?.onAction((a) => {
if (a.action === "open_page") {
router.navigate(a.url);
return true; // handled, Custard does nothing else
}
});
// Or listen for the event anywhere on the page:
window.addEventListener("custard:action", (e) => {
console.log(e.detail); // { action, label, url, selector }
});Work together on screen: when the AI opens one of your screens (a planner, a calendar, a guest picker), the visitor can tap their choices there instead of saying them. Report each choice and the AI hears it straight away, confirms it in a few words and moves to the next question. Only flat values are kept (text, numbers, lists of text, up to 12 fields), and they are treated as the visitor's answer, never as instructions.
// Your own screens open when Custard asks (onAction above), e.g. a hosting planner.
// When the visitor picks something there, tell the AI so it carries on from that choice:
window.CustardWidget?.reportAction("picked_time", { date: "2026-11-06", time: "20:00", guests: 8 });
window.CustardWidget?.reportAction("invited_guests", { guests: ["Ana", "Kofi", "Mei"] });To save the result in your system (create the event, mark someone available, add them to a guest list), switch on "Make changes in your system" for the staff member. Once the visitor confirms, your lookup link receives event: "action" with action: "other", the member or account id as reference and every detail in details. Reply with what was done and the AI tells the visitor exactly that.
Stuck?
Write to hello@custardai.dev and we will help you connect it.