---
title: "CDN / Tag de script"
description: "Adicione o widget de voz do ThunderPhone a qualquer site sem um bundler"
---

A versão CDN inclui o React internamente, então você pode usar o widget em sites estáticos, WordPress, Webflow ou qualquer página em que possa adicionar HTML. Não é necessário npm, bundler nem framework.

## URLs da CDN

<CodeGroup>
```html Latest (recommended)
<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
```

```html Pinned version
<!-- Each stable release also publishes an immutable /widget/vX.Y.Z/ path
     matching the @thunderphone/widget npm version (v1.1.2 at the time of
     writing). If you pin, you own updating the URL for new releases. -->
<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/v1.1.2/style.css" />
<script src="https://cdn.thunderphone.com/widget/v1.1.2/widget.js"></script>
```
</CodeGroup>

<Tip>
  As URLs `latest` são geradas pelo gerador de snippets de incorporação do dashboard. Elas são armazenadas em cache por 5 minutos e recebem automaticamente novas versões estáveis. Os caminhos fixados `/widget/vX.Y.Z/` são imutáveis e armazenados em cache a longo prazo -- se você fixar uma versão, faça-a corresponder à versão npm `@thunderphone/widget` usada no seu desenvolvimento.
</Tip>

---

## Uso básico

```html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
</head>
<body>

  <div id="thunderphone"></div>

  <script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
  <script>
    ThunderPhone.mount({
      element: '#thunderphone',
      publishableKey: 'pk_live_your_publishable_key',
    })
  </script>

</body>
</html>
```

O widget é montado no elemento de destino e renderizado como uma **barra de posição fixa em um canto da viewport** (o padrão é `bottom-right`, controlado pela opção `position`). O elemento de montagem é apenas a raiz do React -- sua localização na página não afeta onde o widget aparece.

---

## Opções de montagem

`ThunderPhone.mount()` aceita as mesmas opções do componente React, além da propriedade `element`:

| Opção | Tipo | Obrigatório | Padrão | Descrição |
|--------|------|----------|---------|-------------|
| `element` | `string \| HTMLElement` | Sim | -- | Seletor CSS (por exemplo, `'#thunderphone'`) ou referência a um elemento DOM. |
| `publishableKey` | `string` | Sim | -- | Chave de API publicável (`pk_live_...`). O agente é resolvido automaticamente com base na configuração do widget da chave. |
| `theme` | `'light' \| 'dark'` | Não | `'light'` | Esquema de cores. |
| `primaryColor` | `string` | Não | `'#000000'` (claro) / `'#ffffff'` (escuro) | String de cor CSS usada como cor de destaque. |
| `title` | `string` | Não | `'Voice assistant'` | Texto exibido na barra do widget. |
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | Não | `'bottom-right'` | Posição fixa na viewport. |
| `apiBase` | `string` | Não | `'https://api.thunderphone.com/v1'` | Substituição do URL base da API. |
| `language` | `string` | Não | -- | Substituição de idioma por sessão -- um código de idioma ou localidade, como `en`, `es` ou `fr-FR`. Quando não definido, o idioma configurado do agente é aplicado. Requer `language` nas [substituições do navegador](/pt/guides/embed-web-widget) da chave. |
| `voice` | `string` | Não | -- | Substituição de voz por sessão -- um nome de voz, como `maria`. Quando não definida, a voz configurada do agente é aplicada. Requer `voice` nas [substituições do navegador](/pt/guides/embed-web-widget) da chave. |
| `context` | `string` | Não | -- | Contexto factual da página ou do site por sessão transmitido ao agente. Truncado no servidor para 12.000 caracteres. Requer `context` nas [substituições do navegador](/pt/guides/embed-web-widget) da chave. |
| `onConnect` | `() => void` | Não | -- | Chamado quando a sessão de voz é conectada. |
| `onDisconnect` | `() => void` | Não | -- | Chamado quando a sessão termina. |
| `onError` | `(error) => void` | Não | -- | Chamado em caso de erros. O erro tem os campos `error` (código) e `message`. |
| `ringtone` | `boolean \| string` | Não | `false` | Reproduz um toque durante a conexão. `true` para o toque padrão ou uma string de URL para áudio personalizado. |

