Website Widget
Add a floating assistant to your website so visitors can talk, chat, or video with an AI concierge — ask questions, get guided, and hear answers grounded in your own content. You create and configure the widget in Erdo, then drop one line of code on your site. Everything runs through Erdo; your site never loads a third-party SDK or holds any keys.The widget is a website embed, separate from outbound phone
calls. Same agent technology, different surface: here a visitor starts
the conversation from your page.
Create a widget
Everything below — modes, voice, and branding — is configured in Settings → Voice widgets, so the embed snippet stays a single line and you never have to hand-edit code to change how the widget looks or sounds.1
Open Settings → Voice widgets
Click New widget and give it a name.
2
Choose its modes
Pick any combination of Voice (talk out loud), Chat (type messages),
and Video (an on-screen avatar). With more than one selected, visitors get
a switcher to move between them.
3
Pick a voice
Search the voice library and preview candidates, then select one — or leave
it on the default. This is the spoken voice for the voice mode.
4
Pick a video avatar (video mode only)
When Video is enabled, choose the on-screen avatar visitors see. The picker
shows each available avatar as a thumbnail that plays a short preview on hover —
select one, or leave it on the default avatar.
5
Describe the concierge
Set its greeting, what it helps with and its tone, plus any compliance
guardrails it must always follow.
6
Brand it
Set the accent colour and the header / button / intro copy. A live preview
in the dialog shows your changes before you save — see Match your
brand.
7
Let visitors book meetings (optional)
Connect a calendar and enable meeting scheduling so the assistant can offer
real open slots and book meetings during the conversation — see Book meetings
on your calendar.
8
Set who can embed it (optional)
Add the allowed origins for your site — see Allowed
origins below. Leave it empty while testing.
9
Copy the embed snippet
Each widget has a one-line
<script> snippet. Copy it from the widget card.Widget settings
Every setting lives on the widget itself, so changing any of them never touches the snippet on your site — the embedded widget picks the new configuration up automatically. The full set, and what each controls:Embed it on your site
Paste the snippet once into your site’s HTML, just before the closing</body> tag (or in your CMS / theme’s “custom code” / footer area), on every
page where you want the assistant:
Pages you build inside Erdo (the “make me a page” flow) that embed a widget
work automatically — Erdo’s own page hosts are always allowed, so you don’t need
to add them to the allowed origins.
Preview your widget on a demo page
Before you drop the snippet on your own site — or when you just want to show a colleague — each widget card in Settings → Voice widgets has a Preview button. It opens a public demo page in a new tab: a placeholder website for a fictional real-estate development with your widget embedded on it, running exactly as it would on a real page. The widget pulls its modes, voice, and branding from its settings and grounds its answers in the demo site’s content, so you can start a conversation and ask about the development’s prices, viewing hours, or buying process to hear how the concierge behaves in context. The demo page is a shareable, no-login link — anyone you send it to can open it and try the widget without an Erdo account (the samevw_ key that’s designed
for public embedding). It’s the quickest way to get sign-off before you touch your
own site’s code.
The page has a Floating / Inline panel toggle at the top so you can see both
embed styles: the default floating launcher in the bottom corner, and the
always-open inline panel that
fills a section of the page. Switching between them reloads the demo with that
style applied.
The demo works even while your allowed origins are locked down to your own
site — Erdo’s own hosts are always allowed, so the demo page never needs to be in
the list. If the widget is disabled, the demo page still loads the placeholder
site but shows a banner instead of the widget; enable the widget to try it.
Conversation modes — voice, text, and video
One widget, one snippet — the same assistant can talk (voice), chat (text), or appear as a video agent. You choose which modes a widget offers; all three are answered by the same assistant, grounded in the same Knowledge, so the experience is consistent however a visitor reaches out.
When a widget offers more than one mode, visitors see a small Talk / Chat /
Video switcher; with a single mode they just get that experience. Permissions
are only requested when a visitor actually starts that mode — a voice- or
text-only widget never prompts for the camera. For the Video mode you can also
pick which on-screen avatar appears (see the avatar step above); leave it on the
default to use Erdo’s standard avatar.
Your existing snippet doesn’t change. Turning on text or video for a widget is
a setting on the widget itself — the
<script> tag you’ve already embedded picks
the new modes up automatically. Widgets default to voice only, so nothing
changes until you opt in.Give the assistant knowledge
The widget answers from your workspace’s Knowledge: publish the facts it may use, attach photos and videos to them, and the assistant both answers visitors’ questions and shows them what it’s describing. You never wire content to a specific widget — every widget in the organization draws from the same published Knowledge.What the assistant can answer from
The widget talks to anonymous visitors on the open web, so it deliberately does not see everything in your workspace. It answers only from Knowledge that is both:- Public — the entry’s visibility is set to Public, opting it into external surfaces. Every new Knowledge entry starts as Workspace (organization-internal), so nothing is exposed by default.
- Approved — making an entry public approves a draft in the same step, so publishing is all you need; entries approved through the review flow also qualify once made public.
Showing photos and videos
In every mode — talking, typing, or on a video call — the assistant can show what it’s describing: a photo of the lobby, a residence, a product — pulled straight from your Knowledge. To give it something to show, attach the images or videos to a Knowledge entry (a photo gallery, a product sheet) and publish it like any other entry. The assistant finds the best-matching media and displays it in the widget; you don’t configure anything per widget, and it only ever shows media attached to Knowledge that is public and approved (see What the assistant can answer from). On a video call, the avatar shrinks aside so the photos take the stage while it keeps talking. In the compact floating panel these appear as cards in the conversation. When the widget is expanded to fullscreen (or embedded in a page tab), it opens a two-pane showcase: the conversation stays on the left while a large image portal fills the right, with a row of thumbnails to click through and any matching video playable inline. Each item can carry a short caption and a highlight (for example a price). Tap the main image to view it full-size.Book meetings on your calendar
A widget can let visitors book a meeting with your team during the conversation — in any mode. A visitor asks about a demo, the assistant checks your live calendar availability, offers real open slots, collects the visitor’s name and email, and books the meeting. The visitor gets the calendar invite by email from your calendar provider; nothing else is needed from them. Booking works the same way whether the visitor is talking, typing, or on a video call, and it always lands on your organization’s connected calendar. Three calendar providers are supported, each with its own way of describing what gets booked:
To set it up:
- Connect the calendar provider in Settings → Connectors (once, for the organization).
- Enable scheduling on the widget and pick the provider — plus the event type (Calendly / Cal.com) or the calendar and default meeting length (Google). Two ways: ask Erdo in chat (“let visitors book meetings through the Acme widget using our Cal.com”), or edit the widget in Settings → Voice widgets (the Meeting scheduling section).
Conversation transcripts & follow-up
Every widget conversation — voice, text, or video — is saved in your workspace, so a visitor question is never lost when the tab closes. Each conversation keeps its full transcript along with the mode it used, the page it started on, when it happened, how long it lasted, and a short auto-generated summary of what the visitor wanted. You review them by asking Erdo in chat:- List conversations — “what did visitors ask the Acme widget this week?”, “show me yesterday’s widget conversations”. Erdo lists them newest first with their summaries, so you can scan what visitors are asking without opening each one.
- Read one back — “pull up the conversation where someone asked about enterprise pricing”, or point at one from the list. Erdo reads back the full exchange, exactly as the visitor and the assistant said it.
Read conversations programmatically
The same list-and-read surface is available over the REST API and to MCP clients, so a scheduled automation or an external dashboard can pull conversations without going through chat. Both are org-scoped to the caller’s credentials and identify a widget by its name or public key (vw_…), never
an internal id:
- List —
GET /v1/voice/widget-conversations?widget=Acme%20Concierge(or aPOSTwith a JSON body) returns each conversation’s session id, mode, timing, duration, and summary, newest first and paginated. MCP tool:erdo_voice_widget_conversation_list. - Read one —
POST /v1/voice/widget-conversations/getwith{"widget": "…", "session_id": "…"}returns the rendered transcript, the raw transcript, and — for voice conversations — a structuredturnsarray. MCP tool:erdo_voice_widget_conversation_get.
turns is one assistant turn that drove the language model, with
the fields ops teams watch for latency and cost monitoring:
A typical use is an hourly automation that reads recent conversations and
appends the per-turn latency rows to a dataset, so you can chart TTFB and
fail-over rate over time. Text and video conversations carry no model metrics, so
their
turns array is empty.
Match your brand
Set the widget’s accent colour and copy in Settings → Voice widgets — the dialog shows a live preview as you type, and the branding is saved on the widget, so the same one-line snippet always reflects your latest look:
The widget runs in a sandboxed frame, so its inside is styled by these settings,
not your page’s CSS. To target the widget’s container (position, size,
z-index) from your own CSS, it has a stable id/class:
#erdo-voice-widget /
.erdo-voice-widget.
Per-page overrides (advanced)
If a single widget appears on pages that need different branding, you can override any branding field for one page with adata-erdo-* attribute on the
embed script. A present attribute wins over the widget’s saved setting; anything
you omit falls back to the saved value.
Together,
data-erdo-bg / text / muted / border (plus accent) let you run
the widget in a fully dark or branded palette. Colours must be hex; anything else
is ignored and the default is kept.
Language & translation
The widget speaks your visitor’s language on two levels: its own chrome (buttons, status, hints, placeholders) and the assistant’s replies. It follows the page automatically. If your page declares a language —<html lang="es">, <html lang="pt-BR"> — the widget picks it up with no extra
configuration: the chrome is translated, and both the voice and video avatar
conversations speak that language. Set data-erdo-lang on the embed to override the
page’s language for the widget specifically:
data-erdo-* attribute (title, intro, launcher CTA/tagline, button labels) — is shown
exactly as you wrote it and is never auto-translated. Only the copy you leave at its
default gets the built-in translation. So a single widget can serve a localized page in
that language out of the box, while still honouring any wording you set yourself.
Translations currently ship for a starter set of languages; any language not yet
translated falls back to English per string (a partial translation never shows a blank).
Give each language its own voice. In the widget’s settings, under Voice &
languages, you set a primary language and can add extra languages — up to 10 in
total — each with its own voice picked from the voice library. The agent then answers
every configured language in that language’s voice (so Spanish sounds like a native
Spanish speaker, not an English voice reading Spanish), and your greeting is translated
into each language automatically. This is one agent serving all of them: a
data-erdo-lang page (or a visitor who switches language) is met in the right voice
with no per-page setup. Leave the extra languages empty and the widget stays
single-language.
Open it from your own button, script, or agent
By default the widget shows a floating launcher. You can also drive it yourself — useful for a custom “Talk to us” button, a help menu, or an in-page assistant. Declaratively — add adata-erdo-voice-* attribute to any element; clicking it
controls the widget (no JavaScript needed):
open() /
toggle() / expand() — goes straight into the call: on a voice widget it asks for
the microphone and connects, so there’s no second tap on the orb. If the visitor
declines the microphone prompt, the call ends and the widget stays open on its
maximized screen, where they can type a question in chat or tap the orb to try the
call again. (Because a browser only starts audio in response to a real click, call
open() from within a click handler so the microphone prompt appears reliably.)
Calls made before the widget finishes loading are queued and run once it’s ready.
Visitors can also expand to fullscreen with the ⤢ button in the widget header,
and tap any photo to view it full-size.
Hide the built-in launcher and use your own call-to-action
Adddata-erdo-launcher="none" to the embed to suppress the floating pill entirely.
The widget mounts hidden — no launcher, and nothing that intercepts clicks — so your
page owns the call-to-action and opens the widget whenever you choose:
Embed it inline as a panel (no floating bubble)
Adddata-erdo-embed="panel" to mount the widget inline, as an always-open panel that
fills a container — a concierge section, a sidebar, a modal you own — instead of a
floating launcher. Point it at the container with data-erdo-target="#your-element"
(or, with no target, it mounts into the embed script’s own parent element):
data-erdo-bg / -text / -muted / -border) if you want it to
read as part of the section rather than a light box.
Allowed origins
Allowed origins restrict which websites may embed this widget, so someone can’t copy your snippet onto their own site and run up your usage. Leave the list empty to allow any site (handy while testing); add origins to lock it down — up to 50 per widget. The rules — the widget shows an error and won’t start on a site that doesn’t match:- Scheme + domain only. Enter the full origin including
https://, with no path:https://acme.com, notacme.comand nothttps://acme.com/contact. - No wildcards.
*.acme.comis not supported. - Matching is exact, and subdomains count as different sites.
https://acme.comdoes not coverhttps://www.acme.comorhttps://shop.acme.com— add each one you actually use, on its own line. - Matching ignores case and a trailing
/.
www:
Usage limits
Each widget has a daily session cap (how many conversations it will start per day) to keep usage predictable — 500 per day unless you change it, and0
means unlimited. Every mode counts toward the same cap — a voice call, a text
chat, and a video session each use one conversation. When the cap is reached, the
widget tells visitors it’s unavailable until the next day. Raise or lower it in
the widget’s settings.

