tellcasey

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

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

OptionTypeDescription
participant_profileobjectPre-fill participant info: first_name, last_name, email, organization_name
user_tokenstringEphemeral JWT for authenticated sessions (from your backend via the API)
get_user_tokenfunctionAsync function that returns a fresh token — called automatically on expiry
themeobjectTheme overrides (see Theming below)
api_urlstringOverride 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

PropertyTypeDescription
primary_colorstringPrimary brand color
primary_foreground_colorstringText color on primary backgrounds
background_colorstringWidget background
foreground_colorstringMain text color
secondary_colorstringSecondary accent color
muted_colorstringMuted background color
muted_foreground_colorstringText on muted backgrounds
border_colorstringBorder color
border_radiusstringBorder radius (e.g., 12px)
button_radiusstringButton border radius: full, lg, md, sm, none
font_familystringFont 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

EventDetailDescription
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.requestedMicrophone permission dialog shown
permission.grantedUser granted microphone
permission.deniedUser denied microphone
token.expiredToken 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;
  },
});

On this page