📝

WordPress に AI レビューを自然に統合する──Structured Outputs 実践ガイド

に公開

これは、1人アドベントカレンダー2025 10日目の記事です。


はじめに

私は普段 WordPress をメインで使っているわけではありません。ただ、業務の中で 「文章を AI に評価させる仕組み」 を作る機会があり、その技術要素を整理していたとき、

「これ、WordPress に組み込めたら便利なのでは?」

と思いついたのが、この記事の出発点です。

ブロガー・編集者・広報チームなど、文章を扱う人が抱える悩みは共通しています。

  • タイトルが弱い気がする
  • 読者がどこで離脱しそうか判断できない
  • 説明を足したいが、どこから肉付けすべきかわからない
  • 全体を俯瞰して評価してほしい

これらを 投稿画面の中だけで完結 できる仕組みがあれば、かなり役立つはず!!

そこで今回は、WordPress に AI 記事レビュー機能 を組み込む構成を設計し、その実装方法をまとめます。

注意: この記事は「構成と設計の理解」が主目的です。掲載しているコードは概念実装(サンプル)であり、利用環境・WordPress バージョンにより微調整が必要です。本番環境に組み込む際は公式ドキュメントも併せて確認してください。

技術的なテーマとしても、

  • Structured Outputs(JSON Schema)
  • WordPress REST API
  • プラグイン構造
  • 投稿画面への React ボタン埋め込み

などがバランスよく扱える題材です。

将来的には「AI レビュープラグイン」として独立させても成立する設計です。需要がありそうなら実際に作ってみようかな〜と思っています。

(作ってみたい気持ちだけはあります!期待が多ければ、ワンチャン…)

できること(今回作るレビュー機能)

投稿画面に 「AI レビュー」ボタン を配置し、以下 4 つの観点でフィードバックを返します。

  1. タイトル改善案の生成
  2. 読者離脱ポイントの検出
  3. どこを肉付けすべきかの指摘
  4. 記事全体の 5 段階評価

これらを 1 つの Structured Outputs(JSON Schema) で返すように設計しています。


全体アーキテクチャ

前提: この記事では OpenAI の Responses API(2025年3月〜)を使用しています。従来の Chat Completions API (/v1/chat/completions) とはリクエスト形式が異なります。

※ Responses API は現在移行期で、input / input_texttext.format / response_format の両方がサポートされています。今回は公式 example に沿って input + text.format を使用しています。

WordPress 投稿画面
↓(fetch)
独自 REST API(/wp-json/ai-review/v1/review)
↓
OpenAI Responses API(Structured Outputs)
↓
JSON を受け取り UI に表示
  • API キーは安全のため WordPress サーバ側で保持
  • 投稿画面の JS からは WordPress REST API を叩くだけ
  • Responses API は JSON Schema を返すモード なのでパースが安定

Step 1. プロンプト(Structured Outputs)

以下が 1 つのプロンプトで 4 種類のレビューを返す JSON Schema の例です。

{
  "title_suggestions": {
    "type": "array",
    "items": { "type": "string" },
    "description": "より読まれやすいタイトル候補を3つ返す"
  },
  "weak_points": {
    "type": "array",
    "items": { "type": "string" },
    "description": "読者が離脱しそうな箇所の指摘"
  },
  "expansion_advice": {
    "type": "array",
    "items": { "type": "string" },
    "description": "説明を追加すべき段落と理由"
  },
  "score": {
    "type": "integer",
    "description": "読みやすさを1〜5で評価"
  }
}

PHP 側では、この Schema を使って記事本文をレビューさせます。

Step 2. WordPress 側に REST API を作る(PHP)

wp-content/plugins/ai-review/ai-review.php

<?php
/**
 * Plugin Name: AI Review
 */

add_action('rest_api_init', function () {
    register_rest_route('ai-review/v1', '/review', [
        'methods'  => 'POST',
        'callback' => 'ai_review_callback',
        'permission_callback' => function () {
            // 投稿編集権限を持つユーザーのみ AI レビューを実行できます
            // (必要に応じて 'edit_pages' や 'manage_options' に変更してください)
            return current_user_can('edit_posts');
        }
    ]);
});

