#Web widget
Try the agent on the inbox's Test page, the link vatio push prints.
To put chat in front of customers on your own website, publish the agent and
create a token that allows your site's origin:
vatio push
vatio publish
vatio tokens create --env live --label website \
--origin https://acme.com --origin http://localhost:3000
Each publishable token has its own allowed origins, and works only from those
plus Vatio's own pages and the app builders. They govern the whole public API — the widget, the
browser SDK and iOS and Android apps alike. Origins are exact scheme://host[:port]
values, with no path or wildcard. An iOS app is ios-app:// plus its bundle
id — see the iOS SDK — and an Android app is android-app:// plus
its package name — see the Android SDK.
Every token also accepts any https subdomain of the app builders, preview and
published alike, without listing it: Lovable (lovable.app,
lovableproject.com), Replit (replit.dev, replit.app), Bolt (bolt.host,
webcontainer-api.io), v0 (vusercontent.net) and Base44 (base44.app). A
token with no origins works only there. Once the app moves to a domain of its
own, list that one.
A page on an origin the token does not accept gets origin_not_allowed, and the
browser console names that origin, ready to paste. Change a token's list with vatio tokens origins PREFIX URL... or on
the tokens section of Channels → Web widget in the inbox, which also lists
the token in the install snippet that page shows.
Copy the returned vatpub_ token into your page:
<script async src="https://cdn.vatio.ai/v1/widget.js"
data-workspace="acme"
data-token="vatpub_REPLACE_ME"></script>
Publishable tokens are intended for page source and select one workspace and
environment. They do not authorize deployment or access to the workspace inbox.
Never use a vat_ developer token in a browser.
#From your app's code
With a bundler, install the widget from npm and mount it yourself. It is the
same widget, with the same options as the data-* attributes, in camelCase:
npm install @vatio-ai/widget
import { mountVatioWidget } from "@vatio-ai/widget";
const widget = mountVatioWidget({ workspace: "acme", token: "vatpub_REPLACE_ME" });
widget.identify(jwt); // who is signed in now, or null to sign out
widget.unmount(); // closes the connection and removes the widget
In React, mount it in an effect and return widget.unmount as its cleanup.
There is one widget per page: a second mountVatioWidget does nothing until
the first is unmounted. The widget is open source (MIT), at
github.com/vatio-ai/widget.
vatio env prints an environment's install snippet with its token; the
Channels → Web widget in the inbox edits the widget's look and its tokens'
origins.
vatio tokens list lists tokens; vatio tokens revoke PREFIX revokes one.
Revocation prevents new chats and conversation lists with that token; existing
chat credentials remain valid until expiry.
#Widget configuration
Visual values resolve in this order: page override, workspace setting, platform
default. Set the shared defaults in Channels → Web widget in the inbox, and
use data-* attributes for a specific page.
These settings belong
to the workspace, not to a deployment: they apply to every environment as soon
as you save. widget: and allowed_origins: in an older vatio.yml are
ignored, with a warning on push.
The logo, the brand color and about belong to the business: they are set on
the Business page of the inbox, or with
vatio business set, and marked † below. Everything else is
in Channels → Web widget.
| Field | Page attribute | Value / default |
|---|---|---|
accent_color † | data-accent | #RRGGBB brand color |
accent_ink | data-accent-ink | #RRGGBB; otherwise automatic contrast |
surface, ink, muted, line | data-surface, data-ink, data-muted, data-line | #RRGGBB theme colors |
scheme | data-scheme | auto, light, or dark; default auto |
position | data-position | right or left; default right |
reply_style | data-reply-style | stream: one answer, written out as it arrives. paced: short messages, each after a typing indicator, as on WhatsApp and Instagram. Default stream |
font | data-font | CSS font stack; inherit uses the host's font |
radius | data-radius | CSS length such as 16px; default 16px |
title | data-title | Up to 200 characters; defaults to the agent's name |
greeting | data-greeting | Up to 200 characters; defaults to localized copy |
suggestions | data-suggestions | Up to four prompts, 200 characters each; attribute uses pipe-separated text |
about † | data-about | Up to 2,000 characters of visitor-facing copy |
locale | data-locale | en, es, or pt; default en |
| Logo † | — | PNG, JPEG, WebP, or GIF upload, up to 2 MB |
about is displayed to visitors; the business description the agent works
with is set on the Business page of the inbox. locale sets interface labels; the agent's language
follows the conversation.
For example, data-suggestions="Products|Track an order" sets two prompts.
The widget normally waits for page load and idle time; data-eager="true"
starts it immediately.
To tell the agent who is signed in, render a visitor token onto the same tag — see Sessions and channels. To build your own UI instead of embedding this one, use the browser SDK.
#Visitor feedback
The widget asks how the conversation went when Jev detects a resolved request, visitor confirmation of closure, and no pending question or action. Evaluation runs in the background a few seconds after the agent's last message, using the latest 12 user and assistant messages (up to 4000 characters each), rather than message counts or inactivity; a visitor who writes again in those seconds is not asked. The question is written for that conversation in the agent's voice, and falls back to “How did [agent name] help you?” when it cannot be.
Feedback is offered once per conversation: Good, So-so, or Bad, with an optional comment of up to 2000 characters for So-so and Bad. Visitors can skip it or continue chatting. Ratings appear in the inbox separately from supervisor ratings, and in visitor_feedback on the developer chat API.