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

# Sematkan widget web

> Tambahkan agen suara ke situs pemasaran atau dukungan Anda — tanpa memerlukan nomor telepon.

Widget web memberi pengunjung situs Anda percakapan klik-untuk-berbicara
dengan agen AI, menggunakan mikrofon browser. Ini adalah SDK
JavaScript / React terpisah dengan [referensi SDK](/id/widget/overview)
sendiri — panduan ini berfokus pada penyiapan sisi ThunderPhone yang dibutuhkan widget.

<Note>
  Anda dapat melakukan semuanya tanpa cURL: halaman dasbor **Widget Web**
  (`/dashboard/web-widgets`) membuat widget, menetapkan mode dan agennya,
  mengelola domain yang diizinkan, dan memberikan snippet sematan.
</Note>

## Prasyarat

<Steps>
  <Step title="Buat agen">
    Agen yang Prompt dan suaranya akan menjalankan sesi widget. Tetapkan
    `widget_enabled: true` (default).
  </Step>

  <Step title="Tentukan mode perutean">
    * `mode="agent"` — satu agen statis per kunci. Paling sederhana.
    * `mode="webhook"` — server Anda memilih agen per pengunjung melalui
      [webhook `web.incoming`](/id/webhooks/call-incoming). Gunakan ini untuk
      pengguna yang masuk, pengujian A/B, atau perutean per halaman.
  </Step>

  <Step title="Daftarkan domain yang diizinkan">
    Kunci yang dapat dipublikasikan terkunci ke origin. Anda harus mencantumkan setiap hostname
    yang akan menyematkan widget. `localhost` / `127.0.0.1` selalu
    diizinkan selama pengembangan lokal.
  </Step>
</Steps>

## Buat kunci yang dapat dipublikasikan

<CodeGroup>
  ```bash Static agent theme={null}
  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"]
    }'
  ```

  ```bash Dynamic via webhook theme={null}
  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>

Respons mencakup `key` yang diawali dengan `pk_live_...`. **Kunci yang dapat dipublikasikan
bersifat publik secara desain** — aman untuk disertakan dalam bundle front-end Anda.
Lihat [referensi kunci yang dapat dipublikasikan](/api-reference/publishable-keys) untuk
semua field.

<Warning>
  `allowed_domains` harus berisi setidaknya satu entri. `*.example.com`
  cocok dengan subdomain (misalnya, `api.example.com`) tetapi **tidak**
  dengan domain utama. Wildcard utama seperti `*` atau `*.*` ditolak.
</Warning>

## Tambahkan widget ke situs Anda

Tiga opsi integrasi dibahas dalam
[dokumentasi SDK widget](/id/widget/overview):

<CardGroup cols={3}>
  <Card title="Komponen React" icon="react" href="/id/widget/react">
    `<ThunderPhoneWidget publishableKey="pk_live_..." />`.
  </Card>

  <Card title="Hook headless" icon="circle-nodes" href="/id/widget/headless-hook">
    `useThunderPhone()` untuk UI kustom.
  </Card>

  <Card title="Tag skrip CDN" icon="code" href="/id/widget/cdn-script-tag">
    `ThunderPhone.mount({...})` untuk situs tanpa bundler.
  </Card>
</CardGroup>

Ketiganya menerima `publishableKey` yang sama dan merender tombol mikrofon
beserta elemen audio saat panggilan.

`context` widget dipotong hingga 12.000 karakter (sekitar 3.400
token teks bahasa Inggris biasa) dan diperhitungkan dalam
[biaya tambahan ukuran Prompt](/id/guides/billing-and-topups).

## Webhook mode widget

Saat `mode="webhook"`, ThunderPhone memanggil `webhook_url` Anda pada setiap
awal sesi dengan payload `web.incoming`. Kembalikan konfigurasi agen
yang ingin Anda jalankan untuk pengunjung tersebut — konfigurasi ini mengikuti
[skema respons](/id/webhooks/call-incoming) yang sama seperti
panggilan telepon:

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

Anda dapat mencampurkan konteks dari sesi Anda sendiri (pelanggan mana yang sedang menjelajah,
halaman mana yang mereka buka) ke dalam Prompt, dan mengganti agen untuk setiap peluncuran.

## Pantau sesi

Sesi widget muncul di
[`GET /v1/calls`](/api-reference/calls#list-calls) dengan
`direction="widget"` — dengan transkrip, rekaman, penilaian, dan
penagihan yang sama seperti panggilan telepon. Filter berdasarkan `direction` untuk membuat
dasbor khusus widget.

***

## Langkah berikutnya

<CardGroup cols={2}>
  <Card title="Referensi SDK widget" icon="window-maximize" href="/id/widget/overview">
    Detail integrasi React / hook / CDN.
  </Card>

  <Card title="Konfigurasi dinamis per panggilan" icon="bolt" href="/id/guides/dynamic-call-config">
    Terapkan alur `mode="webhook"` secara menyeluruh.
  </Card>

  <Card title="Referensi kunci yang dapat dipublikasikan" icon="key" href="/api-reference/publishable-keys">
    Setiap field pada resource kunci.
  </Card>

  <Card title="API sesi mikrofon" icon="microphone" href="/api-reference/mic-sessions">
    Lewati widget; gunakan LiveKit secara langsung untuk UI kustom.
  </Card>
</CardGroup>
