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

# CDN / Script-Tag

> Fügen Sie das ThunderPhone-Sprach-Widget ohne Bundler zu jeder Website hinzu

Der CDN-Build bündelt React intern, sodass Sie das Widget auf statischen Websites, WordPress, Webflow oder jeder Seite verwenden können, auf der Sie HTML hinzufügen können. Kein npm, kein Bundler und kein Framework erforderlich.

## CDN-URLs

<CodeGroup>
  ```html Latest (recommended) theme={null}
  <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 theme={null}
  <!-- 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>
  Die `latest`-URLs werden vom Generator für Embed-Snippets im Dashboard erzeugt. Sie werden 5 Minuten zwischengespeichert und übernehmen neue stabile Releases automatisch. Angeheftete `/widget/vX.Y.Z/`-Pfade sind unveränderlich und werden langfristig zwischengespeichert -- wenn Sie eine Version anheften, muss sie dem `@thunderphone/widget`-npm-Release entsprechen, gegen das Sie entwickeln.
</Tip>

***

## Grundlegende Verwendung

```html theme={null}
<!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>
```

Das Widget wird im Zielelement eingebunden und als **Leiste mit fester Position in einer Ecke des Viewports** dargestellt (standardmäßig `bottom-right`, gesteuert durch die Option `position`). Das Einbindungselement ist lediglich die React-Root -- seine Position auf der Seite beeinflusst nicht, wo das Widget erscheint.

***

## Einbindungsoptionen

`ThunderPhone.mount()` akzeptiert dieselben Optionen wie die React-Komponente sowie die Eigenschaft `element`:

| Option           | Typ                                                            | Erforderlich | Standard                                  | Beschreibung                                                                                                                                                          |
| ---------------- | -------------------------------------------------------------- | ------------ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `element`        | `string \| HTMLElement`                                        | Ja           | --                                        | CSS-Selektor (z. B. `'#thunderphone'`) oder eine DOM-Elementreferenz.                                                                                                 |
| `publishableKey` | `string`                                                       | Ja           | --                                        | Veröffentlichbarer API-Schlüssel (`pk_live_...`). Der Agent wird automatisch anhand der Widget-Konfiguration des Schlüssels bestimmt.                                 |
| `theme`          | `'light' \| 'dark'`                                            | Nein         | `'light'`                                 | Farbschema.                                                                                                                                                           |
| `primaryColor`   | `string`                                                       | Nein         | `'#000000'` (hell) / `'#ffffff'` (dunkel) | CSS-Farbzeichenfolge, die als Akzentfarbe verwendet wird.                                                                                                             |
| `title`          | `string`                                                       | Nein         | `'Voice assistant'`                       | In der Widget-Leiste angezeigter Text.                                                                                                                                |
| `position`       | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | Nein         | `'bottom-right'`                          | Feste Viewport-Position.                                                                                                                                              |
| `apiBase`        | `string`                                                       | Nein         | `'https://api.thunderphone.com/v1'`       | Überschreibung der API-Basis-URL.                                                                                                                                     |
| `language`       | `string`                                                       | Nein         | --                                        | Sprachüberschreibung pro Sitzung -- ein Sprachcode oder Gebietsschema wie `en`, `es` oder `fr-FR`. Wenn nicht festgelegt, gilt die konfigurierte Sprache des Agenten. |
| `voice`          | `string`                                                       | Nein         | --                                        | Stimmenüberschreibung pro Sitzung -- ein Stimmenname wie `maria`. Wenn nicht festgelegt, gilt die konfigurierte Stimme des Agenten.                                   |
| `context`        | `string`                                                       | Nein         | --                                        | Faktischer Seiten- oder Website-Kontext pro Sitzung, der an den Agenten übergeben wird. Serverseitig auf 12.000 Zeichen gekürzt.                                      |
| `onConnect`      | `() => void`                                                   | Nein         | --                                        | Wird aufgerufen, wenn die Sprachsitzung verbunden wird.                                                                                                               |
| `onDisconnect`   | `() => void`                                                   | Nein         | --                                        | Wird aufgerufen, wenn die Sitzung endet.                                                                                                                              |
| `onError`        | `(error) => void`                                              | Nein         | --                                        | Wird bei Fehlern aufgerufen. Error enthält die Felder `error` (Code) und `message`.                                                                                   |
| `ringtone`       | `boolean \| string`                                            | Nein         | `false`                                   | Spielt während des Verbindungsaufbaus einen Klingelton ab. `true` für den Standardklingelton oder eine URL-Zeichenfolge für benutzerdefiniertes Audio.                |

***

## Bereinigung

`ThunderPhone.mount()` gibt eine Widget-Instanz mit Bereinigungsmethoden zurück:

```html theme={null}
<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>
```

Sowohl `unmount()` als auch `destroy()` bewirken dasselbe – sie trennen alle aktiven Sprachsitzungen und entfernen das Widget aus dem DOM. Verwenden Sie die Variante, die sich in Ihrem Code besser liest.

<Note>
  Bereinigen Sie das Widget immer, wenn Sie in Single-Page-Anwendungen weg navigieren oder das enthaltende Element entfernt wird. Dadurch wird sichergestellt, dass aktive Sprachsitzungen ordnungsgemäß getrennt werden.
</Note>

***

## Beispiele

### Dunkles Theme mit benutzerdefinierter Farbe

```html theme={null}
<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>
```

### Benutzerdefinierte Position

```html theme={null}
<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>
```

### Mit Ereignis-Callbacks

```html theme={null}
<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>
```

### Mit Klingelton

```html theme={null}
<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>
```

### Mit einer DOM-Elementreferenz

```html theme={null}
<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-Integration

