> ## Documentation Index
> Fetch the complete documentation index at: https://docs.timothe.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# React への組み込み

> React（Vite / Create React App / React Router）のサイトに Turnint AI の埋め込みスクリプトを組み込む 3 つのパターン

React（Vite、Create React App、React Router など）で構築されたサイトに Turnint AI の埋め込みスクリプトを組み込む方法をまとめます。専用の npm パッケージや React コンポーネントの追加は基本的に不要で、embed script を 1 度読み込めば、あとは `data-turnint-*` 属性または `window.turnintai.open()` で起動できます。

## 3 つの組み込みパターン

| パターン            | 使いどころ                                     | 必要な実装                                       |
| --------------- | ----------------------------------------- | ------------------------------------------- |
| A. ボタンで開く       | LP の CTA、ヘッダーやフッターの「資料を見る」など、ユーザー操作で起動したい | `data-turnint-*` 属性を付けたボタン                  |
| B. ページ表示時に自動で開く | 専用ルート（例: `/start`）に着地したら即座に埋め込みを立ち上げたい    | `useEffect` で `window.turnintai.open()` を呼ぶ |
| C. インライン表示      | ページ内の特定領域に埋め込みをそのまま表示したい                  | `data-turnint-*` 属性を付けた `<div>` など          |

いずれのパターンでも、共通の前提として **embed script をアプリ全体で 1 度だけ読み込む** 必要があります。次のセクションで設定します。

## 共通: embed script を読み込む

### 方法 1: `index.html` に追加する（推奨）

Vite や Create React App では、プロジェクトルートの `index.html` の `<head>` に script タグを追加するのが最もシンプルです。

```html theme={null}
<!doctype html>
<html lang="ja">
  <head>
  ...
    <script
      async
      src="https://cdn.turnint.ai/js/latest/turnint.ai.embed.js"
      data-turnint-namespace="ws_xxxxxxxxxxxxxxxx"
      data-turnint-locale="ja"
    ></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
```

`async` を付けることで、初期描画をブロックせずにスクリプトを読み込めます。読み込みが完了すると `window.turnintai` が利用可能になり、以後すべてのルートで起動 API が使えます。

### 方法 2: ルートコンポーネントから動的に注入する

`index.html` を触れない場合や、環境ごとに読み込みを切り替えたい場合は、ルート付近で 1 度だけ script を挿入します。

```tsx theme={null}
// src/components/TurnintEmbedScript.tsx
import { useEffect } from "react";

export function TurnintEmbedScript() {
  useEffect(() => {
    if (document.querySelector("script[data-turnint-embed-script-tag]")) {
      return;
    }
    const script = document.createElement("script");
    script.setAttribute("data-turnint-embed-script-tag", "true");
    script.setAttribute("data-turnint-namespace", "ws_xxxxxxxxxxxxxxxx");
    script.setAttribute("data-turnint-locale", "ja");
    script.src = "https://cdn.turnint.ai/js/latest/turnint.ai.embed.js";
    script.async = true;
    document.body.appendChild(script);
  }, []);

  return null;
}
```

```tsx theme={null}
// src/App.tsx
import { TurnintEmbedScript } from "./components/TurnintEmbedScript";

export default function App() {
  return (
    <>
      <TurnintEmbedScript />
      {/* ルーターやページ本体 */}
    </>
  );
}
```

<Note>
  embed script はルートで 1 度だけ読み込めば十分です。各ページコンポーネントで個別に注入する必要はありません。
</Note>

<Note>
  Next.js（App Router）を使っている場合は、`app/layout.tsx` の `<head>` に同じ script タグを置くか、`next/script` の `Script` コンポーネントで読み込んでください。
</Note>

## パターン A: ボタンクリックで開く

最もシンプルな方法です。任意の要素に `data-turnint-*` 属性を付与すると、その要素がクリックされたタイミングで埋め込みが開きます。

```tsx theme={null}
export function HeroCta() {
  return (
    <button
      type="button"
      data-turnint-id="pub_xxxxxxxxxxxxxxxx"
      data-turnint-type="fullscreen"
    >
      AI と資料を読む
    </button>
  );
}
```

