n8nで動かしていたAI自動投稿システムをWordPressプラグインとして作り直しました。単なる移行作業ではなく、将来的な配布・販売も視野に入れた設計で進めています。本番化の過程で直面した問題は想定以上に多く、「ローカルでは動いていたのに本番では動かない」という場面が繰り返されました。
この記事では、設計から本番デプロイまでの全工程と、詰まったポイントの解決策を開発記録として整理します。WordPressプラグイン開発を検討している方や、AI APIをWordPressと連携させる実装の参考にしてください。
(筆者注:私自身がこのプラグインを開発・運用しており、この記事はその実装経験をもとに執筆しています。)
検証環境
- 開発環境:LocalWP / PHP 8.x / WordPress 6.x
- 本番環境:ConoHa VPS / PHP 8.x / WordPress 6.x
- テーマ:Cocoon(子テーマ)
- 使用API:Anthropic Claude API / Unsplash API
- 検証時期:2026年5月〜6月時点
このプラグインで何をしているか
「AI Auto Blogger」は、Claude(Anthropic)またはGPT-4o(OpenAI)を使ってブログ記事を生成・投稿するWordPressプラグインです。主な仕組みは以下のとおりです。
- wp-cronで指定時刻に起動
- カテゴリを日付ベースでローテーション
- AIにプロンプトを送信してJSON形式の記事データを受け取る
- UnsplashからアイキャッチをDLしてメディアライブラリに登録
- WordPressに投稿・SEOメタ情報を書き込む
生成された記事は下書きとして保存し、人間がレビューしてから公開するフローで運用しています。AIの出力をそのまま公開するのではなく、人間の確認ステップを必ず挟む設計にしています。
なぜn8nからWordPressプラグインへ移行したのか
もともとn8nを使ってClaude APIによる記事生成・WordPress自動投稿・SEOメタ情報更新を行うシステムを構築していました。移行の主な理由は以下のとおりです。
n8nの課題
- 月額コストが継続的にかかる(執筆時点での料金は公式サイトをご確認ください)
- n8nサーバーが落ちると処理が実行されない
- 設定変更にn8nの知識が必要で、他者への引き継ぎが困難
- Credential管理が複雑で、複数サイト運用時に混乱しやすい
プラグイン化のメリットと現実的な比較
| 比較項目 | n8n | WPプラグイン |
|---|---|---|
| 月額コスト | n8n利用料が別途必要 | n8n利用料は不要。ただしWP運用費・API利用料は別途必要 |
| 設定場所 | n8n管理画面 | WP管理画面で完結 |
| 外部依存 | n8nサーバーへの依存あり | n8n依存はなくなるが、AI API・画像API等への依存は残る |
| 将来の配布 | 配布困難 | ZIP配布・販売できる設計に近づく |
Phase 1〜3:設計と開発環境の構築
まずn8nフローの構成を整理し、プラグインとして再現すべき機能を定義しました。
クラス設計
機能ごとに責務を分離した設計にしました。
| クラス名 | 役割 |
|---|---|
| class-scheduler.php | wp-cronによるスケジュール管理 |
| class-ai-client.php | Claude / OpenAI API呼び出し |
| class-unsplash.php | Unsplash画像取得(API利用条件・クレジット表記要件に準拠した実装が必要) |
| class-post-creator.php | 記事投稿・SEOメタ書き込み |
| class-json-parser.php | AIレスポンスのJSONパース |
| class-logger.php | 実行ログ管理 |
開発環境
開発環境はLocalWP + VSCode + Claude Code(VSCode拡張)で構築しました。AIとの対話型開発スタイルで、設計から実装まで効率よく進めることができました。
Phase 4:技術的な壁と解決策
開発中に複数の技術的な問題に直面しました。それぞれの原因と解決策を記録します。
問題1:JSONパースエラーの泥仕合
ClaudeのAPIレスポンスにem dash(—)などの特殊文字が含まれ、json_decodeが失敗する問題が発生しました。さらにLocalWP環境ではmbstringが使えないことも判明。解決策として3段階パース戦略を実装しました。
- 高速パス:json_decodeをそのまま試みる。通れば完了
- 修復パス(repair_json):HTML属性変換+バイト走査でcontentフィールド内の生改行・特殊文字を修正してから再パース
- フォールバック(fallback_extract):正規表現で位置ベースにcontentフィールドだけ個別抽出
バイト走査でUTF-8多バイト文字をスルーしながら生の改行文字だけエスケープする処理が地味に難しいポイントでした。mb_* / iconvに依存しない実装にしたことで、環境を問わず動作するようになりました。
問題2:SSL証明書エラー(ローカル環境)
ローカル環境でcURL error 60が発生。開発時はsslverify: falseを設定して回避しましたが、本番環境ではこの記述ごと削除するのが正解です。wp_remote_post()はデフォルトでSSL検証が有効なため、記述を消すだけで完了します。開発用と本番用でフォルダを完全分離して管理しました。
問題3:BOM混入による文字コード問題
PowerShellでファイル操作を行った際にBOM(UTF-8 BOM)が混入し、WordPressでheaders already sentエラーが発生しました。PowerShellのWriteAllTextでBOMなしUTF-8を明示的に指定して解決しました。
問題4:CSS/JSが読み込まれない
管理画面を開いてもスタイルが一切当たっていない状態に。原因はadmin_enqueue_scriptsフックの登録漏れでした。$hookでプラグインのページかどうかを判定し、余計なページにJSを読み込まないようにするのがWordPressのベストプラクティスです。
問題5:日本語翻訳が表示されない
本番環境をWordPressの日本語設定で使っていても、プラグインだけ英語になる問題が発生しました。今回の構成では、プラグインヘッダーのText Domain/Domain Path設定と、翻訳読み込み処理の不足が原因で日本語化が反映されませんでした。WordPressの構成や配布方法によって要件は異なりますが、少なくとも今回の自作プラグインではこれらの設定が必要でした。
WordPressの翻訳システムは.poファイルではなく.mo(バイナリ)を読むため、msgfmtでのコンパイルが必要です。今回の環境にはmsgfmtがなかったため、PHPスクリプトでバイナリを生成して対応しました。
問題6:AIのモデルIDが間違っていた
本番で実行したらAPIエラーが発生しました。原因はモデルIDの記述ミスです(執筆時点での正しいモデルIDは各公式ドキュメントをご確認ください。モデルIDは更新される場合があります)。ローカルでは古いバージョンで動いていた可能性があります。APIのエラーメッセージを素直に読めばすぐ気づける問題でした。
問題7:画像が本文に入らない
set_post_thumbnail()だけでは「サムネイル」として登録されるだけで、本文には含まれません。Cocoonなど一部のテーマはサムネイルを自動表示しますが、確実に表示したい場合は本文HTMLに直接埋め込む実装が必要です。冒頭と末尾の両方に<figure>タグで挿入するようにしました。
問題8:スケジュール変更が反映されない
管理画面で投稿時刻を変更しても、次回実行時刻が変わらない問題が発生しました。原因はschedule()がプラグイン有効化時にしか呼ばれない実装になっていたことです。
WordPressにはupdate_option_{option_name}という特定オプションの更新時に発火するフックがあります。これを使って設定保存時に自動で再スケジュールされるよう修正しました。
Phase 5〜6:機能追加とUX改善
技術的な問題を解消した後、管理画面の機能とUXを充実させました。
管理画面の機能
- APIキー設定(Claude・OpenAI・Unsplash)
- カテゴリ設定(1行1カテゴリ、日付ベースローテーション)
- スケジュール時刻設定
- プロンプトエディタ
- デフォルト投稿ステータス(即公開 / 下書き)
- 今すぐ実行ボタン:AJAXで即時実行・結果をリアルタイム表示
- 実行ログ画面:日時・タイトル・ステータス・エラーを最大50件記録
- 多言語対応(日本語翻訳ファイル .po/.mo を作成)
生成中のプログレス表示
AI APIの呼び出しは1〜2分かかることがあります。ボタンを押したまま無反応だと処理が進んでいるか判断できないため、時間ベースのステップメッセージを実装しました。サーバーサイドの実際の進捗を取得する手段がないため、経過時間に応じてメッセージを切り替える疑似プログレスです。
| 経過時間 | 表示メッセージ |
|---|---|
| 0秒〜 | AIサーバーへリクエストを送信中… |
| 5秒〜 | AIが記事を生成中です。そのままお待ちください… |
| 80秒〜 | 記事の投稿・画像をアップロード中… |
cronステータスの可視化
「定期実行が本当に動いているのか?」が管理画面からわからない問題を解消しました。wp_next_scheduled()で次回実行時刻を取得し、「次回: 04:00(3時間12分後)」のように残り時間を表示。前回の実行結果も成功なら緑ドット・失敗なら赤ドットで視覚的に確認できるようにしました。
補足:配布を見据えたセキュリティ実装
管理画面の設定保存やAJAX実行処理では、nonce検証・権限チェック・入力値のサニタイズを実装しています。特にAPIキーやプロンプトのような設定値は、用途に応じたバリデーション/サニタイズを行うことが重要です。配布型プラグインでは、これらのセキュリティ要件を満たしていないとWordPress.orgの審査を通過できないため、販売前に改めて確認する予定です。
Phase 7:本番デプロイ
本番用フォルダのPHPファイル全体の構文チェックで0エラーを確認した後、ai-work-lab-jp.comにZIPアップロードでインストールしました。n8nフローと1ヶ月並走して安定性を確認してからn8nを停止する予定です。
本番化で詰まったポイントまとめ
振り返ると、大半は「ローカルでは動いていたが本番では前提が違った」パターンでした。
| 問題 | 原因 | 解決策 |
|---|---|---|
| SSL検証エラー | 開発時のsslverify:falseが残存 | 本番フォルダから記述ごと削除 |
| 翻訳が表示されない | Text Domain未設定・load未呼出 | ヘッダー追記+.moファイル生成 |
| モデルIDエラー | 古いモデルIDを使用 | 公式ドキュメントで最新IDを確認 |
| 画像が本文に入らない | set_post_thumbnail()のみ | 本文HTMLに直接埋め込み |
| スケジュール変更が反映されない | 有効化時にしか登録されない | update_optionフックで再登録 |
| BOMによるエラー | PowerShellでBOM混入 | BOMなしUTF-8を明示指定 |
移行によって得られたもの
- n8n依存がなくなった:処理の起点と管理画面をWordPress側に集約でき、n8nサーバーの稼働状況に左右されにくくなった(AI API・画像API等への依存は引き続き残る)
- 設定がWP管理画面で完結:サーバーやn8nの知識不要で設定変更できる
- 実行ログで投稿状況を可視化:何が起きたか一目でわかる
- 手動テスト実行が管理画面から可能:デバッグが格段に楽になった
- 定期監視の負担を大きく減らせる設計に:ただし定期的な動作確認とログチェックは引き続き必要
- プラグインとして配布・販売できる設計に近づいた:将来の展開に向けた基盤ができた
よくある質問
Q1. n8nのself-hosted版と比較してもプラグイン化のメリットはありますか?
n8nをself-hostedで運用している場合、サーバー費用の観点ではプラグイン化のコスト優位性は小さくなります。ただし「設定をWP管理画面で完結させたい」「他者に引き継ぎしやすくしたい」「将来的に配布・販売したい」という目的がある場合はプラグイン化の優位性があります。自分の運用コストと将来の使い方に合わせて判断することが重要です。
Q2. wp-cronではなくサーバーcronにした方がよいですか?
wp-cronはページアクセス時に実行判定されるため、アクセスが少ない時間帯は実行時刻がずれる可能性があります。正確な時刻実行が必要な場合はサーバーcron(ConoHaのcron設定など)からwp-cron.phpを叩く方が安定します。今回はまずwp-cronで試験運用し、ズレが許容できない場合はサーバーcronへの切り替えを検討する方針です。
Q3. 画像APIが止まった場合のフォールバックはどうしていますか?
現状はUnsplash APIが失敗した場合にアイキャッチなしで記事が投稿される実装になっています。フォールバックとして「デフォルト画像を使用する」「投稿をスキップしてエラーログに記録する」の2つの選択肢があり、後者の方が品質管理の観点では安全です。この点は今後の改善項目として残っています。
Q4. Unsplash画像のクレジット表記はどうしていますか?
Unsplash APIの利用には、写真家名とUnsplashへの適切な帰属表示(attribution)が必要です。現状はメディアライブラリの説明欄に写真家名を保持する実装にしていますが、投稿本文へのクレジット表示方法は運用ルールとして事前に決めておく必要があります。また、WordPressのような分散型アプリではAPIキーの扱いに追加の考慮が必要なケースがあります。実装前に必ず最新の公式ドキュメントを確認してください。
Q5. 生成した記事は人間がレビューしてから公開していますか?
はい。プラグインのデフォルト投稿ステータスを「下書き」に設定しており、生成された記事は必ず人間がレビューしてから公開しています。AIが生成した記事をそのまま自動公開する運用は行っていません。品質管理の観点から、レビューステップを必ず挟む設計にしています。
Q6. このプラグインはどのWordPress環境でも動きますか?
開発・テスト環境はLocalWP(PHP 8.x)+本番ConoHa VPS(WordPress 6.x)です。mb_* / iconvに依存しない実装にしているため、mbstringが使えない環境でも動作します。ただし、WordPressのバージョン・PHPバージョン・サーバー設定によって動作が異なる場合があります。自分の環境でのテストを必ず行ってください。
次のステップ
- 1ヶ月の並走期間でプラグインの安定性を確認する
- 問題がなければn8nを完全に停止してプラグインに一本化する
- プラグインの配布に向けてドキュメントを整備する
参考リンク
- WordPress: admin_enqueue_scripts
- WordPress: set_post_thumbnail()
- WordPress: WP-Cron
- WordPress: プラグイン国際化
- Unsplash API Documentation
- n8n Pricing
※本記事の情報は執筆時点のものです。サービス料金・制度の内容は変更される場合があります。最新情報は各公式サイトをご確認ください。収益・投資の効果は個人の状況によって異なります。本記事の内容は特定の商品・サービスへの加入を推奨するものではありません。



コメント