> For the complete documentation index, see [llms.txt](https://docs.maiagent.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.maiagent.ai/tech/ja/serve/web-chat-sdk.md).

# Web Chat の埋め込みと SDK

MaiAgent Web Chat を任意のウェブサイトに埋め込む：埋め込みコード、ウィンドウモード、ユーザー識別、設定リファレンス、JavaScript SDK API

ページに埋め込みコードを追加するだけで、MaiAgent の AI Agent をウェブサイトに組み込めます。埋め込みコードは `embed.min.js`（以下 SDK）を読み込み、SDK がページ上にチャットボタンと iframe のチャットウィンドウを作成し、プログラムから操作できるグローバルな `MaiAgent` JavaScript API を提供します。

このページは Web Chat 埋め込みの完全な技術リファレンスです。関連トピック：

* [MaiGPT の連携：適切な Agent の選択と機能の補完](/tech/ja/work/maigpt-system-integration-guide/maigpt-integration.md) — MaiGPT 製品と MaiGPT ウィンドウモードの違い、および埋め込んだ Agent に画像生成やツール利用をさせる方法
* [Web Chat MaiGPT モードの埋め込み](/tech/ja/serve/web-chat-sdk/web-chat-maigpt-mode.md) — ChatGPT のようなフル機能の対話インターフェース
* [Web Chat へのページ Context の注入](/tech/ja/serve/web-chat-sdk/web-chat-context-data.md) — ページ情報を LLM System Prompt に注入
* [コンタクト ID 同期とトークン更新](/tech/ja/serve/contacts/contact-credentials-sync.md) — バックエンドでのコンタクトと認証情報の作成
* [ソフトウェアベンダー向け連携ガイド](/tech/ja/serve/vendor-integration-guide.md) — 埋め込みと権限連携の全体の流れ（一括補完、ログイン同期、ログアウト時の失効）

## 一、クイックスタート <a href="#quickstart" id="quickstart"></a>

ページの `</body>` の前に次を追加します：

```html
<script>
  window.maiagentChatbotConfig = {
    webChatId: 'your-web-chat-id',
    baseUrl: 'https://chat.maiagent.ai/web-chats',
    primaryColor: '#1890ff',
  }
</script>
<script src="https://chat.maiagent.ai/js/embed.min.js" defer></script>
```

* `webChatId` は管理画面の Web Chat 設定ページで取得します（[チャネル連携：ウェブサイト](https://docs.maiagent.ai/build/choose-channel/web-chat/website)を参照してください。管理画面で生成される埋め込みコードには自動的に設定されます）
* `baseUrl` と SDK の URL は SaaS 環境（`chat.maiagent.ai`）を例にしています。プライベートクラウドやオンプレミス環境では、お使いの環境のドメインに置き換えてください
* `window.maiagentChatbotConfig` は **SDK スクリプトの読み込み前に定義する必要があります**

デフォルトの動作：ページの右下にチャットボタンが表示され、クリックするとフローティングのチャットウィンドウが開きます。ユーザーはフローティング（floating）とサイドバー（sidebar）の 2 つのウィンドウモードを切り替えられます。

### 初期化のタイミング <a href="#init-timing" id="init-timing"></a>

SDK は読み込み後に `document.body.onload` ハンドラーを登録して初期化を実行するため、通常は手動で操作する必要はありません。初期化のタイミングを制御する必要がある場合（たとえば SPA のコンテナーのマウント待ちや遅延レンダリング）：

1. **スクリプトの遅延読み込み**：適切なタイミングで `embed.min.js` の `<script>` タグを動的に挿入します
2. **手動でトリガー**：先に `window.maiagentChatbotConfig` を設定し、その後 `document.body.onload()` を呼び出します

同一ページで SDK が初期化されるのは 1 回だけで、重複して読み込んでも無視されます。

## 二、ウィンドウモード <a href="#window-modes" id="window-modes"></a>

`enabledWindowModes` 配列でユーザーが利用できるウィンドウモードを指定します。**最初の要素がデフォルトのモード**です。未設定の場合は `['floating', 'sidebar']` と同じです。

| モード        | 形態                                                                          | 適したシーン                                                                                               |
| ---------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `floating` | ページ右下に重ねて表示されるフローティングウィンドウ。ボタンをドラッグでき、ウィンドウサイズも変更できます（320×400 ～ 900×900 px） | 一般的なカスタマーサポート、相談                                                                                     |
| `sidebar`  | ウィンドウの右端に沿って表示されるサイドバー（幅 320～800 px、ドラッグで調整可能）。ページの内容は自動的に縮小して場所を空けます       | ページを見ながら対話したい業務シーン                                                                                   |
| `inline`   | チャットウィンドウを指定したコンテナー（`container`）に直接配置し、コンテナーの幅と高さいっぱいに常時表示します。チャットボタンはありません | ページ内に固定の対話エリアを設ける場合（サポートセンターのページ、製品ページのサイドバーなど）                                                      |
| `maigpt`   | ChatGPT のような完全なインターフェース（対話履歴サイドバー、検索、設定）。指定したコンテナーまたは全画面いっぱいに表示します          | ページの主要機能エリア、サイト全体の AI の入口。[MaiGPT モード](/tech/ja/serve/web-chat-sdk/web-chat-maigpt-mode.md)を参照してください |

```javascript
// サイドバーモードのみを許可
window.maiagentChatbotConfig = {
  webChatId: 'your-web-chat-id',
  baseUrl: 'https://chat.maiagent.ai/web-chats',
  enabledWindowModes: ['sidebar'],
}
```

* 配列に 2 つ以上のモードがある場合、チャットウィンドウにモード切り替えボタンが表示されます。`allowWindowModeSwitch: false` で非表示にできます
* `maigpt` が最初の要素の場合は MaiGPT モードになり、それ以外の要素は無効です（このモードには切り替えがありません）
* `inline` は単独でのみ使用できます（`enabledWindowModes: ['inline']`）。`floating` や `sidebar` と同じ配列に入れると埋め込まれず、console にエラーが表示されます
* 旧フィールド `defaultWindowMode` は非推奨です。引き続き動作します（`enabledWindowModes: [その値]` として扱われます）が、console に非推奨の警告が表示されます

### inline モードのコンテナー <a href="#inline-container" id="inline-container"></a>

`inline` モードでは `container` で埋め込み位置を指定します。コンテナーの高さは各自で指定してください（チャットウィンドウの最小高さは 400 px です）：

```html
<div id="chat-container" style="height: 640px;"></div>

<script>
  window.maiagentChatbotConfig = {
    webChatId: 'your-web-chat-id',
    baseUrl: 'https://chat.maiagent.ai/web-chats',
    enabledWindowModes: ['inline'],
    container: '#chat-container',
  }
</script>
<script src="https://chat.maiagent.ai/js/embed.min.js" defer></script>
```

| `container` の指定方法                           | 動作                                                                          |
| ------------------------------------------- | --------------------------------------------------------------------------- |
| CSS セレクターの文字列（例：`'#chat-container'`）        | 要素が現れるまで最大 5 秒待機します                                                         |
| HTMLElement、または `{ element }`               | そのまま使用します。要素はすでにページに追加されている必要があります                                          |
| `{ selector, waitForElement, waitTimeout }` | `waitForElement: false` で待機しません。`waitTimeout` で待機時間をミリ秒で調整できます（デフォルトは 5000） |

* `container` が未設定の場合、セレクターが誤っている場合、または要素が見つからない場合は、チャットウィンドウは表示されず、console に原因が表示されます
* コンテナーが `position: static` の場合、SDK は `position: relative` に変更します
* inline モードは常に表示され、開閉の操作はありません。`MaiAgent.control.open()`／`close()` は動作しません

### floating、sidebar、maigpt の実際の画面 <a href="#window-modes-gallery" id="window-modes-gallery"></a>

{% tabs %}
{% tab title="floating フローティングウィンドウ" %}

<figure><img src="https://605688223-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVYMUz6J7vDZ0QTvb1rbN%2Fuploads%2Fgit-blob-56a6936e787340e6429586677d8be3bacc08b308%2Fwebchat-mode-floating.png?alt=media" alt="floating モード：チャットウィンドウがページ右下に重ねて表示される"><figcaption><p>floating：チャットウィンドウはページ右下に重ねて表示され、ページのレイアウトに影響しません。ボタンをドラッグして位置を移動できます</p></figcaption></figure>
{% endtab %}

{% tab title="sidebar サイドバー" %}

<figure><img src="https://605688223-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVYMUz6J7vDZ0QTvb1rbN%2Fuploads%2Fgit-blob-4d989af74c4a47e70c3d61a6f6f4b496a31f6a09%2Fwebchat-mode-sidebar.png?alt=media" alt="sidebar モード：チャットウィンドウが右端に沿って表示され、ページの内容が自動的に縮小される"><figcaption><p>sidebar：チャットウィンドウはウィンドウの右端に沿って表示され、ページの内容は自動的に縮小して場所を空けます。ページを見ながら対話するのに適しています</p></figcaption></figure>
{% endtab %}

{% tab title="maigpt 完全なインターフェース" %}

<figure><img src="https://605688223-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVYMUz6J7vDZ0QTvb1rbN%2Fuploads%2Fgit-blob-aab515bf01f9122d1b558aeaefcd1e59079466a0%2Fwebchat-maigpt-mode-a-container.png?alt=media" alt="maigpt モード：ChatGPT のような完全な対話インターフェース"><figcaption><p>maigpt：ChatGPT のような完全なインターフェース（対話履歴サイドバーを含む）。詳細は <a href="/tech/ja/serve/web-chat-sdk/web-chat-maigpt-mode.md">MaiGPT モードの埋め込み</a>を参照してください</p></figcaption></figure>
{% endtab %}
{% endtabs %}

## 三、ユーザーの識別 <a href="#identify-users" id="identify-users"></a>

Web Chat は、コンタクト（Contact）に紐づけるかどうかによって、3 つの識別レベルに分かれます：

| レベル          | 設定方法                                                                                                                        | 対話履歴                    | AI のパーソナライズ／ユーザー権限でのツール呼び出し |
| ------------ | --------------------------------------------------------------------------------------------------------------------------- | ----------------------- | --------------------------- |
| 匿名           | 何も設定しない                                                                                                                     | ブラウザー単位で保持              | ✖                           |
| フロントエンド auth | config に `auth: { sourceId, ... }` を指定すると、SDK が自動的にコンタクトを作成または照合します                                                         | コンタクトに紐づき、デバイスをまたいで利用可能 | ✔                           |
| バックエンド連携     | バックエンドが[ID 同期 API](/tech/ja/serve/contacts/contact-credentials-sync.md) を呼び出して `contactId` を取得し、config に `contactId` を指定します | コンタクトに紐づき、デバイスをまたいで利用可能 | ✔                           |

**フロントエンド auth**：SDK の初期化が完了すると、`auth` の内容で MaiAgent の ID 同期 API（`setup-contact-credentials`）を自動的に呼び出し、`sourceId` に基づいてコンタクトを作成または照合します：

```javascript
window.maiagentChatbotConfig = {
  webChatId: 'your-web-chat-id',
  baseUrl: 'https://chat.maiagent.ai/web-chats',
  auth: {
    sourceId: 'user-12345',   // 必須：お客様のシステムにおけるそのユーザーの一意の識別子
    name: '山田太郎',          // 任意：コンタクトの表示名（初回作成時のみ有効）
    contextData: { ... },     // 任意：LLM System Prompt に注入。contextData のページを参照
    ts: 1785500000,           // 署名検証を有効にした場合は必須：Unix 秒（UTC）。お客様のバックエンドで生成
    sig: '9f2c...',           // 署名検証を有効にした場合は必須：HMAC-SHA256 署名。下記「署名検証」を参照
    getToken: async () => ({ accessToken, organizationId, sourceId }),  // 「メンバー ID での埋め込み」でのみ使用：お客様のバックエンドでメンバー用の短期トークンを発行し、SDK が自動更新
  },
}
```

`getToken`（または固定の `accessToken` ＋ `organizationId`）は、組織内蔵の MaiGPT を組織のメンバー向けに埋め込む場合にのみ使用します。この場合、`sourceId` はメンバーのユーザー ID である必要があります。詳しい流れは[メンバー ID での埋め込み](/tech/ja/work/maigpt-system-integration-guide/maigpt-integration.md#member-embed)を参照してください。一般の顧客／訪問者の識別では、これらのフィールドは不要です。

その Web Chat のログイン設定で「埋め込み側が Source ID でログインなしに対話することを許可する」を有効にし、署名モードを選択した場合、`ts` と `sig` は必須で、不足している場合や検証に失敗した場合、ユーザーはログインページに誘導されます。手動で `MaiAgent.auth.setup()` を呼び出す場合も、この 2 つのフィールドを指定できます。

**バックエンド連携**：ユーザーのログイン時に、お客様のバックエンドが同じ API を呼び出し（MCP ツールの認証情報も同時に紐づけられます）、返された `contactId` を会員データに保存します。フロントエンドでは `contactId` だけを指定します。

2 つの方法の選び方：

* 「ユーザーを識別し、デバイスをまたいで対話を保持する」だけが必要な場合 → **フロントエンド auth** が最も簡単です
* ユーザーの Access Token を MCP ツールの認証情報に紐づけ（AI がユーザー権限でお客様の API を呼び出せるようにし）、かつトークンをフロントエンドのページソースに出したくない場合 → **バックエンド連携**
* どちらも基盤は同じコンタクトの仕組みで、`sourceId` が同じであれば同一のコンタクトとして扱われるため、併用できます

{% hint style="info" %}
`queryMetadata` を使うと、そのユーザーのナレッジベース検索範囲を制御できます（RAG の権限フィルタリング）。詳しくは[ナレッジ管理の権限（Query Metadata）の概要](/tech/ja/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan.md)を参照してください。`queryMetadata` は LLM の prompt には入りません。ある値を AI に「知らせたい」場合は [contextData](/tech/ja/serve/web-chat-sdk/web-chat-context-data.md) を使用してください。
{% endhint %}

### セキュリティ上の注意事項 <a href="#identity-security" id="identity-security"></a>

{% hint style="danger" %}
**`contactId` は ID の認証情報です**：これを入手すると、そのユーザーとして対話し、対話履歴を閲覧できてしまいます。`contactId` は**ログイン後**のページで、そのユーザー本人にのみ出力してください。公開ページのソースには含めないでください。

`auth.sourceId` に求められる要件は、署名検証を有効にしているかどうかで異なります：

* **署名検証が無効の場合**：ID 同期は公開エンドポイントのため、推測可能な `sourceId` はなりすまし可能な ID と同じです。推測できない値（UUID など）を使用し、連番、メールアドレス、携帯電話番号は使用しないでください。
* **署名検証が有効の場合**：安全性は `sourceId` そのものではなく署名によって確保されるため、学籍番号、社員番号、登録済みメールアドレスなどの読み取り可能な値をそのまま使用できます。秘密鍵はお客様のサーバーにのみ存在し、秘密鍵がなければ `sourceId` を知っていても有効な署名は計算できません。
  {% endhint %}

### 署名検証 <a href="#source-id-signature" id="source-id-signature"></a>

Web Chat のログイン設定で「埋め込み側が Source ID でログインなしに対話することを許可する」を有効にすると、お客様のウェブサイトでログイン済みのユーザーが、チャットウィンドウで再度ログインする必要がなくなります。スイッチ、秘密鍵、署名の有効期限、検証失敗ログは、管理画面のログイン設定タブにあります。操作方法はユーザーマニュアルの[コンタクトの Source ID によるログインなし対話](https://docs.maiagent.ai/build/choose-channel/web-chat/source-id-access)を参照してください。

検証方式は 2 種類あり、署名モードを推奨します：

| 検証方式         | 動作                                                         |
| ------------ | ---------------------------------------------------------- |
| 署名検証を必須にする   | `ts` と `sig` が必要で、検証に成功した場合のみ許可します                         |
| Source ID のみ | 検証を行わず、`sourceId` があれば許可します。テストまたは閉じた社内ネットワーク環境でのみ使用してください |

**署名アルゴリズム**

```
HMAC-SHA256(秘密鍵, "{webChatId}.{sourceId}.{ts}")
```

16 進数の小文字の文字列として渡します。`ts` は Unix 秒（UTC）です。秘密鍵はプラットフォームが管理画面で生成するもので、お客様のサーバーの環境変数にのみ保存し、フロントエンドのコードに書き込んではいけません。

{% tabs %}
{% tab title="PHP" %}

```php
$ts  = time();
$sig = hash_hmac('sha256', "{$webChatId}.{$sourceId}.{$ts}", $SIGNING_SECRET);
```

{% endtab %}

{% tab title="Node" %}

```javascript
const ts = Math.floor(Date.now() / 1000);
const sig = crypto.createHmac('sha256', SIGNING_SECRET)
  .update(`${webChatId}.${sourceId}.${ts}`).digest('hex');
```

{% endtab %}

{% tab title="Python" %}

```python
ts = int(time.time())
sig = hmac.new(SIGNING_SECRET.encode(),
  f"{web_chat_id}.{source_id}.{ts}".encode(), hashlib.sha256).hexdigest()
```

{% endtab %}
{% endtabs %}

**フロントエンドでの署名の受け渡し**

バックエンドで計算した `ts`、`sig` を `sourceId` とともに SDK に渡します。ページの読み込み時にユーザーの ID が分かっている場合は config の `auth` に指定し、SPA でログイン後に署名を取得する場合は `MaiAgent.auth.setup()` を呼び出します：

```javascript
// 方法 1：config に指定すると、SDK の準備完了後に auth.setup() が自動実行されます
window.maiagentChatbotConfig = {
  webChatId: 'your-web-chat-id',
  baseUrl: 'https://chat.maiagent.ai/web-chats',
  auth: { sourceId, name, ts, sig },
}

// 方法 2：SDK の準備完了後に手動で呼び出す
MaiAgent.auth.setup({ sourceId, name, ts, sig })
```

{% hint style="warning" %}
管理画面の「連携サンプル」で生成されたフロントエンドのサンプルに `setupAuth` と表示されている場合は、`auth.setup` に置き換えてください。SDK に `setupAuth` メソッドは公開されておらず、そのまま貼り付けるとブラウザーで TypeError が発生します。
{% endhint %}

**検証ルール**

| ルール           | 説明                                                     |
| ------------- | ------------------------------------------------------ |
| 有効期限          | 管理画面で 1／5／15 分から設定でき、デフォルトは 5 分です                      |
| 時計のずれの許容      | 60 秒のずれを許容します。未来側に 60 秒を超えるタイムスタンプは一律拒否されます            |
| 一度きり          | 同じ署名で成功できるのは 1 回のみです。署名自体がリプレイ攻撃防止の nonce になります        |
| プラットフォームへの紐づけ | 署名には `webChatId` が含まれるため、同じ組織の他の Web Chat の署名は再利用できません |
| 拒否時のレスポンス     | すべての失敗理由で外部へのレスポンスは同一で、理由も `sourceId` の存在有無も明かしません     |

{% hint style="warning" %}
署名は一度だけ有効です。**アクセスのたびに再計算し、キャッシュしないでください**。有効期限が制限するのは「この署名でコンタクトの ID と交換できる期間」であり、対話の存続期間ではありません。ID を取得した後は、署名の期限が切れても対話は中断されません。
{% endhint %}

**有効期限とログアウトの関係**

取得した `contactId` 自体には有効期限がなく、プラットフォームには現在それを無効化するエンドポイントもありません。ユーザーがお客様のウェブサイトでログアウトした後、お客様が制御できるのは新しい署名を発行しないことです。フロントエンドでは `MaiAgent.auth.signOut()` を呼び出してチャットウィンドウを匿名状態に戻せます。ツールの認証情報の失効については[ログアウトと認証情報の失効](/tech/ja/serve/contacts/contact-credentials-sync.md#logout-revoke)を参照してください。

**検証失敗のトラブルシューティング**

管理画面のログイン設定にある「検証失敗ログを表示」には、最近の失敗イベントとその理由が一覧表示されます。各理由のよくある原因については、ユーザーマニュアルの[検証失敗ログ](https://docs.maiagent.ai/build/choose-channel/web-chat/source-id-access#verification-failures)を参照してください。最も多い「署名の不一致」は、多くの場合、秘密鍵の不一致、または署名文字列の組み立てミス（区切り文字は半角のピリオドです）が原因です。

### 埋め込みを許可するドメイン <a href="#embed-origin-allowlist" id="embed-origin-allowlist"></a>

対話プラットフォームの管理者は、管理画面の <mark style="color:blue;">基本設定</mark> → <mark style="color:blue;">埋め込みを許可するドメイン</mark> でリストを自分で入力できます。手順はユーザーマニュアルの[埋め込みを許可するドメイン](https://docs.maiagent.ai/build/conversation-settings/platform-settings/basic-settings#allowed-embed-origins)を参照してください。リストが空でない場合、次の 2 つを同時に制限します：

* **埋め込み**：ブラウザーが、リスト以外のサイトからの埋め込みをブロックします。
* **ID 同期**：`auth` も setup-contact-credentials も、オリジンの照合を通過する必要があります。サーバー間の呼び出しにはブラウザーの `Origin` ヘッダーがないため、body に `embedOrigin` を指定してください。[コンタクト ID 同期とトークン更新](/tech/ja/serve/contacts/contact-credentials-sync.md)を参照してください。

照合ルール：

| リストの状態                    | 動作                                                     |
| ------------------------- | ------------------------------------------------------ |
| 空のリスト（デフォルト）              | オリジンを制限しません                                            |
| `https://example.com` を記載 | scheme ＋ host（＋ port）を完全一致で照合します                       |
| `*.example.com` を記載       | `example.com` とそのすべてのサブドメインを対象とします（scheme／port は問いません） |
| リストに値があるがすべて形式が無効         | **すべてのオリジンを拒否**します（fail closed）。黙って制限なしに戻ることはありません     |

外部に埋め込み、かつ ID 機能を使用する Web Chat には、`contactId` を取得できるオリジンを絞り込むため、常にこのリストを設定することをお勧めします。

## 四、設定オプションリファレンス <a href="#config-reference" id="config-reference"></a>

`window.maiagentChatbotConfig` がサポートするすべてのフィールドです。未知のフィールドを設定してもエラーにはなりませんが、スペルを確認しやすいように console に `[maiagent] Unknown config options: ...` という警告が表示されます。

### 基本 <a href="#config-basic" id="config-basic"></a>

| フィールド           | 型                     | 必須 | 説明                                                                                                                                                                                                                                                   |
| --------------- | --------------------- | -- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `webChatId`     | `string`              | ✅  | Web Chat の一意の識別子                                                                                                                                                                                                                                     |
| `baseUrl`       | `string`              | ✅  | Web Chat サービスのアドレス。SaaS では `https://chat.maiagent.ai/web-chats`                                                                                                                                                                                      |
| `contactId`     | `string`              |    | コンタクト ID（バックエンド連携で使用。[ユーザーの識別](#identify-users)を参照）                                                                                                                                                                                                  |
| `auth`          | `object`              |    | フロントエンドの ID 設定：`sourceId`（必須）、`name`、`contextData`、`mcpCredentials`、`ts` と `sig`（署名検証を有効にした場合は必須。[署名検証](#source-id-signature)を参照）。SDK の準備完了後に `auth.setup()` が自動実行されます                                                                               |
| `queryMetadata` | `object` または `string` |    | ナレッジベース検索範囲のフィルター（LLM の prompt には入りません）                                                                                                                                                                                                              |
| `locale`        | `string`              |    | インターフェースのロケール（例：`zh-TW`、`en`）。AI の回答言語の参考にもなります。サポート一覧と決定順序は [MaiGPT モードのページ第五節](/tech/ja/serve/web-chat-sdk/web-chat-maigpt-mode.md#locale)を参照してください。優先順位：ユーザーがウィンドウで手動選択したロケール > config／`locale.set()` > このブラウザーで前回使用したロケール > ブラウザーのロケール > `zh-TW` |

### ウィンドウモードと動作 <a href="#config-behavior" id="config-behavior"></a>

| フィールド                   | 型                                   | デフォルト値                    | 説明                                                                                                |
| ----------------------- | ----------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------- |
| `enabledWindowModes`    | `string[]`                          | `['floating', 'sidebar']` | 利用可能なウィンドウモード。最初の項目がデフォルトです。[ウィンドウモード](#window-modes)を参照してください                                    |
| `allowWindowModeSwitch` | `boolean`                           | `true`                    | ウィンドウモードの切り替えボタンを表示するかどうか（2 つ以上のモードを有効にした場合のみ意味があります）                                             |
| `showButton`            | `boolean`                           | `true`                    | チャットボタンを表示するかどうか。`false` にした場合は、プログラムから `MaiAgent.control.open()` を呼び出して開きます                      |
| `showChatNotification`  | `boolean`                           | `false`                   | ウィンドウを閉じている間に返信を受け取ったとき、ボタンの横に通知を表示するかどうか                                                         |
| `chatNotificationTitle` | `string`                            |                           | 通知のタイトル文字列                                                                                        |
| `preventIosInputZoom`   | `boolean`                           |                           | iOS Safari で入力欄にフォーカスしたときにページが自動的に拡大されるのを防ぎます                                                     |
| `container`             | `string`、`HTMLElement` または `object` |                           | inline モード専用：埋め込みコンテナー。[inline モードのコンテナー](#inline-container)を参照してください                             |
| `targetElement`         | `string` または `HTMLElement`          |                           | MaiGPT モード専用：埋め込みコンテナー。[MaiGPT モード](/tech/ja/serve/web-chat-sdk/web-chat-maigpt-mode.md)を参照してください |
| `maigptTitle`           | `string`                            |                           | MaiGPT モード専用：サイドバーのブランドタイトル。デフォルトでは `MaiGPT` を表示します                                               |

### 外観 <a href="#config-appearance" id="config-appearance"></a>

サイズ系のフィールドは、数値（px として扱われます）、`'Npx'`、または `'Nrem'` の文字列を受け付けます。

| フィールド           | 型                     | デフォルト値                               | 説明                                      |
| --------------- | --------------------- | ------------------------------------ | --------------------------------------- |
| `primaryColor`  | `string`              | `#1890ff`                            | テーマカラー（ボタンとインターフェースのメインカラー）             |
| `buttonSize`    | `string` または `number` | `3rem`                               | チャットボタンのサイズ                             |
| `buttonRadius`  | `string`              | `50%`                                | チャットボタンの角丸                              |
| `buttonIcon`    | `string`              |                                      | ボタンアイコンの画像 URL（`openIconHtml` より優先されます） |
| `openIconHtml`  | `string`              | 内蔵 SVG                               | ボタンの「開く」状態のカスタム HTML                    |
| `closeIconHtml` | `string`              | 内蔵 SVG                               | ボタンの「閉じる」状態のカスタム HTML                   |
| `windowWidth`   | `string` または `number` | `24rem`                              | フローティングウィンドウの幅                          |
| `windowHeight`  | `string` または `number` | `40rem`                              | フローティングウィンドウの高さ                         |
| `windowRadius`  | `string`              | `0.75rem`                            | フローティングウィンドウの角丸                         |
| `boxShadow`     | `string`              | `0.125rem 0.125rem 0.5rem #00000044` | ボタンとウィンドウの影                             |

### 位置 <a href="#config-position" id="config-position"></a>

| フィールド                  | 型                     | デフォルト値   | 説明                                       |
| ---------------------- | --------------------- | -------- | ---------------------------------------- |
| `buttonPositionBottom` | `string` または `number` | `16`（px） | ボタンのウィンドウ下端からの距離                         |
| `buttonPositionRight`  | `string` または `number` | `16`（px） | ボタンのウィンドウ右端からの距離                         |
| `windowPositionBottom` | `string`              | `5rem`   | フローティングウィンドウの下端からの距離                     |
| `windowPositionRight`  | `string`              | `1rem`   | フローティングウィンドウの右端からの距離                     |
| `windowPosition`       | `string`              |          | `'center'` を設定すると、フローティングウィンドウが中央に表示されます |

チャットボタンはドラッグして移動でき、位置はブラウザーに記憶されます。再読み込みの際、記憶された位置が現在のウィンドウの範囲外にある場合は、自動的に安全な位置に戻ります。

### ボタン位置の決定順序 <a href="#button-position-behavior" id="button-position-behavior"></a>

* `buttonPositionBottom`／`buttonPositionRight` が、ボタン位置の唯一の設定元です。ユーザーがドラッグした後の位置はそのブラウザーのウィンドウ状態にのみ保存され、ユーザーが再度ドラッグするかサイトデータを消去するまで、設定値より優先されます。
* チャットウィンドウを開くとき（ボタンのクリックまたは `MaiAgent.control.open()`）、フローティングウィンドウはボタンの現在位置を基準に配置され、ボタン自体は移動しません。ウィンドウを閉じた後も、ボタンは元の位置にあります。
* ブラウザーのウィンドウサイズを変更すると、ユーザーがドラッグした位置は比率に応じて調整され、表示範囲内に収められます。設定値で配置されたボタンは、CSS によって自然に追従します。
* ボタンの位置を固定してユーザーが移動できないようにする場合、現在ドラッグを無効にする設定はありません。代わりに `showButton: false` で内蔵ボタンを非表示にし、`MaiAgent.control.open()` を呼び出す独自のボタンを配置してください（[完全なサンプル](#full-example)を参照）。
* 位置が「ずれて」見える場合は、まずページの CSS がボタンコンテナーの `position`、`bottom`、`right` を上書きしていないかを確認し、そのうえでそのサイトのブラウザーデータを消去して、記憶された位置をリセットしてください。

## 五、SDK API <a href="#sdk-api" id="sdk-api"></a>

SDK の初期化後は、グローバルな `MaiAgent` オブジェクトから操作できます。すべてのメソッドは SDK の準備完了後に呼び出してください（[トラブルシューティング](#troubleshooting)の利用可否チェックを参照）。

### ウィンドウ制御 `MaiAgent.control` <a href="#api-control" id="api-control"></a>

| メソッド       | 説明                                  |
| ---------- | ----------------------------------- |
| `open()`   | チャットウィンドウを開きます                      |
| `close()`  | チャットウィンドウを閉じます                      |
| `isOpen()` | チャットウィンドウが開いているかどうかを返します（`boolean`） |

同等のグローバルなショートカット `window.maiagentOpenChat()` / `window.maiagentCloseChat()` もあります。

### メッセージ `MaiAgent.chat` <a href="#api-chat" id="api-chat"></a>

| メソッド                | 説明                         |
| ------------------- | -------------------------- |
| `send(content)`     | ユーザーとしてテキストメッセージを 1 件送信します |
| `clearHistory()`    | 現在の対話の履歴メッセージを消去します        |
| `newConversation()` | 新しい対話を開始します                |

```javascript
MaiAgent.chat.send('こんにちは、御社のサービスについて知りたいです')
MaiAgent.control.open()
```

### イベント `MaiAgent.events` <a href="#api-events" id="api-events"></a>

| メソッド                       | 説明                                            |
| -------------------------- | --------------------------------------------- |
| `on(eventType, callback)`  | イベントリスナーを登録します                                |
| `off(eventType, callback)` | イベントリスナーを削除します（登録時と同じ callback の参照を渡す必要があります） |

リッスンできるイベント：

| イベント           | 発火タイミング                      | callback の引数                                                                           |
| -------------- | ---------------------------- | -------------------------------------------------------------------------------------- |
| `messageReply` | AI Agent からの返信を受信したとき        | パース済みのオブジェクト：`{ content: string, sender?: { name, avatar }, timestamp?: number, ... }` |
| `sdkReady`     | SDK の初期化が完了したとき              | —                                                                                      |
| `authReady`    | `auth.setup()` が完了したとき       | —                                                                                      |
| `iframeReady`  | チャットウィンドウの iframe の準備が完了したとき | —                                                                                      |

```javascript
// スペルミスを防ぐため、MaiAgent.EVENT_TYPES の定数を使用することをお勧めします
MaiAgent.events.on(MaiAgent.EVENT_TYPES.MESSAGE_REPLY, (data) => {
  console.log('返信を受信しました：', data.content)
})
```

### ロケールと音声 <a href="#api-locale-speech" id="api-locale-speech"></a>

| メソッド                                   | 説明                                                                                                                                                                                 |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MaiAgent.locale.set(lang)`            | インターフェースのロケールを切り替えます（例：`'zh-TW'`、`'zh-CN'`、`'en'`）。サポート一覧は [MaiGPT モードのページ第五節](/tech/ja/serve/web-chat-sdk/web-chat-maigpt-mode.md#locale)を参照してください。ユーザーがウィンドウで手動選択したロケールは上書きされません |
| `MaiAgent.speech.set(lang, provider?)` | 音声認識と音声合成の言語を設定します。`provider` で音声サービスのプロバイダーを指定できます（例：`'azure'`）                                                                                                                   |

`locale` はインターフェースの文字列を決定します。また、ユーザーの希望言語を判断できない場合の返信言語の参考として、メッセージごとに AI へ送信されます。ユーザーが別の言語で質問した場合、AI は通常その質問の言語に合わせて回答します（[ロール指示：プラットフォームが付加するコンテキスト](/tech/ja/advanced-genai-tech/system-prompt.md#platform-context)、ユーザーマニュアルの[多言語サポート](https://docs.maiagent.ai/build/agent/multi-language-support#reply-language)を参照）。ユーザーが Web Chat のメニューから言語を切り替えた場合は、新しい会話が開始されます。`locale.set()` でロケールが変更され、かつユーザーがまだメッセージを送信していない場合も、Web Chat は新しいロケールで会話を開き直します。

### ID `MaiAgent.auth` <a href="#api-auth" id="api-auth"></a>

| メソッド                | 説明                                                                                                                                                                                                  |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setup(authConfig)` | コンタクトを作成または対応付けて ID を適用し、`Promise<string \| null>`（成功時は `contactId`）を返します。`authConfig` のフィールドは config の `auth` と同じです                                                                                |
| `signOut()`         | 現在の ID からサインアウトし、匿名状態に戻して `contextData` をクリアします。フロントエンドにのみ作用します。バックエンドですでに紐付けられたツールの認証情報は別途失効させる必要があります。[ログアウトと認証情報の失効](/tech/ja/serve/contacts/contact-credentials-sync.md#logout-revoke)を参照してください |

config に `auth` がある場合、SDK は自動的に `setup()` を呼び出すため、手動で実行する必要はありません。SPA でユーザーがログイン／ログアウトしたとき、または `contextData` を更新する必要があるときにのみ手動で呼び出してください。

## 六、完全なサンプル <a href="#full-example" id="full-example"></a>

```html
<!doctype html>
<html lang="zh-TW">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>MaiAgent Web Chat 連携サンプル</title>
  </head>
  <body>
    <h1>私のウェブサイト</h1>

    <button onclick="MaiAgent.control.open()">サポートを開く</button>
    <button onclick="startNewChat()">新しい会話</button>

    <script>
      window.maiagentChatbotConfig = {
        webChatId: 'your-web-chat-id',
        baseUrl: 'https://chat.maiagent.ai/web-chats',
        primaryColor: '#007bff',
        enabledWindowModes: ['floating', 'sidebar'],
        locale: 'zh-TW',
        auth: {
          sourceId: 'user-12345',
          name: '王小明',
        },
      }
    </script>
    <script src="https://chat.maiagent.ai/js/embed.min.js" defer></script>

    <script>
      document.addEventListener('DOMContentLoaded', () => {
        MaiAgent.events.on(MaiAgent.EVENT_TYPES.MESSAGE_REPLY, (data) => {
          console.log('AI の返信を受信しました：', data.content)
          // ここで分析ツールと連携できます。例：GA4
          // gtag('event', 'chat_interaction', { event_label: 'bot_reply' })
        })
      })

      function startNewChat() {
        MaiAgent.chat.newConversation()
        MaiAgent.control.open()
      }
    </script>
  </body>
</html>
```

## 七、トラブルシューティング <a href="#troubleshooting" id="troubleshooting"></a>

| 症状                                             | 確認事項                                                                                                                                                                                                                                                                                                       |
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ボタンが表示されない                                     | `maiagentChatbotConfig` が SDK スクリプトより前に定義されているか、`webChatId` / `baseUrl` が正しいか、console にエラーが出ていないか                                                                                                                                                                                                          |
| console に `Unknown config options: ...` と表示される | [設定オプションリファレンス](#config-reference)と照らし合わせて、フィールド名のスペルを確認してください                                                                                                                                                                                                                                             |
| `MaiAgent is not defined`                      | SDK の読み込みがまだ完了していません。`DOMContentLoaded` の後に呼び出すか、先に `typeof MaiAgent !== 'undefined'` を確認してください                                                                                                                                                                                                            |
| イベントリスナーが発火しない                                 | イベント名が正しいか確認してください（`MaiAgent.EVENT_TYPES` の定数の使用をお勧めします）。`off()` には `on()` と同じ関数参照を渡す必要があります                                                                                                                                                                                                               |
| デバイスを変えると会話が消える                                | 匿名状態の会話はブラウザ単位で保持されます。デバイスをまたぐ場合は `auth` または `contactId` を設定してください（[ユーザーの識別](#identify-users)を参照）                                                                                                                                                                                                          |
| `auth` を設定しても ID が反映されない（400 エラー）              | Web Chat で「埋め込みを許可するドメイン」を設定している場合、リスト内のドメインのページだけが ID 同期を完了できます。埋め込み先ページのドメインがリストに追加されているか確認してください                                                                                                                                                                                                        |
| ボタンの位置がおかしい                                    | ページの CSS がボタンのスタイルと競合していないか、位置パラメータの形式（数値、`px`、`rem`）が正しいかを確認してください。ドラッグ後の位置はブラウザに記憶されます。[ボタン位置の決定順序](#button-position-behavior)を参照してください                                                                                                                                                                  |
| iframe を自分で配置し、`postMessage` でチャットウィンドウと通信したい  | サポートされていません。SDK とチャットウィンドウの iframe 間の `postMessage` メッセージは SDK の内部プロトコルであり、形式はバージョンによって変わります。また、他のオリジンからのメッセージは受け付けません。埋め込みコードで SDK を読み込み、[イベント](#api-events)（`messageReceived` など）でメッセージを受信し、[`MaiAgent.chat`](#api-chat) でメッセージを送信してください。ページ内に固定したチャット領域が必要な場合は [inline モード](#inline-container)を使用してください |

SDK を安全に呼び出す：

```javascript
function safeOpenChat() {
  if (typeof MaiAgent !== 'undefined' && MaiAgent.control) {
    MaiAgent.control.open()
  }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.maiagent.ai/tech/ja/serve/web-chat-sdk.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
