〜AI Guardianという社内ツールを作って、ルールベースで9割は解決できると気づいた記録〜
WP本体やプラグインのアップデートは、ずっと人間がやっていました。
管理しているサイトが増えるにつれて「誰かがやらないといけないけど、誰もやりたくない作業」の筆頭になっていました。更新を忘れていて脆弱性が放置されていたり、アップデートしたらサイトが壊れたり。地味だけどリスクが高い。
今年から、これをAIにやらせることにしました。同時に、SEO状態のチェックとクライアントへの月次レポートも自動化する。そういうツール「AI Guardian」を社内で作りました。
この記事は「作った話」でありながら、途中から「AIがやると思っていたことを、AIに任せなかった話」になります。
なぜ作ったか:3つの課題が重なっていた
課題1:保守作業が人依存になっていた
サイトを管理しているのに、アップデートのタイミングは担当者の記憶頼みでした。プラグインのアップデート通知メールを見て「後でやろう」と思ったまま数週間経つ、みたいなことが実際にありました。
1サイトなら管理できます。10サイトになるとギリギリです。20サイトを超えると、誰かが見落とすことが前提になってきます。
課題2:セキュリティインシデントの実体験があった
過去にクライアントの医療サイトで改ざん被害を経験しています。バックドアを仕込まれて、フォレンジック調査から復旧まで対応しました。
あの経験から「早期発見」の重要性は痛感していました。気づいた時には手遅れ、という状況を繰り返したくない。
AI普及で攻撃の速度とコストが下がっている今、人間が週に1回確認するサイクルでは追いつかない場面が増えてきました。
課題3:SEO提案が感覚値になっていた
クライアントに月次レポートを送るとき、「今月はこういう状態でした」という数字を出しているつもりでも、ページごとの課題を定量化できていませんでした。
Search ConsoleやGA4を見ればデータはあるのに、それを整理してレポートに落とすのに時間がかかっていた。AIに投げればいい所見が書けるのに、投げるための素材を作るのが手作業だった。
「作れる?」という問いから始まった設計
最初はざっくりした問いでした。
「WP本体やプラグインのアップデートをAIにやらせて、更新前にバックアップ、エラーが出たら自動修復、修復できなければロールバック、毎月クライアントにレポートを自動送付する——こんなことできる?」
Claudeとの壁打ちで最初に出た答えがこれです。
「アップデート・バックアップ・死活監視は、AIは不要です。シェルスクリプト+cronで9割できます」
えっ、そうなの、というのが正直な反応でした。
詳しく聞くと、WP更新後のエラーパターンはほぼ有限だと。
- 画面が真っ白になったらロールバック
- fatal errorが出たらプラグインを無効化
- DB接続エラーならロールバック
この3パターンをif文で書けば、「エラーが出たらAIが自動修復」という機能は、実質AIなしで実現できます。AIにAPIコールして修復コードを生成させるより、単純な条件分岐の方が速くて確実です。
AIが輝くのは文章生成の部分だ、という整理ができたのがこの段階でした。
具体的には:
- SEOスコアの所見を自然な日本語で書く
- 「このページはなぜ低スコアで、どう直せばいいか」を説明する
- クライアントに送れるレポート文章を生成する
この3つだけAIに担当させる設計にしました。
実際に作ったもの
hgr.jp/seo/
├── index.html # サイト一覧・管理画面
├── dashboard.html # SEOダッシュボード
├── admin.php # 管理API(スキャン実行など)
├── api.php # Anthropic APIプロキシ
├── sc_auth.php # Google OAuth / SC・GA4データ取得
├── content_analyze.php # ページコンテンツ分析
├── report.php # PDFレポート生成
└── scanner.py # SEOスキャナー(Python)
ブラウザからサイトを追加してスキャンを実行すると、SEOスコアが出て課題が一覧になり、AIが所見を書いてレポートPDFを出力できる。Search ConsoleとGA4のデータも重ねて表示される。そういうものができました。
開発秘話1:エックスサーバーでpipが動かない
SEOスキャン用のPythonスクリプト(scanner.py)を書いたのですが、サーバーで動かそうとしたらライブラリのインストールができませんでした。
PermissionError: [Errno 13] 許可がありません: '/etc'
pip installを実行したら、エラーも出ないまま静かに失敗するものまで出てきました。共用レンタルサーバーの制約です。
解決策は「外部ライブラリを使わない」でした。
BeautifulSoup4を使うつもりでいたHTMLパーサーを、Pythonの標準ライブラリhtml.parserを継承して自作しました。SEOParserというクラスを書いて、タイトル・メタタグ・h1・h2・canonicalなどを拾う処理を全部自分で実装する。
制約がある方がシンプルな設計になることもある、という好例でした。外部ライブラリに依存しないのでバージョン問題も起きません。
開発秘話2:CORSエラーでAPIが叩けない
ブラウザからAnthropicのAPIを直接呼ぼうとしたら、当然CORSでブロックされました。
Error: Load failed
解決策はapi.phpというPHPのプロキシを1枚挟むことでした。
ブラウザ → hgr.jp/seo/api.php → Anthropic API
これでCORSの問題が解消されて、APIキーもサーバー側に置けるのでセキュリティ的にも正解でした。
ただ最初はストリーミング(文字が流れてくる表示)も実装しようとして、エックスサーバーではバッファリングの関係でうまく動かず、結局非ストリーミングで安定させました。動かないと分かったら割り切るのも大事です。
開発秘話3:Search ConsoleにサービスアカウントのメールアドレスがNG
Google Cloud Consoleでサービスアカウントを作り、そのメールアドレスをSearch Consoleに追加しようとしたら:
メールアドレスが見つかりません
何度やっても通りませんでした。サービスアカウントのメールアドレスはGoogleアカウントとして認識されないケースがある、という話でした。
切り替えてOAuth2.0でホノカのGoogleアカウントで認証する方式にしました。sc_auth.phpにOAuthのフローを実装して、ログインしたらトークンをサーバーに保存する。GA4連携も同じトークンで対応できました。
ただOAuthのトークンは定期的に期限切れになります。「SCデータが表示されなくなった」という症状が出たら再認証、というのが運用上の注意点として残りました。
開発秘話4:h1タグが5個と誤検知される
hgr.jpをスキャンしたら「h1タグが複数あります(5個)」という警告が出続けました。実際には1個しかありません。
原因を調べたら、スキャナーがページを2回取得していたことがわかりました。クロール時と解析時で別々にfetch_pageを呼んでいて、2回目にPageSpeedが最適化した別バージョンのHTMLを返していた。そのHTMLに空のh1タグが4個含まれていた。
さらに空のh1タグを除外しても改善しない問題が残りました。SSHでパーサーを直接動かして調べると:
h1数: 5
'\n'
'\n'
'デザイン・ホームページ・ブランディング|岡山のクリエイティブ制作会社 HONOKA'
'\n'
'\n'
空白行だけのh1が4つあった。修正は「strip()して空の文字列になるh1は除外する」という1行でしたが、気づくまでに時間がかかりました。
開発秘話5:Safariで印刷したら真っ白なPDFが出てきた
ChromeではPDFレポートが正常に出力されるのに、Safariでは白紙になりました。
-webkit-print-color-adjust: exactを付けて、印刷ダイアログで「背景のグラフィック」をオンにしてもらう案内を追加しても改善しない。
最終的に背景色を全廃して、ボーダーとテキストだけで構成した印刷専用CSSに作り直しました。見た目はシンプルになりましたが、Safariでも確実に出力できます。
ただ率直に言うと、Chromeで出力を推奨することにしました。Safariのために複雑な回避策を入れ続けるより、「これはChromeで使うもの」と割り切ったほうが保守が楽です。
開発秘話6:「眺めるだけのツール」になりかけた
ある時期にスタッフからフィードバックをもらいました。
「なんというか、何の成果のために、どういう状態に持っていきたいから、そこまでに何をすればいいか、がわかるツールがありがたいです。SEOの知識がない若手スタッフが何したらいいか、直感的にわかるようなUIだと嬉しい」
確かに、と思いました。スコアや数字を並べても「で、何をすればいいの?」になる。
そこで「アクションリスト」タブを追加しました。課題を優先度別に並べて、それぞれに「なぜ問題か」「対応方法」「改善すると何が起きるか」を添えた形式にしました。
🔴 今すぐ対応
/contact/ がnoindex設定されています
→ このままでは検索結果に一切表示されません
→ WordPress管理画面 > 固定ページ > お問い合わせ >
「検索エンジンに表示しない」のチェックを外してください
→ 設定を外すと数週間〜1ヶ月でインデックスされ始めます
meta descriptionの課題には「AIで文章を生成」ボタンも付けて、ボタン1つで3パターンの候補文が出てくるようにしました。
「情報を見るツール」から「行動につながるツール」に変えた、という体験でした。
「AIがやる」という話の正直なところ
最初の構想では「エラーが出たらAIが自動修復する」機能も考えていました。
設計段階でやめました。
WP更新後のエラーパターンはほぼ3種類しかありません。それをif文で書いたほうが速くて確実で、AIに毎回APIコールするより遥かにシンプルです。
「AIが判断する」べき場面は、実は思ったより少ない。AIが本当に得意なのは非構造な文章生成で、「スコアと数字から所見を書く」「課題の説明と改善案を生成する」この2点でした。
今のAI Guardianで、AIが担当しているのはこの2点だけです。スキャン・クロール・データ取得・レポート生成の仕組みそのものは、シェルスクリプトとPHPとPythonで動いています。
数字で振り返る
開発にかかった時間: 実質2〜3日(Claudeとの対話形式で進行)
主なコスト:
- Anthropic API(従量課金)
- 月次レポート5〜10サイト分の所見生成で数十円レベル
構成ファイル数: 8ファイル
動作環境: エックスサーバー共用サーバー(特別なインフラ不要)
実際に見つかった課題(hgr.jp):
- /contact/ にnoindexが設定されていた(検索結果に出ない状態だった)
- SCデータで「表示1,280回・CTR2.0%・順位19.8位」という具体的な数字が可視化された
- ブログ・制作実績ページにmeta descriptionが未設定だった
やってみてわかったこと
1. 「AIが全部やる」より「AIが得意なことだけやる」が正解だった
ルールベースで解決できるものにAIを使うのはコスト的にも合わない。「なぜこのページのスコアが低いか、どう改善すればいいか」という説明を生成するところだけ、AIでなければ難しい作業になっています。
2. ツールは「見せる」だけでなく「動かせる」ようにする
スコアと課題の一覧を出しても、「で、自分は何をすれば?」という疑問が残ります。アクションリストを作って初めて、スタッフが一人で動けるようになりました。情報量より、行動までの距離を縮めることの方が大事でした。
3. 制約が設計をシンプルにすることがある
エックスサーバーでpipが使えないという制約から、標準ライブラリのみで動くスキャナーを作りました。依存ライブラリがゼロなので、バージョン問題が起きません。これは制約がなければ選ばなかった設計です。
4. 思い込みで「できない」と判断しない
「共用サーバーだから重い処理は無理」と最初は思っていました。実際に試したら、85分かかるスキャンもバックグラウンド実行で問題なく動きました。測る前に諦めない。
おわりに
「AIにWP保守をやらせる」という話から始まりましたが、作ってみるとAIが担当しているのは所見の文章生成だけという結論になりました。
それでも価値はあって、「毎月クライアントに送るレポートの文章を手で書く必要がなくなった」という変化は実際に大きいです。数字は自動で集まって、所見はAIが書いて、担当者は確認と送付だけでいい。
保守という作業が「やらないといけない仕事」から「提案の入口」に変わりつつあります。
まだPageSpeedの連携やキーワード分析など実装したい機能があります。Claude Codeを使いながら少しずつ進めていく予定です。
タスク管理ツールや検品ツールの開発話も書いているので、よければ読んでみてください。
WordPressの保守・運用や、サイトのセキュリティ・SEO状態が気になる方は、お気軽にご相談ください。
