# WordPress プラグイン

askai-button の WordPress プラグイン「Elephancube Ask AI Button」の説明です。必要な環境、設定画面の項目、ページ別の設定、ボタンを表示しない場所、開発者向けのフィルター、Polylang・WPML での動作、アンインストール時の動作をまとめています。

プラグイン「Elephancube Ask AI Button」は、WordPress のサイトに「AIに質問」ボタンを追加し、管理画面で設定できるようにします。ボタンの動作そのものは JavaScript ライブラリ（askai-button）が行い、プラグインは設定を渡すだけです。

インストールの手順は「[導入方法](https://elephancube.github.io/askai-button/install/#wordpress)」をご覧ください。

## 必要な環境

- WordPress 6.4 以上
- PHP 7.4 以上

有効化すると、標準の設定のまま、サイトの公開ページにボタンが表示されます。AIのAPIは呼ばず、APIキーも必要ありません。サーバーから外部への通信もしません。標準の設定では、ボタンの利用状況も保存しません。「[利用回数の記録](#usage)」をオンにした場合だけ、月ごとの合計をサイト自身に保存します。

## 設定画面

設定は「設定 > AIに質問」の1画面にまとまっています。変更できるのは、管理者（`manage_options` 権限のあるユーザー）です。

### 表示

| 項目 | 内容 |
| --- | --- |
| サイトにボタンを表示する | ボタン全体のオン・オフ。 |
| 投稿タイプ | ボタンを表示する投稿タイプ。どれにもチェックを入れなければ、すべてで表示します。絞り込めるのは投稿や固定ページなどの個別ページだけで、トップページやアーカイブなどの一覧ページには常に表示されます。 |
| 位置 | 右下、または左下。 |
| 画面端からの余白 | 0〜500px。標準は 24px。 |
| 重なり順（z-index） | テーマのほかの要素にボタンが隠れる場合に、数値を大きくします。標準は 9999。 |
| ボタンの色 | `#1a73e8` のような形式で指定します。文字は白なので、濃い色を選びます。空欄なら標準の色です。 |
| 多言語サイトでは、表示中の言語のトップページのURLを渡す | Polylang または WPML が有効なときだけ表示されます。標準はオフで、どのページでもサイトのトップのURLを渡します。「[多言語のサイト](#multilingual)」を参照。 |

### 文言

ボタンのラベル、パネルのタイトル、パネルの補足文、質問欄のプレースホルダー、注記の5つを変更できます。空欄にすると標準の文言を使います。標準の文言はページの言語に合わせて切り替わるので、多言語のサイトでは空欄のままにしておくのが簡単です。

入力できるのはプレーンテキストで、200文字までです。HTMLタグは取り除かれます。

### プリセット質問

訪問者がタップして使える「質問の例」を、6件まで登録できます。並べ替えもできます。

「質問をタップしたとき」の動作は、「質問欄に入力する」（標準）と「すぐにAIサービスを開く」から選べます。

### AIサービス

ChatGPT、Claude、Google AIモードのそれぞれについて、次の項目を設定できます。並び順も変えられます。

| 項目 | 内容 |
| --- | --- |
| このサービスを表示する | パネルの選択肢に出すかどうか。すべてオフにすると、ボタンは表示されません。 |
| 最初に選択しておく | パネルを開いたときに選ばれているサービス。 |
| URLテンプレート | サービスを開くURL。`https://` で始まり、`{query}` を含む必要があります。空欄なら標準のURLです。 |
| 質問の渡し方 | 「URLに含めて渡す」（標準）または「クリップボードにコピーしてからサービスを開く」。 |
| 色 | 選択中のサービスと送信ボタンの色。空欄なら標準の色です。 |

URLの形式は各サービスが公式に公開しているものではなく、予告なく変わることがあります。動かなくなったときは、ここでURLテンプレートを直すか、質問の渡し方を切り替えるか、そのサービスをオフにできます。

### クエリ

| 項目 | 内容 |
| --- | --- |
| クエリテンプレート | AIサービスに渡す文面。空欄なら、ページの言語に合わせた標準の文面です。使える変数は `{question}`、`{site_url}`、`{url}`、`{title}`、`{site_name}` です。 |
| 質問の最大文字数 | 1〜2000。標準は 500。 |

`{site_url}` には、サイトのトップページのURL（`home_url('/')`）が入ります。Polylang または WPML を使っているサイトでは、どの言語のページでも、既定の言語のトップページのURLが入ります（設定「多言語サイトでは、表示中の言語のトップページのURLを渡す」をオンにした場合を除く）。表示中のページのURLを渡したい場合は、テンプレートで `{url}` を使います。

### 利用回数の記録

| 項目 | 内容 |
| --- | --- |
| ボタンと各AIサービスが押された回数を記録する | 標準はオフです。オンにすると、月ごとの合計をサイト内に保存します。「[利用回数の記録](#usage)」を参照してください。 |

### プレビュー

設定画面には、保存前の内容でボタンとパネルを表示するプレビューがあります。サンプルの質問を入れると、実際に開かれるURLも確認できます。プレビューと並べ替えのボタンには JavaScript が必要ですが、設定の入力と保存は JavaScript がなくてもできます。

## ページ別の設定

投稿、固定ページ、そのほかの公開された投稿タイプの編集画面に、「AIに質問」というボックスが追加されます。

- **このページではボタンを表示しない**：チェックを入れると、そのページではボタンを出しません。
- **このページ専用の質問**：6件まで。入力すると、そのページではサイト共通のプリセット質問の代わりに表示します。

## 利用回数の記録

回数の記録は、標準ではオフです。「設定 > AIに質問」で「ボタンと各AIサービスが押された回数を記録する」にチェックを入れて保存すると、次の4つを月ごと（サイトのタイムゾーンの暦月）に数えます。

- 「AIに質問」ボタンでパネルが開かれた回数
- ChatGPT、Claude、Google AIモードのそれぞれへ質問が送られた回数

`askai_providers` フィルターで追加したサービスは、その id で数え、表に列が追加されます。

**保存するもの。** 月と項目ごとに整数を1つだけ、サイト自身のデータベース（options テーブル。通常のページ表示では読み込まれません）に保存します。それ以外は保存しません。質問の内容、ページのURL、IPアドレス、ブラウザーの情報、Cookie、アカウント、月より細かい日時は、どれも保存しません。

**クリックの伝え方。** 記録がオンの間、ボタンを表示するページは、小さなスクリプト `counter.js` も読み込みます。このスクリプトは、クリック1回につき1回、サイト自身（`POST /wp-json/elephancube-ask-ai-button/v1/count`）へリクエストを送ります。内容は、クリックの種類（`open` または `send`）と、質問を送った場合はサービスの id だけです。ほかの場所へは何も送りません。ボタンの JavaScript ライブラリ自体は、この場合も通信しません。このリクエストがAIサービスを開く動作を遅らせることはなく、失敗したリクエストは捨てられます。

**回数はおおよその値です。** ボットや繰り返しのクリックも数えます。投稿を編集できるログイン中のユーザー（投稿者、編集者、管理者）のクリックは数えません（これらのユーザーにはスクリプトを読み込みません）。ページキャッシュを使っていても記録できます。ページには訪問者ごとに異なる情報を入れていないためです。受け付けるのは、2種類のクリックと、ボタンが現在表示しているサービスだけです。ほかのサイトから送られたとブラウザーが示すリクエストは拒否します。

**回数の確認。** 「設定 > AIに質問」の一番下にある「利用回数」に、月ごとの行（新しい月が上）と合計の行を表示します。「CSVをダウンロード」で表をファイルに保存できます。「回数をリセット」は、横のチェックボックスにチェックを入れたうえで押すと、すべての回数を削除します。設定を保存しても回数は変わりません。記録をオフにすると、それまでの回数は表示されたまま、新しい回数は加算されなくなります。

## ボタンを表示しない場所

次の場所には、設定やフィルターにかかわらず、ボタンを表示しません。

- 管理画面、ログイン画面
- プレビュー（カスタマイザーのプレビューを含む）
- 404 ページ
- 添付ファイルのページ
- 公開されていない投稿、パスワードで保護された投稿
- フィード、埋め込み表示、REST API などのページ以外の応答

AIサービスが読めないページでボタンを出しても役に立たないためです。

## フィルター

テーマやプラグインから、次のフィルターで動作を変えられます。フィルターが返した値は、設定画面の値と同じように検査されます。

### askai_should_display

```php
apply_filters( 'askai_should_display', bool $show, WP_Post|null $post )
```

表示中のページにボタンを出すかどうか。`$show` は「投稿タイプ」の設定とページ別の設定から決まった値、`$post` は個別ページでは投稿、それ以外では `null` です。`true` を返したときだけ表示します。「[ボタンを表示しない場所](#never)」では、このフィルターは呼ばれません。

```php
add_filter( 'askai_should_display', function ( $show, $post ) {
	// 「members」カテゴリーの投稿では表示しない
	if ( $post && in_category( 'members', $post ) ) {
		return false;
	}
	return $show;
}, 10, 2 );
```

### askai_presets

```php
apply_filters( 'askai_presets', string[] $presets, WP_Post|null $post )
```

パネルに表示する質問の例。`$presets` は、ページ専用の質問があればそれ、なければサイト共通の質問です。返した値のうち、空でない文字列が6件まで使われます。

```php
add_filter( 'askai_presets', function ( $presets, $post ) {
	if ( $post && 'product' === $post->post_type ) {
		return array( '送料はいくらですか？', '返品はできますか？' );
	}
	return $presets;
}, 10, 2 );
```

### askai_providers

```php
apply_filters( 'askai_providers', array $providers )
```

スクリプトに渡すAIサービスの一覧。各要素は、標準のサービスの id（`chatgpt`、`claude`、`googleai`）か、`id` と、必要に応じて `name`、`urlTemplate`、`method`（`url` または `copy_and_open`）、`color`（16進数の色）を持つ配列です。標準にないサービスには、`name` と、`https://` で始まり `{query}` を含む `urlTemplate` が必要です。条件を満たさない要素は取り除かれます。

```php
add_filter( 'askai_providers', function ( $providers ) {
	$providers[] = array(
		'id'          => 'example',
		'name'        => 'Example AI',
		'urlTemplate' => 'https://ai.example.com/search?q={query}',
		'color'       => '#444444',
	);
	return $providers;
} );
```

`ai.example.com` は説明用の架空のアドレスです。

### askai_query_template

```php
apply_filters( 'askai_query_template', string $query_template )
```

AIサービスに渡す文面のテンプレート。空の文字列を返すと、ページの言語に合わせた標準の文面を使います。

```php
add_filter( 'askai_query_template', function ( $query_template ) {
	return "{question}\n\n次のページを参照して回答してください。\n{url}";
} );
```

### askai_site_url

```php
apply_filters( 'askai_site_url', string $site_url, bool $lang_home )
```

`{site_url}` としてAIサービスに渡すサイトのURL。`$site_url` はプラグインが選んだURLで、サイトのトップページです。多言語のサイトでは既定の言語のトップページ、設定をオンにしている場合は表示中のページの言語のトップページになります。`$lang_home` は、その設定「多言語サイトでは、表示中の言語のトップページのURLを渡す」の値です。フィルターは、設定がどちらの場合も最後に実行されます。返した値は、`http://` または `https://` で始まる絶対URLの文字列である場合だけ使われます。それ以外は無視され、`$site_url` が使われます。

```php
add_filter( 'askai_site_url', function ( $site_url, $lang_home ) {
	// ドメインの直下ではなく、下の階層にあるサイト
	return 'https://example.com/shop/';
}, 10, 2 );
```

## 多言語のサイト（Polylang・WPML）

標準の文言のまま使う場合は、何も設定する必要はありません。どのページでも、そのページの言語でボタンが表示されます。同梱している言語は日本語と英語で、ほかの言語のページでは英語で表示されます。設定画面は英語と日本語に対応しています。

自分で入力した文言（5つの文言、サイト共通のプリセット質問、クエリテンプレート）は、Polylang、または WPML と String Translation アドオンが有効なときに翻訳できます。

1. 「設定 > AIに質問」で、サイトの主言語で文言を入力して保存します。
2. 多言語プラグインの文字列翻訳の画面（Polylang では「言語 > 翻訳」）を開き、グループ「Elephancube Ask AI Button」を探します。文字列の名前は、`button_label`、`panel_title`、`panel_subtitle`、`placeholder`、`note`、`preset_1`〜`preset_6`、`query_template` です。
3. 翻訳を入力します。各ページには、その言語の翻訳が表示されます。翻訳がない場合は、入力した文言がそのまま表示されます。

知っておくとよいこと：

- 翻訳も、設定画面の文言と同じように処理されます。HTMLは取り除かれ、長さの上限があります。
- AIサービスに渡すサイトのURLは、ページの言語にかかわらず、どのページでもサイトのトップのURLです。これは既定の言語のトップページで、たとえば `https://example.com/` です。既定の言語にも `https://example.com/ja/` のような接頭辞を付けている場合は、転送されるだけのドメイン直下ではなく、そのURLを渡します。
- 表示中の言語のトップページを渡したい場合は、「設定 > AIに質問」の「表示」にある「多言語サイトでは、表示中の言語のトップページのURLを渡す」をオンにします。たとえば英語のページは `https://example.com/en/` を渡すようになります。この設定は Polylang または WPML が有効なときだけ表示され、どちらもない場合は何も変わりません。変わるのは渡すURLだけで、ボタンの文言と言語は常にページに合わせて切り替わります。どちらの場合も、`askai_site_url` フィルターでURLを差し替えられます。
- 「このページ専用の質問」と「このページではボタンを表示しない」は、投稿ごとの設定です。翻訳された投稿はそれぞれ別の設定を持ち、ほかの翻訳にはコピーされません。Polylang でカスタムフィールドの同期を有効にしていても、コピー・同期されません。
- Polylang は、文言が使われている間だけ文字列を一覧に表示します。質問を書き換えると、新しい文言が翻訳のない状態で現れます。元の文言の翻訳は Polylang に残っており、文言を元に戻せば再び使われます。不要になった翻訳は、Polylang の文字列翻訳の画面にある「Clean strings translation database」（使われていない文字列翻訳の削除）で消せます。
- WPML は、WPML の画面で削除するまで文字列を保持します。質問を削除しても、その項目（たとえば `preset_3`）は使われないまま残ります。WPML は質問を番号で区別するため、質問の順序を変えたあとは翻訳を確認してください。
- Polylang との連携は、実際の WordPress サイトで動作を確認しています。WPML との連携は、WPML が公開しているフック（文言には `wpml_register_single_string` と `wpml_translate_single_string`、サイトのURLには `wpml_default_language` と `wpml_permalink`）に沿って実装していますが、WPML を導入した環境ではまだ動作を確認していません。
- どちらのプラグインも必須ではありません。無効にしても不具合は起きず、入力した文言がそのまま表示されます。

## アンインストール

プラグインを「削除」すると、プラグインが保存したデータをすべて消します。

- 設定（オプション `askai_settings`）
- 投稿ごとの2つの値（投稿メタ `_askai_disabled` と `_askai_presets`）
- 利用回数（名前が `askai_count_` で始まるオプション）

マルチサイトでは、すべてのサイトから削除します。Polylang や WPML に入力した翻訳は、それぞれのプラグインが保存しているため、そのまま残ります。「無効化」しただけでは、データは消えません。

## 外部サービスとの関係

プラグイン自体は、外部のサービスと通信しません。訪問者が送信ボタンを押したときに、訪問者のブラウザーが、選ばれたAIサービスを別のタブで開きます。データがサイトの外に出るのは、このときだけです。「[利用回数の記録](#usage)」をオンにした場合のクリックの記録は、サイト自身にだけ送られます。何が渡るかは「[しくみと注意点](https://elephancube.github.io/askai-button/how-it-works/#privacy)」をご覧ください。

---

- HTML: https://elephancube.github.io/askai-button/wordpress/
- English: https://elephancube.github.io/askai-button/en/wordpress/index.md
- llms.txt: https://elephancube.github.io/askai-button/llms.txt
