年別アーカイブ 2026年7月23日

Events ManagerでGutenbergのイベントが公開できない時の直し方

Events ManagerでGutenbergのイベントが公開できない時の直し方

Events ManagerをGutenberg編集モードで使っているときに新規イベントが公開できず、クラシックエディタでは問題なく動作する場合、プラグインのバージョンが7.3.1〜7.3.4のいずれかであることが主な原因だ。7.3.5以降へアップデートすると修正される。

どんな操作をしたときに発生するのか

どんな操作をしたときに発生するのか

Gutenbergモードを有効にしたEvents Managerで新規イベントを作成する。すべての項目を入力して「公開」ボタンを押しても、画面が再読み込みされステータスが「下書き」のままになり、公開状態に切り替わらない。一方でクラシックエディタに切り替えると、同じ内容でも問題なく公開できるという状況だ。

この現象は、WP標準テーマ(Twenty Twenty-FourやTwenty Twenty-Five)に切り替えても、他のプラグインをすべて無効化しても変わらない。Events Manager側のGutenberg統合部分にバージョン固有の不具合が存在しているために起きる。

公開ボタンが反応しない直接の原因は何か

公開ボタンが反応しない直接の原因は何か

Events Managerのバージョン7.3.1から7.3.4には、Gutenbergエディタ上でイベントを保存する際に走るバリデーション(検証)処理に問題がある。具体的には、イベントの必須項目が正しく入力されていても内部的な検証に失敗し、「公開」操作が受理されない状態になる。

とくに繰り返しイベント(定期的な開催設定)を扱う場合、「Main recurrence set times are required(メインの繰り返し時刻設定が必要です)」という趣旨の検証エラーが返され、公開をブロックされるケースが報告されている。このバリデーションエラーは管理画面の見た目には表示されず、ブラウザの開発者ツール上で確認できる。

エラー状態 Gutenbergでイベントを保存しようとする
↓
内部処理 EMのバリデーションAPIが検証失敗を返す(7.3.1〜7.3.4の不具合)
↓
結果 ステータスが「下書き」のまま公開されない
■ 公開に失敗する流れ(Events Manager 7.3.1〜7.3.4)

このデモが示すように、エディタの見た目上は正常に操作しているのに、プラグイン内部のAPI応答が原因で公開処理が止まる。Events Manager 7.3.5でこのバリデーション不具合が修正されている。

Events Managerを最新版にアップデートして修正する

Events Managerを最新版にアップデートして修正する

最も確実な解決策は、Events Managerをバージョン7.3.5以降にアップデートすることだ。管理画面から数ステップで完了する。

STEP 1 WordPress管理画面で「ダッシュボード」→「更新」を開く
↓
STEP 2 Events Managerに更新がある場合「プラグイン」一覧から更新する
↓
STEP 3 更新後、Gutenbergで新規イベントを作成し公開できるか確認する

サイトの運用途中でアップデートをためらう場合は、まずステージング環境(テスト用の複製サイト)でアップデート後の動作を確認すると安全だ。近年の国内レンタルサーバーでは、管理パネルからワンクリックでステージング環境を作成できるものも多い。

すぐに公開したい場合の一時的な回避策

すぐに公開したい場合の一時的な回避策

プラグインのアップデートが何らかの理由ですぐにできない場合、以下の回避策で公開できることがある。

  • 公開ボタンを2回以上連続でクリックする。1回目でいったん下書きとして保存され、2回目以降のクリックで公開状態に切り替わるケースが報告されている。
  • イベント編集画面の「Events Manager」設定パネルで、Gutenbergモードを無効にしてクラシックエディタを使う。クラシックエディタでは問題なく公開できる。

これらの回避策は、あくまでアップデート前の応急処置として使う。根本的には7.3.5以降へのアップデートが必要だ。

アップデート後も繰り返しイベントでエラーが出る場合の対処

アップデート後も繰り返しイベントでエラーが出る場合の対処

7.3.5以降でも、繰り返しイベントの設定時にまれに「Main recurrence set times are required(メインの繰り返し時刻設定が必要です)」という趣旨のバリデーションエラーが表示されることがある。このエラーは、繰り返し設定の中核となる日時情報がバリデーションAPIに正しく渡っていない場合に発生する。

まず試すべきは、繰り返し設定を一度クリアして再入力することだ。とくに開始日時と終了日時、および繰り返しパターンの「初回の日時」が空欄になっていないか確認する。カスタムコードでGutenberg有効化を制御していた場合は、そのコードが完全に削除されているかも確認する。残留したコードがAPI通信に干渉している可能性がある。

よくある質問

Events ManagerのGutenbergモードはどこで切り替えられるか

管理画面の「Events」→「設定」→「管理画面」タブにある「イベントエディタの種類」で切り替えられる。ここで「Gutenberg」を選択するとブロックエディタが有効になり、「クラシックエディタ」を選ぶと従来の編集画面に戻る。

Gutenberg有効化のカスタムコードが原因になることはあるか

過去にfunctions.phpなどへ追加したGutenberg有効化コードが削除されずに残っていると、プラグインの設定と競合して予期しない動作を起こす可能性がある。コードが完全に削除されているか、もしくはコメントアウトされているか確認する。

公開ボタンを押しても何も反応しない場合はどうすればよいか

ブラウザの開発者ツール(F12キー)の「コンソール」タブにJavaScriptエラーが表示されていないか確認する。別のプラグインがGutenbergと競合してJavaScriptエラーを起こしている場合、それが原因で公開処理が止まることがある。

クラシックエディタでは問題ないのにGutenbergだけ不具合が出る理由は何か

GutenbergはREST APIを介してデータを保存する仕組みをとっている。Events Managerのバリデーション処理も、GutenbergモードではAPI経由で実行される。クラシックエディタの場合は異なる保存経路を使うため、API側の不具合の影響を受けずに公開できる。

7.3.5はいつリリースされたのか

Events Manager 7.3.5は2026年7月下旬にリリースされ、本件のGutenberg公開不具合が修正されている。管理画面の更新通知から適用できる。

この記事のポイント

  • Events Manager 7.3.1〜7.3.4のGutenbergモードには公開できない不具合がある
  • 7.3.5以降へアップデートすると修正される
  • アップデートできない場合は公開ボタンの複数回クリックやクラシックエディタで一時回避できる
  • 繰り返しイベントでの検証エラーは設定の再入力で直ることが多い
  • 過去のカスタムコードが競合していないか確認することも大切だ
WordPressテーマのアクセシビリティ対応、思ったより簡単な理由

WordPressテーマのアクセシビリティ対応、思ったより簡単な理由

アクセシビリティ対応を難しく感じる本当の理由

アクセシビリティ対応を難しく感じる本当の理由

WordPressテーマのアクセシビリティ対応に取り組もうとした開発者の多くが、最初の段階でつまずくポイントがある。WordPress.orgのテーマリポジトリで「accessibility-ready」タグを取得するための要件文書だ。WP TavernのポッドキャストでJessica Lyschik氏が指摘したように、この要件文書は初めて読む人にとって「暗号的」に映りがちだ。

問題の核心はドキュメントの書き方にある。要件には「こうあるべき」という達成目標と簡単なテスト手順は書かれているが、具体的にどのような技術的実装をすればよいのかが明示されていない。例えば「適切なHTML5タグを使用すること」という趣旨の要件があっても、header、footer、main、section、asideの各タグをどう配置すべきかまでは書かれていない。

Lyschik氏自身もこの問題を実感した一人だ。彼女が管理するテーマを新要件に合わせて見直した際、アクセシビリティの知識を何年も積んできた自分ですら「なるほど、こういう意味だったのか」と再確認する場面があったという。ましてやアクセシビリティに初めて触れる開発者にとっては、抽象的な要件と実際のコードを結びつけること自体が大きな障壁になる。アクセシビリティは「難しい」のではなく、「何をすればいいかが分かりにくい」分野なのだ。

現在のドキュメント(Before)
「テーマは適切なHTML5セマンティック要素を使用しなければならない」
■ 要件は分かるが実装方法が不明
↓
理想的なドキュメント(After)
「テーマは適切なHTML5セマンティック要素を使用しなければならない。headerタグはサイトのヘッダー部分に、mainタグは主要コンテンツに、footerタグはフッターに使用する。ブロックテーマではグループブロックにmainのHTMLタグを割り当てることで対応できる」
■ 具体的なHTMLタグ名と設定方法が明示されている
※Lyschik氏はRian Rietveld氏らと協力し、このギャップを埋めるドキュメント改善に取り組む意向を示している

Lyschik氏がWordCamp Europe 2026のセッションで伝えたかったのは、まさにこの点だ。要件文書の「行間」に埋もれた実装知識を言語化し、開発者が自信を持ってアクセシビリティに取り組めるようにすること。ドキュメント改善は現在進行形の課題だが、基本的なHTMLとCSSの知識があれば、大半の要件は想像よりはるかに簡単にクリアできる。

今日から実践できる3つの具体的な改善策

今日から実践できる3つの具体的な改善策

WP TavernのインタビューでLyschik氏は「ロー・ハンギング・フルーツ(手の届きやすい果実)」という表現を使った。大きな努力をしなくてもすぐに成果が出る、アクセシビリティ改善の第一歩が確かに存在する。以下は彼女が実際に推奨する3つの即効性のある施策だ。

画像の代替テキストを省略しない

最も基本的かつ効果が大きいのが代替テキスト(alt属性)の付与だ。WordPressのメディアライブラリには代替テキストを入力するフィールドが標準で用意されている。ブロックテーマなら画像ブロックを選択するだけで、サイドバーにaltテキスト入力欄が表示される。目の前にある入力欄を飛ばさずに埋めるだけの作業で、スクリーンリーダーユーザーやAIエージェントに画像の意味を伝えられる。

正しいHTMLタグの選択とスキップリンクの設定

ブロックテーマでは、HTMLタグの割り当てが驚くほど簡単になっている。コンテンツ全体をグループブロックで囲み、そのグループに「main」のHTMLタグを設定するだけで、WordPressがスキップリンク(Skip to Content)を自動生成する。このスキップリンクは、キーボード操作ユーザーが毎回ヘッダーメニューを通過せずに、直接本文へジャンプできる重要な導線だ。

クラシックテーマでは手動で実装する必要があったこの機能も、ブロックテーマなら数クリックで完了する。テンプレートパーツのheader/footerも適切に割り当てれば、Coreが自動で正しいHTML構造を出力してくれる。

本文中のリンクには下線を付ける

本文中のリンクテキストに下線を付けることは、CSS1行で実現できる変更だ。Lyschik氏は「text-decoration: underline; の1行を追加するだけ」と表現している。色だけに依存したリンク識別は、色覚特性のあるユーザーやコントラストが低下した環境で機能しなくなる。特にWCAG(Web Content Accessibility Guidelines)が要求するコントラスト比を満たす設計では、下線による補助表示が欠かせない。

