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

# Embed the AI Widget

> Drop a User Intuition study directly into your web app with an embeddable on-site interview widget. Install in minutes with HTML, JavaScript, or React.

The User Intuition AI widget is an embeddable on-site interview surface. Drop it into any web app and participants can start a voice or chat interview without leaving your product. The widget triggers a live Study from inside your page, captures the response, and feeds it back into your dashboard like any other interview.

Use it for in-app feedback, post-purchase surveys, churn intercepts, or always-on listening from inside your product.

***

## What you need

Every embed needs two values:

| Prop           | Description                                                                                                                   |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `public-key`   | Your User Intuition public API key. Safe to expose in client-side code.                                                       |
| `assistant-id` | Your **Study ID**. The widget API calls it `assistant-id` for historical reasons, but it points to the Study you want to run. |

Both values live on your account. See [Account Settings](/essentials/account-settings) to find them.

<Note>
  Wherever you see `assistant-id` (HTML attribute) or `assistantId` (JavaScript prop), pass the ID of the Study you want participants to take. The two terms are interchangeable in this widget.
</Note>

***

## Install

The package is published as `@userintuition-ai/web`.

<CodeGroup>
  ```bash npm theme={null}
  npm install @userintuition-ai/web
  ```

  ```html CDN theme={null}
  <script src="https://unpkg.com/@userintuition-ai/web/dist/embed/widget.umd.min.js"></script>
  ```
</CodeGroup>

***

## Embedding methods

There are four ways to mount the widget. Pick the one that matches your stack.

### 1. HTML custom element

The simplest option. Drop in the script tag and a `<userintuition-widget>` element anywhere in your HTML.

```html theme={null}
<!DOCTYPE html>
<html>
  <head>
    <script src="https://unpkg.com/@userintuition-ai/web/dist/embed/widget.umd.min.js"></script>
  </head>
  <body>
    <userintuition-widget
      public-key="your-public-key"
      assistant-id="your-study-id"
      mode="voice"
      theme="dark"
      position="bottom-right"
    ></userintuition-widget>
  </body>
</html>
```

### 2. JavaScript loader

If you need to mount programmatically (for example, after a route change or user action), use `WidgetLoader`.

```javascript theme={null}
import { WidgetLoader } from '@userintuition-ai/web';

const container = document.getElementById('widget-container');

WidgetLoader({
  container,
  component: 'VapiWidget',
  props: {
    publicKey: 'your-public-key',
    assistantId: 'your-study-id',
    mode: 'voice',
    theme: 'dark',
    position: 'bottom-right',
  },
});
```

You can also use HTML data attributes for automatic initialization:

```html theme={null}
<div
  data-client-widget="VapiWidget"
  data-props='{
    "publicKey": "your-public-key",
    "assistantId": "your-study-id",
    "mode": "voice",
    "theme": "dark",
    "position": "bottom-right"
  }'
></div>
```

### 3. React component

For React apps, install the npm package and import the component.

<CodeGroup>
  ```tsx React theme={null}
  import { UserIntuitionWidget } from '@userintuition-ai/web';

  export default function App() {
    return (
      <UserIntuitionWidget
        publicKey="your-public-key"
        assistantId="your-study-id"
        mode="voice"
        theme="dark"
        position="bottom-right"
      />
    );
  }
  ```

  ```tsx TypeScript theme={null}
  import { UserIntuitionWidget, type UserIntuitionWidgetProps } from '@userintuition-ai/web';

  const props: UserIntuitionWidgetProps = {
    publicKey: 'your-public-key',
    assistantId: 'your-study-id',
    mode: 'voice',
    theme: 'dark',
  };

  export default function App() {
    return <UserIntuitionWidget {...props} />;
  }
  ```
</CodeGroup>

### 4. Web component variant

For React apps that prefer a thin wrapper around the underlying custom element, use `UserIntuitionWidgetWebComponent`. It is the package's default export and the recommended React surface.

```tsx theme={null}
import { UserIntuitionWidgetWebComponent } from '@userintuition-ai/web';
// or use the default export
import UserIntuitionWidget from '@userintuition-ai/web';

export default function App() {
  return (
    <UserIntuitionWidgetWebComponent
      publicKey="your-public-key"
      assistantId="your-study-id"
      mode="voice"
      theme="dark"
    />
  );
}
```

***

## Modes

The widget supports three interview modes. Set the mode that fits your audience and the depth of feedback you want.

