Why the Cevro Widget?
Cevro integrates with the helpdesks you already use—Intercom, Zendesk, LiveChat, Zoho—and that works great. But there’s a ceiling. Third-party platforms weren’t built for AI-first support, and some features just aren’t possible when you’re working within someone else’s system. The Cevro Widget removes that ceiling. It’s a native chat experience built from the ground up for AI-powered support. Faster responses, richer interactions, and new capabilities that ship here first.Built for AI
Designed from the ground up for AI-powered support. Features like rich player context, real-time tool calls, and intelligent escalation work seamlessly—no third-party constraints.
Your Workspace, Your Widget
Connects directly to your AI Procedures, knowledge base, and back-office integrations. Everything you’ve configured in Cevro works out of the box.
New Features First
Advanced capabilities—like proactive messaging, smart nudges, and deeper personalization—will launch here first. Some features won’t be possible on third-party widgets at all.
Simple & Reliable
One integration, one source of truth. No complex API choreography between systems. Faster responses, fewer failure points.
How It Works
Installation
Copy and paste this snippet before the closing</body> tag. The loader fetches the latest SDK version automatically.
Configuration
Required Settings
| Setting | Type | Description |
|---|---|---|
apiBase | string | Backend API URL (e.g., https://chat.cevro.ai) |
workspaceId | string | Your workspace identifier |
brandId | string | The brand to use for this widget instance |
Optional Settings
| Setting | Type | Default | Description |
|---|---|---|---|
player | PlayerData | — | Authenticated player information |
alignment | 'left' | 'right' | 'right' | Widget horizontal position |
verticalPadding | number | 20 | Distance from bottom (px) |
horizontalPadding | number | 20 | Distance from edge (px) |
primaryColor | string | — | Primary brand color (hex, e.g. '#6366f1') |
theme | ThemeConfig | — | Custom theme colors and styling |
locale | Partial<LocaleStrings> | — | UI text overrides for localization |
hideDefaultLauncher | boolean | false | Hide the default launcher button |
customLauncherSelector | string | — | CSS selector for your own launcher element |
zIndex | number | 2147483647 | Stacking order |
Theming & Appearance
The widget appearance can be customized at two levels:- Admin dashboard — Configure colors, logo and icons in Settings → Cevro (applies to all visitors)
- SDK config — Override specific properties per-instance during initialization
Primary Color
The simplest way to brand the widget. Set a singleprimaryColor and all accent elements (launcher button, user message bubbles, send button, links) will derive from it automatically:
Custom Theme
For granular control, pass atheme object to override specific colors and styles:
Theme Properties Reference
General
| Property | Type | Description |
|---|---|---|
backgroundColor | string | Main background color of the chat window |
backgroundSecondaryColor | string | Secondary/alternate background |
textColor | string | Primary text color |
textSecondaryColor | string | Secondary/muted text color |
borderColor | string | Border color for dividers and outlines |
Messages
| Property | Type | Description |
|---|---|---|
userMessageBackgroundColor | string | User message bubble background |
userMessageTextColor | string | User message text color |
agentMessageBackgroundColor | string | Agent/AI message bubble background |
agentMessageTextColor | string | Agent/AI message text color |
Header
| Property | Type | Description |
|---|---|---|
headerBackgroundColor | string | Chat header background |
headerTextColor | string | Chat header text color |
Input
| Property | Type | Description |
|---|---|---|
inputBackgroundColor | string | Message input field background |
Launcher Button
| Property | Type | Description |
|---|---|---|
launcherBackgroundColor | string | Launcher button background (defaults to primaryColor) |
launcherIconColor | string | Launcher button icon color |
launcherHoverShadowColor | string | Shadow color on hover (e.g. rgba(0, 0, 0, 0.3)) |
Action Buttons
| Property | Type | Description |
|---|---|---|
sendButtonBackgroundColor | string | Send button background (defaults to primaryColor) |
sendButtonIconColor | string | Send button icon color |
fileButtonBackgroundColor | string | File/attachment button background |
fileButtonIconColor | string | File/attachment button icon color |
Style
| Property | Type | Description |
|---|---|---|
borderRadius | number | Border radius in pixels for rounded corners |
shadowColor | string | Box shadow color with opacity (e.g. rgba(0, 0, 0, 0.2)) |
Admin Dashboard Appearance
All theme properties can be managed from the admin dashboard under Settings → Cevro → Appearance:- Primary Color — Set the main brand color. All accent elements derive from it automatically.
- Full Theme — Override any individual color (backgrounds, text, messages, buttons, launcher, etc.).
- Reset to Primary — Clear all custom theme overrides and go back to deriving everything from the primary color.
- Bubble Icon — Custom icon for the launcher button.
- Custom Logo — Brand logo displayed in the chat header.
Theme settings are merged with the following priority (highest first):
- SDK config — Values passed in
themeduring initialization - Admin dashboard — Appearance configured in Settings → Cevro
- Defaults — Built-in default values
Player Authentication
For authenticated players, pass their information during initialization:Supported Player Fields
| Field | Type | Description |
|---|---|---|
playerId | string | Required. Unique player identifier |
playerHash | string | HMAC signature for identity verification |
firstName | string | Player’s first name |
lastName | string | Player’s last name |
email | string | Player’s email address |
phone | string | Player’s phone number |
avatar | string | URL to player’s avatar image |
createdAt | number | Unix timestamp of player account creation |
customAttributes | object | Custom key-value pairs (string, number, or boolean values) |
Identifying Players After Login
Useidentify() to associate an anonymous visitor with an authenticated player after they log in:
identify() performs a soft re-initialization — it reconnects with the new player identity and creates a new session without destroying the UI. If called before boot(), the data is stored and used when boot() is called later. Returns a Promise if you need to wait for completion.
Connecting Player Data to Integrations
Player data you pass through the widget becomes available to your AI Procedures and back-office integrations. Here’s how.Standard Fields
Fields likeplayerId, email, firstName, lastName, and phone are stored directly on the player’s contact record. Integrations can reference them automatically — for example, a tool parameter set to {{contact.email}} will resolve to the player’s email.
Custom Attributes
For additional data (session tokens, account types, VIP levels), usecustomAttributes:
{{contact.sessionToken}}, {{contact.accountType}}, etc.
Define your fields first. Before passing custom attributes, create the corresponding fields in Settings → Player Attributes. This ensures proper type handling and makes the fields visible across your workspace.
Example: Passing a Session Token to a Tool
Define the field
Go to Settings → Player Fields and create a field called
sessionToken (type: string).Pass it in the widget
Include
sessionToken in customAttributes when initializing the widget (see example above).Public API
Lifecycle
| Method | Description |
|---|---|
boot() | Initialize widget, render UI, fetch appearance config from dashboard |
shutdown(options?) | Remove widget. Pass { clearVisitorData: true } to clear local storage. |
show() | Open chat window (also initializes session and WebSocket connection) |
hide() | Close chat window |
toggle() | Toggle visibility |
showLauncher() | Show the launcher button (creates it if hideDefaultLauncher was set) |
hideLauncher() | Hide the launcher button |
Player & Config
| Method | Description |
|---|---|
identify(playerData) | Identify a player after login. Performs soft re-init (async). |
update(config) | Update SDK configuration (theme, locale, etc). Does not re-init session. For player identity changes, use identify(). |
getVisitorId() | Get the current visitor ID |
getUnreadCount() | Get the current unread message count |
Appearance
| Method | Description |
|---|---|
updateAppearance(config) | Dynamically update colors, theme, icons, and logo |
getAppearance() | Get the current appearance configuration |
Custom Launcher
By default the SDK renders a floating launcher button. You can hide it and use your own button instead.Hide the Default Launcher
Use Your Own Launcher Element
PointcustomLauncherSelector at any element on your page. Clicks on that element will toggle the chat window:
Show / Hide Launcher at Runtime
You can show or hide the default launcher dynamically — even if it was hidden at boot:Events
Subscribe to events usingon(). It returns an unsubscribe function:
off():
Available Events
| Event | Payload | Description |
|---|---|---|
boot | — | Widget initialized |
ready | — | WebSocket connected and ready |
show | — | Chat window opened |
hide | — | Chat window closed |
shutdown | — | Widget removed |
session:initialized | { sessionId, contactId, ticketId, isNewSession, isNewTicket } | Session created or restored |
message:received | { ticketId, message } | New message from agent/AI |
message:sent | { message } | Message successfully sent |
unread_count_change | { count } | Unread count changed |
conversation:started | { ticketId } | New conversation started |
conversation:updated | { ticketId, status, message?, closedAt? } | Conversation status changed (e.g. closed) |
chat:new_started | — | New chat started after previous was closed |
typing:start | { ticketId, actor } | Agent/AI started typing |
typing:stop | — | Agent/AI stopped typing |
error | { type, error, message? } | An error occurred |
connection:open | — | WebSocket connected |
connection:close | — | WebSocket disconnected |
connection:error | { error } | WebSocket error |
appearance:updated | WidgetAppearanceConfig | Appearance changed |
Example: Notifications & Analytics
Localization
Override default UI strings by passing alocale object. All fields are optional — only the ones you provide will be overridden:
Available Locale Keys
| Key | Default |
|---|---|
headerTitle | 'Cevro' |
headerSubtitle | 'We typically reply within a few minutes' |
inputPlaceholder | 'How can we help?' |
preChatTitle | 'Start a conversation' |
preChatSubtitle | 'Please provide your contact information to get started.' |
preChatFirstNameLabel | 'First name' |
preChatFirstNamePlaceholder | 'Your first name' |
preChatEmailLabel | 'Email' |
preChatEmailPlaceholder | '[email protected]' |
preChatSubmit | 'Start Chat' |
preChatFirstNameRequired | 'First name is required' |
preChatEmailRequired | 'Email is required' |
preChatEmailInvalid | 'Please enter a valid email' |
closedMessage | 'The agent closed the chat.' |
newConversation | 'Start New Conversation' |
csatTitle | 'How was your conversation?' |
csatSubtitle | 'Your feedback helps us get better.' |
csatPlaceholder | 'Thank you! What stood out?' |
csatSubmit | 'Submit Feedback' |
csatThankYou | 'Thank you for your feedback!' |
poweredBy | 'Powered by Cevro AI' |
File Uploads
Players can upload files directly in the chat:- Max file size: 25MB
- Allowed: Images, documents, audio, video, archives
- Blocked: Executables (.exe, .dll, .js, .php, etc.)
- Rate limit: 5 uploads per minute
Escalation to Human Agents
When the AI cannot resolve an issue or the player requests human help, the conversation is escalated to your configured helpdesk system.Supported Escalation Targets
LiveChat
Conversations transfer to your LiveChat operators. Players continue chatting in the widget while agents respond from LiveChat dashboard.
Intercom
Conversations transfer to your Intercom team. Players continue chatting in the widget while agents respond from Intercom inbox.
Zendesk
Conversations transfer to your Zendesk Agent Workspace via Sunshine Conversations. Players continue chatting in the widget while agents respond from Zendesk.
Built-in Help Desk
No external helpdesk? No problem. Escalated conversations appear in the Cevro inbox. Your team replies directly from the dashboard.
How Escalation Works
With LiveChat, Intercom, or Zendesk configured:- AI determines escalation is needed (or player requests it)
- Conversation is created in your helpdesk
- Human agent receives the full conversation context
- Messages sync bidirectionally:
- Player messages from widget → Helpdesk
- Agent responses from helpdesk → Widget
Zendesk requirement: If you use Zendesk as your escalation target, you must enable Multi-Conversation in your Zendesk account. Without this, escalations will fail after the first conversation per player.To enable: go to Admin Center → Channels → Messaging → Manage settings → Multi-conversations → Turn on.
- AI determines escalation is needed (or player requests it)
- Conversation appears in the Cevro inbox with escalation status
- Your team member opens the ticket and replies directly
- Reply is delivered to the player’s widget in real-time
The player never leaves your website. Whether your team responds from an external helpdesk or directly from the Cevro inbox, the player continues chatting in the widget seamlessly.
Admin Settings
Configure widget appearance and security in Settings → Cevro.Appearance
Manage the complete visual appearance of your widget from the dashboard — no code changes needed.| Setting | Purpose |
|---|---|
| Primary Color | Set the main brand color. All accent elements (launcher, send button, user messages, links) derive from it. |
| Full Theme | Override any individual color for every widget element: backgrounds, text, messages, header, input, launcher, buttons. |
| Reset to Primary | Clear all custom theme overrides and go back to a clean look derived from just the primary color. |
| Bubble Icon | Custom icon for the launcher button |
| Custom Logo | Brand logo displayed in the chat header |
| Auto-open | Automatically open the chat window on page load |
| CSAT Survey | Enable/disable the satisfaction survey after conversations end |
Security
| Setting | Purpose |
|---|---|
| HMAC Verification | Require player identity verification |
| HMAC Secret | Key for generating playerHash (server-side) |
| Allowed Domains | Whitelist domains that can embed the widget |
HMAC Setup
Generate HMAC Secret
In Settings → Cevro, click Generate to create an HMAC secret key. Copy it immediately — it’s only shown once.
Store Securely
Save the secret on your backend server. Never expose it to frontend code or commit it to version control.
Automatic authentication: When HMAC verification is enabled and you toggle on Require Identity Verification in Settings → Cevro, players are automatically authenticated — no security questions needed.How it works:
- Player identified before first message — Authentication happens instantly at session start. The AI skips verification and goes straight to handling the request.
- Player identifies mid-conversation (e.g., logs in after starting chat) — The AI detects the identity automatically and authenticates without asking manual questions.
customAttributes (e.g., playerId, username) so the AI can query your back-office immediately after authentication.Allowed Domains
Restrict which websites can embed your widget:example.com— Specific domain*.example.com— All subdomains*— Any domain (not recommended for production)
Full Example
Troubleshooting
Widget doesn't appear
Widget doesn't appear
- Is
boot()being called? Check browser console for errors. - Verify your domain is in the Allowed Domains list in Settings → Cevro.
- Check that
workspaceIdandbrandIdare correct.
'Domain not allowed' error
'Domain not allowed' error
Add your domain to allowed origins in Settings → Cevro → Allowed Domains. The domain must match exactly (including subdomains).
'Invalid player hash' error
'Invalid player hash' error
- Verify HMAC secret matches between dashboard and your server.
- Ensure you’re generating the hash server-side, not client-side.
- Check that the
playerIdmatches exactly between hash generation and widget init. - If you regenerated the HMAC key, all old hashes are invalidated.
Messages not sending
Messages not sending
- Verify
workspaceIdandbrandIdare correct. - Ensure the brand has automation enabled.
- Check browser console for network errors.
File upload fails
File upload fails
- Check file size (max 25MB).
- Verify file type is allowed (no executables like .exe, .js, .php).
- Rate limit: maximum 5 uploads per minute.
Escalation not working
Escalation not working
- Verify LiveChat or Intercom integration is configured in Settings.
- Check that human agents are available in the helpdesk.
- Ensure the helpdesk integration is enabled for this brand.
Related Documentation
- AI Procedures — Configure AI responses
- Player Authentication — Identity verification setup
- Escalation & Delegation — Human handoff strategies