---
title: "CDN / Script Tag"
description: "Voeg de ThunderPhone-spraakwidget toe aan elke website zonder bundler"
---

De CDN-build bundelt React intern, zodat je de widget kunt gebruiken op statische sites, WordPress, Webflow of elke pagina waarop je HTML kunt toevoegen. Geen npm, bundler of framework vereist.

## CDN-URL's

<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>
  De `latest`-URL's worden gegenereerd door de insluitcodegenerator van het dashboard. Ze worden 5 minuten gecachet en nemen automatisch nieuwe stabiele releases over. Vastgezette `/widget/vX.Y.Z/`-paden zijn onveranderlijk en worden langdurig gecachet -- als je een versie vastzet, laat deze dan overeenkomen met de npm-release van `@thunderphone/widget` waarvoor je ontwikkelt.
</Tip>

---

## Basisgebruik

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

De widget wordt in het doelelement gemount en weergegeven als een **balk met vaste positie in een hoek van de viewport** (standaard `bottom-right`, aangestuurd door de optie `position`). Het mountelement is alleen de React-root -- de locatie ervan op de pagina heeft geen invloed op waar de widget verschijnt.

---

## Mountopties

`ThunderPhone.mount()` accepteert dezelfde opties als de React-component, plus de eigenschap `element`:

| Optie | Type | Vereist | Standaard | Beschrijving |
|--------|------|----------|---------|-------------|
| `element` | `string \| HTMLElement` | Ja | -- | CSS-selector (bijv. `'#thunderphone'`) of een verwijzing naar een DOM-element. |
| `publishableKey` | `string` | Ja | -- | Publiceerbare API-sleutel (`pk_live_...`). De agent wordt automatisch bepaald op basis van de widgetconfiguratie van de sleutel. |
| `theme` | `'light' \| 'dark'` | Nee | `'light'` | Kleurenschema. |
| `primaryColor` | `string` | Nee | `'#000000'` (licht) / `'#ffffff'` (donker) | CSS-kleurtekenreeks die wordt gebruikt als accentkleur. |
| `title` | `string` | Nee | `'Voice assistant'` | Tekst die wordt weergegeven in de widgetbalk. |
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | Nee | `'bottom-right'` | Vaste positie in de viewport. |
| `apiBase` | `string` | Nee | `'https://api.thunderphone.com/v1'` | Overschrijving van de basis-URL voor de API. |
| `language` | `string` | Nee | -- | Taaloverschrijving per sessie -- een taalcode of landinstelling zoals `en`, `es` of `fr-FR`. Indien niet ingesteld, wordt de geconfigureerde taal van de agent gebruikt. Vereist `language` onder de [browseroverschrijvingen](/nl/guides/embed-web-widget) van de sleutel. |
| `voice` | `string` | Nee | -- | Stemoverschrijving per sessie -- een stemnaam zoals `maria`. Indien niet ingesteld, wordt de geconfigureerde stem van de agent gebruikt. Vereist `voice` onder de [browseroverschrijvingen](/nl/guides/embed-web-widget) van de sleutel. |
| `context` | `string` | Nee | -- | Feitelijke pagina- of sitecontext per sessie die aan de agent wordt doorgegeven. Wordt server-side afgekapt op 12.000 tekens. Vereist `context` onder de [browseroverschrijvingen](/nl/guides/embed-web-widget) van de sleutel. |
| `onConnect` | `() => void` | Nee | -- | Wordt aangeroepen wanneer de spraaksessie verbinding maakt. |
| `onDisconnect` | `() => void` | Nee | -- | Wordt aangeroepen wanneer de sessie eindigt. |
| `onError` | `(error) => void` | Nee | -- | Wordt aangeroepen bij fouten. Error heeft de velden `error` (code) en `message`. |
| `ringtone` | `boolean \| string` | Nee | `false` | Speel een beltoon af tijdens het verbinden. `true` voor de standaardbeltoon, of een URL-tekenreeks voor aangepaste audio. |

---

## Opschonen

`ThunderPhone.mount()` retourneert een widgetinstantie met opschoonmethoden:

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

Zowel `unmount()` als `destroy()` doen hetzelfde -- ze verbreken actieve spraaksessies en verwijderen de widget uit de DOM. Gebruik wat het best leesbaar is in je code.

<Note>
  Ruim de widget altijd op wanneer je weg navigeert in single-page applications of wanneer het bevattende element wordt verwijderd. Zo worden actieve spraaksessies correct verbroken.
</Note>

---

## Voorbeelden

### Donker thema met aangepaste kleur

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

### Aangepaste positie

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

### Met eventcallbacks

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

### Met beltoon

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

### Een DOM-elementverwijzing gebruiken

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

### WordPress- / CMS-integratie

Voeg dit toe aan een blok met aangepaste HTML of aan de footer van je thema:

```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>
  De `<div>` kan overal staan -- dit is alleen het aankoppelpunt. De widget zelf wordt weergegeven als een vaste overlay in een hoek van het venster (ingesteld met de optie `position`) en loopt niet mee met de omringende inhoud.
</Tip>

---

## Problemen oplossen

<AccordionGroup>
  <Accordion title="Widget wordt niet weergegeven">
    Zorg dat zowel de CSS- als de JS-bestanden zijn geladen. Controleer de browserconsole op netwerkfouten. Verifieer dat het doelelement in de DOM bestaat voordat je `ThunderPhone.mount()` aanroept.
  </Accordion>

  <Accordion title="ThunderPhone is niet gedefinieerd">
    Het script is nog niet geladen. Zorg dat de `<script>`-tag voor `widget.js` vóór je mount-aanroep staat, of plaats de mount-aanroep in een `DOMContentLoaded`-listener.
  </Accordion>

  <Accordion title="Domein niet toegestaan">
    Voeg je domein toe aan de toegestane domeinen van de widget op de pagina **Web Widgets** in [app.thunderphone.com](https://app.thunderphone.com). `localhost` is in productie niet automatisch toegestaan; voeg het toe aan de lijst om lokaal te testen.
  </Accordion>
</AccordionGroup>

---

## Volgende stappen

<CardGroup cols={2}>
  <Card title="Stijlen" icon="palette" href="/nl/widget/styling">
    Pas het uiterlijk van de widget aan met aangepaste CSS-eigenschappen.
  </Card>
  <Card title="React-component" icon="react" href="/nl/widget/react">
    Gebruik je React? De componentintegratie is eenvoudiger.
  </Card>
</CardGroup>