---

## Limpeza

`ThunderPhone.mount()` retorna uma instância do widget com métodos de limpeza:

```html
<script>
  var widget = ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
  })

  // Later, when you want to remove the widget:
  widget.unmount()

  // Or equivalently:
  widget.destroy()
</script>
```

Tanto `unmount()` quanto `destroy()` fazem a mesma coisa -- desconectam qualquer sessão de voz ativa e removem o widget do DOM. Use o que fizer mais sentido no seu código.

<Note>
  Sempre faça a limpeza do widget ao navegar para outra página em aplicações de página única ou quando o elemento que o contém for removido. Isso garante que as sessões de voz ativas sejam desconectadas corretamente.
</Note>

---

## Exemplos

### Tema escuro com cor personalizada

```html
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    theme: 'dark',
    primaryColor: '#8b5cf6',
    title: 'Talk to our AI',
  })
</script>
```

### Posição personalizada

```html
<div id="thunderphone"></div>

<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    position: 'bottom-left',
  })
</script>
```

### Com callbacks de eventos

```html
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    onConnect: function () {
      console.log('Call started')
    },
    onDisconnect: function () {
      console.log('Call ended')
    },
    onError: function (error) {
      console.error('Widget error:', error.error, error.message)
    },
  })
</script>
```

### Com toque de chamada

```html
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    ringtone: true, // or a custom URL: 'https://example.com/ringtone.mp3'
  })
</script>
```

### Usando uma referência a um elemento DOM

```html
<div id="thunderphone"></div>

<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  var container = document.getElementById('thunderphone')

  ThunderPhone.mount({
    element: container,
    publishableKey: 'pk_live_your_publishable_key',
  })
</script>
```

### Integração com WordPress / CMS

Adicione isto a um bloco de HTML personalizado ou ao rodapé do seu tema:

```html
<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>

<div id="thunderphone-widget"></div>
<script>
  ThunderPhone.mount({
    element: '#thunderphone-widget',
    publishableKey: 'pk_live_your_publishable_key',
  })
</script>
```

<Tip>
  A `<div>` pode ficar em qualquer lugar -- ela é apenas o ponto de montagem. O widget em si é renderizado como uma sobreposição fixa em um canto da janela de visualização (definido pela opção `position`) e não acompanha o fluxo do conteúdo ao redor.
</Tip>

---

## Solução de problemas

<AccordionGroup>
  <Accordion title="O widget não aparece">
    Certifique-se de que os arquivos CSS e JS estejam carregados. Verifique o console do navegador em busca de erros de rede. Confirme que o elemento de destino existe no DOM antes de chamar `ThunderPhone.mount()`.
  </Accordion>

  <Accordion title="ThunderPhone não está definido">
    O script ainda não foi carregado. Certifique-se de que a tag `<script>` para `widget.js` apareça antes da sua chamada de montagem ou envolva a chamada de montagem em um listener `DOMContentLoaded`.
  </Accordion>

  <Accordion title="Erro de domínio não permitido">
    Adicione seu domínio aos domínios permitidos do widget na página **Widgets da Web** em [app.thunderphone.com](https://app.thunderphone.com). `localhost` não é permitido automaticamente em produção; adicione-o à lista para testar localmente.
  </Accordion>
</AccordionGroup>

---

## Próximas etapas

<CardGroup cols={2}>
  <Card title="Estilização" icon="palette" href="/pt/widget/styling">
    Personalize a aparência do widget com propriedades personalizadas de CSS.
  </Card>
  <Card title="Componente React" icon="react" href="/pt/widget/react">
    Usa React? A integração com o componente é mais simples.
  </Card>
</CardGroup>