function ai_review_callback($request) {
    $content = $request->get_param('content');

    // ※ getenv() はサーバー環境により使えないことがあります
    // 必要に応じて define('OPENAI_API_KEY', 'xxx') や get_option() に変更してください
    $api_key = getenv('OPENAI_API_KEY') ?: (defined('OPENAI_API_KEY') ? OPENAI_API_KEY : '');

    // システムプロンプト
    $system_prompt = "あなたはプロの編集者です。以下の記事を読み、JSON Schema に従って 4 つのレビュー結果を返してください。
- title_suggestions: より読まれやすいタイトル候補を3つ
- weak_points: 読者が離脱しそうな箇所の指摘
- expansion_advice: 説明を追加すべき段落と理由
- score: 読みやすさを1〜5で評価";

    // Responses API 用のペイロード
    $payload = [
        'model' => 'gpt-5.1',  // 2025年12月時点の最新モデル
        'input' => [
            [
                'role' => 'system',
                'content' => $system_prompt
            ],
            [
                'role' => 'user',
                'content' => $content
            ]
        ],
        'text' => [
            'format' => [
                'type' => 'json_schema',
                'name' => 'article_review',
                'strict' => true,
                'schema' => [
                    'type' => 'object',
                    'properties' => [
                        'title_suggestions' => ['type' => 'array', 'items' => ['type' => 'string']],
                        'weak_points' => ['type' => 'array', 'items' => ['type' => 'string']],
                        'expansion_advice' => ['type' => 'array', 'items' => ['type' => 'string']],
                        'score' => ['type' => 'integer']
                    ],
                    'required' => ['title_suggestions', 'weak_points', 'expansion_advice', 'score'],
                    'additionalProperties' => false
                ]
            ]
        ]
    ];

    // Responses API エンドポイント
    $response = wp_remote_post('https://api.openai.com/v1/responses', [
        'headers' => [
            'Content-Type'  => 'application/json',
            'Authorization' => 'Bearer ' . $api_key
        ],
        'body' => json_encode($payload),
        'timeout' => 60
    ]);

    if (is_wp_error($response)) {
        return ['error' => $response->get_error_message()];
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);

    // Responses API のレスポンス構造から結果を取得
    // ※ Responses API は 2025 年時点で活発に更新されており、
    //    output → content → text の階層が将来変わる可能性があります。
    //    本番環境ではレスポンス構造を必ずログに記録し、
    //    フォールバック処理を追加することを推奨します。
    $output = $body['output'][0]['content'][0]['text'] ?? null;

    if ($output) {
        return json_decode($output, true);
    }

    // 構造変更時のデバッグ用に raw レスポンスを返す
    // 本番では error_log(print_r($body, true)) などでログに記録してください
    return ['error' => 'Unexpected API response', 'raw' => $body];
}

Step 3. 投稿画面に「AI レビュー」ボタンを追加(JavaScript)

wp_enqueue_script を使い、投稿画面にスクリプトを差し込みます。

補足: 本番環境では fetch よりも WordPress 標準の wp.apiFetch を使うことを推奨します。nonce 処理が自動化され、CSRF 対策も組み込まれています。

まず、PHP 側でスクリプトを登録し、nonce を渡します。

add_action('enqueue_block_editor_assets', function () {
    wp_enqueue_script(
        'ai-review-js',
        plugins_url('ai-review.js', __FILE__),
        ['wp-data'],
        '1.0.0',
        true
    );
    // CSRF 対策として nonce をスクリプトに渡す
    wp_localize_script('ai-review-js', 'aiReviewData', [
        'nonce' => wp_create_nonce('wp_rest')
    ]);
});

次に、JavaScript 側で nonce を使用します。

注意: 本記事のサンプルは Gutenberg(ブロックエディタ) 向けです。Classic Editor 環境では wp.data.select("core/editor") が利用できないため、textarea から記事内容を取得する処理に差し替える必要があります。

document.addEventListener("DOMContentLoaded", () => {
  const button = document.createElement("button");
  button.innerText = "AI レビュー";
  button.style.marginLeft = "8px";

  button.onclick = async () => {
    const content = wp.data.select("core/editor").getEditedPostContent();

    // 本番では wp.apiFetch を推奨(nonce 自動付与)
    const res = await fetch("/wp-json/ai-review/v1/review", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-WP-Nonce": aiReviewData.nonce
      },
      body: JSON.stringify({ content })
    });

    const json = await res.json();
    console.log(json);

    alert("AI レビューを完了しました。コンソールを確認してください。");
  };

  document.querySelector(".edit-post-header").append(button);
});

本格的に UI を作るなら

  • モーダル表示
  • タブ切り替え
  • 段落横にハイライト

などの拡張も可能です。

API キーの管理について

この記事では例として getenv('OPENAI_API_KEY') を使っていますが、

  • .env は WordPress 標準では読み込まれない
  • 環境によっては getenv() が無効化されている

といった理由から、本番環境では次のいずれかの方法が確実です。

1. wp-config.php に define() を書く(最も簡単で確実)

define('OPENAI_API_KEY', 'sk-xxxx');

2. 管理画面で保存したキーを get_option() から取得する(プラグイン化する場合に推奨)

$api_key = get_option('openai_api_key');

.env を使いたい場合は、vlucas/phpdotenv などのライブラリ導入が必要です。


今後の展開(プラグインとしての可能性)

今回の構成は、そのまま以下のような未来に発展できます。

  • 記事の自動要約プレビュー
  • 下書きに対する改善レコメンド
  • タイトル A/B テスト支援
  • 「読みやすさスコア」の可視化ダッシュボード
  • 自社メディア向けワークフローの自動化

Structured Outputs のおかげで API レスポンスが安定しているため、
WordPress プラグイン化 との相性が非常に良いです。

個人開発でも企業メディアでも役立つテーマだと思います。

おわりに

WordPress に AI を組み込む方法はたくさんありますが、
「投稿画面で完結するレビュー機能」 は手軽で効果が大きい実装のひとつです。

  • 文章を書く人の負担を減らす
  • 編集者の観点を補助する
  • 記事の質を底上げする

そんな仕組みを、自分たちで作れる時代になりました。

もし発展形に興味がある方は気軽にコメントください!


明日は「AIにコミットメッセージを考えてもらうカスタムコマンド」を書きます。

📚 1人アドベントカレンダー2025 全記事一覧


megusunu

🐦 X (@megusunu)
🧶 megusunuLab(ハンドメイド)
🏢 Wells合同会社

GitHubで編集を提案

Discussion