| Mode     | When to use it                                                                                                        |
| -------- | --------------------------------------------------------------------------------------------------------------------- |
| `voice`  | Spoken interviews. Best for richer, longer-form feedback and natural conversation. Default mode.                      |
| `chat`   | Text-only interviews. Best for quiet environments, accessibility, or users who prefer typing.                         |
| `hybrid` | Lets the participant choose voice or chat at the start. Best when you don't know the context the widget will load in. |

```html theme={null}
<userintuition-widget
  public-key="your-public-key"
  assistant-id="your-study-id"
  mode="hybrid"
></userintuition-widget>
```

***

## Position and size

Control where the widget anchors and how much room it takes up on screen.

### Position

| Value          | Description                                                                  |
| -------------- | ---------------------------------------------------------------------------- |
| `bottom-right` | Default. Anchored bottom-right, ideal for chat-style launchers.              |
| `bottom-left`  | Bottom-left corner.                                                          |
| `top-right`    | Top-right corner.                                                            |
| `top-left`     | Top-left corner.                                                             |
| `center`       | Centered on screen. Use for full-screen takeovers or modal-style interviews. |

### Size

| Value     | Description                                                           |
| --------- | --------------------------------------------------------------------- |
| `compact` | Default. Small launcher that expands when opened.                     |
| `full`    | Full launcher panel — more visible, larger surface for the interview. |
| `minimal` | Smallest footprint. Good for unobtrusive, always-on placement.        |

```html theme={null}
<userintuition-widget
  public-key="your-public-key"
  assistant-id="your-study-id"
  position="bottom-right"
  size="full"
></userintuition-widget>
```

***

## Theme and branding

The widget ships with `light` and `dark` presets. You can override individual colors to match your brand.

| React prop           | HTML attribute          | Description                                                   |
| -------------------- | ----------------------- | ------------------------------------------------------------- |
| `theme`              | `theme`                 | Preset — `light` or `dark`. Default: `light`.                 |
| `baseBgColor`        | `base-bg-color`         | Base background color (hex).                                  |
| `baseColor`          | `base-color`            | Base color (hex).                                             |
| `accentColor`        | `accent-color`          | Accent color used across the interview UI (hex).              |
| `ctaButtonColor`     | `cta-button-color`      | Background color of the call-to-action button (hex).          |
| `ctaButtonTextColor` | `cta-button-text-color` | Text color of the call-to-action button (hex).                |
| `buttonBaseColor`    | `button-base-color`     | Base color for buttons (hex).                                 |
| `buttonAccentColor`  | `button-accent-color`   | Accent color for buttons (hex).                               |
| `borderRadius`       | `border-radius`         | One of `none`, `small`, `medium`, `large`. Default: `medium`. |

```html theme={null}
<userintuition-widget
  public-key="your-public-key"
  assistant-id="your-study-id"
  theme="dark"
  base-bg-color="#000000"
  accent-color="#14B8A6"
  cta-button-color="#000000"
  cta-button-text-color="#ffffff"
  border-radius="large"
></userintuition-widget>
```

You can also customize widget copy with `title`, `cta-title`, `cta-subtitle`, `start-button-text`, `end-button-text`, and mode-specific empty-state messages (`voice-empty-message`, `chat-empty-message`, `chat-placeholder`, `hybrid-empty-message`, and others).

***

## Consent flow

When `consent-required` is enabled, the widget shows a consent dialog before the interview can start. The participant's choice is stored in `localStorage` so they only see the dialog once per device.

| React prop          | HTML attribute        | Description                                                          |
| ------------------- | --------------------- | -------------------------------------------------------------------- |
| `consentRequired`   | `consent-required`    | Show a consent dialog before the interview begins. Default: `false`. |
| `consentTitle`      | `consent-title`       | Title of the consent dialog.                                         |
| `consentContent`    | `consent-content`     | Body text of the consent dialog.                                     |
| `consentStorageKey` | `consent-storage-key` | LocalStorage key used to persist consent.                            |
| `termsContent`      | `terms-content`       | Optional terms-and-conditions text.                                  |

```html theme={null}
<userintuition-widget
  public-key="your-public-key"
  assistant-id="your-study-id"
  consent-required="true"
  consent-title="Terms and conditions"
  consent-content='By clicking "Agree," and each time I interact with this AI agent, I consent to the recording, storage, and sharing of my communications with third-party service providers, and as otherwise described in our Terms of Service.'
  consent-storage-key="userintuition_widget_consent"
></userintuition-widget>
```