アクセシビリティ非対応(Before)
詳しくはこちらの記事をご覧ください。
■ 色の違いだけでリンクを識別。色覚特性によっては本文と区別できない
↓
アクセシビリティ対応(After)
詳しくはこちらの記事をご覧ください。
■ 下線付きで色に依存しないリンク識別が可能

Lyschik氏が強調するのは「最初から組み込む」ことの重要性だ。後から数百ページにわたってボタンのaria-labelを修正する作業を想像してみてほしい。彼女の同僚が実際に経験した「12箇所×2種類のボタン」修正は、事前に対応していれば5分で済んだはずの作業だった。あとから修正するコストは、最初に対応する手間と比べて指数関数的に増大する。

ブロックテーマが変えるアクセシビリティの常識

ブロックテーマが変えるアクセシビリティの常識

WordPressのテーマ開発はクラシックテーマからブロックテーマへと大きな転換点を迎えている。アクセシビリティの観点から見ると、この移行は単なるトレンドではなく、根本的な実装難易度の低下をもたらしている。

Coreが肩代わりするようになった処理群

ブロックテーマで最も大きな変化は、WordPress Core(コア)がアクセシビリティ対応の多くを自動処理するようになった点だ。Lyschik氏が具体的に挙げた例をいくつか紹介する。

Coreが自動処理する主な項目
スキップリンク mainタグ設定で自動生成
フォームラベル コメント・検索フォームで標準対応
HTML5セマンティクス テンプレートパーツ割り当てで自動出力
■ 開発者が設定すべきこと ■ Coreが自動処理すること

特筆すべきは検索フォームとコメントフォームの扱いだ。クラシックテーマではフォームのラベル設定やエラー処理をテーマ開発者が実装する必要があったが、ブロックテーマではCoreがこれを完全に引き受けている。テーマ開発者はブロックを配置するだけで、自動的にアクセシブルなフォームが出力される。

既存テーマの構造をテンプレートとして再利用する

Lyschik氏が提案する効率的なアプローチは、アクセシビリティ対応済みのテーマからテンプレート構造をコピーすることだ。新しいテンプレートを作成する際、ゼロから設計するのではなく、すでに正しいHTML構造を持つ既存テンプレートを複製して色やレイアウトだけを変更する。これにより、header、main、footerのタグ割り当てが自動的に継承され、意図せずアクセシビリティを損なうリスクを回避できる。

この手法の前提として「どのテーマが正しくアクセシビリティ対応されているか」の知識が必要になるが、WordPress.orgテーマリポジトリで「accessibility-ready」タグを取得しているテーマ(現在約270テーマ、全体の1.5%程度)が信頼できる参照先となる。

AIエージェントが変えるアクセシビリティの優先順位

AIエージェントが変えるアクセシビリティの優先順位

インタビューの中でLyschik氏が特に強調したのが、AIエージェントの台頭がアクセシビリティの重要性を根本的に変えつつあるという洞察だ。この視点は、従来の「障がい者支援」という枠組みを超えて、アクセシビリティをビジネス上の競争力として再定義する可能性を秘めている。

AIエージェントは「見た目」ではなく「構造」を読む

Lyschik氏がAnne-Mieke Bovelett氏から共有されたという資料では、AIエージェントとスクリーンリーダーの動作原理が本質的に同じであることが指摘されている。AIエージェントはWebサイトを人間のように「視覚的」に理解するわけではない。HTMLの構造、適切なタグ、正確なラベル付けに依存して情報を取得し、操作を実行する。

AIエージェントがECサイトで買い物をする流れ
STEP 1 ユーザーがAIに「コーヒー豆を1kg購入して」と指示
↓
STEP 2 AIエージェントがECサイトのHTML構造を解析
↓
STEP 3 適切なラベル付きボタンを検出 → カートに追加 → チェックアウト
↓
STEP 4 購入完了。不適切な構造のサイトではこの操作が途中で失敗する
■ アクセシビリティ非対応サイト:AIエージェントが操作に失敗し、販売機会を喪失
■ アクセシビリティ対応サイト:AIエージェントがスムーズに取引を完了

Googleが2026年6月に発表したドキュメントでも、AIエージェント向けのアクセシビリティに注力する方針が示されている。これは単なる技術的関心ではなく、ECサイトの将来像に直結する話だ。ユーザーが直接ブラウザを操作せず、AIエージェントに「コーヒー豆を購入して」と依頼する世界では、アクセシビリティ対応の有無が売上に直結する。

アクセシビリティは「コスト」ではなく「投資」になる

Lyschik氏が言及したAnne-Mieke Bovelett氏の事例では、ある企業がWebサイトのアクセシビリティ改善に取り組んだ結果、売上が実際に増加したという。この事例が示すのは、アクセシビリティ対応が単に「法的リスクの回避」や「道徳的義務」という枠を超えて、ビジネス成果に寄与するという事実だ。

AIエージェントの普及はこの傾向を加速させるだろう。適切に構造化されたHTML、明確なラベル付け、正しいフォーム処理を持つWebサイトは、AIエージェントによる自動操作の信頼性を高める。2025年以降、この「AIフレンドリー」な設計がECやサービスサイトの競争優位性を左右する可能性は高い。

最初から組み込むアクセシビリティの設計思想

最初から組み込むアクセシビリティの設計思想

Lyschik氏が一貫して訴えているのは「アクセシビリティは後付けの修正ではなく、設計段階から組み込むべきもの」という原則だ。彼女自身の経験と、同僚が直面した「24回のaria-label追加作業」のエピソードが、この主張を裏付けている。

ボタンのaria-label追加に見る「後付けの代償」

インタビューで紹介された実例がある。クライアントのアクセシビリティテストで、アイコンのみのボタン(電話アイコンなど)がスクリーンリーダーで機能しないと指摘された。アイコンだけでは「このボタンが何をするのか」を読み上げられないからだ。修正にはaria-label属性を追加するだけで済むが、問題はその数だった。12箇所×2種類のボタン、合計24回の手動修正が必要になった。

Lyschik氏はこの経験を「設計時にaria-labelを追加しておけば5分で終わっていた作業」と総括する。テーマやサイトの構築時にアクセシビリティを考慮していれば、後から数百ページにわたって同じ修正を繰り返す必要はなかったはずだ。

学際的な意識共有が不可欠

アクセシビリティは開発者だけの責任ではない。Lyschik氏は「interdisciplinary(学際的)」という言葉を使い、SEO担当者、コンテンツ制作者、デザイナーを含む全ての関係者が基本的な知識を持つべきだと指摘する。

各ロールに求められるアクセシビリティ知識
開発者 HTML構造、WAI-ARIA、フォームのラベル付け、スキップリンク実装
デザイナー コントラスト比(WCAG AA基準は4.5対1以上)、フォーカス表示の設計
コンテンツ制作者 正しい見出し階層(H1→H2→H3の順序)、代替テキストの記述
SEO担当者 アクセシビリティ対応が検索エンジン評価にも影響する構造的理解
見出しの階層を飛ばす(H2の次がH6になる)ことは、スクリーンリーダーユーザーに混乱を招き、SEO上もマイナス評価となる。正しい階層構造の維持は、全ロールに関わる共通ルールだ。

見出しタグ(H1〜H6)の正しい階層構造は、その典型的な例だ。H1の下にH2、その下にH3という順序を守ることは、スクリーンリーダーユーザーの文書理解を助けるだけでなく、検索エンジンのコンテンツ解析精度にも影響する。SEOとアクセシビリティは、しばしば同じ方向を向いている。

この記事のポイント

  • アクセシビリティ対応の難しさは「技術そのもの」ではなく「ドキュメントの分かりにくさ」に起因している
  • 画像の代替テキスト入力、正しいHTMLタグ割り当て、リンク下線付与は今日から着手できる即効性の高い施策だ
  • ブロックテーマではスキップリンクやフォームラベルなど、Coreがアクセシビリティ処理を大幅に肩代わりする
  • AIエージェントの普及により、アクセシビリティ対応はECサイトの売上やビジネス成果に直結する要素になりつつある
  • 設計段階からの組み込みが、後工程での膨大な修正作業を回避する最も効率的なアプローチだ
WooCommerce 11.0で失敗注文の在庫が自動復元へ、変更点と対応を解説

WooCommerce 11.0で失敗注文の在庫が自動復元へ、変更点と対応を解説

WooCommerce 11.0で、注文が「失敗」ステータスに移行した際の在庫処理に変更が入った。従来、注文が在庫を減らした後に「失敗」になると在庫が戻らなかったが、今後は自動で在庫が復元されるようになる。

この変更はほとんどのストアにとっては歓迎すべき改善だが、一部のカスタムフローでは注意が必要だ。ここでは変更の具体的な内容と、開発者が取るべき対応を整理する。

具体的に何が変わったのか

具体的に何が変わったのか

この変更の核心はシンプルだ。WooCommerce 11.0以降、注文ステータスが「失敗(failed)」に移行したとき、その注文が以前に在庫を減らしていた場合、自動的に在庫が復元されるようになる。

技術的には、woocommerce_order_status_failedフックにwc_maybe_increase_stock_levels()関数が登録された。この関数は、注文が以前に在庫を減らしていたかどうかを確認した上で在庫を戻す処理を行う。

WooCommerce 11.0 より前の挙動
保留中 在庫を減らす → 失敗 → 在庫は戻らない
保留中 在庫を減らす → キャンセル → 在庫が復元される
■ 失敗は在庫復元の対象外だった
↓
WooCommerce 11.0 以降の挙動
保留中 在庫を減らす → 失敗 → 在庫が復元される
保留中 在庫を減らす → キャンセル → 在庫が復元される(従来通り)
■ 失敗も在庫復元の対象に追加

上記の図で示したように、WooCommerce 11.0では「失敗(failed)」がキャンセルや保留中と同様に在庫復元の対象へと引き上げられた。

なぜこの変更が必要だったのか

この問題は非同期決済で顕在化しやすかった。たとえば、顧客が支払いを開始すると注文は「保留中(on-hold)」に移行し、その時点で在庫が減る。しかし、何らかの理由で決済が拒否され、注文が「失敗(failed)」になると、在庫だけが減ったまま戻らなかった。

結果として、実際には販売できていないにもかかわらず、在庫数だけが減った状態が続いていた。特に在庫が1点ものの商品を扱うストアでは、実害の大きい挙動だったと言える。今回の変更で、このギャップが解消される。

在庫の二重減算は起こらないのか

wc_maybe_increase_stock_levels()関数は、注文が実際に在庫を減らしたかどうかをフラグで確認してから在庫を戻す。そのため、在庫を減らしていない注文が「失敗」になった場合には在庫は変動しない。

また、管理者や拡張機能が「失敗」から再度「支払い済み」などのステータスに戻した場合、WooCommerceは以前の履歴を参照して二重に在庫を減らすことはないよう設計されている。

この変更はチェックアウト時の在庫予約機能には影響しない。あくまで在庫を実際に減らした注文が対象だ。

どのようなストアや拡張機能が影響を受けるか

