Skip to main content

What Is the Widget?

The widget is a small piece of Callers that lives on your website. Visitors see a floating button in the corner of the page; when they click it, they can start a conversation with your AI agent right there in the browser - by voice or by text, with no phone number and no app to install. Because the conversation runs on your own website, you already know who the visitor is. You can pass their name, email, or plan into the campaign so the agent greets them by name and skips the questions you already have answers to.

No Phone Number Needed

Conversations run over the browser, so there are no per-minute telephony costs and no number to provision.

Voice or Text

Visitors choose how they want to talk. The same campaign script handles both.

Context From Your Site

Pass what you already know about the visitor into the campaign as variables.

Two Installation Paths

A one-line script tag for most sites, or the Web SDK when you need full control.
Widget campaigns are enabled per account. If you don’t see the Widget option described below, contact support@callers.ai to have it turned on.

Step 1: Create a Widget Campaign

1

Start a new campaign

From your dashboard, click New Campaign.
2

Open General Settings

In the campaign editor, open the General Settings modal.
3

Select Widget as the channel

In the channel row - Voice, Text, Email, Widget - choose Widget.
4

Name your campaign

Give the campaign a descriptive name so you can find it later, then close the modal.
General Settings modal with the Widget channel selected

Selecting Widget as the campaign channel in General Settings

What Changes When You Pick Widget

Selecting Widget reconfigures the campaign automatically:
  • The campaign becomes Incoming. Your visitors start the conversation - the widget never dials out.
  • Outgoing phone numbers are cleared, and incoming phone calls are switched off. A widget campaign is reached through your website only.
  • A web call secret is generated for the campaign. You’ll need it only if you build a custom integration (see below).
Switching an existing campaign to Widget removes its phone numbers. If you want to keep a phone campaign running, create a separate campaign for the widget instead of converting the one you already have.

Build Your Script

A widget campaign uses the same script builder as a voice campaign. Write your steps, add actions, and set up variables exactly as you normally would - see Campaign Script and Campaign Variables. Any variables you define here become available to the widget, so you can pass real values from your website into the conversation.
Save your campaign before continuing. The installation code is generated from the saved campaign, so the installer stays empty until the campaign exists.

Step 2: Open the Installer

In the campaign toolbar, click the plug icon to open the Install the widget window.
Campaign toolbar with the widget connection button highlighted

The plug icon in the campaign toolbar opens the installer

This icon appears only on widget campaigns - it takes the place of the Channels button used by phone and messaging campaigns.
The window has two tabs: Most sites should use Embed on Web.

Embed on Web

Install the widget modal showing the Embed on Web tab

The Embed on Web tab: domains, bot protection, and the installation snippet

1. Add Your Domains

List every domain the widget is allowed to run on. Type a domain and press Enter to add it; each one appears as a removable chip. This list is a security boundary, not a suggestion. When a visitor opens the widget, Callers checks the page’s origin against this list and refuses the conversation if it isn’t there.
Domains are matched exactly. A few consequences worth knowing before you start:
  • Wildcards are rejected. *.example.com will not be accepted.
  • Subdomains are separate entries. Adding example.com does not cover app.example.com or www.example.com - add each one you actually use.
  • Ports are not stored. A local address like localhost:3000 is saved as localhost, which will not match a request coming from port 3000. To test locally, use the Custom integration with a token instead, since token authentication skips the domain check.
If the list is empty, the widget cannot start a conversation at all - you’ll see the error No allowed origins configured.

2. Bot Protection

Bot protection stops automated traffic from burning through your conversation minutes. Callers uses Cloudflare Turnstile, which is free.
1

Create a Turnstile widget

Open the Cloudflare Turnstile dashboard and create a new widget.
2

Add your website domains

Enter the same domains you added in the previous step. Cloudflare will only issue challenges for domains listed here.
3

Copy both keys into Callers

Cloudflare gives you a Site key and a Secret key. Paste both into the matching fields in the installer.
Both keys are required. Bot protection switches on only when the site key and the secret key are filled in - fill in just one and it stays off. The secret key lives in Callers because verification happens on our servers, not in the visitor’s browser.
Once enabled, bot protection applies to both installation methods - the embed script and the Web SDK. Unlike the domain list, a token does not bypass it.
After a visitor passes a challenge and the conversation ends, they must close and reopen the widget to start another one. This is intentional: each conversation gets its own challenge.

