メインコンテンツへスキップ
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)に着地したら即座に埋め込みを立ち上げたいuseEffectwindow.turnintai.open() を呼ぶ
C. インライン表示ページ内の特定領域に埋め込みをそのまま表示したいdata-turnint-* 属性を付けた <div> など
いずれのパターンでも、共通の前提として embed script をアプリ全体で 1 度だけ読み込む 必要があります。次のセクションで設定します。

共通: embed script を読み込む

方法 1: index.html に追加する(推奨)

Vite や Create React App では、プロジェクトルートの index.html<head> に script タグを追加するのが最もシンプルです。
<!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 を挿入します。
// 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;
}
// src/App.tsx
import { TurnintEmbedScript } from "./components/TurnintEmbedScript";

export default function App() {
  return (
    <>
      <TurnintEmbedScript />
      {/* ルーターやページ本体 */}
    </>
  );
}
embed script はルートで 1 度だけ読み込めば十分です。各ページコンポーネントで個別に注入する必要はありません。
Next.js(App Router)を使っている場合は、app/layout.tsx<head> に同じ script タグを置くか、next/scriptScript コンポーネントで読み込んでください。

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

最もシンプルな方法です。任意の要素に data-turnint-* 属性を付与すると、その要素がクリックされたタイミングで埋め込みが開きます。
export function HeroCta() {
  return (
    <button
      type="button"
      data-turnint-id="pub_xxxxxxxxxxxxxxxx"
      data-turnint-type="fullscreen"
    >
      AI と資料を読む
    </button>
  );
}
属性値の例説明
data-turnint-idpub_xxxxxxxxxxxxxxxx開きたいコンテンツの ID。ダッシュボードから取得
data-turnint-typefullscreen / popover開き方。fullscreen は画面全体を覆うモーダル、popover はチャットバブル
埋め込みの UI 言語は embed script 側の data-turnint-locale で指定します。複数のボタンやインライン埋め込みを同じページに置く場合も、script は 1 度だけ読み込めば十分です。
React Router の <Link> でクライアントサイド遷移したあとにマウントされたボタンも、embed script が自動検知して起動可能になります。ルート変更のたびに手動で再マウントする必要はありません。

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

「LP の CTA から専用ページに飛ばし、着地した瞬間に埋め込みを立ち上げたい」というユースケース向けのパターンです。専用のページコンポーネントを 1 つ作り、useEffect 内で window.turnintai.open() を呼びます。
// 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 などのルートに割り当てます。
// 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() を呼び出せます。
type: "fullscreen" 以外の指定は現状サポートされていません。インライン表示が必要な場合はパターン C を使ってください。

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

ページ内の特定領域に埋め込みを表示したい場合は、<div> などに data-turnint-* 属性を付けます。data-turnint-type="inline" を指定すると、その要素の中に埋め込みが描画されます。
export function InlineEmbed() {
  return (
    <div
      data-turnint-id="pub_xxxxxxxxxxxxxxxx"
      data-turnint-type="inline"
      style={{ width: "100%" }}
    />
  );
}
要素の幅は CSS 側で確保してください(埋め込みは親要素のサイズに合わせて描画されます)。

TypeScript で型を効かせる

window.turnintai の公式型定義はパッケージとしては配信していないため、プロジェクト側で型を宣言します。src/turnintai.d.tstypes/turnintai.d.ts を作成し、以下を貼り付けてください。
// 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/ 配下に置けば tsconfiginclude に含まれ、自動的に読み込まれます。

関連ドキュメント