どのようなストアや拡張機能が影響を受けるか

大多数のストアや拡張機能にとっては、今回の変更はそのまま歓迎すべき改善だ。決済失敗時に在庫が正しく戻るようになることで、手動での在庫修正が不要になる。

しかし、一部のカスタムフローでは注意が必要だ。具体的には、「失敗(failed)」ステータスを支払い以外の目的で流用しているケースである。たとえば、配送失敗時に注文を「失敗」としてマークしつつ、商品はすでに発送済みで在庫を確保しておきたい、といったフローだ。

こうしたストアでは、WooCommerce 11.0にアップデートすると、注文が「失敗」に移行した瞬間に在庫が復元されてしまい、意図しない在庫の増加が発生する。

開発者が取るべき対応

開発者が取るべき対応

基本的には対応不要

まず前提として、決済の失敗にのみ「失敗」ステータスを使っているストアや拡張機能では、何も対応する必要はない。アップデート後、自動的に在庫が正しく処理される。

意図的に在庫を減らしたままにしたい場合

もし拡張機能やストアが「失敗」ステータスを支払い以外の目的で使用しており、在庫を減らしたままにしておく必要があるなら、以下のコードで新しい在庫復元フックを削除すればよい。

remove_action( 'woocommerce_order_status_failed', 'wc_maybe_increase_stock_levels' );

ただし、これはあくまで「旧来の挙動を維持する明確な理由がある場合」に限るべきだ。ほとんどのストアでは、在庫が自動で復元される新しい挙動のほうが望ましい。

アップデート前のテスト事項

アップデートを配信する前に、以下の項目を実環境に近いステージング環境でテストすることを強く推奨する。

  • 「保留中」→「失敗」のフローで在庫が正しく復元されること
  • 「失敗」→「処理中」→「完了」のフローで在庫が二重に減算されないこと
  • カスタムフローで「失敗」ステータスを使っている場合、在庫数と注文メモが意図した通りになっていること

特に、非同期決済を利用しているストアでは、「保留中」で在庫が減った後、決済拒否で「失敗」に移行した際の挙動を重点的に確認しておくと安心できる。

この記事のポイント

  • WooCommerce 11.0では、注文が「失敗(failed)」に移行した際に在庫が自動復元される
  • 従来は「キャンセル」「保留中」のみが復元対象で、「失敗」は対象外だった
  • ほとんどのストアは対応不要で、むしろ在庫管理が正確になるメリットがある
  • 「失敗」ステータスを支払い以外で流用しているストアは、フック削除で旧来の挙動に戻せる
  • アップデート前には必ずステージング環境で在庫の動きをテストすること
LiteSpeed Cacheでパージ成功してもキャッシュが残る原因と直し方

LiteSpeed Cacheでパージ成功してもキャッシュが残る原因と直し方

LiteSpeed Cacheで管理画面やWP-CLIから「Purge All(全キャッシュ削除)」を実行し成功メッセージが出ているにもかかわらず、公開ページがいつまでも古い内容のまま更新されない場合、プラグインのキャッシュ制御と実際に動作しているサーバーレベルのキャッシュ層との間に不整合が起きている可能性が高い。根本的には、LSCacheプラグインの設定最適化と、場合によってはプラグインを一時的に無効化しての強制リフレッシュが有効な解決策になる。

なぜ「全削除」に成功してもキャッシュが残り続けるのか

なぜ「全削除」に成功してもキャッシュが残り続けるのか

LiteSpeed Cacheのキャッシュ構造は多層的で、プラグインの管理画面と実際のキャッシュストレージが常に一対一で対応しているとは限らない。管理画面で「Purge All」を実行すると、プラグインは内部的にパージタグを生成し、LSWS(LiteSpeed Web Server)に対してキャッシュ削除の指示を出す。ここで成功メッセージが返ってくるのは、あくまで「指示が出せた」という意味であり、ディスクやメモリ上の実ファイルが完全に消えたことの保証にはならない。

まず試すべきプラグイン側の設定見直し

まず試すべきプラグイン側の設定見直し
修正前の状態
パージを実行しても、レスポンスヘッダーに x-litespeed-cache:hit が返ってくる。
x-litespeed-cache: hit
x-litespeed-cache-control: no-cache
↓
修正後の状態
キャッシュヘッダーが miss になり、サーバーが動的生成に切り替わった。
x-litespeed-cache: miss
■ キャッシュヒットして古い内容が表示される  ■ キャッシュミスで最新の内容が表示される

キャッシュ有効期限とブラウザキャッシュ設定の確認

まず、LSCacheプラグインの「キャッシュ」タブでTTL(Time To Live、キャッシュの有効期限)が極端に長く設定されていないか確認する。デフォルトは604800秒(1週間)だが、公開ページの更新頻度が高いサイトでは3600秒(1時間)程度に短くすることで、パージ操作の効果が出やすくなる。また「ブラウザキャッシュ」タブで、ブラウザ側のキャッシュ保持期間が長すぎると、サーバーのパージ後もユーザーのローカルキャッシュが優先されて古い表示になる。短期間に設定するか、問題切分け中は一時的に無効化(オフ)にする。

オブジェクトキャッシュとRedisの影響を見極める

RedisやMemcachedといった外部オブジェクトキャッシュを使っている環境では、LSCacheがページキャッシュを削除しても、データベースクエリの結果がオブジェクトキャッシュに残り、結果として同じ古い情報でページが再生成される。Redisを使っているなら、管理画面の「LiteSpeed Cache」→「オブジェクトキャッシュ」でステータスを確認し、「Purge Object Cache」を手動で実行する。それでも直らない場合は、問題の切分けとしてredis-cacheやRedis Object Cacheプラグイン自体を一度無効化し、LSCacheだけの状態でパージを試す。

サーバーレベルで強制的にキャッシュを削除する手順

プラグインの操作で改善しない場合、LiteSpeed Web Serverが保持しているキャッシュをOSレベルで手動削除する。特に、LSCacheプラグインが生成したキャッシュ情報と、LSWSの内部キャッシュマップがずれてしまった場合に有効だ。

サーバーレベルの強制キャッシュクリア手順
STEP 1 SSHでサーバーにログインし、LSWSのキャッシュディレクトリを特定する
↓
STEP 2 LSWSを完全停止し、スワップファイルとキャッシュファイルをすべて削除する
↓
STEP 3 LSWSを起動し、LSCacheプラグインの「Purge All」を再度実行する
↓
STEP 4 ブラウザのシークレットモードで動作を確認する

ディスクキャッシュの格納場所と削除コマンド

SSHでサーバーに接続し、まずLSWSのキャッシュパスを特定する。デフォルトでは /tmp/lshttpd/ または /usr/local/lsws/cachedata/ 以下にキャッシュが格納されている。LSCacheプラグインの「CDN/キャッシュ設定」にある「キャッシュルートパス」を確認すると確実だ。

次に、LSWSを完全に停止する。systemctl restart lsws や管理画面からのグレースフルリスタートではプロセスがクリアされず、内部のキャッシュマップが生き残る。以下の手順で、キャッシュディレクトリを物理的に空にしてから再起動する。

# LSWSを完全停止
/usr/local/lsws/bin/lswsctrl stop

