---
title: "Incorpora il widget web"
description: "Aggiungi un agente vocale al tuo sito di marketing o assistenza con un solo tag di copione: i visitatori possono parlarci direttamente dal browser, senza bisogno di un numero di telefono."
---

Il widget web offre ai visitatori del tuo sito una conversazione click-to-talk
con un agente IA, utilizzando il microfono del browser. È un SDK
JavaScript / React separato con la propria [documentazione di riferimento dell'SDK](/it/widget/overview)
— questa guida si concentra sulla configurazione lato ThunderPhone necessaria al widget.

<Note>
  Puoi fare tutto questo senza cURL: la pagina della dashboard **Widget web**
  (`/dashboard/web-widgets`) crea il widget, ne imposta la modalità
  e l'agente, gestisce i domini consentiti e ti fornisce lo snippet di incorporamento.
</Note>

## Prerequisiti

<Steps>
  <Step title="Crea un agente">
    L'agente il cui prompt e la cui voce eseguiranno la sessione del widget. Imposta
    `widget_enabled: true` (impostazione predefinita).
  </Step>
  <Step title="Decidi la modalità di instradamento">
    - `mode="agent"` — un agente statico per chiave. La soluzione più semplice.
    - `mode="webhook"` — il tuo server seleziona l'agente per visitatore tramite un
      [webhook `web.incoming`](/it/webhooks/call-incoming). Usalo per utenti
      autenticati, test A/B o instradamento per pagina.
  </Step>
  <Step title="Elenca i domini consentiti">
    Indica ogni hostname che incorporerà il widget. I browser inviano l'origine
    della pagina con ogni richiesta di sessione, quindi l'elenco impedisce che la tua chiave
    funzioni quando qualcuno la copia su un altro sito. Non è
    autenticazione: uno script esterno a un browser può inviare qualsiasi intestazione
    `Origin`. `localhost` non è consentito automaticamente in produzione; per
    eseguire test locali con l'API di produzione, aggiungi `localhost` all'
    elenco.
  </Step>
  <Step title="Scegli le sovrascritture del browser">
    Decidi quali impostazioni di sessione può inviare la tua pagina. Le nuove chiavi non ne accettano
    nessuna; consulta [Sovrascritture del browser](#browser-overrides).
  </Step>
</Steps>

## Crea una chiave pubblicabile

<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>

La risposta include una `key` che inizia con `pk_live_...`. **Le chiavi
pubblicabili sono pubbliche per progettazione** — puoi includerle senza rischi
nel bundle front-end. Consulta la [documentazione di riferimento delle chiavi pubblicabili](/api-reference/publishable-keys) per
tutti i campi.

<Warning>
  `allowed_domains` deve contenere almeno una voce. `*.example.com`
  corrisponde ai sottodomini (ad esempio `api.example.com`) ma **non** al
  dominio principale. I caratteri jolly generici come `*` o `*.*` vengono rifiutati.
</Warning>

## Inserisci il widget nel tuo sito

La [documentazione dell'SDK del widget](/it/widget/overview) descrive tre opzioni
di integrazione:

<CardGroup cols={3}>
  <Card title="Componente React" icon="react" href="/it/widget/react">
    `<ThunderPhoneWidget publishableKey="pk_live_..." />`.
  </Card>
  <Card title="Hook headless" icon="circle-nodes" href="/it/widget/headless-hook">
    `useThunderPhone()` per interfacce utente personalizzate.
  </Card>
  <Card title="Tag script CDN" icon="code" href="/it/widget/cdn-script-tag">
    `ThunderPhone.mount({...})` per siti senza bundler.
  </Card>
</CardGroup>

Tutte e tre accettano lo stesso `publishableKey` e visualizzano il pulsante
del microfono più l'elemento audio durante la chiamata.

## Override del browser

Il widget può inviare quattro impostazioni per sessione dalla pagina:

| Impostazione | Proprietà del widget | Cosa modifica |
|---------|-------------|-----------------|
| `context` | `context` | Testo della pagina, aggiunto al prompt dell'agente come riferimento |
| `variables` | nessuna (solo `POST /v1/widget/session` non elaborato) | Valori per i segnaposto `{{variable}}` nel prompt |
| `voice` | `voice` | La voce dell'agente per questa sessione |
| `language` | `language` | La lingua in cui inizia la sessione |

La tua chiave pubblicabile è pubblica, quindi chiunque la possieda può inviare queste
impostazioni, anche da un copione che falsifica il tuo dominio. Ciascuna è
quindi disattivata finché non la autorizzi sulla chiave: selezionala in **Override del browser**
quando crei o modifichi il widget nella dashboard, oppure imposta
`allowed_overrides` tramite l'
[API delle chiavi pubblicabili](/api-reference/publishable-keys). Autorizza solo ciò
che la tua pagina invia effettivamente.

Una richiesta di sessione che include un'impostazione non consentita dalla chiave
non riesce con `400` e la indica:

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

Il controllo si applica in entrambe le modalità. In modalità webhook, un'impostazione consentita viene
inoltre inoltrata al tuo webhook `web.incoming` (`context` arriva come
`website_context`). Le chiavi create prima dell'introduzione di questa impostazione consentono tutte
e quattro, quindi gli embed esistenti continuano a funzionare; disattiva ciò che non usi.

Il `context` del widget viene troncato a 12.000 caratteri (all'incirca 3.400
token di testo inglese tipico) e contribuisce al
[sovrapprezzo per le dimensioni del prompt](/it/guides/billing-and-topups).
All'agente viene indicato di trattarlo come contenuto della pagina, non come istruzioni.

## Webhook in modalità widget

Quando `mode="webhook"`, ThunderPhone chiama il tuo `webhook_url` a ogni
avvio di sessione con un payload `web.incoming`. Restituisci la configurazione
dell'agente che vuoi eseguire per quel visitatore — segue lo stesso
[schema di risposta](/it/webhooks/call-incoming) delle chiamate telefoniche:

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

Puoi combinare nel prompt il contesto della tua sessione (quale cliente sta navigando,
quale pagina sta visualizzando) e cambiare agente per ciascun rilascio.

## Osserva le sessioni

Le sessioni del widget vengono visualizzate in
[`GET /v1/calls`](/api-reference/calls#list-calls) con
`direction="widget"` — stessa trascrizione, registrazione, valutazione e
fatturazione delle chiamate telefoniche. Filtra per `direction` per creare una
dashboard dedicata al widget.

---

## Passaggi successivi

<CardGroup cols={2}>
  <Card title="Riferimento SDK del widget" icon="window-maximize" href="/it/widget/overview">
    Dettagli sull'integrazione React / hook / CDN.
  </Card>
  <Card title="Configurazione dinamica per chiamata" icon="bolt" href="/it/guides/dynamic-call-config">
    Implementa il flusso `mode="webhook"` end-to-end.
  </Card>
  <Card title="Riferimento delle chiavi pubblicabili" icon="key" href="/api-reference/publishable-keys">
    Ogni campo della risorsa chiave.
  </Card>
  <Card title="API delle sessioni microfono" icon="microphone" href="/api-reference/mic-sessions">
    Salta il widget; usa LiveKit direttamente per interfacce utente personalizzate.
  </Card>
</CardGroup>
