@custral/widget is the Custral chat widget as a React component, plus the
headless engine underneath it. It uses a publishable key (pk_…), which is
safe to ship to the browser.
No bundler, or not a React app? Load the standalone
widget.js script instead. It is this same
package: a 7 KB script that draws the launcher, and the chat itself, built on
Preact (a small stand-in for React), which loads when a visitor reaches for it.Install
The widget
One component, mounted once, anywhere in your tree. It renders its own bubble and panel and positions itself.string
required
Your publishable key (
pk_…), from Settings → Applications.string
Target a specific widget channel. Defaults to the workspace’s first.
string
Defaults to
https://api.custral.com.boolean
Force dark or light. Omitted, the widget uses the theme set in Settings → Chat Widget, where Auto reads the host page.
{name?, email?, phone?}
Pre-fill who the visitor is. Skips the intake form. Self-reported, so it only fills
empty fields on the visitor’s record.
string
A token minted by your server that vouches for who this visitor is. See
below.
Identifying a visitor
visitor is convenient and self-reported: it fills the form in, and the person
on the other end typed it. That is fine for lead capture and not fine for
anything that has to be right.
identityToken is the version the product will trust. Your server mints it with
its secret key, so the claim comes from you rather than from the browser:
Signing a visitor out
The widget remembers its visitor in the browser between page loads. On a shared computer, the next person to use your app would resume the previous visitor’s conversations, unless that visitor was signed in with anidentityToken: the
widget never reopens those without the same person’s token. Call
resetCustralChat() when someone signs out:
identityToken and visitor
it was rendered with until you pass a different token, so the person who just
left is not signed straight back in. Requires @custral/widget 1.0.1 or later.
Building your own UI
The component is assembled from parts the package also exports, so you can replace the shell and keep the machinery.useCustralChat owns the conversation: init, socket, messages, typing,
intake, conversation list, booking. ChatBubble, ChatPanel, ChatHeader,
ChatMessageList, ChatMessage, ChatInput, IntakeForm, ConversationList
and SchedulePicker are the pieces it drives.
For no React at all, CustralChat is the engine on its own:
This
CustralChat is the engine class. The window.CustralChat that the widget.js script adds is a different
object: the page API with open(), hide() and events. See
Control the chat from your page. The React component
doesn’t add it, and doesn’t read data-custral-open.Construct a headless client.
Loads widget config, restores any prior visitor from
localStorage, and
returns the resolved config (or null on failure).Registers a callback for agent messages pushed in real time.
Sends a visitor message, creating a conversation on the first send.
Attaches self-reported contact info for lead capture.
Tears down the socket and in-memory session. By default the browser keeps its
visitor, so the next
init() resumes it. Pass {clearSession: true} when a
user signs out, so the next person on this browser starts as a new visitor.Troubleshooting
CustralChat: publishableKey is required / init returns null
CustralChat: publishableKey is required / init returns null
The widget needs a publishable key (
pk_…), not a secret key. Create one in
Settings → Applications. If init() returns null, the /widget/init
call failed: check the browser console and confirm the key and channelId.No real-time messages arrive
No real-time messages arrive
Delivery uses a WebSocket to
/widget. If your environment blocks
WebSockets, history still loads on demand, but pushed agent replies will not
arrive. Look for Socket connected in the console.Hooks throw, or the widget renders blank
Hooks throw, or the widget renders blank
Two copies of React in one page. React and React DOM are peers here for that
reason; check your bundler is deduping them.
I was importing from @custral/ui 1.x or @repo/widget
I was importing from @custral/ui 1.x or @repo/widget
CustralChat and the components are all in @custral/widget now. Change the
import and nothing else. @custral/ui 2.0 is a different package, the
React data SDK.