> ## Documentation Index
> Fetch the complete documentation index at: https://docs.truedy.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Embed a Voice Widget on Your Website

> Add a live AI voice call button to any website in minutes using the Truedy pre-built widget — no backend required.

# Embed a Voice Widget on Your Website

The Truedy embed widget lets anyone add a live AI voice call button to their website with a single `<script>` tag. Visitors click the button and speak directly to your Truedy AI agent in real time — no phone number, no app download, no backend required.

<Note>
  This guide covers the **pre-built Truedy widget** — the fastest way to go live. If you need full control over the UI and want to build a completely custom widget from scratch, see the [Custom Voice Widget guide](/guides/webrtc-custom-widget) instead.
</Note>

***

## How it works

```
Visitor clicks widget button
       │
       ├─ Widget JS requests a call session
       │     POST https://api.truedy.ai/api/v1/widgets/call?widget_id=xxx
       │
       ├─ Truedy validates the widget & returns a WebRTC joinUrl
       │
       └─ Browser connects directly to your Truedy agent via WebRTC audio
              (live, low-latency, two-way voice)
```

There is **no API key exposed in your frontend** — the widget authenticates via your Widget ID, and domain restrictions protect against misuse.

***

## Step 1 — Create a widget in the dashboard

1. Go to **[app.truedy.ai](https://app.truedy.ai)** → **Widgets** in the sidebar
2. Click **Create Widget**
3. Configure your widget:
   * **Agent** — which AI agent answers calls from this widget
   * **Display name & subtext** — shown to visitors
   * **Primary colour** — matches your brand
   * **Avatar** — upload a profile image (displayed when the agent is idle)
   * **Speaking avatar** — optional image shown when the agent is talking
   * **Widget style** — Bubble (floating FAB), Pill, or Side Tab
   * **Position** — bottom-right or bottom-left
   * **Placement mode** — Overlay (floating) or Embedded (inline in your page)
   * **Allowed domains** — restrict which websites can use this widget (recommended)
4. Click **Save**

***

## Step 2 — Copy the embed code

After saving, the widget builder shows your embed snippet in the **Embed Code** panel. Copy it — it looks like this:

**Overlay mode (floating button):**

```html theme={null}
<!-- Truedy™ Voice Widget -->
<script src="https://api.truedy.ai/widget.js"></script>
<script>
  TruedyWidget.init({
    "widgetId": "YOUR_WIDGET_ID",
    "agentId": "YOUR_AGENT_ID",
    "agentName": "AI Assistant",
    "agentSubtext": "Live AI Voice Assistant",
    "primaryColor": "#6366f1",
    "position": "bottom-right",
    "buttonText": "Talk to AI",
    "darkMode": false
  });
</script>
```

**Embedded mode (inline in your page):**

```html theme={null}
<!-- Truedy™ Voice Widget - Embedded -->
<div data-truedy-embed="YOUR_WIDGET_ID" style="width:100%"></div>
<script src="https://api.truedy.ai/widget.js"></script>
<script>
  TruedyWidget.init({
    "widgetId": "YOUR_WIDGET_ID",
    "agentId": "YOUR_AGENT_ID",
    "placementMode": "embedded",
    "embeddedJustification": "center"
  });
</script>
```

***

## Step 3 — Paste it on your website

Paste the embed snippet just before the closing `</body>` tag on any page where you want the widget to appear.

**HTML site:**

```html theme={null}
    <!-- your page content -->

    <!-- Truedy™ Voice Widget -->
    <script src="https://api.truedy.ai/widget.js"></script>
    <script>
      TruedyWidget.init({ "widgetId": "YOUR_WIDGET_ID", ... });
    </script>
  </body>
</html>
```

**WordPress:** Paste in **Appearance → Theme Editor → footer.php**, or use a plugin like *Insert Headers and Footers*.

**Webflow:** Go to **Project Settings → Custom Code → Footer Code**.

**Framer / Squarespace / Wix:** Use the site-wide custom code or script injection setting.

**React / Next.js:** Use `next/script` or a `useEffect` to load the script:

```tsx theme={null}
// app/layout.tsx (Next.js App Router)
import Script from 'next/script'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Script src="https://api.truedy.ai/widget.js" strategy="afterInteractive" />
        <Script id="truedy-init" strategy="afterInteractive">{`
          TruedyWidget.init({
            widgetId: "${process.env.NEXT_PUBLIC_TRUEDY_WIDGET_ID}",
            agentId: "${process.env.NEXT_PUBLIC_TRUEDY_AGENT_ID}"
          });
        `}</Script>
      </body>
    </html>
  )
}
```

***

## Configuration reference

All options passed to `TruedyWidget.init()`:

### Identity

| Option     | Type   | Default | Description                                                                                     |
| ---------- | ------ | ------- | ----------------------------------------------------------------------------------------------- |
| `widgetId` | string | —       | **Recommended.** Your widget's UUID from the dashboard. Loads all saved settings automatically. |
| `agentId`  | string | —       | Your agent's UUID. Required alongside `widgetId`.                                               |

### Display

| Option               | Type    | Default                     | Description                                   |
| -------------------- | ------- | --------------------------- | --------------------------------------------- |
| `agentName`          | string  | `"AI Assistant"`            | Name shown in the widget header               |
| `agentSubtext`       | string  | `"Live AI Voice Assistant"` | Subtitle shown below the name                 |
| `primaryColor`       | string  | `"#6366f1"`                 | Brand colour (6-digit hex, e.g. `#FF5733`)    |
| `buttonText`         | string  | `"Talk to AI"`              | Label on the trigger button                   |
| `profilePictureUrl`  | string  | —                           | Avatar image URL (shown when idle)            |
| `speakingPictureUrl` | string  | —                           | Avatar image URL shown when agent is speaking |
| `fontFamily`         | string  | `"Inter, sans-serif"`       | CSS font-family for the widget UI             |
| `darkMode`           | boolean | `false`                     | Enable dark theme                             |

### Layout & Position

| Option                  | Type                                 | Default          | Description                                    |
| ----------------------- | ------------------------------------ | ---------------- | ---------------------------------------------- |
| `position`              | `"bottom-right"` \| `"bottom-left"`  | `"bottom-right"` | Corner for the floating widget                 |
| `size`                  | `"small"` \| `"medium"` \| `"large"` | `"medium"`       | Size of the trigger button                     |
| `placementMode`         | `"overlay"` \| `"embedded"`          | `"overlay"`      | Floating overlay or inline in your layout      |
| `embeddedJustification` | `"left"` \| `"center"` \| `"right"`  | `"center"`       | Alignment when `placementMode` is `"embedded"` |

### Behaviour

| Option              | Type      | Default | Description                                                                     |
| ------------------- | --------- | ------- | ------------------------------------------------------------------------------- |
| `showPostCallRecap` | boolean   | `false` | Show a transcript summary after the call ends                                   |
| `speakingAnimation` | boolean   | `true`  | Animate the avatar with a pulse when the agent speaks                           |
| `autoOpen`          | boolean   | `false` | Automatically open the widget panel on page load                                |
| `allowedDomains`    | string\[] | —       | Restrict the widget to specific domains (e.g. `["mysite.com", "*.mysite.com"]`) |

***

## Domain restrictions (recommended)

Lock your widget to your own domains so it cannot be used on other sites. Set allowed domains either in the dashboard UI or in the `allowedDomains` config option:

```javascript theme={null}
TruedyWidget.init({
  widgetId: "YOUR_WIDGET_ID",
  agentId: "YOUR_AGENT_ID",
  allowedDomains: ["mysite.com", "*.mysite.com"]
});
```

Wildcards (`*.mysite.com`) match all subdomains. The check runs both client-side (blocks render) and server-side (blocks call creation), so it cannot be bypassed.

***

## Embedded mode

To place the widget inline inside your page layout rather than as a floating overlay, use `placementMode: "embedded"` and add a `<div>` target:

```html theme={null}
<!-- Place this where you want the widget to appear -->
<div data-truedy-embed="YOUR_WIDGET_ID" style="width:100%; max-width:400px;"></div>

<script src="https://api.truedy.ai/widget.js"></script>
<script>
  TruedyWidget.init({
    widgetId: "YOUR_WIDGET_ID",
    agentId: "YOUR_AGENT_ID",
    placementMode: "embedded",
    embeddedJustification: "center"
  });
</script>
```

The widget renders inside the `div`, inheriting its width. Use CSS to control size and positioning.

***

## Programmatic control

You can trigger the widget from your own buttons or application logic:

```javascript theme={null}
// Start a call immediately (e.g. from a custom CTA button)
TruedyWidget.start()

// End the active call
TruedyWidget.end()

// Remove the widget from the page entirely (useful in SPAs)
TruedyWidget.destroy()
```

**Example — trigger from your own button:**

```html theme={null}
<button onclick="TruedyWidget.start()">Talk to our AI</button>

<script src="https://api.truedy.ai/widget.js"></script>
<script>
  TruedyWidget.init({
    widgetId: "YOUR_WIDGET_ID",
    agentId: "YOUR_AGENT_ID",
    autoOpen: false
  });
</script>
```

***

## React / SPA lifecycle cleanup

When using the widget in a single-page app, call `destroy()` to clean up when the component unmounts:

```tsx theme={null}
import { useEffect } from 'react'

export function VoiceWidget() {
  useEffect(() => {
    const script = document.createElement('script')
    script.src = 'https://api.truedy.ai/widget.js'
    script.onload = () => {
      window.TruedyWidget?.init({
        widgetId: process.env.NEXT_PUBLIC_TRUEDY_WIDGET_ID,
        agentId: process.env.NEXT_PUBLIC_TRUEDY_AGENT_ID,
      })
    }
    document.body.appendChild(script)

    return () => {
      window.TruedyWidget?.destroy()
    }
  }, [])

  return null
}
```

***

## Post-call transcript

Enable `showPostCallRecap: true` to automatically show the visitor a summary of the conversation after the call ends. This is useful for support or sales contexts where the visitor wants a record.

```javascript theme={null}
TruedyWidget.init({
  widgetId: "YOUR_WIDGET_ID",
  agentId: "YOUR_AGENT_ID",
  showPostCallRecap: true
});
```

To receive transcripts on your server (for CRM logging, follow-ups, etc.), set up a [webhook](/guides/webhooks) — Truedy sends a `call.ended` event with the full transcript when each call finishes.

***

## Troubleshooting

**Widget doesn't appear**

* Check browser console for errors
* Ensure the script URL is correct: `https://api.truedy.ai/widget.js`
* Confirm `widgetId` and `agentId` are valid UUIDs

**"Domain not allowed" — widget blocked**

* Your current domain is not in the widget's `allowedDomains` list
* Add your domain in the dashboard under **Widgets → Edit → Allowed Domains**, or remove the restriction entirely during development

**"Microphone access denied"**

* The page must be served over HTTPS (or localhost) — browsers block mic access on plain HTTP
* The visitor must grant microphone permission when prompted

**Agent doesn't respond / call drops immediately**

* Verify your agent is set to **Active** in the dashboard
* Check that the agent has been saved and synced (a spinner may appear briefly after creation)

**Call works but no audio**

* Ensure the visitor hasn't muted the browser tab
* Some corporate networks block WebRTC — this is outside Truedy's control

***

## Next steps

* [Webhooks](/guides/webhooks) — receive call events and transcripts on your server
* [Creating an Agent](/guides/creating-an-agent) — configure your AI agent's voice, personality, and tools
* [Custom Voice Widget](/guides/webrtc-custom-widget) — build a fully custom widget UI with the Ultravox SDK
* [WebRTC API Reference](/api-reference/webrtc) — low-level API docs for programmatic call creation