# キャッシュディレクトリとスワップを完全に削除
rm -rf /tmp/lshttpd/swap/*
rm -rf /tmp/lshttpd/cache/*

# LSWSを起動
/usr/local/lsws/bin/lswsctrl start

起動後、WordPress管理画面からLSCacheの「Purge All」を実行し、ブラウザのシークレットウィンドウ(または開発者ツールでキャッシュを無効化した状態)で動作を確認する。x-litespeed-cache ヘッダーが miss になっていれば成功だ。

どうしても治らない場合の一時的切り分け

上記の手順を実行しても、ベアURL(パラメータなしの通常アクセス)だけが古いキャッシュを返し続ける場合、LSCacheプラグイン自体がリクエスト段階でキャッシュの再取得を意図せず阻害している可能性が高い。この状況は、特定の条件下でLSCacheプラグインがブラウザやリバースプロキシに強力なCache-Controlヘッダーを設定し、サーバー側でミスになってもCDNやブラウザが古いデータを返し続けるケースだ。

最終的な切分けとして、LSCacheプラグインを5分〜10分間だけ完全に無効化する。無効化後に即座にキャッシュが更新されるなら、LSCacheプラグインの内部ロジックまたは設定が主因であると特定できる。プラグインを再有効化した後、デフォルト設定へのリセットや、問題を再現させた設定項目を一つずつ絞り込む。

よくある質問

クエリ文字列を付けるとキャッシュがバイパスされる理由は?

LiteSpeed Cacheは、URLにパラメータ(?=xxx)が付与されたリクエストを、デフォルトでキャッシュ対象外とみなす。そのためベアURLでは x-litespeed-cache:hit で古いキャッシュが返っているのに、/?v=2 のような文字列を付けると miss となり、動的に生成された最新ページが表示される。

サーバーを再起動できない共有サーバーではどう対処すればよいか

多くの共用サーバーではSSHやLSWSの制御権限が制限されている。この場合、LSCacheプラグインの「ツールボックス」→「Purge All」を実行し、即座にプラグインを無効化する。その後「LiteSpeed Cache」を再有効化し、デフォルト設定へのリセットを試す。サーバー側のキャッシュディレクトリに触れない環境では、この手順が最も確実な強制リセットになる。

パージ後のキャッシュ再生成を防ぎたい場合の設定は?

公開前のプレビューや検証でキャッシュを完全に止めたい場合、LSCacheプラグインの「キャッシュ」→「キャッシュを有効化」のトグルを一時的にオフにする方法が最も確実だ。ただしこの設定はサイト全体のパフォーマンスに影響するため、検証後は必ずオンに戻し、特定のページだけ除外したい場合は「URI 除外」機能を使う。

この記事のポイント

  • LSCacheのパージ成功表示が実キャッシュ削除の保証にはならない
  • サーバーレベルでディスクキャッシュを直接削除すると治るケースが多い
  • Redisなどの外部オブジェクトキャッシュも同時に削除する必要がある
  • クエリ文字列でバイパスされる現象はLSCacheの正常動作だが、ベアURLが古いのは異常
  • どうしても治らなければ、プラグインの一時無効化で原因をLSCacheに特定できる
Google LSAがGoogle広告に統合、2026年8月から段階移行へ

Google LSAがGoogle広告に統合、2026年8月から段階移行へ

GoogleがLSA(Local Services Ads / ローカルサービス広告)の管理画面をGoogle広告に統合する。2026年8月から一部の米国広告主を対象に移行が始まり、2027年にかけて段階的に拡大される予定だ。

移行後はGoogle広告内でキャンペーン管理やリード対応が完結する。ただし入札方式やレポートの扱いが変わるため、事前の準備が欠かせない。本記事では移行のスケジュールや変更点、広告主が取るべき対応を3つのポイントに絞って解説する。

LSAのGoogle広告統合で何が変わるのか

LSAのGoogle広告統合で何が変わるのか

LSA(ローカルサービス広告)は、もともとGoogle検索やマップの上部に表示される問い合わせ獲得型の広告だ。ユーザーが「近くの電気工事業者」などと検索すると、電話やメッセージでのリード獲得を主目的とした事業者一覧が表示される仕組みである。

今回の統合により、LSAはGoogle広告の管理画面から操作する形へと一本化される。従来のLSA専用ダッシュボードは廃止され、キャンペーンの作成からリード対応までをGoogle広告内で処理できるようになる。

移行スケジュールは2026年8月から段階的に

Googleが公開したスケジュールによると、最初の移行対象は米国の一部広告主であり、ペットケアやホームサービス、ウェルネス、教育関連の業種が含まれる。2026年8月にこの第1陣の移行が始まり、同年後半に米国内の対象が拡大される見込みだ。

米国以外のアカウントや残りの業種については2027年に対応が進む。アカウント管理者には移行の14日前と7日前に通知が届き、移行完了時にも確認の連絡があるため、突然ダッシュボードが使えなくなる事態は避けられる。

現在のLSA管理フロー(変更前)
LSAダッシュボード キャンペーン設定
↓
GBP管理画面 ビジネス情報の更新
↓
LSA受信箱 リード対応
※複数の管理画面にまたがるため情報の更新漏れが生じやすい
↓
Google広告統合後(変更後)
Google広告 キャンペーン設定とビジネス情報の一元管理
↓
Google広告 Lead Manager リード対応
※1つのインターフェースで管理業務が完結する
■ 変更前の分散管理  ■ 統合後の一元管理

管理フローの一元化によって作業負荷は減る一方で、従来のLSA専用画面に慣れた事業者や代理店には操作変更への対応が求められる。

新しいLSAキャンペーンの仕組み

新しいLSAキャンペーンの仕組み

統合後のLSAは、Google広告のP-MAX(Performance Max)キャンペーンとして配信される。ただし名称こそP-MAXだが、配信面や課金方式は従来のLSAと変わらない点に注意が必要だ。

配信面と課金方式は変更なし

LSAは今後もキーワードの入札なしで、Google検索とマップにのみ表示される。クリック課金ではなく、電話、メッセージ、予約といった有効リードに対して料金が発生する仕組みも維持される。P-MAXと聞くとディスプレイ広告や動画広告まで配信対象が広がるイメージがあるが、LSAの場合はあくまで検索とマップに限定される形だ。

Google広告内で完結するキャンペーン管理

広告主はGoogle広告の管理画面でLSAキャンペーンの設定、リードの確認、返信をすべて行えるようになる。従来のLSA専用ダッシュボードは移行後に利用できなくなるため、操作に不慣れな場合は早めにGoogle広告の画面構成を確認しておくとスムーズだ。

キャンペーン管理で変わる5つのポイント

キャンペーン管理で変わる5つのポイント

統合に伴い、予算の考え方や入札、レポートの扱いが一部変更される。Search Engine Journalの記事で挙げられた主な変更点を整理する。

現在のLSA設定(Before)
予算は週単位で管理
手動入札でリード単価の上限を設定できる
サービスカテゴリ別に目標CPAを設定可能
LSAダッシュボードとGBPで情報を別管理
過去レポートはLSAダッシュボードからアクセス
↓
Google広告移行後(After)
予算は日単位で管理
手動入札は廃止
全カテゴリをまとめたキャンペーン単位の目標CPA1つ
GBPの情報が自動同期
過去レポートは移行後アクセス不可になるため事前保存が必要
■ 移行前  ■ 移行後

予算は週単位から日単位へ

従来のLSAは週平均の予算で運用されていたが、移行後はGoogle広告の他のキャンペーンと同様に日額予算での管理に変わる。1日あたりの支出上限が設定されるため、週単位のざっくりした予算配分からより細かい調整が必要になる。

手動入札が廃止され目標CPAがキャンペーン単位に

これまで一部の広告主は「リード1件あたりの上限単価」を手動で設定できたが、この機能は使えなくなる。代わりに、Googleが算出するキャンペーン単位の目標CPA(リード獲得単価の目標値)が適用される。

サービスカテゴリごとに異なる目標CPAを設定することもできなくなる。たとえば配管工事と空調工事の両方を1つのキャンペーンで広告している事業者の場合、双方のリードコスト差にかかわらず1つの目標CPAに統一される。この点は業種によって影響が大きいため、キャンペーン分割の要否を検討する必要がある。

ビジネス情報はGBPと自動同期

事業者名や住所、営業時間といった基本情報はGBP(Google Business Profile / グーグルビジネスプロフィール)から自動で同期される。これまではLSAとGBPで別々に情報を更新する手間があったが、統合により片方だけ変更するリスクは減る。ただし、大幅な名前や住所の変更を行うと24〜48時間の確認プロセスが入り、キャンペーンが一時停止する可能性がある。

レポートとリード管理の拠点が切り替わる

過去のパフォーマンスレポートはGoogle広告に引き継がれない。リードの履歴は移行されるものの、レポートデータへのアクセスは移行完了と同時に失われる。年度比較や顧客報告に必要なデータは事前にダウンロードしておくことが必須だ。リード対応についても、Google広告内のLead Manager(リード管理画面)に切り替わる。

広告主が移行前後に取るべき対策

広告主が移行前後に取るべき対策

移行をスムーズに進めるために、広告主や代理店が今から着手できる準備を整理する。移行の通知を受け取ってから慌てないよう、以下の2点を押さえておきたい。

履歴レポートのダウンロードを最優先に

最も重要なのは、LSAダッシュボードに保存されている過去のパフォーマンスデータをエクスポートすることだ。移行後はレポート画面自体がなくなるため、後から取り出すことはできない。

複数アカウントを管理する代理店は、通知を受け取る前にバックアップ作業を始めておくと安全だ。前年比較レポートを作る予定のある事業者も、今のうちに必要な期間のデータを保存しておくことを推奨する。

移行後の設定を丁寧に確認する

Googleがキャンペーン設定を自動で移行するが、広告主自身で以下の項目を再確認すべきである。

  • 日額予算が事業計画と合っているか
  • キャンペーン単位の目標CPAが過去のリード単価と大きく乖離していないか
  • サービスカテゴリや配信地域が正しく設定されているか
  • 広告スケジュールが想定通りか
  • リード転送先の電話番号や写真、訴求文に誤りがないか

事業者名や住所に大きな変更があると、前述の通り審査が入りキャンペーンが止まる可能性がある。配信再開までに数日かかるケースもあるため、移行直後の大口変更は避けたほうが無難だ。

Googleは移行後すぐに広告が表示される場合もあるとしているが、パフォーマンスが安定するまで最大2週間をみておく必要がある。

統合がもたらす影響と今後の見通し

統合がもたらす影響と今後の見通し

今回の統合の最大の焦点は、カテゴリ別の目標CPAが廃止される点にある。リード単価の大きく異なる複数サービスを1つのキャンペーンで運用してきた事業者は、キャンペーンを分割するか、まとめたまま自動入札に任せるかの判断を迫られる。

分割すれば入札のコントロールは細かくなるが、各キャンペーンのコンバージョンデータが少なくなり、Googleの自動最適化が働きにくくなる面もある。リード数の多い事業者は分割、まだボリュームの少ない事業者は統合したまま様子を見るという選択肢が現実的だ。

初期移行グループの状況を見ながら、Googleは追加のガイダンスを出すとみられる。とくに日本国内の広告主が対象となるのは2027年以降と見込まれるため、まずは米国の事例を参考にしつつ、自社のLSAデータを整理しておくのが賢明だろう。

この記事のポイント

  • LSAの管理画面が2026年8月からGoogle広告に統合される
  • 配信面とリード課金の仕組みは変わらないが、予算管理や入札方式が変更される
  • カテゴリ別目標CPAの廃止が事業者に与える影響は大きく、キャンペーン分割の要否を検討する必要がある
  • 過去レポートは移行前に必ずダウンロードしておくこと
  • 日本国内の移行は2027年以降の見込みだが、今からデータ整理を始めておくとよい
WordPress wp2shell攻撃後の完全クリーンアップと再発防止手順

WordPress wp2shell攻撃後の完全クリーンアップと再発防止手順

WordPress が REST Batch API を悪用した wp2shell 攻撃を受け、Web シェルを仕込まれたり偽の管理者を作られたりした場合は、WordPress 本体の更新だけでなくファイルとデータベースの完全な掃除が必要になる。攻撃者は認証なしでコードを実行できるため、必ず FTP/SSH と SQL の両面から対処する。

この攻撃は SQL インジェクションで PHP ファイルをサーバーに直接書き込み、データベース内にも偽のメニュー項目や changeset を残す。パッチを当てただけではバックドアが生き残り、再侵入される危険がある。

Before 攻撃直後、WordPress だけ更新した状態
✗ /wp-content/cache/ に不明な PHP ファイルが残る ✗ データベースに偽の customize_changeset が残る ✗ 攻撃者の管理者アカウントが有効なまま ✗ 全員のセッションが生きている
↓
After 完全クリーンアップ後の状態
✓ キャッシュ内の Web シェルを全削除 ✓ DB から偽データを削除し FILE 権限を剥奪 ✓ 全員のパスワード変更とセッション強制切断 ✓ DISALLOW_FILE_MODS でファイル改変を遮断

上図は攻撃直後と完全クリーンアップ後の違いだ。この記事ではファイル・データベース・ユーザー管理の3層で掃除し、再発を防ぐまでの手順を詳しく解説する。

wp2shell 攻撃で何が起きているのか

wp2shell 攻撃で何が起きているのか

WordPress の REST Batch API は複数の REST API リクエストをまとめて送信できる機能だ。この脆弱性を突かれると、認証なしで SQL インジェクションを起こし、INTO OUTFILE 命令で PHP ファイルをサーバーに書き込める。書き込まれた PHP ファイルは Web シェルとして機能し、攻撃者が自由にコマンドを実行できるようになる。

さらに攻撃者はデータベースに直接アクセスできるため、パスワードのハッシュを盗んだり、自分自身に管理者権限を付与したりすることが可能だ。偽のプラグインを /wp-content/mu-plugins/ に仕込んで恒久的なバックドアにする手口も確認されている。

被害にあったサイトを完全に掃除する手順

被害にあったサイトを完全に掃除する手順

掃除は「ファイルの掃除」「ユーザーとセッションの掃除」「データベースの掃除」の3段階で進める。始める前に必ずファイルとデータベースの完全バックアップを取る。

ファイルシステムから Web シェルと偽プラグインを削除する

FTP クライアントや SSH でサーバーに接続し、まず /wp-content/cache/ ディレクトリを開く。キャッシュ系のディレクトリ(/cache/ や /wpo-cache/ など)に不自然な英数字の羅列(e042u9xy9ra1.php のようなファイル名)があれば、それが Web シェルだ。すべて削除する。

次に /wp-content/mu-plugins/ を確認する。Must-Use プラグインは自動的に有効化されるため、攻撃者が好んで使う場所だ。身に覚えのないファイル(galex_patch.php など)があれば削除する。通常の /wp-content/plugins/ にも見慣れないプラグインが追加されていないか調べる。

STEP 1 FTP/SSH でサーバーに接続
↓
STEP 2 /wp-content/cache/ 内の怪しい PHP ファイルを削除
↓
STEP 3 /wp-content/mu-plugins/ の身に覚えのないファイルを削除
↓
STEP 4 WordPress 本体を 6.9.5 または 7.0.2 以上に更新
↓
STEP 5 wp-config.php に DISALLOW_FILE_EDIT / DISALLOW_FILE_MODS を追加

ファイルの掃除が終わったら、WordPress 本体をパッチ適用済みバージョン(6.9.5 または 7.0.2 以上)に更新する。この更新で Batch API の脆弱性自体が塞がる。

wp-config.php にファイル改変防止の定数を追加する

将来の攻撃に備え、管理画面からのファイル編集とプラグインのインストールを無効化する。FTP または SSH で wp-config.php を開き、以下の2行を追記する。

define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true );

DISALLOW_FILE_EDIT は管理画面の「テーマエディター」「プラグインエディター」を無効化する。DISALLOW_FILE_MODS は管理画面からのプラグイン追加や更新をブロックする。すでに侵入された後の対策ではなく、掃除が完了した後に再発を防ぐ設定だ。

ユーザーとパスワード、セッションの掃除

ユーザーとパスワード、セッションの掃除

攻撃者はデータベースに直接アクセスしていたため、パスワードのハッシュを抜き取った可能性が高い。管理者を含む全ユーザーのパスワードを変更する。WordPress 管理画面だけでなく、MySQL データベース自体のパスワードも変更し、wp-config.php の DB_PASSWORD を新しいものに書き換える。

パスワード変更だけでは不十分だ。攻撃者がまだログインしたままかもしれない。全セッションを強制的に切断するには、Salt Keys(ソルトキー)を再生成して wp-config.php に上書きする。WordPress 公式の Salt Keys ジェネレーターで新しいキーセットを取得し、既存のキーと置き換えれば全デバイスのログイン状態が即座に無効になる。

最後に、管理画面の「ユーザー」一覧を開き、見覚えのない管理者アカウントが作られていないか確認する。もし存在すれば即座に削除する。

データベースに残った偽のレコードを削除する

データベースに残った偽のレコードを削除する

wp2shell 攻撃は、WordPress のセキュリティフィルターをすり抜けるために、データベース上に偽のナビゲーションメニュー項目と changeset(カスタマイザーの変更履歴)を一時的に生成する。これらのレコードは post_date が 2020-01-01 00:00:00 に固定されており、URL ペイロードに example.invalid を含むという特徴がある。

以下の SQL を phpMyAdmin などで実行する。なお、接頭辞(プレフィックス)がデフォルトの wp_ ではない場合は、コード内の wp_ を実際のプレフィックス(例: wp2_ や mysite_)に置き換える必要がある。

偽の changeset を削除する

DELETE FROM wp_posts WHERE post_type = 'customize_changeset' AND post_date = '2020-01-01 00:00:00';

偽のナビゲーションメニュー項目を削除する

DELETE FROM wp_posts WHERE post_type = 'nav_menu_item' AND post_date = '2020-01-01 00:00:00';

悪意のあるメタデータを削除する

DELETE FROM wp_postmeta WHERE meta_value LIKE '%example.invalid%';

これらのクエリでデータベース上の痕跡を一掃できる。実行前には必ずデータベースのバックアップを取る。

データベースユーザーから FILE 権限を剥奪する

データベースユーザーから FILE 権限を剥奪する

今回の攻撃は SQL インジェクション経由で INTO OUTFILE 命令を使い、データベースからディスクにファイルを書き込んでいた。WordPress の通常動作に FILE 権限はまったく不要だ。この権限を WordPress のデータベースユーザーから剥奪しておけば、同種の攻撃が再び成功する可能性を大きく下げられる。

データベースに root 権限でログインし、以下の SQL を実行する。'wp_user_name'@'localhost' は実際の WordPress 用データベースユーザー名に置き換える。

REVOKE FILE ON *.* FROM 'wp_user_name'@'localhost';
FLUSH PRIVILEGES;

REVOKE FILE は FILE 権限を取り消し、FLUSH PRIVILEGES は変更を即時反映する。これでデータベースからファイルシステムへの書き込み経路が遮断される。

Before FILE 権限あり
攻撃者 → SQL インジェクション → INTO OUTFILE → ディスクに PHP ファイル書き込み
↓
After FILE 権限なし
攻撃者 → SQL インジェクション → INTO OUTFILE → 権限エラーで書き込み失敗
■ 権限あり(攻撃経路あり) ■ 権限剥奪後(経路遮断)

よくある質問

WordPress を更新しただけで掃除は不要か

更新だけでは不十分だ。攻撃者はすでに Web シェルをサーバーに書き込んでおり、そのファイルは更新では削除されない。データベース内の偽レコードや不正な管理者アカウントも残ったままになる。必ずファイルとデータベースの両方を掃除する。

DISALLOW_FILE_MODS を設定すると管理画面からプラグインを追加できなくなるのか

そのとおりだ。DISALLOW_FILE_MODS を true にすると、管理画面からのプラグインのインストール・更新・削除、テーマのインストール・更新がすべてブロックされる。必要な更新は FTP や SSH 経由で手動で行う運用になるが、攻撃者が管理画面からファイルを改変する経路を完全に塞げる。

SQL クエリのプレフィックス wp_ を変更し忘れるとどうなるか

テーブルが存在しないというエラーが出るだけで、データが破壊されることはない。それでも、間違ったテーブルを操作しないよう実行前に必ず実際のプレフィックスを確認する。多くのレンタルサーバーではインストール時に自動生成された固有のプレフィックスが使われている。

FILE 権限を剥奪すると WordPress の動作に影響は出るか

WordPress の通常動作に FILE 権限は一切使われない。記事の投稿やプラグインの動作、データベースの読み書きに影響は出ないため、安全に剥奪できる。

この記事のポイント

  • WordPress 本体の更新だけではバックドアとデータベースの痕跡が残る
  • /wp-content/cache/ と /wp-content/mu-plugins/ の不審な PHP ファイルを削除する
  • 全ユーザーのパスワード変更と Salt Keys 再生成でセッションを強制切断する
  • データベースから post_date が 2020-01-01 の偽 changeset とメニュー項目を削除する
  • WordPress の DB ユーザーから FILE 権限を剥奪し INTO OUTFILE 経路を塞ぐ
WooCommerce.comがプラグイン読み込みを最適化、応答時間を最大400ms短縮

WooCommerce.comがプラグイン読み込みを最適化、応答時間を最大400ms短縮

WooCommerce.comが大規模WordPressサイトのパフォーマンスを大幅に改善した手法が公開された。特定のリクエストで不要なプラグインを読み込まない「選択的プラグイン読み込み」である。この手法により、WooCommerce.comの内部APIエンドポイントではメモリ使用量が50%以上削減され、主要エンドポイントの応答時間が最大400ミリ秒以上短縮されたという。

WordPressはリクエストのたびにすべての有効化プラグインを読み込む仕組みだ。大多数のサイトでは問題にならないが、WooCommerce.comのように100を超えるプラグインが稼働する大規模サイトでは無視できないオーバーヘッドになる。今回の事例は、大規模WordPressサイトのパフォーマンスチューニングに新たな選択肢を示すものだ。

プラグインの一括読み込みは大規模サイトの足かせになる

プラグインの一括読み込みは大規模サイトの足かせになる

WordPressのプラグインモデルはシンプルだ。有効化されているプラグインは、フロントエンドの表示でも管理画面の操作でも、REST APIの呼び出しでも、すべてのリクエストで例外なく読み込まれる。ほとんどのサイトにとってこれは合理的な設計である。挙動が予測しやすく、プラグイン同士の依存関係を意識せずに組み合わせられる。

しかしWooCommerce.comのように、マーケットプレイス、決済、アカウント管理、API、チェックアウト、パートナー向けワークフロー、検索連携、トラッキング、そして運用コードが複雑に絡み合う大規模アプリケーションでは、事情が異なる。100個以上のプラグインのうち、特定のリクエストで実際に必要なのはごく一部であることが多いのだ。

WooCommerce.comの開発者ブログで紹介された実例を見てみよう。商品の検索・表示ページは、マーケットプレイスへの出品ツールを必要としない。キャッシュされた内部APIは、チェックアウト処理と同じプラグイン群を必要としない。公開ドキュメントの表示に注文番号の採番ロジックは不要だ。にもかかわらず、これらすべてのリクエストが同じプラグインセットを読み込んでいる。

各プラグインは読み込み時にフックの登録、サービスの初期化、オプションの読み出し、翻訳ファイルのロード、カスタム投稿タイプの定義、RESTルートの追加、アセットのキューイング、互換性コードの実行などを行う。1つひとつは小さなコストでも、成熟したWooCommerceアプリケーションで積み重なると無視できない負荷になる。

ページキャッシュやエッジキャッシュはこの問題をある程度隠すが、根本的な解決にはならない。キャッシュミスは依然として発生する。APIリクエストは動的なものが多い。ログイン状態のリクエストはキャッシュをバイパスする。トラフィックが急増するタイミングで、運用系のエンドポイントが高いレイテンシに悩まされることもある。大規模WordPressサイトにとって、ブートストラップ処理の削減は確かなパフォーマンス向上手段だ。

選択的プラグイン読み込みの基本的な仕組み

選択的プラグイン読み込みの基本的な仕組み

WordPressは有効化プラグインの一覧を active_plugins オプションに保持している。ブートストラップ時にこのオプションを読み取り、リストにある各プラグインのメインファイルを順に読み込んでいく。

ここに介入する仕組みがオプションフィルターだ。pre_option_active_plugins または option_active_plugins フィルターを使えば、WordPressが実際にプラグインを読み込む前にリストを書き換えられる。重要なのは、このフィルターを通常のプラグインより先に実行される mu-plugin(Must-Use Plugin)に配置することだ。

add_filter(
    'option_active_plugins',
    function ( array $plugins ): array {
        if ( ! should_limit_plugins_for_this_request() ) {
            return $plugins;
        }
        return array_values(
            array_diff(
                $plugins,
                plugins_to_skip_for_this_request()
            )
        );
    }
);

このコードの要点は3つある。どのリクエストでフィルターを適用するか、そのリクエストにとって安全に除外できるプラグインはどれか、そしてプラグインの一部を読み込まなかったことでサイト全体の状態が破損しないか、という点だ。

WooCommerce.comでは、mu-pluginでルートルールを早期に登録し、リクエストURIを完全一致、前方一致、または正規表現で照合する。ルールがマッチすると、あらかじめ定義されたプラグインを読み込み対象から外す仕組みだ。

従来のリクエスト処理(Before)
⚙️ 決済ゲートウェイ
⚙️ 税金計算プラグイン
📦 マーケットプレイス出品ツール
📝 ブログ用SEOプラグイン
✅ 注文管理プラグイン
全プラグインを読み込み → メモリ消費大
↓
高速化後のリクエスト処理(After)
⚙️ 決済ゲートウェイ
⚙️ 税金計算プラグイン
📦 マーケットプレイス出品ツール
📝 ブログ用SEOプラグイン
✅ 注文管理プラグイン
必要なプラグインのみ読み込み → メモリ消費50%以上の削減が可能
テキスト+灰色背景 = 除外(ロードされない) ■ = APIが実際に必要とするプラグイン

この仕組みは、APIエンドポイントやブログ記事の表示など「ほとんどのプラグインが不要なリクエスト」で高い効果を発揮する。

ルール設計と安全性のトレードオフ

ルール設計と安全性のトレードオフ

許可リストと除外リスト

選択的プラグイン読み込みの設計で最初に直面するのが、読み込むプラグインを決める方式だ。大きく分けて許可リスト方式と除外リスト方式がある。

許可リスト方式は、そのルートに絶対必要なプラグインだけをゼロからリストアップする。理論上は最も効果が高いが、大規模サイトでは脆さが問題になる。テーマ関数が別プラグインのクラスに依存しているケース、RESTハンドラが間接的に他のプラグインのヘルパー関数を呼んでいるケース、キャッシュミス時にのみ実行されるコードパスなど、暗黙の依存関係を見落とすとルートが壊れる。見落としはテストをすり抜けやすい。

除外リスト方式は、通常のアクティブプラグインリストから「このルートでは確実に不要」とわかっているものだけを取り除く。理想的な最小化にはならないが、安全性が段違いに高い。管理画面専用ツール、決済ゲートウェイ、メール配信処理など、明らかに関係ないグループをまとめて外すので、予期せぬ依存による障害が起こりにくい。

WooCommerce.comのチームは後者を主軸に採用している。開発者ブログの言葉を借りれば「各ルールをコードレビューの差分として確認でき、どのプラグインを残したか、なぜ外したかをコメントで説明できる」状態が、運用上の安心感をもたらすという。

除外が危険なリクエスト

すべてのリクエストが選択的読み込みの対象になるわけではない。WooCommerce.comでは以下のリクエストタイプを一律で除外対象から外している。

  • wc-ajax
  • wc-api
  • rest_route(広範なクエリ文字列エントリポイント)
  • クエリパラメータを含むダウンロードリクエスト

これらは動的に多様なコードパスに分岐する可能性があり、副作用の範囲を予測しにくいためだ。チェックアウト、カート、アカウント、管理画面、cron、Webhook、決済コールバック、ダウンロードといった「金銭・顧客データ・認証・権利確認・メール送信・サードパーティ連携」に触れるリクエストには、特に慎重な扱いが求められる。

依存関係の発見が最大の難所

動的なWordPressアプリケーションでは、あるルートが実際にどのプラグインに依存しているかを静的に解析する方法は存在しない。WooCommerce.comのチームは、ルートのコードを読み込み、明白な依存関係を追跡し、手動でリクエストフローを検証し、URLマッチングとエンドポイント動作のテストを書き、段階的にロールアウトしてエラーログとパフォーマンスデータを監視する、という実践的なアプローチを取っている。

注意すべきは、問題が特定の条件下でのみ表面化することだ。特定の商品ページ、特定のロケール、特定のリクエストパラメータ、キャッシュミス時、ログイン状態など、組み合わせは膨大になる。プラグインの読み込み不足によるエラーは再現条件が狭く、発見が遅れやすい。

WooCommerce.comで得られた具体的な効果

WooCommerce.comで得られた具体的な効果

WooCommerce.comの開発者ブログでは、いくつかのエンドポイントで測定された具体的な数値が公開されている。

  • 必要なプラグインのみを読み込んだリクエストでは、メモリ使用量が50%以上削減された
  • 接続ストアが所有する有料サブスクリプション情報を返すエンドポイントは、約800msから約475msに短縮
  • ストアにインストールされたプラグインの利用可能アップデートを通知するエンドポイントは、約880msから約550msに短縮
  • WooCommerceオンボーディングフローで毎回呼ばれるエンドポイントも、同様の大幅改善
  • 商品ページに対して決済ゲートウェイと無関係な拡張機能を除外した初期テストでは、ページ生成時間が約10%改善

これらの改善は、高トラフィックで責務が限定されたエンドポイントや、大規模なプラグイン構成を持つ匿名ユーザー向けページで特に顕著だった。逆に、ほぼすべてのプラグインが関与しうる動的なステートフルフローでは、相対的な効果は小さくなる。

監視すべき指標は、レスポンスタイム、PHPメモリ使用量、データベースクエリ数、高コストなプラグインのブートストラップ処理、デプロイ後のエラー率、予期しないリライトルールの変更、キャッシュミス時のルート固有の致命的エラーなど、多岐にわたる。

この手法が適するサイトと適さないサイト

この手法が適するサイトと適さないサイト

この手法が効果を発揮するのは、以下の条件が揃っているサイトだ。

✅ 導入に向いているサイト
• アクティブプラグインが多い(数十個以上)
• トラフィックが高く、ブートストラップコストが無視できない
• 特定のルートの責務が限定されている
• エンジニアリングチームがデプロイと監視を担当できる
• テストの作成と維持が可能
• 改善効果を測定できる
• 問題が起きたときに素早くロールバックできる
↓
❌ 導入が不向きなサイト
• 小規模サイト
• プラグイン数がすでに少ない
• ルートが動的でステートフル
• ステージング環境や本番監視がない
• 非エンジニアが依存関係ルールを維持する必要がある
• 依存関係の発見作業を継続的に行う余裕がない
■ 適性あり ■ 適性なし

繰り返しになるが、これは最初に手をつけるべき最適化ではない。キャッシュ戦略の見直し、クエリパフォーマンスの改善、アセット読み込みの最適化、オブジェクトキャッシュの導入、明らかに不要なプラグインの整理といった基本的な施策を先に済ませてから検討するのが現実的な順序だ。

STEP 1 ページキャッシュ・CDNの導入
↓
STEP 2 データベースクエリの最適化
↓
STEP 3 オブジェクトキャッシュ・アセット最適化
↓
STEP 4 選択的プラグイン読み込みの検討
選択的プラグイン読み込みは、基本的な高速化施策を実施した後の追加施策として位置づける

この記事のポイント

  • 特定のリクエストで不要なプラグインを読み飛ばす「選択的プラグイン読み込み」により、WooCommerce.comの大規模サイトでメモリ使用量50%以上の削減と大幅な応答時間短縮が達成された
  • 仕組みは option_active_plugins フィルターとmu-pluginの組み合わせで実装でき、技術的なハードル自体は高くない
  • 安全性を確保するには「許可リスト」より「除外リスト」方式が現実的であり、ルールをコードとして管理しテストと監視を徹底することが不可欠
  • この手法は大規模サイト向けの「最後の一手」であり、キャッシュやクエリ最適化といった基本的な施策を先に実施すべき
WooCommerceバリエーション商品のカート追加で重大エラーが出る時の修正方法

WooCommerceバリエーション商品のカート追加で重大エラーが出る時の修正方法

WooCommerce のブロックベースカートでバリエーション商品を追加した際に「woo-min-max-quantity-step-control-single」プラグインが原因で「このサイトで重大なエラーが発生しました」と表示される場合、原因はプラグインが商品オブジェクトの取得失敗を考慮していないことだ。該当ファイルの PHP コードに数行の修正を加えればエラーを回避できる。

なぜブロックカートでバリエーション商品だけエラーになるのか

エラーログを確認すると、問題はプラグインの min-max-controller.php 872行目付近で発生している。この行では wc_get_product() で商品情報を取得した直後に ->get_id() を呼んでいるが、wc_get_product() は対象の商品が見つからなかった場合に false を返す。ブロックベースのカート(Store API)経由でバリエーション商品が追加されると、この関数がまれに false を返す状況が発生する。プラグインのコードはその可能性をまったく想定しておらず、結果として「Call to a member function get_id() on false」という致命的な PHP エラーに直結している。

エラーを根本解決するためのコード修正手順

エラーを根本解決するためのコード修正手順
STEP 1 FTP や管理画面から該当ファイルを探す
↓
STEP 2 872 行目付近のコードを確認し false チェックを追加する
↓
STEP 3 修正したファイルをサーバーにアップロードする

該当ファイルを開き 872 行目周辺を特定する

FTP クライアント、またはレンタルサーバーのファイルマネージャーで、以下のパスにあるファイルを開く。WordPress 管理画面の「プラグイン」→「プラグインファイルエディター」から編集するのはできるだけ避ける。エディター画面で編集ミスをするとサイト全体が停止するリスクがあるためだ。

/wp-content/plugins/woo-min-max-quantity-step-control-single/includes/min-max-controller.php

使用しているエディタで行番号表示を有効にし、872 行目付近まで移動する。エラーログに表示されているとおり、->get_id() を直接呼んでいる箇所を探そう。

修正前と修正後のコードを比較する

修正前(エラー) Before
$product = wc_get_product( $product_id );
$min = $product->get_id();
↓
修正後(安全) After
$product = wc_get_product( $product_id );
if ( ! $product || ! is_a( $product, ‘WC_Product’ ) ) {
    return;
}
$min = $product->get_id();
■ エラー状態  ■ 修正後

PHP コード修正の内容と意味

修正の核心は、$product が有効なオブジェクトかどうかを事前に検証することだ。

! $product は wc_get_product() が false を返した場合を検出する。is_a( $product, 'WC_Product' ) は、取得できたとしてもそれが WooCommerce の正規の商品オブジェクトであることを確認する。どちらかの条件を満たさなければ return で処理を中断し、以降の ->get_id() が呼ばれないようにする仕組みだ。

このガード節を入れることで、ブロックカート経由でどういった商品情報が渡ってきても、致命的なエラーにはならなくなる。

修正してもエラーが直らない場合の確認点

まれに、修正だけでは根本解決しないケースがある。以下の点も確認してみてほしい。

WooCommerce データベースのクリーンアップを実行する

「WooCommerce」→「ステータス」→「ツール」タブに移動し、「WooCommerce トランジェントをクリア」と「期限切れのトランジェントを削除」を実行する。キャッシュが原因で商品情報が正しく取得できていない場合に効果がある。

最小最大数量プラグインのバージョンと WooCommerce のバージョンを確認する

プラグインが最新の WooCommerce や Store API に対応していない可能性がある。プラグインの公式ページで対応バージョンを確認し、場合によっては別の数量制御プラグインを検討する必要がある。修正を加えても根本的な設計の問題で他の不具合が発生する場合は、開発者に修正リクエストを送りつつ、一時的に従来のショートコードカート([woocommerce_cart])へ切り戻すことも視野に入れる。

よくある質問

この問題はブロックカートだけに発生するのか

主にブロックベースのカートとチェックアウト(Store API)で発生する。従来のショートコードカートではエラーが出ないことも多いが、プラグインコードに潜在的な問題があるため、修正しておく方が安全だ。

プラグインがアップデートされたら修正は消えるか

消える。今回の修正はプラグインのコアファイルを直接編集しているため、プラグインにアップデートが配信されると編集内容は上書きされる。アップデート後に同様のエラーが再発した場合は、再び同じ手順で修正するか、開発者が修正を取り込むまでアップデートを控える必要がある。

子テーマの functions.php でこのエラーを回避できるか

難しい。今回のエラーはプラグイン内部の特定の行で発生しており、かつ商品取得のロジック周辺にフックが用意されていない限り、テーマファイル側から割り込んで防御することはできない。直接ファイルを編集する今回の方法が最も確実な対処法になる。

修正中にサイトが壊れてしまった場合の直し方は

FTP でサーバーにアクセスし、修正前にバックアップしておいた min-max-controller.php を上書きアップロードする。バックアップがない場合は、プラグインを一度削除して再インストールするのが早い。ただし、プラグインの設定内容はあらかじめメモしておく必要がある。

この記事のポイント

  • エラー原因はプラグイン内での get_id() 呼び出し前に false チェックがないこと
  • 修正対象は min-max-controller.php の 872 行目付近
  • wc_get_product() が false を返す状況を考慮したガード節を追加する
  • ブロックカート(Store API)利用時に特に発生しやすい PHP エラーへの対処法
  • 直接ファイルを修正するため、プラグインのアップデートで編集が上書きされる点に注意
AIで返金証拠の偽造が容易に、EC事業者に迫る新たな脅威

AIで返金証拠の偽造が容易に、EC事業者に迫る新たな脅威

オンラインストアにおける返金申請に、生成AIで偽造された証拠写真や配送記録を使う手口が急増している。実店舗を持たずに商品を販売するEC事業者にとって、返品プロセスのデジタル化はコスト削減に直結するが、その裏で「証拠の信頼性」という前提が根底から揺らぎ始めたのだ。特に自動審査システムを導入する事業者ほど、巧妙化するAI画像に脆弱になりやすい。

米国では2025年の返品総額が約8,499億ドルに達し、そのうち約9%が不正申告と推計されている。ECの返品率は実店舗の2倍以上に上る。実務に詳しい業界関係者の間では、これまで人の手で検知できていた偽装が、AIによって誰でも量産できる段階へ移行したとの危機感が強い。この記事では、AI返金詐欺の実態と、事業者が現実的に取りうる対策、そしてその経済的なジレンマまでを整理する。

EC返金の仕組みと「証拠写真」の脆さ

EC返金の仕組みと「証拠写真」の脆さ

写真1枚で成立していた返金審査

一般的なECサイトでは、返品返金の審査を写真と購入者の申告文のみで完了させるケースが多い。商品の破損やパッケージの潰れを写した画像を確認し、配送記録と照合して問題がないと判断すれば、そのまま返金が実行される。

この流れを支える前提は「購入者が提出する写真は、実際の商品を写したものだ」という一点に尽きる。生成AIはこの前提そのものを無力化してしまう。実在しない破損をあたかも本物のように描写できるため、写真1枚の信頼性では太刀打ちできなくなるからだ。

特に低額商品や食品など、返送コストが商品価格を上回るケースでは、商品の返却を求めずに返金に応じる「返品不要返金」が多用される。詐欺師がこの仕組みを悪用するのは以前からだが、AI画像の登場でそのハードルは大幅に下がった。

返品不要返金が狙われる理由

送料と検品コストを考慮し、商品を送り返させずに返金する方式は、カスタマーサポートの効率化に寄与する。しかし同時に、詐欺師にとっては「商品を手元に残したまま返金だけを受け取れる」絶好の抜け穴になる。生成AIによる偽造証拠は、この穴をさらに拡大する存在だ。

Practical Ecommerceの記事は、米国の小売企業Bogg BagとBoll & Branchが、実際にAIで改ざんされた返品証拠に遭遇したと報じている。こうした事例は大企業に限らず、中規模以下のネットショップにも波及しつつある。

生成AIが作る偽造証拠の手口

生成AIが作る偽造証拠の手口

AIによる返金詐欺は、単に商品画像を改変するだけにとどまらない。返品プロセス全体のストーリーを捏造できる点が、これまでの手口と一線を画す。

偽造できる証拠の範囲

詐欺師が短時間で生成できる偽造証拠の範囲は広い。以下に主な種類を整理する。

  • 商品のひび割れ、汚れ、カビ、破れ、漏れ、へこみ、部品欠落
  • 損傷したパッケージや潰れた配送箱の写真
  • 掲載写真と色・機能が異なると見せかける加工
  • 「返金を承諾した」とする架空のカスタマーサポートチャット
  • 配送記録、運送会社の書類、配達完了画面の偽スクリーンショット
  • 各ストアの返品ポリシーに合わせた苦情文の自動生成
  • 複数店舗で使い回すためのバリエーション作成

いずれの偽造も、数回のプロンプト入力で完成させられる。写真編集ソフトの知識や文書の改ざんスキルはもはや不要だ。これが「誰でも詐欺師になれる」と言われるゆえんである。

AI画像のリアリティと簡単さ

Practical Ecommerceの記事では、わずか10単語のプロンプトから、ガラス花瓶が粉々に割れた説得力のある画像が生成された例が紹介されている。照明の反射や影の付き方まで自然で、一見しただけでは実写と区別がつかない。

詐欺の実行に必要なコストも時間も極小化され、同時に複数アカウントや複数店舗を横断して悪用できる。従来のように一人の詐欺師が手作業で細工する手法とは、規模感がまったく異なる。AI返金詐欺は、取引・紛争・物流・カスタマーサポートの各段階にまたがる「拡張可能な欺瞞」と呼べるレベルに達している。

従来の詐欺フロー(Before)
詐欺師 写真を自前で撮影・編集 → 手作業で文書改ざん → 1件ずつ店舗に申請
※スキル・時間・コストがかかる
↓
AI活用の詐欺フロー(After)
詐欺師 プロンプト入力のみ → AIが画像・文章を一括生成 → 複数店舗に同時申請
※数分・ほぼゼロコストで量産可能

この比較で示すように、詐欺の効率性と拡張性が段違いに向上した。事業者は、こうした「量産型の偽装」への耐性を今から備えなければならない。

AI詐欺に立ち向かうための対策とコスト

AI詐欺に立ち向かうための対策とコスト

検知技術と審査プロセスの強化

EC事業者が取れる防御策はいくつか存在する。画像のメタデータ分析や圧縮パターンの精査、逆画像検索による使い回し画像の発見、アカウントの返品履歴や行動ログのスコアリングなどは、従来からある不正検知の延長線上にある手法だ。

さらに実効性が高いとされるのは、次のような対策である。

  • 商品写真を1枚だけでなく、別アングルや短い動画の提出を必須にする
  • 高額商品や返品履歴に不審な動きがあるアカウントは、人手による詳細審査に切り替える
  • 特定の商品カテゴリや顧客セグメントに対して、返品時に現物の返送を義務付ける
  • 提出された画像をAIでスキャンし、合成や改変の痕跡を自動判定する

ただし、これらの対策にも限界はある。AIによる画像生成技術は日進月歩で進化しており、検知ツールが誤って正当な申告を不正とみなす「偽陽性」も無視できない。偽陽性が増えれば、誠実な顧客に無用な負担を強いることになり、サポートコストやブランドイメージへの悪影響につながる。

対策コストが上回るジレンマ

より深刻なのは、不正防止にかけるコストが、防げる被害額を上回ってしまうケースだ。Practical Ecommerceの記事は「3万ドルの不正を防ぐために10万ドルのコストをかけるのは無意味だ」という端的な指摘を紹介している。

厳格な返品ポリシーを設ければ、返送送料や検品費用、カスタマーサポートの問い合わせ対応が増大する。顧客満足度の低下がリピート率やLTV(顧客生涯価値)に及ぼす影響を加味すれば、単純に「不正をゼロにする」施策は経済合理性を欠くのだ。

このジレンマは、AI詐欺のコストがあまりに低いことに起因する。詐欺師側は数分で偽造証拠を作れる一方、事業者側はそれを証明するためにサポートスタッフの確認作業、倉庫記録の照合、運送会社との連携、場合によっては正式な異議申し立て手続きまでが必要になる。攻撃と防御の非対称性が、年々拡大しているのが現状だ。

詐欺師のコスト(攻撃側)
AIプロンプト → 数分で画像・文書を量産
費用:ほぼゼロ 時間:1件あたり数分
↓
事業者のコスト(防御側)
サポートスタッフ 手動確認 → 倉庫・運送記録照合 → 異議申し立て
費用:人件費+物流コスト 時間:1件あたり数時間〜数日

攻撃側と防御側の非対称性を視覚化すると、その差は歴然としている。AIがもたらすインパクトは、単に詐欺が増えたという量的な問題にとどまらず、防御の経済性そのものを破綻させかねない質的な変化だ。

実務に落とし込む現実的なアプローチ

実務に落とし込む現実的なアプローチ

全件精査ではなく「優先度ベースの審査」へ

限られたリソースの中でAI詐欺に対抗するには、「全件を完璧に防ぐ」発想を手放すことが出発点になる。代わりに、不正のリスクが高い申告を優先的に精査し、それ以外はある程度の漏れを許容する設計が現実的だ。

具体的には、商品単価の高い申告、返品頻度が異常に高い顧客、新規アカウントからの高額返金申請、画像のメタデータに不自然な欠落があるケースなどをスコアリングし、閾値を超えたものだけを手動で再確認する仕組みが考えられる。これらのルールベースのフィルタは、AI検知ツールと組み合わせることで精度を上げられる。

不正対策とCXのバランス設計

返品ポリシーを厳格化するほど、一般的な顧客の購入障壁は上がる。「返品時に動画を必須とする」「返送を全商品に義務付ける」といった一律のルール変更は、CX(顧客体験)を大きく毀損し、売上全体に悪影響を及ぼす可能性が高い。

むしろ有効なのは、優良顧客と疑わしい顧客をセグメントし、前者にはこれまで通りのスムーズな返金体験を維持しつつ、後者にのみ追加の証拠提出を求める段階的なアプローチだ。購買履歴や会員登録からの経過期間、過去の返品率などは、セグメントの判断材料として実装しやすい。

また、AIによる画像スクリーニングを導入する場合も、完全自動化ではなく「疑わしい画像を人間の担当者に提示する」補助ツールとして位置づけることで、偽陽性による誤った拒否を減らせる。

STEP 1 全返金リクエストをルールベースで自動スコアリング
↓
STEP 2 低リスクは即時承認、中〜高リスクのみAI画像チェックへ
↓
STEP 3 AIが合成疑い画像をピックアップ、担当者に提示
↓
STEP 4 人手による最終判断を経て返金可否を決定

この段階的なアプローチなら、防御コストを抑えつつ、AIが生成した偽装画像の多くを発見できる可能性が高まる。最初から完璧を目指さず、リスクベースでリソースを集中させる考え方こそ、AI時代の返金審査に求められる現実解である。

今後広がるAI詐欺とEC事業者の備え

今後広がるAI詐欺とEC事業者の備え

画像生成AIの進化はさらに加速する

画像生成AIの品質は、ここ1〜2年だけでも目覚ましく向上してきた。指の本数に違和感が残っていた初期段階はすでに過去のものとなり、テクスチャの再現性や光の反射、被写界深度の自然さは、人間の目では実写と区別できない水準に近づいている。

音声や動画の生成技術も同時に進化しており、将来的には「壊れた商品を手にした購入者が不満を訴える短い動画」すら数クリックで捏造される可能性がある。そうなれば、動画による証拠提出ですら防御策としての有効性を失いかねない。

まずは直近の返金履歴を監査する

Practical Ecommerceの記事は「問題を認識することが戦いの半分だ」と述べ、近い時期の返金記録を精査し、AIによる偽装がすでに紛れ込んでいないか確認することを推奨している。

具体的には、過去3〜6ヶ月の返金申請から、同じような構図・影の付き方・背景の写真が複数アカウントで使われていないか、メタデータに不自然な欠落や一貫性のなさがないか、という観点でのチェックが有効だ。AI画像生成ツールは撮影機器情報やGPSタグを埋め込まないため、Exifデータの不在そのものが一つのシグナルになりうる。

AI返金詐欺はまだ黎明期にある。にもかかわらず、手口の洗練と低コスト化は予想以上の速度で進んでいる。EC事業者にとっての最善手は、抜本的な対策を急ぎつつ、経済的なバランスを冷静に見極めることだ。

この記事のポイント

  • 生成AIにより、返金詐欺の証拠写真や文書が誰でも短時間で偽造できるようになった
  • 「返品不要返金」のような効率重視のプロセスが、AI詐欺に悪用されやすい構造になっている
  • 防御策には画像解析や動画提出の義務化があるが、偽陽性やコスト増という副作用を伴う
  • 不正額を上回る防御コストをかけることは経済的に無意味であり、リスクベースの優先審査が現実解
  • まずは直近の返金履歴を監査し、AIによる偽装の混入有無を確認することから始めるべきである
WordPressカスタムHTMLブロックが編集画面で消える原因と直し方

WordPressカスタムHTMLブロックが編集画面で消える原因と直し方

WordPress のブロックエディターでカスタム HTML ブロックを保存後に編集画面を開き直すと、ブロックの中身がまるごと消えて空欄に見える現象は、Gutenberg の React 側パーサーが HTML 構造を正しく解析できずに描画を放棄しているのが主な原因だ。script タグや閉じタグのない要素、複雑なインラインスタイルなどが引き金になる。

なぜカスタムHTMLブロックが編集画面で空になるのか

なぜカスタムHTMLブロックが編集画面で空になるのか

フロントエンドでは正しく表示されるのに、管理画面のブロックエディターだけで中身が空になるのは、データそのものはデータベースに保存されている証拠だ。コードエディターモードに切り替えれば、貼り付けた HTML が消えずに残っているのが確認できる。この現象が起こるのは、ブロックエディターがビジュアルモードでブロック内容を再表示するときに、DOM パーサーが特定の HTML を「壊れた構造」と判断してレンダリングを飛ばしてしまうからだ。

具体的には、Gutenberg が内部的に使用している React の DOM レンダリング機構が、管理画面の安全な枠組みの中で処理できないタグや構文に遭遇すると、そのブロック全体を安全のためにスキップする。結果として視覚的には空のブロックに見えるが、データベースの post_content には元のコードがそのまま格納されている。

カスタムHTMLブロックの中身が消える原因を特定する手順

カスタムHTMLブロックの中身が消える原因を特定する手順

まず、どの部分が問題を引き起こしているのかを切り分ける。以下の手順で原因箇所を絞り込む。

ブロックエディターのコードエディターモードで現状を確認する

編集画面右上の「︙」メニューから「コードエディター」を選択すると、ビジュアル表示ではなく生の HTML 構造が表示される。カスタムHTMLブロック内のコードがここで確認できれば、データは失われていない。このとき、Markdown 記法でブロック境界を示す <!-- wp:html --> と <!-- /wp:html --> のコメント行の内側にコードが残っているかを確かめる。

HTMLを最小単位に分解して原因のタグを特定する

ブロックに貼り付けた HTML を、1つのタグ単位で分割してカスタムHTMLブロックに1つずつ入れ直す。たとえば script タグ、style タグ、空要素(<div></div> など)、インラインイベントハンドラ(onclick など)をそれぞれ別のブロックに分けて保存し、再読み込み時に消えるかどうかをテストする。問題を起こすタグが特定できれば、その部分だけ別の実装方法に切り替えられる。

プラグイン競合の可能性を調べる

特定のプラグインがブロックエディターの動作に干渉して、カスタムHTMLブロックの描画を阻害しているケースもある。特にエディター拡張系のプラグインや、セキュリティ目的でスクリプトをフィルタリングするプラグインが入っている場合は、すべてのプラグインを一度無効化して標準テーマに切り替え、問題が再現するか確認する。プラグインが原因であれば、1つずつ再有効化して犯人を特定する。

カスタムHTMLブロックを正常に表示させる具体的な修正手順

カスタムHTMLブロックを正常に表示させる具体的な修正手順

原因が特定できたら、次は実際にブロックを正常に表示させる。script タグや複雑な HTML 構造が原因だった場合、以下のアプローチで回避できる。

STEP 1 原因となっているタグを特定する(script タグなど)
↓
STEP 2 script タグはカスタムHTMLブロックの外に出す
↓
STEP 3 複雑なHTMLはACFのフィールドやウィジェットで管理する
↓
STEP 4 コードエディターモードで編集する運用に切り替える

script タグや iframe はカスタムHTMLブロックではなく適切な場所に配置する

Gutenberg のカスタムHTMLブロックは、セキュリティ上の理由から script タグの実行を制限している。また、ビジュアルエディターでの再レンダリング時に script タグを含むブロックを空として扱う挙動が確認されている。JavaScript を埋め込みたい場合は、カスタムHTMLブロックではなく、functions.php に wp_enqueue_script で登録するか、専用のコード埋め込みプラグインを使う。iframe も同様に、エディターのプレビューで空白になることがあるため、フロントエンドのみで描画される仕組みを検討する。

閉じタグのない空要素を見直す

カスタムHTMLブロックに <div></div> のような中身のない空タグや、閉じタグを省略した要素が含まれていると、Gutenberg のブロックパーサーが構造を正しく解釈できずにブロック全体をスキップすることがある。空の div や span は削除するか、&nbsp; を入れて実体を持たせる。とくに WordPress の自動整形機能(wpautop)が余分な p タグや br タグを挿入することで、意図しない空要素が生まれることもある。

複雑なHTML構造はカスタムフィールドやショートコードに置き換える

テーブルやフォーム、装飾を多用したマークアップは、カスタムHTMLブロック1つにまとめるよりも、ACF(Advanced Custom Fields)のテキストエリアフィールドや、ショートコード化して出力する方が安定する。とくにクライアントが自分で編集する前提のサイトでは、カスタムHTMLブロックを直接触らせると今回のようなトラブルが再発しやすい。テーマ側でテンプレートパーツとして管理し、投稿画面では入力欄だけを提供する設計が安全だ。

今後同様のトラブルを防ぐための運用ポイント

今後同様のトラブルを防ぐための運用ポイント

カスタムHTMLブロックに貼り付ける前にコード検証を行う

外部の HTML スニペットをそのまま貼り付ける前に、W3C のバリデーターや VSCode の構文チェック機能でタグの閉じ忘れや文法エラーがないかを確認する。コピー元の Web ページから取得したコードには、不要な属性や非推奨のタグが混じっていることが多い。貼り付け前に一度テキストエディターにペーストし、明らかな問題を取り除いてからブロックに入力する習慣をつける。

WordPress と Gutenberg を最新バージョンに保つ

Gutenberg プラグインを単体でインストールしている場合は、定期的に更新することでブロックパーサーの改善や既知の不具合修正が適用される。コア組み込みのブロックエディターであっても、WordPress 本体のアップデートによってパースエンジンの挙動が改良されることがある。編集画面でカスタムHTMLブロックが空になる現象の一部は、過去のバージョンで修正されたバグに起因している可能性もあるため、まずは最新の状態であることを確認する。

どうしても必要な場合はコードエディターモードを常用する

ビジュアルエディターで空になってしまう HTML をどうしてもページに残したいときは、編集時にコードエディターモードに切り替えて作業する方法が最終的な回避策になる。データベースにコードが正しく保存されているなら、コードエディター表示では常に中身が確認できる。手間は増えるが、複雑なマークアップや埋め込みコードを扱うページでは、あらかじめこの運用を前提にしておくとトラブルが起きても編集が止まらない。

よくある質問

カスタムHTMLブロックの中身は完全に消えたのか

ビジュアルエディターでは空に見えても、コードエディターモードに切り替えると HTML が残っていることがほとんどだ。データベースの post_content にも保存されているため、失われたわけではない。

プラグインをすべて無効化しても直らない場合はどうすればいいか

テーマの functions.php や使用中の子テーマがエディターの動作に干渉している可能性がある。標準テーマ(Twenty Twenty-Five など)に一時的に切り替えて再現するか確認し、テーマ側のフィルターやアクションを調査する。

script タグをカスタムHTMLブロックで使う正しい方法はあるか

原則としてカスタムHTMLブロック内の script タグは推奨されない。管理画面でのレンダリング問題に加え、セキュリティプラグインやサーバー側のフィルターで除去されるリスクもある。どうしても必要な場合はショートコード化するか、wp_enqueue_script でテーマに登録するのが安全だ。

ビジュアルエディターで空白になる特定の HTML タグの一覧はあるか

公式の一覧は存在しないが、script タグ、style タグ、iframe、object、embed、空の div や span、コメントアウト行、複雑に入れ子になったインラインスタイル付き要素などが報告されている。問題が起きたら該当タグを一つずつ検証するのが確実だ。

ビジュアルエディターで空になる現象は Gutenberg のバグなのか

仕様とバグの両面がある。script タグの実行制限はセキュリティ上の意図的な制限であり、空要素のパース失敗はブロックエディターの改善が期待される領域だ。WordPress コアのバージョンアップによって挙動が変わることもあるため、最新バージョンへの更新が有効な場合が多い。

この記事のポイント

  • カスタムHTMLブロックが空に見えてもデータはデータベースに残っている
  • script タグや空要素、閉じタグ省略がパース失敗の主原因
  • コードエディターモードで中身を確認し原因タグを特定する
  • 複雑な HTML はカスタムフィールドやショートコードで管理する
  • WordPress と Gutenberg の最新化で改善するケースがある