3. Copy the Code

Copy the snippet and paste it into your HTML, just before the closing </body> tag, on every page where you want the widget to appear.
That’s the whole installation. The floating button appears in the corner of the page as soon as the script loads.

Passing Visitor Information

If your campaign defines variables, the snippet includes a data-vars attribute pre-filled with placeholders:
The {{ name }} placeholders are not filled in automatically. Replace them with real values from your page or template before going live - otherwise your agent will greet visitors with the literal text {{ name }}.
Rendered by your server or templating engine, the final tag should look like this:

Script Tag Reference


Custom Integration (Web SDK)

Use the Custom tab when the standard widget isn’t enough - you want your own launch button, you need the conversation embedded inside your page layout, or your visitors are logged in and you want to authenticate them properly.
Install the widget modal showing the Custom SDK tab

The Custom tab: install the SDK, authenticate, and initialize

1. Install the SDK

2. Authenticate

Instead of checking the visitor’s domain, the SDK authenticates with a short-lived token that you generate on your own backend. The Authenticate step in the installer shows your campaign’s web call secret. Copy it and store it as a server-side environment variable.
Never put the secret in browser code. Anyone who reads your page source could mint their own tokens and run conversations on your account. The secret belongs on your backend only - your frontend should only ever receive the finished token.

Generating a Token

The SDK ships the helper, so on a JavaScript backend it’s one call:
That returns a token valid for one hour. Send it to your frontend and pass it to WebCall.

Generating a Token Without the SDK

If you’d rather not add the SDK as a server dependency, the format is simple enough to build yourself. A token is three dot-separated parts: the campaign ID, an expiry timestamp in seconds, and an HMAC-SHA256 signature of the first two parts, hex-encoded.
Here it is in Node. It ports directly to any language with an HMAC library - the only thing that has to match is the payload string and hex encoding:
Expose it through an endpoint your frontend can call - ideally one that requires the visitor to be logged in, so only real users can obtain a token.
Tokens expire after one hour. Generate a fresh token each time a visitor loads the page rather than caching one. Requests with an expired token are rejected with Invalid web call token.
Token authentication replaces the domain allowlist - a valid token is accepted from any origin. Bot protection, if enabled, still applies.

3. Initialize the SDK

Pass the token your backend generated, along with any campaign variables:
webCall.call() starts a voice conversation immediately. To show the floating button and let the visitor start it themselves, create the instance without calling call() - the widget renders and waits.

Try It in the Playground

Before wiring the SDK into your own application, you can exercise it against a real campaign in the SDK Playground. Enter your campaign ID and secret, click Load SDK, and a working widget appears on the page - with every SDK method available as a button, a live event feed, and a running transcript.
SDK Playground with a campaign connected, the SDK loaded, and the widget button running on the page

A campaign loaded in the playground - the widget is live in the bottom-right corner

It doubles as a visual theme builder. See Styling the Widget for that side of it.

Verify the Installation

1

Load the page

Open a page where you pasted the snippet. The floating button should appear in the corner within a second or two.
2

Start a conversation

Click the button and allow microphone access when the browser asks. Try both the voice option and the text composer.
3

Check the transcript

Open the campaign in Callers and confirm the conversation appears with its full transcript.

Common Errors

Check that the script tag is inside <body> and not blocked by a content blocker or a Content Security Policy. If your site sets a CSP, allow scripts from https://cdn.callers.ai.Then check the tag itself: if neither data-campaign nor data-token is present, the SDK stops without rendering anything and without logging - a silent page is almost always a missing or misspelled data-campaign. Malformed data-vars or data-theme JSON does get reported in the browser console.
Your data-vars placeholders were never replaced. The installer generates them as templates; your page or server needs to substitute real values before the HTML reaches the browser.
The domain field stores hostnames without ports, so localhost:3000 is saved as localhost and won’t match. Use the Custom integration with a token for local development - token authentication skips the domain check entirely.

Next Steps

  • Add campaign actions so your agent can book meetings or push data to your CRM during a conversation.
  • Review Analytics & Insights to see how widget conversations are performing.
  • Set up webhooks to receive conversation results in your own systems.