---
title: "Вбудуйте вебвіджет"
description: "Додайте голосового агента на свій маркетинговий сайт або сайт підтримки за допомогою одного тега скрипту — відвідувачі спілкуватимуться з ним безпосередньо в браузері, номер телефону не потрібен."
---

Вебвіджет надає відвідувачам вашого сайту можливість розмовляти з AI-агентом натисканням кнопки, використовуючи мікрофон браузера. Це окремий JavaScript / React SDK із власним [довідником SDK](/uk/widget/overview) — у цьому посібнику описано налаштування на боці ThunderPhone, потрібні для віджета.

<Note>
  Усе це можна зробити без cURL: сторінка панелі керування **Вебвіджети**
  (`/dashboard/web-widgets`) створює віджет, задає його режим і агента,
  керує дозволеними доменами та надає фрагмент коду для вбудовування.
</Note>

## Передумови

<Steps>
  <Step title="Створіть агента">
    Агент, підказка й голос якого використовуватимуться під час сеансу віджета. Установіть
    `widget_enabled: true` (значення за замовчуванням).
  </Step>
  <Step title="Визначте режим маршрутизації">
    - `mode="agent"` — один статичний агент для кожного ключа. Найпростіший варіант.
    - `mode="webhook"` — ваш сервер вибирає агента для кожного відвідувача через
      [вебхук `web.incoming`](/uk/webhooks/call-incoming). Використовуйте для
      авторизованих користувачів, A/B-тестів або маршрутизації для окремих сторінок.
  </Step>
  <Step title="Перелічіть дозволені домени">
    Укажіть кожне ім’я хоста, на якому буде вбудовано віджет. Браузери надсилають
    походження сторінки з кожним запитом сеансу, тому список не дасть вашому ключу
    працювати, якщо хтось скопіює його на інший сайт. Це не
    автентифікація: скрипт поза браузером може надіслати будь-який заголовок
    `Origin`. `localhost` не дозволено автоматично в продакшні; щоб
    тестувати локально з продакшн API, додайте `localhost` до
    списку.
  </Step>
  <Step title="Виберіть перевизначення для браузера">
    Визначте, які налаштування сеансу може надсилати ваша сторінка. Нові ключі не дозволяють
    жодних; див. [Перевизначення для браузера](#browser-overrides).
  </Step>
</Steps>

## Створіть публічний ключ

<CodeGroup>
```bash Static agent
curl -X POST https://api.thunderphone.com/v1/publishable-key \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":            "Marketing site (prod)",
    "mode":            "agent",
    "agent_id":        12,
    "allowed_domains": ["example.com", "*.example.com"],
    "allowed_overrides": ["context"]
  }'
```

```bash Dynamic via webhook
curl -X POST https://api.thunderphone.com/v1/publishable-key \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":            "Support (dynamic)",
    "mode":            "webhook",
    "webhook_url":     "https://example.com/thunderphone/widget-hook",
    "allowed_domains": ["support.example.com"]
  }'
```
</CodeGroup>

Відповідь містить `key`, що починається з `pk_live_...`. **Публічні
ключі є публічними за задумом** — їх безпечно додавати до пакета вашого фронтенду.
Перегляньте [довідник публічних ключів](/api-reference/publishable-keys), щоб дізнатися
про всі поля.

<Warning>
  `allowed_domains` має містити щонайменше один запис. `*.example.com`
  відповідає піддоменам (наприклад, `api.example.com`), але **не** самому
  домену. Неповні маски на кшталт `*` або `*.*` відхиляються.
</Warning>

## Додайте віджет на свій сайт

У [документації SDK віджета](/uk/widget/overview) описано три варіанти
інтеграції:

<CardGroup cols={3}>
  <Card title="Компонент React" icon="react" href="/uk/widget/react">
    `<ThunderPhoneWidget publishableKey="pk_live_..." />`.
  </Card>
  <Card title="Headless-хук" icon="circle-nodes" href="/uk/widget/headless-hook">
    `useThunderPhone()` для власних інтерфейсів.
  </Card>
  <Card title="Тег скрипту CDN" icon="code" href="/uk/widget/cdn-script-tag">
    `ThunderPhone.mount({...})` для сайтів без збирача пакетів.
  </Card>
</CardGroup>

Усі три варіанти приймають однаковий `publishableKey` і відображають кнопку
мікрофона та аудіоелемент під час дзвінка.

## Перевизначення в браузері

Віджет може надсилати зі сторінки чотири налаштування для кожного сеансу:

| Налаштування | Властивість віджета | Що змінює |
|---------|-------------|-----------------|
| `context` | `context` | Текст зі сторінки, доданий до промпту агента як довідковий матеріал |
| `variables` | немає (лише необроблений `POST /v1/widget/session`) | Значення для заповнювачів `{{variable}}` у промпті |
| `voice` | `voice` | Голос агента для цього сеансу |
| `language` | `language` | Мова, якою починається сеанс |

Ваш публічний ключ є загальнодоступним, тому будь-хто, хто має його, може надсилати ці
налаштування, зокрема зі скрипту, що імітує ваш домен. Тому кожне з них
вимкнено, доки ви не дозволите його для ключа: позначте його в розділі **Перевизначення браузера**, коли створюєте або редагуєте віджет на панелі керування, або задайте
`allowed_overrides` через
[API публічних ключів](/api-reference/publishable-keys). Дозволяйте лише те,
що фактично надсилає ваша сторінка.

Запит сеансу, який містить налаштування, не дозволене ключем, завершується
помилкою `400` і вказує його назву:

```json
{
  "error": "override_not_allowed",
  "fields": ["voice"],
  "message": "This publishable key does not allow the browser to set `voice`. ..."
}
```

Перевірка застосовується в обох режимах. У режимі webhook дозволене налаштування
також пересилається до вашого webhook `web.incoming` (`context` надходить як
`website_context`). Ключі, створені до появи цього налаштування, дозволяють усі
чотири, тому наявні вбудовування продовжують працювати; вимкніть те, чим не
користуєтеся.

`context` віджета скорочується до 12 000 символів (приблизно 3 400 токенів
типового англійського тексту) і враховується в
[доплату за розмір промпту](/uk/guides/billing-and-topups).
Агенту вказано сприймати його як вміст сторінки, а не як інструкції.

## Вебхуки режиму віджета

Коли `mode="webhook"`, ThunderPhone викликає ваш `webhook_url` на початку кожного
сеансу з корисним навантаженням `web.incoming`. Поверніть конфігурацію агента,
яку потрібно запустити для цього відвідувача — вона використовує ту саму
[схему відповіді](/uk/webhooks/call-incoming), що й телефонні
дзвінки:

```json
{
  "prompt":  "You are a VIP concierge for Jane Doe.",
  "voice":   "john",
  "product": "storm-base",
  "tools":   [ /* per-customer tools */ ]
}
```

Ви можете додавати до промпту контекст із власного сеансу (який клієнт переглядає сайт,
на якій сторінці він перебуває) і змінювати агентів для різних етапів розгортання.

## Переглядайте сесії

Сесії віджета відображаються в
[`GET /v1/calls`](/api-reference/calls#list-calls) з
`direction="widget"` — ті самі транскрипт, запис, оцінювання та
білінг, що й для телефонних дзвінків. Фільтруйте за `direction`, щоб створити
панель керування лише для віджета.

---

## Наступні кроки

<CardGroup cols={2}>
  <Card title="Довідник SDK віджета" icon="window-maximize" href="/uk/widget/overview">
    Деталі інтеграції React / hook / CDN.
  </Card>
  <Card title="Динамічна конфігурація для кожного дзвінка" icon="bolt" href="/uk/guides/dynamic-call-config">
    Реалізуйте потік `mode="webhook"` від початку до кінця.
  </Card>
  <Card title="Довідник публічних ключів" icon="key" href="/api-reference/publishable-keys">
    Кожне поле ресурсу ключа.
  </Card>
  <Card title="API сесій мікрофона" icon="microphone" href="/api-reference/mic-sessions">
    Пропустіть віджет; керуйте LiveKit безпосередньо для власних інтерфейсів.
  </Card>
</CardGroup>
