# Chat-Widget in Next.js und React einbinden

> Binde das intoCHAT-Widget in Next.js mit next/script im Root-Layout ein, in React über index.html oder einen useEffect-Hook, ohne doppelte Chat-Bubbles.

Das intoCHAT-Widget ist ein einfaches Script, keine React-Komponente. Es liest deine Agenten-ID aus seinem Attribut `data-chatbot-id` und hängt den Launcher an `document.body`, außerhalb deines React-Baums. Re-Renders und Routenwechsel berühren ihn deshalb nicht.

## Next.js mit App Router

Lade das Script einmal im Root-Layout mit der Komponente `Script` aus `next/script`:

```tsx
import Script from 'next/script'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://www.intochat.ai/api/embed.js"
          data-chatbot-id="YOUR_AGENT_ID"
          strategy="lazyOnload"
        />
      </body>
    </html>
  )
}
```

- **Das Data-Attribut.** Next.js gibt zusätzliche Attribute wie `data-chatbot-id` an das fertige Script-Element weiter. Genau dort sucht das Widget danach.
- **Die Strategie.** `lazyOnload` lädt das Widget, wenn der Browser im Leerlauf ist, nach den übrigen Ressourcen der Seite. `afterInteractive`, die Standardeinstellung, lädt es früher, der Launcher erscheint also schneller. Beides funktioniert.
- **Nicht `beforeInteractive`.** Diese Strategie ist für Scripts gedacht, die die Seite braucht, bevor sie interaktiv wird. Das Chat-Widget gehört nicht dazu, und so früh geladen konkurriert es nur mit deinem eigenen Code.
- **Server Components.** Das Layout kann eine Server Component bleiben, weil dieses `Script` keine Event-Handler hat.

Next.js lädt das Script nur einmal, auch wenn Besucher zwischen Routen wechseln. Im Pages Router fügst du dasselbe `Script` stattdessen in `pages/_app` ein.

Soll der Chat nur unter bestimmten Routen erscheinen, setze das `Script` in ein verschachteltes Layout. Ist es einmal geladen, bleibt der Launcher auch nach clientseitiger Navigation zu anderen Routen auf der Seite, bis zum nächsten vollständigen Seitenaufruf.

## React mit Vite oder Create React App

Wähle eine von zwei Varianten, nicht beide. Das Embed-Script ignoriert eine zweite Kopie für denselben Agenten, mit beiden lädst du es also nur doppelt.

**Variante 1: index.html.** Füge das Script-Tag aus dem Tab **Share** direkt vor `</body>` in `index.html` ein: bei Vite im Projektstamm, bei Create React App in `public/index.html`.

**Variante 2: eine Komponente.** Sinnvoll, wenn du im Code entscheiden willst, ob das Widget lädt, etwa nur in Produktion:

```jsx
import { useEffect } from 'react'

export default function IntoChatWidget() {
  useEffect(() => {
    // Load the widget only once, even when StrictMode runs effects twice
    if (document.getElementById('intochat-embed')) return

    const script = document.createElement('script')
    script.id = 'intochat-embed'
    script.src = 'https://www.intochat.ai/api/embed.js'
    script.setAttribute('data-chatbot-id', 'YOUR_AGENT_ID')
    document.body.appendChild(script)
  }, [])

  return null
}
```

Rendere `IntoChatWidget` einmal in deiner Root-Komponente, etwa `App`. Setze das Attribut, bevor das Element in die Seite kommt, wie oben gezeigt.

### StrictMode und doppelte Launcher

In der Entwicklung führt React StrictMode Effects zweimal aus. Die `id`-Prüfung am Anfang des Effects verhindert, dass das Script zweimal eingefügt wird. Auch ohne sie gäbe es keinen zweiten Launcher, denn das Embed-Script fügt pro Agent und Seite nur einen hinzu. Entferne das Script nicht in einer Cleanup-Funktion: Das entfernt den Launcher nicht, er bleibt bis zum nächsten vollständigen Seitenaufruf in `document.body`.

## Clientseitige Aktionen

Der Agent kann während eines Chats Funktionen in deiner App aufrufen, etwa um einen Zustand zu lesen oder ein Formular zu öffnen. Du registrierst sie mit `window.IntoChatActions.register`. Siehe [Clientseitige Aktionen](/de/docs/client-actions).

## Content Security Policy

Erlaube `https://www.intochat.ai` in `script-src`, `connect-src` und `frame-src`. Nutzt deine Policy Nonces, gib die `nonce` an die Komponente `Script` weiter. Next.js reicht sie durch wie das Data-Attribut.

## Prüfen

Öffne eine beliebige Route. Der Launcher erscheint unten in der Ecke und bleibt beim Navigieren. Zwei Launcher bedeuten, dass zwei Snippets mit verschiedenen Agenten-IDs geladen werden. Kein Launcher und „Chatbot not found.“ in der Konsole bedeuten, dass die Agenten-ID nicht stimmt. Weitere Fälle findest du unter [Fehlerbehebung](/de/docs/troubleshooting), mehr Hintergrund in den Ratgebern zu [Next.js](/de/integrationen/nextjs) und [React](/de/integrationen/react).