<Note>
  Consent state is keyed by `consent-storage-key`. If you change the key, the widget will treat returning participants as new and prompt them again.
</Note>

***

## Smart display

You usually don't want the widget to appear on every page or fire instantly. Use these props to scope when and where it shows.

| React prop       | HTML attribute      | Description                                                                                                                                          |
| ---------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `showWidget`     | `show-widget`       | Hard on/off switch. Default: `true`.                                                                                                                 |
| `showBasedOnUrl` | `show-based-on-url` | Array of URL paths where the widget should appear. Pass a JSON array string in HTML.                                                                 |
| `delayInterval`  | `delay-interval`    | Milliseconds to wait before showing the widget. Default: `0`. Useful when you want to give the page a moment to settle before interrupting the user. |

<CodeGroup>
  ```html HTML theme={null}
  <userintuition-widget
    public-key="your-public-key"
    assistant-id="your-study-id"
    show-based-on-url='["/feedback", "/contact"]'
    delay-interval="3000"
  ></userintuition-widget>
  ```

  ```tsx React theme={null}
  <UserIntuitionWidget
    publicKey="your-public-key"
    assistantId="your-study-id"
    showBasedOnUrl={['/feedback', '/contact']}
    delayInterval={3000}
  />
  ```
</CodeGroup>

***

## Voice and reconnect options

Voice mode has a few extra knobs for transcript display and reconnection.

| React prop            | HTML attribute          | Description                                                              |
| --------------------- | ----------------------- | ------------------------------------------------------------------------ |
| `voiceShowTranscript` | `voice-show-transcript` | Display a live transcript during voice interviews. Default: `false`.     |
| `voiceAutoReconnect`  | `voice-auto-reconnect`  | Reconnect automatically if the audio connection drops. Default: `false`. |
| `reconnectStorageKey` | `reconnect-storage-key` | LocalStorage key used to persist reconnect state.                        |
| `showTranscript`      | `show-transcript`       | Show the transcript surface generally. Default: `false`.                 |

***

## Where to find your keys

Both `public-key` and `assistant-id` come from your User Intuition account.

<CardGroup cols={2}>
  <Card title="Public key" icon="key" href="/essentials/account-settings">
    Find this in your account settings under API keys. Safe to ship in client-side code.
  </Card>

  <Card title="Study ID" icon="flask" href="/essentials/account-settings">
    Each Study has its own ID. Pass it as `assistant-id` (or `assistantId` in React).
  </Card>
</CardGroup>

***

## Browser support

The widget runs in any modern browser that supports:

* ES6+
* The Custom Elements API
* Microphone access (for voice and hybrid modes)

For React installs, React 16.8+ is required as a peer dependency.

***

## Next.js and React Server Components

The widget is a client-only component — it touches `window`, `localStorage`, and the microphone. In Next.js 13+ with the App Router, mark the file as a client component.

```tsx theme={null}
'use client';

import UserIntuitionWidget from '@userintuition-ai/web';

export default function FeedbackWidget() {
  return (
    <UserIntuitionWidget
      publicKey="your-public-key"
      assistantId="your-study-id"
      mode="voice"
    />
  );
}
```

<Warning>
  Don't import the widget into a server component or render it during SSR. The bundle assumes a browser environment and will throw if it loads on the server.
</Warning>

***

## Quickstart

<Steps>
  <Step title="Grab your keys">
    Copy your public key and the Study ID from [Account Settings](/essentials/account-settings).
  </Step>

  <Step title="Install or include the widget">
    Run `npm install @userintuition-ai/web` for React, or drop in the UMD `<script>` tag for plain HTML.
  </Step>

  <Step title="Mount it">
    Add the `<userintuition-widget>` element (or `<UserIntuitionWidget />` component) with `public-key` and `assistant-id`.
  </Step>

  <Step title="Style and scope">
    Set `theme`, `position`, `size`, and brand colors. Use `show-based-on-url` and `delay-interval` so the widget only appears where it should.
  </Step>

  <Step title="Test the interview">
    Open the page, trigger the widget, and complete a test interview. The response will appear in your Study Dashboard alongside link and invite responses.
  </Step>
</Steps>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Share a study link" icon="link" href="/recruiting/share-link">
    The simpler alternative — a hosted URL anyone can open in a browser.
  </Card>

  <Card title="Account settings" icon="gear" href="/essentials/account-settings">
    Find your public key and Study IDs.
  </Card>
</CardGroup>
