Embed
Add Casey conversations to your website with a single script tag.
Add Casey conversations to any website using the embed widget. There are two integration methods: organization-level (recommended) and connection-level.
Quick start
Add this snippet inside the <body> tag of your website:
<script
type="module"
src="https://embed.tellcasey.com/casey.js"
data-org="your-org-slug"
></script>That's it. The widget automatically resolves the right agent based on page path rules configured in your dashboard.
Integration methods
Organization snippet (recommended)
A single script tag for your entire site. The widget auto-resolves which agent to show based on URL path rules you configure in the Casey dashboard.
<script
type="module"
src="https://embed.tellcasey.com/casey.js"
data-org="your-org-slug"
></script>Connection snippet
Hardcode a specific agent on a page using a connection code.
<script type="module" src="https://embed.tellcasey.com/casey.js"></script>
<tellcasey-widget conn-id="your-connection-code"></tellcasey-widget>View modes
The widget supports two view modes, configured in your dashboard:
- Float — An Intercom-style floating bubble in the corner of the page. No DOM element needed; the widget injects itself automatically.
- Block — An inline widget that fits within your page layout. Place a
<tellcasey-widget>element where you want it to appear.
Block mode sizing
<tellcasey-widget
conn-id="your-connection-code"
height="600px"
></tellcasey-widget>The height attribute accepts any valid CSS value: 600px, 100vh, calc(100vh - 100px), etc. Default is 600px.
Boot configuration
For advanced control, you can configure the widget before the script loads using the queue pattern:
<script>
window.tellcasey = window.tellcasey || { _q: [] };
window.tellcasey._q.push(["boot", {
participant_profile: {
first_name: "Jane",
last_name: "Doe",
organization_name: "Acme Corp",
},
theme: {
primary_color: "#3b82f6",
font_family: "Inter, sans-serif",
},
}]);
</script>
<script
type="module"
src="https://embed.tellcasey.com/casey.js"
data-org="your-org-slug"
></script>Boot options
| Option | Type | Description |
|---|---|---|
participant_profile | object | Pre-fill participant info: first_name, last_name, email, organization_name |
user_token | string | Ephemeral JWT for authenticated sessions (from your backend via the API) |
get_user_token | function | Async function that returns a fresh token — called automatically on expiry |
theme | object | Theme overrides (see Theming below) |
api_url | string | Override API base URL (for development) |
Theming
Customize the widget appearance via boot() or the theme HTML attribute:
<tellcasey-widget
conn-id="your-connection-code"
theme='{"primary_color": "#3b82f6", "border_radius": "12px"}'
></tellcasey-widget>Theme properties
| Property | Type | Description |
|---|---|---|
primary_color | string | Primary brand color |
primary_foreground_color | string | Text color on primary backgrounds |
background_color | string | Widget background |
foreground_color | string | Main text color |
secondary_color | string | Secondary accent color |
muted_color | string | Muted background color |
muted_foreground_color | string | Text on muted backgrounds |
border_color | string | Border color |
border_radius | string | Border radius (e.g., 12px) |
button_radius | string | Button border radius: full, lg, md, sm, none |
font_family | string | Font family (e.g., Inter, sans-serif) |
Theme precedence: boot config > HTML attribute > server-configured brand theme.
JavaScript API
After the script loads, window.tellcasey provides programmatic control:
// Boot with config
window.tellcasey.boot({
participant_profile: { first_name: "Jane" },
});
// Float mode controls
window.tellcasey.expand();
window.tellcasey.collapse();
window.tellcasey.toggle();
// Start the conversation (idempotent)
window.tellcasey.start();
window.tellcasey.start({ expand: true }); // start and expand
// Switch modality
window.tellcasey.switchToText();
window.tellcasey.switchToVoice();Events
Listen for widget events to integrate with your application:
const widget = document.querySelector("tellcasey-widget");
widget.addEventListener("conversation.started", (e) => {
console.log("Started:", e.detail.conversationId);
});
widget.addEventListener("conversation.completed", (e) => {
console.log("Completed:", e.detail.conversationId);
});Or using the global API:
window.tellcasey.on("conversation.completed", (e) => {
console.log("Completed:", e.detail.conversationId);
});Event types
| Event | Detail | Description |
|---|---|---|
widget.ready | { conn_id } | Widget initialized |
conversation.started | { conversationId } | Voice session connected |
conversation.completed | { conversationId } | Conversation finished |
conversation.paused | { conversationId } | User intentionally paused |
conversation.interrupted | { conversationId, reason } | Unexpected disconnect |
permission.requested | Microphone permission dialog shown | |
permission.granted | User granted microphone | |
permission.denied | User denied microphone | |
token.expired | Token expired; call boot() with a new token | |
token.invalid | { reason } | Token is invalid |
Authenticated sessions
To associate conversations with known users, generate an ephemeral token from your backend using the API and pass it to the widget:
// Your backend fetches a token
const token = await fetch("/api/casey-token").then((r) => r.json());
window.tellcasey.boot({
user_token: token,
});For automatic token refresh:
window.tellcasey.boot({
get_user_token: async () => {
const res = await fetch("/api/casey-token");
const data = await res.json();
return data.token;
},
});