| 属性                  | 値の例                      | 説明                                               |
| ------------------- | ------------------------ | ------------------------------------------------ |
| `data-turnint-id`   | `pub_xxxxxxxxxxxxxxxx`   | 開きたいコンテンツの ID。ダッシュボードから取得                        |
| `data-turnint-type` | `fullscreen` / `popover` | 開き方。`fullscreen` は画面全体を覆うモーダル、`popover` はチャットバブル |

埋め込みの UI 言語は embed script 側の `data-turnint-locale` で指定します。複数のボタンやインライン埋め込みを同じページに置く場合も、script は 1 度だけ読み込めば十分です。

<Note>
  React Router の `<Link>` でクライアントサイド遷移したあとにマウントされたボタンも、embed script が自動検知して起動可能になります。ルート変更のたびに手動で再マウントする必要はありません。
</Note>

## パターン B: ページ表示時に自動で開く

「LP の CTA から専用ページに飛ばし、着地した瞬間に埋め込みを立ち上げたい」というユースケース向けのパターンです。専用のページコンポーネントを 1 つ作り、`useEffect` 内で `window.turnintai.open()` を呼びます。

```tsx theme={null}
// src/pages/Start.tsx
import { useEffect } from "react";

type TurnintAI = {
  open(config: {
    id?: string
    type?: "fullscreen"
    locale?: "ja" | "en" | "auto"
    onClose?: () => void
  }): void
};
type WindowWithTurnintAI = Window & { turnintai?: TurnintAI };

export function StartPage() {
  useEffect(() => {
    const openWhenReady = () => {
      const w = window as WindowWithTurnintAI;
      if (w.turnintai) {
        w.turnintai.open({
          id: "pub_xxxxxxxxxxxxxxxx",
        });
        return;
      }
      requestAnimationFrame(openWhenReady);
    };
    openWhenReady();
  }, []);

  return <section />;
}
```

React Router を使う場合は、このコンポーネントを `/start` などのルートに割り当てます。

```tsx theme={null}
// src/App.tsx（例）
import { Route, Routes } from "react-router-dom";
import { StartPage } from "./pages/Start";

export default function App() {
  return (
    <Routes>
      <Route path="/start" element={<StartPage />} />
      {/* 他のルート */}
    </Routes>
  );
}
```

embed script は `async` で読み込んでいるため、`useEffect` の発火時点ではまだ `window.turnintai` が定義されていない可能性があります。`requestAnimationFrame` でフレームごとに再チェックすることで、ロード完了直後に確実に `open()` を呼び出せます。

<Note>
  `type: "fullscreen"` 以外の指定は現状サポートされていません。インライン表示が必要な場合はパターン C を使ってください。
</Note>

## パターン C: インライン表示

ページ内の特定領域に埋め込みを表示したい場合は、`<div>` などに `data-turnint-*` 属性を付けます。`data-turnint-type="inline"` を指定すると、その要素の中に埋め込みが描画されます。

```tsx theme={null}
export function InlineEmbed() {
  return (
    <div
      data-turnint-id="pub_xxxxxxxxxxxxxxxx"
      data-turnint-type="inline"
      style={{ width: "100%" }}
    />
  );
}
```

要素の幅は CSS 側で確保してください（埋め込みは親要素のサイズに合わせて描画されます）。

## TypeScript で型を効かせる

`window.turnintai` の公式型定義はパッケージとしては配信していないため、プロジェクト側で型を宣言します。`src/turnintai.d.ts` や `types/turnintai.d.ts` を作成し、以下を貼り付けてください。

```ts theme={null}
// src/turnintai.d.ts
export {}

declare global {
  interface Window {
    turnintai?: {
      open: (config: {
        id?: string
        type?: "fullscreen"
        endpoint?: string
        locale?: "ja" | "en" | "auto"
        onClose?: () => void
      }) => void
    }
  }
}
```

Vite では `src/` 配下に置けば `tsconfig` の `include` に含まれ、自動的に読み込まれます。

## 関連ドキュメント

* [クイックスタート](/ja/get-started/quickstart) — 共有方法と埋め込み方式の全体像
* [Nuxt への組み込み](/ja/get-started/onboarding/nuxt) — Vue / Nuxt 向けの同様の手順
* [Google Tag Manager 経由で導入する](/ja/get-started/onboarding/google-tag-manager) — GTM のカスタム HTML タグで導入する手順
* [トラッキングパラメータの自動保持](/ja/integrations/tracking-params) — UTM などの引き継ぎ