Fügen Sie dies zu einem benutzerdefinierten HTML-Block oder zum Footer Ihres Themes hinzu:

```html theme={null}
<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>
  Das `<div>` kann überall platziert werden – es dient nur als Einbindungspunkt. Das Widget selbst wird als fest positioniertes Overlay in einer Ecke des Viewports gerendert (festgelegt durch die Option `position`) und fließt nicht mit dem umgebenden Inhalt.
</Tip>

***

## Fehlerbehebung

<AccordionGroup>
  <Accordion title="Widget wird nicht angezeigt">
    Stellen Sie sicher, dass sowohl die CSS- als auch die JS-Dateien geladen sind. Prüfen Sie die Browserkonsole auf Netzwerkfehler. Vergewissern Sie sich, dass das Zielelement im DOM vorhanden ist, bevor Sie `ThunderPhone.mount()` aufrufen.
  </Accordion>

  <Accordion title="ThunderPhone ist nicht definiert">
    Das Skript wurde noch nicht geladen. Stellen Sie sicher, dass das `<script>`-Tag für `widget.js` vor Ihrem Mount-Aufruf erscheint, oder kapseln Sie den Mount-Aufruf in einen `DOMContentLoaded`-Listener.
  </Accordion>

  <Accordion title="Fehler: Domain nicht erlaubt">
    Fügen Sie Ihre Domain in den **Developers**-Einstellungen unter [app.thunderphone.com](https://app.thunderphone.com) zur Liste der erlaubten Domains hinzu. Beachten Sie, dass `localhost` immer erlaubt ist.
  </Accordion>
</AccordionGroup>

***

## Nächste Schritte

<CardGroup cols={2}>
  <Card title="Styling" icon="palette" href="/de/widget/styling">
    Passen Sie das Erscheinungsbild des Widgets mit benutzerdefinierten CSS-Eigenschaften an.
  </Card>

  <Card title="React-Komponente" icon="react" href="/de/widget/react">
    Sie verwenden React? Die Komponentenintegration ist einfacher.
  </Card>
</CardGroup>
