投稿者アーカイブ

Kadence BlocksのナビゲーションAdvブロックでフォント設定が効かない時の直し方

Kadence BlocksのナビゲーションAdvブロックでフォント設定が効かない時の直し方

Kadence Blocks のナビゲーション(Adv)ブロックでフォントサイズや太字の設定が反映されず、文字が意図したスタイルにならない現象の原因は、プラグイン側のバグだ。Kadence Blocks 7.3.3 以降のバージョンでは、ブロックが出力するインライン CSS に {{ のような余分な二重括弧が混入し、ブラウザが CSS のパースに失敗して該当の装飾が丸ごと無効になる。この問題はカスタマイズを台無しにするが、Kadence Blocks を 7.3.2 以前の安定版に戻せば即座に直る。

なぜナビゲーションAdvブロックのフォント設定だけが消えるのか

なぜナビゲーションAdvブロックのフォント設定だけが消えるのか

ブロックエディター上や公開サイトで、ナビゲーションメニューの文字サイズが指定したとおりに表示されず、標準テーマのデフォルト値に戻ってしまう。検証ツールで要素に付与されているインラインスタイルを見ると、次のような壊れた CSS が埋め込まれていることが確認できる。

Before(エラー状態)
.kb-nav-link-319_9f80b8-fd > /*…*/ .kb-nav-link-content{{font-size:var(–global-kb-font-size-md, 1.25rem);}}
二重に重なった中括弧があるため、ブラウザがこの行全体を正しいCSSとして認識できない
↓
After(修正後)
.kb-nav-link-319_9f80b8-fd > /*…*/ .kb-nav-link-content{font-size:var(–global-kb-font-size-md, 1.25rem);}
正規の中括弧だけになるので、フォントの装飾が有効に戻る
■ エラー状態 ■ 正しいCSS

このデモで示したとおり、本来は {…} であるべきブロックのスタイル指定が、バグにより {{…}} と出力されてしまう。この形式はブラウザの構文解析でエラー扱いされ、font-size や font-weight がまったく適用されなくなる。Kadence ナビゲーション(Adv)ブロックを使っているメニューすべてで発生し、管理画面のブロックエディター上でもプレビューが崩れてしまうのが典型的な兆候だ。

ナビゲーションAdvブロックの表示崩れを直す手順

ナビゲーションAdvブロックの表示崩れを直す手順

根本原因は Kadence Blocks 7.3.3 以降のコードにある。修正アップデートがリリースされるまで、自力で解決するには古い安定バージョンにプラグインを差し戻すのが確実かつ短時間で終わる方法だ。サーバーをいじる必要はなく、WordPress 管理画面の操作だけで完了する。

現在の Kadence Blocks のバージョンを確認する

「プラグイン」→「インストール済みプラグイン」で Kadence Blocks 、 Gutenberg Blocks for Page Builder Features を探す。バージョン番号が 7.3.3 以上であれば、この不具合の影響を受けている可能性が高い。日本語環境では「Kadence Blocks(旧 Kadence Gutenberg Blocks)」と表記される場合もある。

一度 Kadence Blocks を削除せずにダウングレードするための準備

WordPress の仕様上、管理画面から直接古いバージョンを上書きインストールすることはできない。必ず一度無効化と削除を行い、その後 7.3.2 以前の ZIP ファイルを手動でアップロードする流れになる。ただし、削除してもデータベースに保存されているブロックの設定は消えないため、再度同じプラグインを導入すれば以前のデザインは保持される。

STEP 1 Kadence Blocks をライブラリから削除する
↓
STEP 2 旧バージョンのZIPを入手し、アップロードしてインストール
↓
STEP 3 有効化してサイトキャッシュを削除すれば完了

STEP 1:Kadence Blocks を無効化して削除する

「プラグイン」画面で Kadence Blocks を無効化し、続けて削除を実行する。「本当に削除してもよいか」という確認画面では、そのまま操作を進めて問題ない。削除によってブロックのレイアウトデータが消えることはなく、再度インストールすれば以前の状態に復元される。

STEP 2:7.3.2 以前のバージョンを手動でインストールする

WordPress.org の Kadence Blocks プラグインページにアクセスし、「アドバンスビュー」から「バージョンを選択」のドロップダウンで 7.3.2 を選び、ZIP ファイルをダウンロードする。バージョン一覧のURLは https://wordpress.org/plugins/kadence-blocks/advanced/ の末尾からアクセスできる。ダウンロードしたら「プラグイン」→「新規追加」→「プラグインのアップロード」から ZIP を選択し、「今すぐインストール」を実行する。

STEP 3:有効化してキャッシュをクリアする

インストール完了後、忘れずに Kadence Blocks を有効化する。続いて、サイトのキャッシュ系プラグイン(W3 Total Cache や WP Super Cache など)で全キャッシュを削除し、ブラウザのキャッシュもリロードして最新の状態を確認する。これでナビゲーションAdvブロックのフォント設定が元どおり反映されるはずだ。

ダウングレードが難しい場合の応急策と今後の注意点

WordPress の自動更新を一時的に停止しておく

Kadence Blocks に限らず、プラグインの自動更新が有効になっていると知らないうちにバグのあるバージョンに上がってしまい、同じ現象が再発する。とくに本番サイトでは「プラグイン」→「インストール済みプラグイン」の各プラグインに表示される「自動更新を有効化」のチェックが外れている状態を推奨し、アップデートはステージング環境で検証してから手動で行う習慣が安心だ。

プラグイン側の修正パッチを追う

この二重括弧の不具合は Kadence Blocks の無料版でも再現する純粋なバグのため、開発者のもとですでに修正が進められている可能性が高い。公式の変更履歴(Changelog)を定期的に確認し、次の安定版リリースがあれば速やかに導入することが基本となる。

よくある質問

ダウングレードしたがまだフォントが反映されない

ブラウザキャッシュや CDN のキャッシュに古いスタイルシートが残っているケースだ。シークレットウィンドウで表示確認するか、管理画面の「外観」→「カスタマイズ」で該当のナビゲーションブロックの設定を一度開いて「公開」を押し直すと、強制的に新しい CSS が生成されて直ることが多い。

ほかの Kadence ブロックも同じ現象が起こるのか

今のところ報告が集中しているのはナビゲーション(Adv)ブロックのみだ。ただし Kadence の高度なブロック群で似たような CSS 生成の仕組みを使っている可能性はゼロではないため、別のブロックで表示の異常を見つけた場合は同じ手順でバージョンを戻してみると切り分けになる。

Pro 版の Kadence Blocks でも同じバグは起こるのか

今回の不具合は無料版のコア機能に起因しており、Pro 版を併用している環境でも 7.3.3 以降に更新すればまったく同じように発生する。ダウングレードの手順も無料版と変わらない。

プラグインを削除せずに直す方法はないのか

functions.php などでフィルターフックを使い、動的に二重括弧を除去するコードを書くことは理論上可能だが、すべてのブロックに干渉するためリスクが高い。安全をとって旧バージョンに戻す方が現実的だ。

この記事のポイント

  • Kadence Blocks 7.3.3 以上でナビゲーションAdvブロックのフォント設定が消えるのは、インラインCSSの二重括弧が原因
  • 解決の最短手段は 7.3.2 以前へのダウングレードとキャッシュクリア
  • プラグインの削除・再インストールでデータは消えず、設定も維持される
  • 自動更新を止めて、本番適用前に検証する運用が望ましい
  • 公式の修正パッチがリリースされ次第、最新版に戻して問題ない
佐々木 太陽
WooCommerceで国別価格設定後にカートで価格が18%下がる原因

WooCommerceで国別価格設定後にカートで価格が18%下がる原因

国別価格プラグインとWooCommerceの標準税設定を併用していると、商品をカートに入れた瞬間に約18%引きの価格が表示される現象が起きる。これはインド向けの税率が米ドル建ての表示価格にまで漏れ出し、税抜き再計算が走ってしまうためだ。

なぜカートで価格が18%下がるのか

なぜカートで価格が18%下がるのか

カートに追加した直後に129ドルが約109ドルに減る理由は、WooCommerceの「税設定」と「価格表示」に潜む優先順位の構造にある。販売地域がインドで基本通貨を米ドルに設定し、かつ国別価格プラグインで国ごとに異なる価格を手動入力している店舗では、インド向けの18%税率が米ドル表示側に干渉しやすい。

WooCommerceの税設定には「税込で価格を入力する」か「税抜きで入力する」かの二択がある。税込(ベース価格に税が含まれている前提)を選ぶと、システムは表示価格を税込み総額とみなし、該当する税率に基づいて税抜き部分と税額に内部で分離する。ここに、本来その国には適用されるはずのないインドの18%スラブが食い込むと、129ドルを「税抜き価格+18%税相当」と計算し直し、税抜き価格約109ドルをカートに表示してしまう。

特にPrice Based on Country系のプラグインは、通貨ごとに手動価格を入力できても、WooCommerceの標準税テーブルと密接に連動しているわけではない。このため国検出ロジックと税ルールが別々に動き、非インド顧客の米ドル表示にもインド税率がかぶさる不整合が起こる。

税テーブルと国別価格の干渉を解消する手順

税テーブルと国別価格の干渉を解消する手順

不整合の根源である税テーブルを整理し、適用範囲を正しく限定すれば価格の引き下げは止まる。管理画面から次の流れで修正する。

STEP 1 WooCommerceの「設定」→「税」を開き、税率一覧を確認する
↓
STEP 2 インド向け税率の「国」欄が「IN」のみであることを確認し、誤って「全地域」などになっていれば修正する
↓
STEP 3 税設定の「税込で価格を入力する」を一旦「税抜きで価格を入力する」に切り替え、すべての通貨で正しい価格を再入力する

税率テーブルを開くと、インド向けの18%行の「国コード」欄が空白または複数国に誤設定されているケースがある。これをIN単独に直し、米国など他国に波及しないようにする。Price Based on Countryプラグイン側でも、米ドル表示の国リストに見落としがないか再確認する必要がある。

価格表示オプションの「税込」「税抜」を整理する

価格表示オプションの「税込」「税抜」を整理する

税込み入力モードは税テーブルと不可分に動くため、通貨ごとに手動価格を割り当てる運用との相性が悪い。税抜き入力に切り替えて価格を純粋な本体金額とし、税は決済時に国ごとのテーブルにしたがって自動加算する形が安定する。

ただし切替時に既存商品の価格は変わらないため、129ドルと入力していた商品は税抜き129ドルとみなされ、かえって値上がりする。そこで切り替え後は全商品の価格を意図した税抜き金額(たとえば税込み表示にしたいなら本体109ドル前後)に書き換える作業が必要になる。国別価格プラグインに一括更新機能があれば活用すると手間を減らせる。

Before 税込み入力モード
商品価格 129ドル → 自動で18%税抜き計算 → カートに109ドル表示
↓
After 税抜き入力モード
商品価格 109ドル(本体) → 税は決済時のみ加算 → カート表示は109ドルで安定
■ 税込み入力で誤動作  ■ 税抜き入力で安定

税込み入力モードのまま運用を続ける場合は、インドの税率をいったん無効化し、Price Based on Countryプラグイン側の価格に税込み金額を直接登録する方法もある。ただこの方法は今後の税率変更に弱く、国ごとの税計算をWooCommerceの標準機能に任せられなくなるため推奨しない。

よくある質問

米ドル建てに18%の税率が見当たらないのに価格が下がるのはなぜか

米ドル用の税率が存在しなくても、WooCommerceは税込み入力モード時に「顧客の所在地に連動した税率」を内部で適用しようとする。国検出がインドと判定された瞬間に18%スラブが動き、価格が再計算されるのが根本原因だ。

国別価格プラグインを一時停止すればすぐ直るか

プラグインを無効化すると国別の価格表示そのものが消え、全ユーザーに基本通貨の価格が表示されるため、18%引きは起こらなくなる。ただし根本解決ではなく、多通貨販売をあきらめることになる。

税率テーブルでIN以外の国をすべて削除しても問題ないか

税率を適用したい国が増えるたびに行を追加する運用になるが、現在問題が起きている状態よりは安全だ。税率テーブルには最低限必要な国コードだけを残し、ワイルドカード指定は避けることを勧める。

価格を税抜き入力に切り替えた後、カートで税が表示されずに困る場合の対処は

税抜き入力にしたら「表示価格」の設定を「税込み」に戻すと、フロントエンドでは本体価格に税が乗った金額が表示される。この設定は「WooCommerce → 設定 → 税」の「店舗での価格表示」で変更できる。

キャッシュが原因で設定変更がすぐ反映されないときはどうするか

WooCommerceの「ステータス → ツール」から顧客セッションと製品の価格キャッシュをクリアし、さらにサイトキャッシュやCDNキャッシュもあわせて削除する。プライベートウィンドウで確認すると切り分けが早い。

この記事のポイント

  • カートでの価格引き下げは税込み入力モードと国別税率の干渉で起こる
  • 税率テーブルの国コードを見直し、不要な適用範囲を削除する
  • 「税抜きで価格を入力する」モードに統一すれば価格は安定する
  • 設定変更後はキャッシュクリアと価格再設定を忘れずに行う
佐々木 太陽
Contact Form 7 PayPal Stripe Add-onの脆弱性と最新版への更新手順

Contact Form 7 PayPal Stripe Add-onの脆弱性と最新版への更新手順

Contact Form 7 PayPal & Stripe Add-on のバージョン 2.4.9 以前には、PayPal 決済を本来の支払い金額や通貨と無関係に「支払い完了」として通過させてしまう脆弱性がある。最新版へ更新すれば対処でき、放置すると注文だけが成立して金銭が回収できない重大なリスクを抱えるため、至急確認する必要がある。

Contact Form 7 用 PayPal & Stripe Add-on にどんな脆弱性があるのか

Contact Form 7 用 PayPal & Stripe Add-on にどんな脆弱性があるのか

この脆弱性は CVE-2026-9189 として採番されており、攻撃者が PayPal の正当な通知(IPN)に見せかけたリクエストを送信することで、実際の支払い金額や通貨、受取人の一致をまったく検証せずに「支払い済み」とマークできてしまう。プラグインは PayPal からの通知の署名検証は行っていたものの、肝心の取引金額・通貨コード・受取人メールアドレスの突き合わせを実装していなかったため、ゼロまたは極端に低い金額の注文が成立してしまう。

具体的には、フォーム送信時に生成される注文レコードに対して、PayPal のトランザクション ID と支払いステータスのみが照合され、注文時に設定された金額と実際に PayPal 上で決済された金額の比較が行われない。このため、正規のトランザクション ID を悪用、あるいは偽装した通知に対してプラグインが「正当な支払い」と誤認する状況が生まれていた。

Before(脆弱な状態)

PayPal 通知の受信 → 署名検証のみ実施 → 金額・通貨・受取人の検証なし → 0円でも「支払い完了」

↓
After(修正後)

PayPal 通知の受信 → 署名検証 → 金額・通貨・受取人を注文情報と突合 → 一致時のみ「支払い完了」

■ 脆弱な状態 ■ 修正後の状態

上の図が示す通り、修正後は金額・通貨・受取人の3点を必ず比較するロジックが追加されている。この検証が欠けていたことが、支払いバイパスを成立させる根本原因だった。

どのバージョンが影響を受けるのか

どのバージョンが影響を受けるのか

Contact Form 7 PayPal & Stripe Add-on のバージョン 2.4.9 以下が影響を受ける。2026年6月中旬時点で修正済みのバージョンがリリースされており、2.5.0 以降に更新すればこの脆弱性は解消される。

自分のサイトでどのバージョンを使用しているかは、WordPress 管理画面の「プラグイン」→「インストール済みプラグイン」一覧で確認できる。該当プラグインが有効化されている場合は、バージョン番号を直ちにチェックしておきたい。

最新版へ更新する具体的な手順

最新版へ更新する具体的な手順
STEP 1 管理画面「ダッシュボード」→「更新」を開く
↓
STEP 2 該当プラグインの更新チェックボックスをオンにする
↓
STEP 3 「プラグインを更新」をクリックして完了

更新前にサイト全体のバックアップを取得しておくとなお安心だ。更新が完了したら、プラグイン一覧でバージョンが 2.5.0 以降に切り替わっていることを必ず確認する。

更新がすぐに実行できない場合の対処

更新がすぐに実行できない場合の対処

何らかの理由で即時更新が難しい場合は、一時的に PayPal 決済機能を停止し、フォームそのものを別の決済手段に切り替えるなどの対策が有効だ。とはいえ、あくまで暫定的な措置であり、根本対策は最新版への更新以外にない。

プラグインを無効化すれば脆弱性は発動しなくなるが、フォーム経由の PayPal 決済も一切使えなくなる。その間に代替として WooCommerce の標準決済や別のフォームプラグインへ移行する判断も必要になるだろう。

よくある質問

Stripe 決済にも同じ問題はあるのか

この脆弱性は PayPal の通知処理に起因する問題であり、Stripe 側の処理ロジックには同様の不備は確認されていない。ただし、セキュリティ修正の一環で Stripe 関連のコードにも改善が加えられているため、プラグイン全体を最新に保つのが賢明だ。

すでに不正な取引が行われていないか調べる方法はあるか

PayPal の取引履歴と Contact Form 7 の送信ログを突き合わせ、注文金額と実際の決済金額が一致しているかを手動で検証する必要がある。プラグイン自体に取引監査の機能はないため、自社の売上レポートと PayPal の管理画面を定期的に照合する習慣をつけることを推奨する。

自動更新を有効にしていれば問題は起きなかったのか

自動更新が有効でも、WordPress.org のプラグインディレクトリに修正版が配信されるタイミング次第では数時間から数日のラグが生じる。さらに、サイトの更新設定によってはメジャーアップデートが自動適用されないケースもあるため、手動での確認を怠らないほうが安全だ。

このプラグインを使い続けるリスクは他にもあるか

Contact Form 7 のアドオンは多数の開発者によって提供されており、サポートや更新の頻度はプラグインごとにまちまちだ。決済を扱う以上、常に開発が継続され、すみやかにセキュリティパッチが提供されるプラグインを選ぶことが大前提となる。

この記事のポイント

  • Contact Form 7 PayPal & Stripe Add-on 2.4.9 以前に支払いバイパスの脆弱性がある
  • PayPal 通知の金額・通貨・受取人を検証しないため 0 円でも「支払い完了」になる
  • 修正済みの最新版(2.5.0 以降)に更新すれば問題は解消される
  • 更新前にバックアップを取り、バージョン番号を必ず確認する
  • 決済系プラグインは常に最新を保ち、定期的なログ照合を習慣化する
佐々木 太陽
Relevanssiで日本語検索クエリが原因のテーブルフルスキャンを防ぐ

Relevanssiで日本語検索クエリが原因のテーブルフルスキャンを防ぐ

—

Relevanssiで日本語だけの検索クエリがデータベースの全テーブルスキャンを引き起こす問題は、トークナイズ結果が空文字になるケースをカスタムコードで事前に検知し、SQLを発行せずに空の結果を返すことで根本的に回避できる。設定のチューニングと併用すれば、サイト全体の検索パフォーマンスを維持できる。

なぜ日本語の検索クエリでRelevanssiがテーブル全体を読み込むのか

なぜ日本語の検索クエリでRelevanssiがテーブル全体を読み込むのか

Relevanssiは登録された投稿のタイトルや本文を分解し、単語単位でインデックスを作る全文検索プラグインだ。英語などスペースで区切られた言語では問題なく機能するが、日本語や中国語、韓国語といったCJK(中国語・日本語・韓国語)テキストでは事情が異なる。

CJKの文字列は単語境界の空白が存在しないため、Relevanssiが検索クエリを受け取ると、内部のトークナイザ(単語への分割処理)で適切な単位に区切れないことがある。特に、形態素解析エンジンがインストールされていない標準環境では、クエリが解析不能と見なされ、トークンがゼロ個、つまり空の状態になりやすい。

この「空のクエリ」が問題の本質だ。Relevanssiの検索SQLでは、本来なら検索語に基づいてWHERE term = '検索語'のように絞り込む。しかしトークンが空になると、検索語を表す変数に何も入らず、SQLがWHERE term = termという常に真になる条件へと崩れる。結果としてwp_relevanssiテーブルの何百万行という全レコードを走査するフルスキャンに陥り、応答に数十秒かかる事態を引き起こす。

これはバグではなく、空のクエリに対するフォールバック(予備動作)が設計上考慮されていないために発生する。本来なら検索語が存在しないと判断された時点で、データベースに問い合わせず「該当なし」を返すのが望ましい。

検索クエリが空になるのをコードで検出し早期リターンする

検索クエリが空になるのをコードで検出し早期リターンする

最も確実な解決策は、RelevanssiがSQLを構築する前に検索クエリの内容をチェックし、有効なトークンがなければ検索処理を打ち切る仕組みをテーマのfunctions.phpに組み込むことだ。Relevanssiは複数のフィルターフックを提供しており、そのうちrelevanssi_search_okまたはrelevanssi_modify_wp_queryを利用する。

具体的な実装コードと設置手順

STEP 1 子テーマまたはカスタムプラグインの準備
↓
STEP 2 functions.php にフィルターフックを追加
↓
STEP 3 検索クエリのトークン有無を判定する条件を記述
↓
STEP 4 空の場合は検索をキャンセルし空結果を返す

このデモが示す流れで、コードを追加する。以下は実際に利用できる実装例だ。

add_filter( 'relevanssi_search_ok', function( $ok, $query ) {
    // 検索クエリが文字列であり、内容が空でないか確認する
    if ( ! is_string( $query->query_vars['s'] ) || '' === trim( $query->query_vars['s'] ) ) {
        return false; // 検索を実行せず早期リターン
    }

    // スペースを除いたテキストがCJK文字だけで構成されているか簡易チェック
    $search_term = trim( $query->query_vars['s'] );
    // CJK統合漢字・ひらがな・カタカナ・ハングルの正規表現
    $cjk_pattern = '/[\x{4e00}-\x{9faf}\x{3040}-\x{309f}\x{30a0}-\x{30ff}\x{ac00}-\x{d7af}]+/u';
    preg_match_all( $cjk_pattern, $search_term, $matches );

    // マッチしたCJK文字列が存在するかを確認
    if ( empty( $matches[0] ) ) {
        // CJK文字がなければ通常の検索を続行
        return $ok;
    }

    // 簡易的なトークン判定: Relevanssiが実際に使うトークナイザを再現
    // ここではCJKクエリが本当にインデックス可能か簡易判定する
    $tokens = relevanssi_tokenize( $search_term, true );
    if ( empty( $tokens[0] ) ) {
        return false; // 有効なトークンがないため検索中止
    }

    return $ok;
}, 10, 2 );

このコードでは、Relevanssiの内部関数relevanssi_tokenize()を呼び出し、実際に検索に使われるトークンが生成されるかどうかを見ている。もし空の配列が返ってきたら、それは全テーブルスキャンを引き起こす危険な状態だと判断し、falseを返すことで検索SQLの実行そのものをブロックする。

もうひとつ重要なのは、relevanssi_search_okフィルターがSQL構築の直前で動作するため、無駄なクエリがデータベースに発行される前に検索を止められる点だ。サイトの規模が大きく、wp_relevanssiテーブルが数百万行を超える場合でも、安全に空の結果を返せるようになる。

テーマの functions.php に追加する際の注意点

コードは必ず子テーマのfunctions.phpまたは専用のカスタムプラグインに記述する。親テーマのfunctions.phpを直接編集すると、テーマのアップデートで変更が失われる。また、PHPのバージョンが7.4以上であることをあらかじめ確認しておく。

コードを追加したら、日本語だけで構成された検索クエリを実際に投げてみる。検索結果がゼロ件で返ってくることを確認し、同時にMySQLのスロークエリログやQuery Monitorプラグインで、フルスキャンが発生していないかチェックすると確実だ。

データベースの負荷を根本的に下げるRelevanssiの設定

データベースの負荷を根本的に下げるRelevanssiの設定

コードによる早期リターンと並行して、インデックスと検索設定そのものを見直すことで、CJKクエリ以外の場面でもパフォーマンスを向上させられる。

最小文字数制限をCJKに合わせて調整する

Relevanssiの管理画面には「インデックスを作成する最小文字数」という設定がある。デフォルトでは2文字程度に設定されていることが多いが、CJK環境では1文字でも意味を持つ(例: 「本」「水」など)ため、1に下げるのが基本だ。ただし、1文字にするとインデックスサイズが膨張しやすいため、サイトの投稿規模に応じて2以上にするか、あるいは後述の文字種フィルタリングと組み合わせる。

検索から除外する投稿タイプやステータスを絞る

wp_relevanssiテーブルが肥大化する大きな要因は、リビジョンや自動下書き、非公開のカスタム投稿タイプまでインデックスに含めているケースだ。設定画面の「インデックスを作成する投稿タイプ」で、実際にサイトのフロントエンド検索で必要になる投稿タイプと公開済みのものだけに限定する。リビジョンが無駄に行を占有しているだけで、テーブルサイズが数割変わることもある。

MySQL / MariaDB のバッファ設定を最適化する

13万投稿、1300万行のインデックスを持つ規模では、サーバーのデータベース設定そのものがボトルネックになる。特にinnodb_buffer_pool_sizeをサーバーの物理メモリの70%程度に設定し、Relevanssiのテーブル全体がメモリに収まるようにすると、たとえスキャンが発生してもディスクI/Oを避けられる。設定変更は必ず本番環境でテストした後に適用する。

よくある質問

コードを追加した後、通常の英語検索に影響はないか

上記のコードは、トークンが空になる場合にのみ検索を中止する。英語のスペース区切りクエリや、英数字が混在する日本語クエリでは通常どおりRelevanssiのインデックスが使われるため、影響はない。万が一、正常な検索がブロックされていると感じたら、relevanssi_tokenize()の結果をエラーログに出力して確認する。

Relevanssi以外の全文検索プラグインでもこの問題は起こるのか

起こりうる。特にPHPベースのトークナイザに依存するプラグインでは、CJK文字の分割に失敗すると同様の空クエリ問題が発生する可能性がある。検索プラグインを選定する際は、形態素解析(MeCabなど)に対応しているか、もしくは外部の検索エンジン(Elasticsearch、Algoliaなど)と統合できるかを基準にするとよい。

大量のクローラーからCJKクエリを繰り返し受けている場合の対策は

検索クエリが空になるパターンは、ボットがランダムな文字列や日本語の記事タイトルを検索ボックスに投げ込むことで頻発する。コードによる早期リターンでサーバー負荷は防げるが、さらにCloudflareやWAFのレート制限で同一IPからの過剰な検索リクエストを制限すると、クローラー起因のリソース浪費全体を抑えられる。

functions.php を触れない環境で他にできることはあるか

管理画面のRelevanssi設定で「検索を許可する最低文字数」を意図的に上げる(例: 3文字)方法がある。ただし、これは短い日本語の単語が検索できなくなる副作用を伴う。根本解決にはならないが、緊急のパフォーマンス低下を抑える応急処置としては有効だ。

この記事のポイント

  • 日本語のみの検索クエリでRelevanssiが全テーブルスキャンに陥る根本原因は、トークナイズ結果が空になりSQLが常に真になるため
  • カスタムコードでSQL実行前に空トークンを検出し、早期リターンさせることでデータベース負荷を回避できる
  • インデックスの最小文字数制限や対象投稿タイプの絞り込みをCJK向けに最適化すると、さらなるパフォーマンス改善につながる
  • コード追加後も通常の英数字検索には影響を与えず、安全に運用できる
  • クローラーからの大量アクセスに対してはWAFやレート制限との併用が効果的
佐々木 太陽
WooCommerce MyParcelで重大エラーが出た時のデフォルト配送業者設定方法

WooCommerce MyParcelで重大エラーが出た時のデフォルト配送業者設定方法

WooCommerce の MyParcel プラグイン使用時に表示される「このサイトで重大なエラーが発生しました」というエラーは、プラグイン内にデフォルトの配送業者が設定されていないことが原因だ。プラグイン設定画面からデフォルトの配送業者を選択すれば、エラーはすぐに解消する。

なぜデフォルト配送業者が未設定だとエラーになるのか

なぜデフォルト配送業者が未設定だとエラーになるのか

このエラーは PHP の致命的エラー(Fatal Error)であり、MyParcel プラグインが「No default carrier available(利用可能なデフォルトの配送業者がない)」という例外を発生させて停止している。スタックトレースを追うと、発端は受注確認ページ(サンキューページ)などで追跡情報を表示しようとする際、プラグインが内部的に呼び出す getDefaultCarrierOrThrow() メソッドで落ちている。

MyParcel は配送ラベル作成や追跡情報の連携を行うプラグインであり、動作には「どの配送業者をデフォルトで使うか」という情報が必須だ。この設定を一度も行っていなかったり、アップデート時に何らかの理由で消えたりすると、サイトの該当ページでエラーが表示される。

≪ エラー発生時 ≫
MyParcel プラグインがデフォルトの配送業者を取得できず、例外をスロー
↓
≪ 設定後 ≫
デフォルト配送業者が設定され、プラグインが正常に動作
■ 設定未完了状態 ■ 設定完了後

デフォルト配送業者を設定する具体的な手順

デフォルト配送業者を設定する具体的な手順
STEP 1 WordPress 管理画面にログインし、左メニューから「WooCommerce」→「MyParcel」を開く
↓
STEP 2 「設定」タブを選択し、「デフォルトの配送業者」項目を探す
↓
STEP 3 プルダウンから利用する配送業者(例: ヤマト運輸や佐川急便など契約中のもの)を選択する
↓
STEP 4 画面下部の「変更を保存」をクリックし、エラーが消えたか確認する

管理画面にアクセスできる状態であれば、この手順だけでエラーは即座に解消する。設定項目の名称はプラグインバージョンによって「デフォルトの配送業者」「Default Carrier」などと表記が異なるが、いずれも一つのプルダウン形式で表示される。

管理画面にすらアクセスできない場合の対処

エラーがサイト全体に影響し、管理画面も真っ白になってしまうケースがある。その場合は FTP またはサーバーのファイルマネージャーを使い、一時的に MyParcel プラグインのフォルダをリネームして無効化する。

  • サーバーに接続し、/wp-content/plugins/ ディレクトリへ移動する
  • woocommerce-myparcel フォルダを woocommerce-myparcel_deactivated などに変更する
  • これでプラグインが停止し、管理画面へアクセスできるようになる
  • 管理画面に入れたら、上の STEP 手順で設定を行い、フォルダ名を元に戻して有効化する

設定を保存してもエラーが再発する場合

設定保存後に再び同じエラーが発生するなら、プラグインまたは関連データベース設定に不整合が起きている可能性が高い。以下の順で追加対応を試す。

  • 一度プラグインを完全に削除し、最新バージョンを再インストールする
  • WooCommerce のシステムステータス画面で、不要なトランジェント(期限付きキャッシュ)をクリアする
  • MyParcel アカウントとの API 接続情報(API キーなど)を再入力する

エラーを未然に防ぐための注意点

エラーを未然に防ぐための注意点

プラグインのメジャーアップデート後や WordPress 本体の自動更新後に、こうした設定がリセットされる事例は珍しくない。MyParcel に限らず、配送系・決済系プラグインは「接続先のデフォルト設定」が必須となるものが多い。アップデート後はテスト環境や低トラフィック時間帯に決済フローとサンキューページの動作を一通り確認する習慣をつけると安心だ。

よくある質問

エラーメッセージが英語で「No default carrier available」と表示されているが日本語環境でも同じ?

日本語環境の WordPress でも管理画面やログに表示されるエラーメッセージは英語のままになる。ただしサイト訪問者には「このサイトで重大なエラーが発生しました」という日本語の汎用エラー画面が表示されるため、管理者はサーバーのエラーログやデバッグモードで英語エラーを確認することになる。

MyParcel 以外の配送プラグインでも同様のエラーは起こる?

配送ラベル生成や追跡機能を持つプラグインは、内部で配送業者を特定する仕組みに依存していることが多く、設定不足で同種のエラーが起きる可能性がある。具体的には「デフォルトの配送業者」「デフォルトの配送方法」が未選択であると、ページ表示時に致命的エラーになる構造は共通している。

Divi テーマを使っていることがエラーと関係ある?

スタックトレースに Divi のパスが含まれているのは、サンキューページを Divi の WooCommerce モジュールで構築しているためだ。エラーの根本原因はあくまで MyParcel プラグイン側の設定不足であり、Divi そのものに問題があるわけではない。

デフォルトの配送業者を設定しても配送ラベルが発行できない

デフォルト配送業者の設定はエラー解消の第一歩だが、実際にラベルを発行するには MyParcel アカウントとの正しい API 接続と、WooCommerce の配送クラスや商品重量の設定が必要になる。エラーが消えた後は、MyParcel の管理画面で接続ステータスが「アクティブ」になっているか確認する。

この記事のポイント

  • PHP の致命的エラーは MyParcel のデフォルト配送業者未設定が原因
  • 管理画面の MyParcel 設定からデフォルト配送業者を選択して保存すれば解決
  • 管理画面に入れない場合はプラグインフォルダのリネームで一時無効化する
  • アップデート後は配送系プラグインの設定リセットに注意が必要
佐々木 太陽
Contact Form 7のPDF出力で条件分岐ショートコードが効かない時の直し方

Contact Form 7のPDF出力で条件分岐ショートコードが効かない時の直し方

Contact Form 7 から出力する PDF に条件分岐のショートコード([if] や [hide-*] など)が反映されないとき、最も多い原因は Send PDF for Contact Form 7 プラグインが、Conditional Fields のような他プラグインのショートコードを PDF 生成時に評価しないことだ。この問題は、PDF テンプレート内で直接条件分岐を記述する代わりに [_mail_body] タグを使ってメール本文を丸ごと流し込むか、出力直前にショートコードを再評価するフィルターフックで解決できる

なぜ PDF 出力で条件分岐ショートコードが効かなくなるのか

なぜ PDF 出力で条件分岐ショートコードが効かなくなるのか

Send PDF for Contact Form 7 は、フォーム送信時に生成されたデータを PDF テンプレートに差し込んで出力する。このとき、[text-123] のような Contact Form 7 の標準タグは正しく展開されるが、Conditional Fields が提供する [group] や [if] といった条件分岐用のショートコードは、PDF 生成のコンテキストでは実行されないことが多い

理由は主に2つある。ひとつは、これらのショートコードが WordPress の do_shortcode フックに登録されていても、PDF プラグインがテンプレートを処理する段階では、フォームの送信データや条件判定に必要なコンテキストが不足しているケースだ。もうひとつは、Conditional Fields のショートコードが「メール送信時」にのみ動作するように設計されており、PDF 作成時にはそもそも処理の対象外になっているパターンだ

Before(修正前) PDF 内の表示

[if kosten-an-arbeitgeber]この見積は雇用主向けです[/if]

※条件にかかわらずショートコードがそのまま表示される

↓
After(修正後) 同じ場所の表示

この見積は雇用主向けです

※条件に合致したテキストだけが PDF に出力される

■ 修正前 ■ 修正後

このデモのように、PDF テンプレート内に [if] や [hide-*] を直書きしても、Send PDF 側で解釈されずに終わってしまう。以前は偶然動いていたとしても、プラグインのバージョンアップで処理順序が変わると即座に壊れる原因になる

プラグイン更新後に突然動かなくなったのはなぜか

プラグイン更新後に突然動かなくなったのはなぜか

「以前は PDF で条件分岐が効いていたのに、更新したら動かなくなった」という声は非常に多い。これは、Send PDF for Contact Form 7 または Conditional Fields for Contact Form 7 の内部実装が変更され、テンプレートの評価タイミングやショートコードの登録順が変わったためだ

具体的には、Send PDF プラグインの旧バージョンでは、PDF テンプレート全体を do_shortcode で処理していたが、パフォーマンスやセキュリティの改善に伴ってその処理が省略されたり、独自の置換処理に切り替わったりすることがある。結果として、Conditional Fields のショートコードが一切処理されなくなる

また、Conditional Fields 側のアップデートで、[if] タグの内部実装が変わり、PDF 出力時に必要なデータが揃わなくなった可能性もある。どちらにせよ、PDF テンプレート内で直接条件分岐を記述する方式は、プラグインのバージョンに依存しやすく、根本的に不安定と言える

[_mail_body] タグでメール本文をそのまま PDF に流し込む

[_mail_body] タグでメール本文をそのまま PDF に流し込む

最も簡単で安全な解決策は、PDF テンプレート内に [_mail_body] を記述することだ。このタグは、Contact Form 7 が送信する「メール本文」をそのまま PDF 内に差し込む。メール本文のほうでは、Conditional Fields の条件分岐が正常に評価されているため、結果的に PDF にも正しい内容が出力される

STEP 1 Contact Form 7 の「メール」タブで、条件分岐を含むメール本文を完成させる
↓
STEP 2 Send PDF のテンプレート編集画面を開き、本文にあたる領域で [_mail_body] とだけ入力する

この方法を使えば、Conditional Fields に限らず、メール本文で動作するあらゆるショートコードが PDF に反映される。ただし、PDF 独自のレイアウトや追加情報(会社ロゴや利用者に合わせた細かな差し込み)が必要な場合は、[_mail_body] の前後に固定の HTML を加えることで対応できる

注意点として、[_mail_body] はメール本文をそのままコピーするため、メール用の改行やスタイルが PDF に持ち込まれる。どうしてもレイアウトを細かく制御したい場合は、次に紹介するフィルターフックを使った方法を選ぶ

functions.php で PDF 生成前に条件分岐を再評価させる

functions.php で PDF 生成前に条件分岐を再評価させる

Send PDF for Contact Form 7 には、PDF の最終的な内容を上書きできるフィルターフックが用意されている。これを利用すれば、テンプレート内の [if] や [hide-*] を手動で再評価できる。テーマの functions.php に次のようなコードを追加すると、Conditional Fields のショートコードが PDF 出力時に正しく展開される

add_filter( 'cf7_send_pdf_template_html', function( $html, $form_id ) {
    // フォームの送信データを取得し、ショートコードを再評価する
    $submission = WPCF7_Submission::get_instance();
    if ( $submission ) {
        $posted_data = $submission->get_posted_data();
        // 一時的に do_shortcode を再度適用
        $html = do_shortcode( $html );
    }
    return $html;
}, 10, 2 );

このコードは、PDF テンプレートが組み立てられた直後に do_shortcode を実行し、[if] や [group] といったショートコードをその場で評価する。投稿データが揃っているため、Conditional Fields の条件判定も正しく動く

ただし、[hide-*] のように独自のショートコードを使っている場合は、そのショートコードがどのプラグインで定義されているかを確認し、該当のプラグインが有効でなければ動作しない。もし自作のショートコードであれば、あらかじめ add_shortcode で登録しておく必要がある

さらに、Send PDF プラグインのバージョンによってはフック名が異なる可能性もあるため、公式ドキュメントを参照し、cf7_send_pdf_template_html の部分を適切なフックに置き換える。このフックが利用できない場合は、wpcf7_before_send_mail などのアクションを使って PDF 生成前にデータを補完する方法もある

よくある質問

[_mail_body] を使うとメールの HTML タグがそのまま PDF に出てしまうのでは?

はい、メールフォーマットが HTML の場合、その HTML が PDF に適用される。多くは問題にならないが、シンプルなテキスト PDF を望むなら、メール設定を「テキスト形式」に切り替えるか、フィルターフックで HTML タグを strip_tags で除去するといった工夫が必要になる

Conditional Fields の [group] ショートコードも [_mail_body] で有効になるのか?

なる。[_mail_body] は、メール送信時に CF7 が最終的に組み立てた本文をそのまま埋め込むため、[group] の条件判定もすでに解決された状態で出力される

functions.php にコードを追加しても PDF が変わらないのはなぜ?

フック名が正しいか、また対象のショートコードが本当に do_shortcode で評価可能な形式かを確認する。Conditional Fields の [if] が内部で別のロジックを使っているレアケースでは、CF7 のメールテンプレート用のフィルター(wpcf7_mail_components など)を利用してメール本文を直接 PDF に渡すほうが確実だ

独自の [hide-*] ショートコードを PDF で動かすにはどうすればいい?

該当のショートコードを定義しているコードがテーマの functions.php にあるなら、そのまま do_shortcode で評価される。もし別のプラグインに依存しているのであれば、そのプラグインが常に有効でなければならない。動作が不安定な場合は、[_mail_body] 方式に切り替えるのが無難だ

この記事のポイント

  • PDF テンプレート内で [if] や [hide-*] が効かないのは、Send PDF がそれらのショートコードを処理しないため
  • [_mail_body] タグを使えば、メール本文ですでに展開された条件分岐結果をそのまま PDF に流し込める
  • functions.php のフックで do_shortcode を再実行すれば、PDF 出力直前に任意のショートコードを動かせる
  • プラグイン更新後に動かなくなったのは、ショートコード処理のタイミングが変わったのが原因
  • 安定運用には[_mail_body]方式を推奨。細かいレイアウトが必要ならフィルターフック方式を使う
佐々木 太陽
Contact Form 7でスパムメールが大量に届く時の根本対策

Contact Form 7でスパムメールが大量に届く時の根本対策

Contact Form 7から件名や本文が空、または広告だけのスパムメールが大量に届くようになった状態は、ハニーポット(honeypot)と呼ばれる手法やシンプルな送信条件の制限を組み合わせることで、高い精度でブロックできる。

なぜContact Form 7にスパムが届くのか

なぜContact Form 7にスパムが届くのか

お問い合わせフォームを設置したばかりのサイトは、公開直後から自動巡回するスパムボットの標的になる。ボットはPHPで生成されたフォームの構造を解析し、name属性やclass名を把握したうえで、迷惑メールの配信やSEO用の被リンク売り込みなどを自動送信する。Contact Form 7は世界中で使われているため、ボット側も「どのフィールドに何を入れれば送信が通るか」を熟知している。そのため、標準の状態ではほとんどのボットが素通りしてしまう。

ボットが大量のスパムを送り込むことによって、メールサーバーの評判低下や共用サーバーのリソース浪費、管理用メールアドレスのブラックリスト入りといった二次被害が発生する可能性がある。件名や本文が空に近いメールが届くときは、すでにボットによる自動送信が常態化しているとみてよい。

Before(対策なし)
ボットがフォームの全項目を埋めて送信
空の件名・本文のメールが毎分数十件届く
↓
After(ハニーポット+制限)
人間だけが条件をクリアして送信
スパムはサーバー側ではじかれメールも届かない
■ 対策前の状態  ■ 対策後の状態

このデモは、対策の有無でスパムの到達状況がどう変わるかを示したイメージだ。対策を入れない限り、ボットはフォームの構造を正確に読んで送信を成功させてしまう。

ハニーポットでボットを静かにブロックする方法

ハニーポットでボットを静かにブロックする方法

ハニーポット(honeypot)とは、人間には見えずボットだけが反応する「罠」のフィールドをフォームに仕込む対策を指す。reCAPTCHAのようにユーザーに手間をかけず、Ajaxの競合リスクも低いため、Contact Form 7との相性が非常によい。

CSSで見えないチェックボックスを設置する

ボットは画面に表示されるかどうかを判断せず、HTMLソース内のすべてのフィールドを機械的に入力しようとする性質を持つ。この行動を利用し、人間には表示されないチェックボックスをフォームに追加する。チェックボックスにチェックが入った状態で送信された場合は、ボットとみなして送信を破棄する、という仕組みだ。

参考までに、公式のContact Form 7は、独自の同意チェックボックスであるacceptance(承諾)タグに対して invert default:on という属性をサポートしている。これは「デフォルトでチェックが入っており、人間だけが外せる」という逆転ロジックを作れる機能だ。ボットはチェックを外す操作を行わないため、罠として機能する。

ただし、acceptanceタグを使う方法は、実際にはCSSでフォーム項目をサイト上で見えなくする処理と組み合わせて使う必要がある。そうしないと、サイトを訪れた人間が混乱する原因になるためだ。

STEP 1 フォーム編集画面で該当フォームを開く
↓
STEP 2 htmlのタグを追加する
<span class=”hp-check”>[acceptance hp-check invert default:on]空のまま送信してください[/acceptance]</span>
↓
STEP 3 サイトの追加CSSに非表示設定を追記する
.hp-check { display:none; }
↓
STEP 4 変更を保存し、動作を確認する
ブラウザのデベロッパーツールでタグが非表示になっているか確認する

この手順ではCSSで視覚的に完全に隠すため、サイト訪問者はこのチェックボックスを一切意識せずに送信できる。一方、ソースコードを解析して全フィールドを埋めようとするボットは、デフォルトでオンになっているチェックを外さないまま送信するため、Contact Form 7のバリデーションでエラー扱いとなりメールが飛ばない。

acceptanceタグのロジックに過度に依存しない

acceptanceの逆転ロジックは簡易なボットに対しては有効だが、高度なボットはチェックボックスの状態を操作できるケースも報告されている。また、CSSを解析してスタイルを操作するスクリプトには、非表示の項目を見抜かれてしまう可能性もある。そのため、ハニーポットはあくまで一次フィルターと捉え、次の追加対策と組み合わせることが現実的な防御線だ。

reCAPTCHA v3でユーザー負荷をかけずに判別する

reCAPTCHA v3でユーザー負荷をかけずに判別する

Contact Form 7はGoogle reCAPTCHA v3のインテグレーションを公式にサポートしている。reCAPTCHA v3は「私はロボットではありません」のチェックボックスや画像選択のような操作をユーザーに一切求めず、ページ滞在中のマウスの動きやスクロールといった行動データをもとにスコアリングし、スパムの可能性が高い送信をブロックする仕組みだ。

設定はGoogle reCAPTCHAの管理画面でサイトキーとシークレットキーを取得し、WordPress管理画面の「Contact」→「Integration」からreCAPTCHAの項目にキーを入力するだけで完了する。v2の「チェックボックス方式」は一部の環境でAjax送信との競合を起こすことがあるが、v3はその心配が少ない。フォームに直接ウィジェットが表示されないため、デザインを損なわない利点もある。

reCAPTCHA 設定フロー
Google管理画面 → サイトキー取得 → WordPress連携設定 → スコア判定で防御
※ v3ではサイト訪問者に操作画面は一切表示されない

このフローは、reCAPTCHA v3導入の全体像を示したものだ。v2と異なり、Widgetの操作ステップが存在しないため、サイトの表示速度やユーザー体験への影響を最小限に抑えつつ、高精度なボット検知を実現できる。

メール本文に日本語必須ルールを追加する

メール本文に日本語必須ルールを追加する

海外から大量に届くスパムの多くは、英語や中国語、あるいは記号だけで構成されている。日本語圏のサイトであれば、送信内容に日本語が含まれていることを必須条件にすると、ボットによる自動送信の大半を止められる。Contact Form 7には、特定の文字種を含んでいるかどうかを検証する正規表現(Regex)の機能は標準で備わっていないが、無料の専用プラグインで補うか、functions.phpにフィルターフックを追加して実装できる。

具体的には、wpcf7_validate_text* や wpcf7_validate_textarea* といったバリデーションフックを使い、本文フィールドにひらがな・カタカナ・漢字のいずれかが1文字でも含まれているかをPHPの正規表現でチェックする。条件を満たさない場合はエラーメッセージを返し、メール送信を中止させるという流れだ。この対応は海外発の機械的スパムには極めて有効で、実装の手間に対する防御効果が高い。

よくある質問

ハニーポットを仕込んでもスパムが続く場合は?

ハニーポットだけで防げない場合は、ボットがCSSを解析して非表示フィールドを識別している可能性がある。その場合は、フィールドを完全に非表示にするのではなく、画面上の見えない位置にずらす方法(positionで画面外に飛ばす)や、JavaScriptを使って動的にフィールドを生成する方式に切り替えると効果が上がる。また、reCAPTCHA v3や日本語必須ルールの併用を必ず検討する。

reCAPTCHA v2よりv3のほうが本当に優秀なのか

ボット検知精度はどちらも高いが、v3は操作性と表示速度の面で大きく優れている。v2の画像選択がユーザーの離脱を招いたり、Ajaxフォームとの競合で送信エラーを起こす場面が減るため、問い合わせフォームとの相性という観点ではv3の導入が望ましい。ただし、v3はサイト全体のスコアリングを行うため、プライバシーポリシーへの記載が必要になる。

Contact Form 7以外のフォームに切り替えたほうがよいか

スパム対策だけを理由にフォームプラグインを移行する必要はない。Contact Form 7は世界的に使われている分、ボットの標的になりやすい面はあるが、今回紹介した対策を適切に組み合わせれば実用上十分な防御力を確保できる。移行によって別の競合やカスタマイズの手間が発生するリスクを考えると、まずは手元のContact Form 7を強化する方針が合理的だ。

この記事のポイント

  • Contact Form 7へのスパムは、ボットがフォーム構造を熟知しているために発生する
  • ハニーポット(CSS非表示のチェックボックス)で、人間には影響なくボットをブロックできる
  • reCAPTCHA v3を導入すると、ユーザー操作なしで高精度なスパム判定が可能になる
  • メール本文に日本語の文字種を必須にするルールを追加すると、海外発スパムの大半を遮断できる
  • 単一の対策に頼らず、複数の層を重ねることでボットの突破を防ぐ
佐々木 太陽
Trustindexプラグインの脆弱性、認証なしでトークンが漏洩する問題と対策

Trustindexプラグインの脆弱性、認証なしでトークンが漏洩する問題と対策

Trustindexプラグインのトラブルシューティング用RESTエンドポイントが認証なしでアクセス可能になっていると、Instagram Graph APIのアクセストークンを含む全オプションが外部に漏洩する。HMAC署名のキーに公開情報を使っている設計上の欠陥が原因であり、修正パッチが配布されるまでの間はエンドポイント自体を遮断する応急処置が必要になる。

何が起きているのか 〜 脆弱性の全体像

何が起きているのか 〜 脆弱性の全体像

この問題は、Trustindexの「Instagram Feed」ウィジェットを設置したWordPressサイトで発生する。プラグインは管理画面のトラブルシューティング用に /wp-json/trustindex_feed_hook_instagram/troubleshooting というRESTエンドポイントを用意している。このエンドポイントに正しい署名付きリクエストを送ると、プラグインが保存している全オプション、つまりInstagramのアクセストークンや各種設定をJSON形式で返してしまう。

認証にはHMAC-SHA256による署名検証が使われているが、その署名用の秘密鍵(キー)がサイトごとに公開されている「パブリックID」になっている。このIDは、プラグインが生成するCDNのURL(https://cdn.trustindex.io/wp-feeds/XX/パブリックID/data.json)に含まれ、ページのソースコードやネットワークリクエストを覗けば誰でも取得できる。つまり署名の計算に必要な材料がすべて攻撃者の手に渡ってしまうため、認証がまったく機能していない状態だ。

影響は深刻だ。漏洩したInstagramアクセストークンを使えば、サイト運営者になりすましてInstagram Graph APIを呼び出し、プロフィール情報の取得やメディア投稿の操作が可能になる。トークンの有効期限が切れるか運営者が手動で失効させるまで、不正利用のリスクが続く。

自分のサイトが影響を受けるかどうかの確認方法

自分のサイトが影響を受けるかどうかの確認方法

まず、TrustindexプラグインをインストールしてInstagramフィードを表示しているサイトが対象だ。それ以外のフィード(FacebookやGoogleレビューなど)を使っているだけの場合は、今回のエンドポイントとは関係がない。確認手順は次の3ステップで行える。

STEP 1 ブラウザで自サイトの任意のページを開き、右クリック→「ページのソースを表示」を選択する。
↓
STEP 2 Ctrl+Fで「cdn.trustindex.io」を検索し、URLの中にある英数字2文字+ハイフン+英数字のパブリックIDを見つける。
↓
STEP 3 curlなどのツールでエンドポイントに署名付きリクエストを送り、レスポンスにトークンが含まれていないか調べる。

STEP 3の詳細は、UNIXのターミナルで以下のようなリクエストを投げる。HMACの計算にはパブリックIDと現在のUNIXタイムスタンプを使うため、スクリプトを組むか手動で計算する必要がある。

# PUBLIC_ID と TIMESTAMP は各自の値に置き換える
PUBLIC_ID="取得したパブリックID"
TIMESTAMP=$(date +%s)
SIGNATURE=$(echo -n "$TIMESTAMP" | openssl dgst -sha256 -hmac "$PUBLIC_ID" | awk '{print $2}')
curl -H "X-Signature: $SIGNATURE" -H "X-Timestamp: $TIMESTAMP" \
  "https://あなたのサイトドメイン/wp-json/trustindex_feed_hook_instagram/troubleshooting"

レスポンスに source.access_token や access_token といった文字列が含まれていれば、情報が丸見えの状態だと判断できる。この確認はあくまで自己診断用であり、他者のサイトに対して行ってはならない。

修正パッチが配布されるまでに取るべき応急措置

修正パッチが配布されるまでに取るべき応急措置

プラグイン開発者から公式のアップデートが提供されるまでは、以下のいずれかの方法で該当エンドポイントへの外部アクセスを完全に遮断する。

修正前 誰でもエンドポイントにアクセス可能。トークンが平文で返る
↓
修正後 外部からのアクセスを禁止。管理者のみ必要に応じて利用

.htaccessでエンドポイントをブロックする

サーバーがApacheを使っている場合、WordPressのインストールディレクトリにある.htaccessファイルに以下の記述を追加する。これにより、該当URLへのリクエストは403 Forbiddenで弾かれる。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^wp-json/trustindex_feed_hook_instagram/troubleshooting - [F]
</IfModule>

functions.phpでREST APIアクセスを制限する

テーマのfunctions.php(子テーマ推奨)に下記のコードを追加すると、未ログインユーザーからの該当エンドポイントへのアクセスを拒否できる。管理画面にログインしているユーザーは引き続き利用できるため、サポートが必要になった際にも支障がない。

add_filter( 'rest_authentication_errors', function( $result ) {
    if ( ! empty( $result ) ) {
        return $result;
    }
    $current_route = $GLOBALS['wp']->query_vars['rest_route'] ?? '';
    if ( strpos( $current_route, '/trustindex_feed_hook_instagram/troubleshooting' ) !== false && ! is_user_logged_in() ) {
        return new WP_Error(
            'rest_forbidden',
            'このエンドポイントへのアクセスにはログインが必要です。',
            array( 'status' => 403 )
        );
    }
    return $result;
} );

プラグインを一時停止する判断

Instagramフィードの表示が必須でないなら、脆弱性が修正されるまでプラグイン自体を無効化するのが最も確実だ。フィードが表示されなくなる影響が許容できるビジネスであれば、この選択肢も検討しよう。

すでにトークンが漏洩した可能性がある場合の対処

すでにトークンが漏洩した可能性がある場合の対処

アクセスログを精査して不審なリクエストがなかったか確認するのが先決だが、ログが十分に残っていないケースも多い。疑わしい場合は、以下の手順でトークンを強制的に無効化し、新しいトークンを再発行する。

STEP 1 Facebook開発者コンソールで該当アプリのInstagram Basic DisplayまたはInstagram Graph APIの設定を開く
↓
STEP 2 既存のアクセストークンをすべて取り消し(Revoke)、新しいトークンを生成する
↓
STEP 3 WordPress管理画面でTrustindexプラグインの設定画面を開き、新しいトークンを再入力する

特にInstagram Graph APIのアクセストークンは長期トークン(Long-Lived Token)で運用していることが多く、一度漏洩すると数カ月単位で悪用されるリスクがある。トークン失効後は、フィードが一時的に表示されなくなるが、再設定すればすぐに復旧する。

根本的な原因と再発防止の考え方

根本的な原因と再発防止の考え方

今回の脆弱性の本質は、認証用の秘密情報が公開前提の値になっている設計ミスにある。HMAC署名を使うこと自体は正しいが、秘密鍵が「誰でも見られるURLの一部」にある時点でセキュリティは成り立たない。

プラグイン開発者側が取るべき修正は、プラグイン有効化時にランダムなシークレットを wp_options テーブルに保存し、その値を署名キーに使う方式へ変更することだ。さらに、トラブルシューティングという目的を考えれば、current_user_can('manage_options') で管理者権限を要求するだけでも十分な防御になる。このエンドポイントはあくまでサポートスタッフ向けであり、未認証ユーザーに開放する理由は一切ない。

サイト運営者としても、すべてのプラグインを無条件に信頼するのではなく、導入後に「どんなRESTエンドポイントが増えたか」「公開される情報はないか」をセキュリティプラグインや手動チェックで確認する習慣が身を守る。WordPressのサイトヘルス機能やQuery Monitorのようなツールを普段から使い、異常なAPIリクエストがないか注視しておくことが再発防止につながる。

よくある質問

プラグインのどのバージョンから修正されますか

2026年6月17日時点では、開発者は調査中と回答しており修正バージョンは未発表だ。Trustindexの公式チェンジログとWordPress管理画面の更新通知を定期的に確認し、セキュリティアップデートが配信され次第ただちに適用する必要がある。

応急処置としてプラグインを無効化すると、フィードはどうなりますか

プラグインを無効化すると、Instagramフィードは表示されなくなる。ただ、表示崩れが起こるだけでサイト全体がダウンするわけではない。トークン漏洩のリスクと天秤にかけて、ビジネス上の重要性が高い場合は上記の.htaccessやfunctions.phpによる遮断を選ぶほうが現実的だ。

Instagramのトークンを変えたあと、再度漏洩することはありますか

アプリやサーバー側の脆弱性が修正されていない限り、新しいトークンも同じエンドポイントから再び漏洩する可能性がある。必ず、アクセス制限の応急措置を先に施したうえでトークンを再発行する順序を守ってほしい。

FacebookやGoogleのフィードにも同じ問題はありますか

今回確認されたのは trustindex_feed_hook_instagram のエンドポイントのみだが、同じ認証設計を他のフィード用エンドポイントにも流用している可能性は否定できない。不安があれば、trustindex_feed_hook_facebook や trustindex_feed_hook_google といった類似のエンドポイントが存在しないか、REST APIのルート一覧で確認しておくと安心できる。

自分のサイトがすでに攻撃されたかどうか確かめる方法はありますか

サーバーのアクセスログに /wp-json/trustindex_feed_hook_instagram/troubleshooting へのリクエストが記録されていれば、それが正規のサポート用途か攻撃かを判別する必要がある。あわせて、Instagram Graph APIの使用状況をFacebook開発者コンソールの「アプリのインサイト」で確認し、見覚えのないAPIコールや異常なリクエスト数がないかを調査するのが確実だ。

この記事のポイント

  • Trustindexプラグインのトラブルシューティング用RESTエンドポイントが認証不備によりInstagramアクセストークンを露出させている
  • 原因はHMAC署名の秘密鍵として、誰でも取得できるパブリックIDを使用している設計ミス
  • 修正パッチが配布されるまでは、.htaccessかfunctions.phpでエンドポイントへの外部アクセスを遮断する
  • トークン漏洩が疑われる場合はInstagram側でトークンを即時失効させ再発行する
  • 常にプラグインのREST APIエンドポイントを定期的に監視し、不要な露出がないか確認する習慣が再発防止の鍵
佐々木 太陽
OptinMonsterなど4プラグインのサプライチェーン攻撃、不正管理者を確認する手順

OptinMonsterなど4プラグインのサプライチェーン攻撃、不正管理者を確認する手順

OptinMonster、TrustPulse、PushEngage、Uncanny Automator のいずれかのプラグインを導入している場合、ただちに管理画面の全ユーザー一覧を確認し、身に覚えのない管理者アカウントが作成されていないか点検する必要がある。これらのプラグインに使用されている CDN スクリプトが改ざんされ、悪意ある管理者を自動生成するサプライチェーン攻撃が 2026 年 6 月に確認された。

何が起きたのか 今回のサプライチェーン攻撃の仕組み

何が起きたのか 今回のサプライチェーン攻撃の仕組み

攻撃者はプラグインのソースコードそのものを改変したわけではなく、各プラグインが配信に利用している外部 CDN 上のスクリプトファイルに細工を施した。このため、プラグイン自体のバージョンアップや通常のマルウェアスキャンでは異常を検知しにくいのが特徴だ。

改ざんされたスクリプトは、サイトのフロントエンドに読み込まれる形で実行され、裏側で WordPress のユーザー登録 API を突いて新規の管理者アカウントを作成する。攻撃者がすでに管理者権限を取得している場合、サイトの改ざんや情報の窃取が自由に行える極めて危険な状態となる。

国内の WordPress サイトでも、マーケティングツールとして該当プラグインを導入しているケースは少なくない。攻撃が表面化した時点で、該当プラグインの開発元はすでに CDN 側の改ざんを修正し、侵害された可能性のある顧客への通知を進めているが、すべてのサイト運営者が自らチェックを行うことが被害の深刻化を防ぐうえで決定的に重要だ。

攻撃前
プラグインが正常な CDN スクリプトを配信している。
サイトに悪意ある管理者は存在しない。
↓
攻撃中
CDN 上のスクリプトが改ざんされる。
サイト訪問時に不正スクリプトが実行され、未知の管理者アカウントが自動生成される。
↓
修正後
CDN の改ざんは解除され、不正ユーザーの削除と全パスワード再設定が必須。
■ 改ざん発生時  ■ 攻撃の実行  ■ 対処後

自分は対象か 影響を受けるプラグインを導入していないか確認する

自分は対象か 影響を受けるプラグインを導入していないか確認する

今回のサプライチェーン攻撃の対象として報告されたのは次の 4 製品だ。いずれか 1 つでも導入している場合は、影響を受けた可能性を前提に全手順を実行する必要がある。

  • OptinMonster(オプティンモンスター)
  • TrustPulse(トラストパルス)
  • PushEngage(プッシュエンゲージ)
  • Uncanny Automator(アンキャニーオートメーター)

プラグイン一覧ページでこれらの名称を検索すれば、導入の有無はすぐに判別できる。ただし、テーマの functions.php に直接コードを埋め込んでいる場合や、カスタム実装で CDN スクリプトを読み込んでいる場合はプラグイン管理画面では発見できないため、サイトのソースコードやタグマネージャーの設定も併せて確認するとより確実だ。

不正な管理者アカウントを特定して削除する手順

不正な管理者アカウントを特定して削除する手順

まず管理画面の「ユーザー」→「ユーザー一覧」を開き、管理者権限を持つアカウントをすべて確認する。身に覚えのない管理者アカウントが存在する場合は、そのアカウントが攻撃によって作成された可能性が極めて高い。

STEP 1 「ユーザー」→「ユーザー一覧」を開き、管理者ロールのアカウントをすべて書き出す。
↓
STEP 2 心当たりのないアカウントがあれば、そのユーザーを即時削除する。
↓
STEP 3 正当な管理者を含むすべてのユーザーのパスワードを強制的にリセットする。
↓
STEP 4 「設定」→「一般」で WordPress アドレスとサイトアドレスに不審な変更がないか確認する。

削除時に「投稿の所有権」をどうするか

不正な管理者を削除する際、WordPress はそのユーザーが作成した投稿の帰属先を尋ねてくる。該当ユーザーが攻撃者である場合、そのアカウントが作成した投稿そのものも悪意あるコンテンツであることが多いため、すべて「削除」を選択して問題ない。もし誤って残す必要がある場合のみ、正当な管理者に帰属を変更する。

不正な管理者アカウントがゼロでも油断できない理由

攻撃スクリプトは任意のタイミングで管理者を作成する仕組みになっている。現在のユーザー一覧に不審点がなくても、改ざんされた CDN スクリプトが過去に読み込まれたことがあれば、攻撃者がすでにアクセストークンや認証情報を窃取している可能性を排除できない。必ず後述の予防措置まで実行する必要がある。

感染後のサイトを安全な状態に戻すために今すぐやるべきこと

感染後のサイトを安全な状態に戻すために今すぐやるべきこと

該当プラグインを完全に削除して再インストールする

単なる無効化では不十分だ。該当プラグインを一度完全に削除し、公式リポジトリまたは開発元から最新版をダウンロードして再インストールする。これにより、仮に攻撃者がプラグインの管理画面内に保存していた設定値や隠しコードを仕込んでいたとしても、完全に除去できる。

全ユーザーのパスワードをリセットし多要素認証を有効にする

攻撃者がすでに正当なユーザーのログイン情報を盗んでいる可能性を想定し、サイトの全ユーザー(特に管理者・編集者権限)のパスワードを変更する。加えて多要素認証(二段階認証)をただちに有効にし、パスワード単体ではログインできない設定に切り替えることが再侵入の防止に直結する。

WP ソルトキーを強制的に無効化する

wp-config.php に定義されている認証用のソルトキー(AUTH_KEY、SECURE_AUTH_KEY、LOGGED_IN_KEY、NONCE_KEY とそれぞれの SALT)をすべて新しい値に置き換える。これで既存のすべてのログインセッションが即座に無効になり、攻撃者が盗んだクッキーではアクセスできなくなる。WordPress の公式ソルト生成ツールを使えば、ランダムな値がすぐに発行できる。

.htaccess や wp-config.php に仕込まれたバックドアを点検する

管理者権限を取得した攻撃者は、テーマファイルやプラグインファイルを編集してバックドアを仕込むことが多い。特に functions.php や wp-config.php、.htaccess に不自然なコードが追記されていないかを FTP またはサーバー管理画面のファイルマネージャーで直接確認する。見慣れない base64 デコード処理や eval 関数を含むコード、不明な外部 URL へのリクエストがあれば攻撃の痕跡だ。

なぜ通常のウイルススキャンでは検知されなかったのか

なぜ通常のウイルススキャンでは検知されなかったのか

一般的なセキュリティプラグインは、サーバー上の PHP ファイルやデータベースの不審なパターンをスキャンする。しかし今回の攻撃は、問題のあるコードがサイト外部の CDN 上にあり、ブラウザの JavaScript 実行を通じて攻撃が成立する仕組みだった。サーバー側のファイルに痕跡が残らないため、従来型のマルウェアスキャンでは検出が困難だった。

この手口が示しているのは、外部リソースに依存するプラグインは、その配信網が侵害された場合にプラグイン本体の安全性とは無関係に危険になりうるという現実だ。CDN から読み込まれるスクリプトに対しては、Subresource Integrity(SRI)属性による改ざん検知が有効だが、これを実装しているプラグインは現状ほとんど存在しないことも今回の問題を深刻にした。

再発を防ぐために導入すべき具体的な対策

外部 CDN スクリプトを監視する仕組みを整える

すべての外部スクリプトをやみくもに拒否するのは現実的ではないが、コンテンツセキュリティポリシー(CSP)ヘッダーを適切に設定することで、どの CDN からのスクリプト実行を許可するかを明示的に制御できる。許可リストにないドメインからのスクリプトはブラウザ側でブロックされるため、未知の改ざんが発生した場合の被害を抑える障壁になる。

管理者ユーザーの監査ログを定期的に確認する

新しい管理者の追加や権限変更を記録する監査ログプラグインを導入しておけば、今回のように見知らぬアカウントが作成されたときに即座に気づける。攻撃が CDN 経由で行われたとしても、サーバー側でユーザーが作成される瞬間をログに残すことができるため、異常検知の有効な補助線になる。

利用プラグインの外部依存関係を定期的に見直す

導入済みのすべてのプラグインが、どの外部ドメインに対してリクエストを送っているかを定期的に棚卸しする習慣をつけると、今回のようなサプライチェーンリスクの芽を早期に見つけやすくなる。プラグインがバックグラウンドで読み込んでいる CDN スクリプトや API エンドポイントを把握していれば、問題発生時に影響範囲を素早く特定できる。

よくある質問

該当プラグインを無効にしただけで安全といえるか

安全とはいえない。改ざんされたスクリプトが過去に読み込まれた時点ですでに不正な管理者が作成されている可能性がある。無効化では既存の被害は解消されず、削除と再インストール、およびユーザー一覧の精査が必須になる。

不正な管理者が見つからなかった場合でも何かすべきことはあるか

全ユーザーのパスワードリセットとソルトキーの変更は必ず実行する。改ざんスクリプトが認証クッキーやアクセストークンを窃取していた場合、攻撃者は管理者アカウントを作らずとも正当なユーザーとしてログインできる可能性があるためだ。

これらのプラグインは今後も使い続けても大丈夫か

各開発元はすでに CDN の改ざんを修正し、再発防止策を強化している。しかしどのプラグインでも外部依存がある以上、同様のリスクをゼロにすることは不可能だ。使用を継続する場合は、この記事で述べた監視と予防の仕組みを併せて導入することが前提になる。

WordPress 本体や他の無関係なプラグインまで影響を受けるのか

今回の攻撃は対象プラグインの CDN スクリプト経由でのみ実行された。ただし管理者権限を奪取された後は、WordPress 本体や他のプラグインを含め、サイト全体が改ざん対象になりうる。該当プラグインを使用していた場合は、サイト全体のファイル整合性チェックを併せて行うとよい。

この記事のポイント

  • OptinMonster、TrustPulse、PushEngage、Uncanny Automator 利用者は要緊急対応
  • 不正な管理者アカウントの有無を「ユーザー一覧」で即座に確認する
  • 該当プラグインの完全削除と再インストールで痕跡を除去する
  • 全ユーザーパスワードのリセットとソルトキー変更が防御の基本線
  • CSP 設定と管理者監査ログで将来の類似攻撃に備える
佐々木 太陽
JavaScriptがログアウト時に動かない原因と直し方

JavaScriptがログアウト時に動かない原因と直し方

管理画面にログインしているときだけ JavaScript が動き、ログアウトすると止まる。この現象の原因は、ほぼ「スクリプトの読み込み順序」と「キャッシュ・最適化プラグインの挙動」のどちらか、あるいは両方の組み合わせだ。ログイン時は管理バー用のスクリプト等が読み込まれるため依存関係が偶然成立し、ログアウト時にそれが外れてエラーになるケースが多い。

ログアウト時だけ JavaScript が動かなくなる仕組み

ログアウト時だけ JavaScript が動かなくなる仕組み
ログイン時(動作する)
jQuery → 管理バー用JS → スライダーJS
管理バー用のスクリプトが jQuery を読み込むため、後続のスライダーが依存できている
↓
ログアウト時(動作しない)
jQuery 未読込 → スライダーJS エラー
管理バーが無いため jQuery が読み込まれず、スライダーの処理が失敗する
■ ログイン時 ■ ログアウト時

このデモは典型的な依存関係の崩れを示している。ログイン中は WordPress が管理バーやフッターに jQuery を読み込むため、その後に記述されたスクリプトが偶然動く。ログアウトすると jQuery が存在せず、$ is not defined や jQuery is not defined といったエラーで止まる。

HTML ブロックに直接書いた JavaScript が招く問題

HTML ブロックに直接書いた JavaScript が招く問題

WordPress の「カスタム HTML」ブロックに <script> タグを直書きする方法は、一見手軽だが制御が難しい。出力される位置がテーマやブロック配置に依存し、jQuery などのライブラリより前に実行されれば必ず失敗する。さらにインラインスクリプトは多くのキャッシュプラグインで最適化対象から外されたり、結合・遅延読み込みの対象にならず、ログアウト時だけ二重に不利な状況を生む。

HTML ブロック直書きスクリプトの3つの弱点

  • 読み込み順序を制御できない(テーマの render 順に依存する)
  • jQuery の依存関係を WordPress に伝えられない
  • キャッシュ・圧縮プラグインがスクリプトとして認識しない場合がある

ログアウト時でも動くようにする正しい組み込み手順

ログアウト時でも動くようにする正しい組み込み手順

原則は「JavaScript は HTML ブロックに直書きせず、WordPress の仕組み(wp_enqueue_script)で読み込む」ことだ。すでに直書きで動いているものを移行するには、以下の手順で進める。

STEP 1 既存の script タグの中身を別ファイルに切り出す
↓
STEP 2 functions.php で wp_enqueue_script を使い、jQuery 依存を明示する
↓
STEP 3 $ の衝突回避のため即時関数または noConflict でラップする
↓
STEP 4 キャッシュプラグインの設定を見直し、スクリプトを除外する

STEP 1 既存の script タグを外部ファイルに移す

HTML ブロック内の <script>〜</script> 部分だけを抜き出し、子テーマのフォルダ内に testimonial-slider.js のような名前で保存する。<script> タグそのものは不要で、中身のコードだけを移す。HTML ブロックにはスライダーの構造(ul や div のマークアップ)だけを残す。

STEP 2 functions.php で安全に読み込む

子テーマの functions.php に以下のコードを追加する。管理画面ではなくフロントエンドだけに読み込ませるために wp_enqueue_scripts フックを使う。依存関係として jquery を指定すれば、WordPress 本体の jQuery が先に読み込まれてから実行される。

function my_testimonial_slider_script() {
    wp_enqueue_script(
        'testimonial-slider',
        get_stylesheet_directory_uri() . '/testimonial-slider.js',
        array('jquery'),
        '1.0.0',
        true
    );
}
add_action('wp_enqueue_scripts', 'my_testimonial_slider_script');

最後の引数 true はフッターで読み込む指定だ。スライダーの DOM 要素が本文中に存在する場合はフッター読み込みで問題ない。もしスライダーを本文より前に実行する必要があるなら false にしてヘッダーで読ませるが、多くのケースではフッターで十分だ。

STEP 3 $ の衝突を防ぐ

WordPress の jQuery は noConflict モードで動作しているため、$ がそのまま使えない環境がある。古いコードを流用している場合は $ is not a function エラーが起きやすい。回避策として、外部ファイル全体を即時実行関数で囲み、引数で $ を受け取る記法が安全だ。

(function($) {
    $(document).ready(function() {
        // ここにスライダーのコード
    });
})(jQuery);

STEP 4 キャッシュプラグインでスクリプトを除外する

ここまで対応しても直らない場合、キャッシュや最適化プラグインが原因の可能性が高い。ログアウト時はページキャッシュが有効になり、スクリプトの遅延読み込みや結合が適用される。自前の testimonial-slider.js をこれらの処理から除外する必要がある。

プラグインの設定画面で「スクリプトの除外」「遅延読み込みの除外」といった項目を探し、testimonial-slider(ハンドル名)または testimonial-slider.js(ファイル名の一部)を指定する。除外後は必ずキャッシュを全削除してからログアウト状態で確認する。

Elementor のフックやテーマのアクションフックを使った場合の注意点

Elementor のフックやテーマのアクションフックを使った場合の注意点

テーマ付属のフック(GeneratePress の Element など)に HTML ブロックごと差し込む方法も考えられるが、根本的にはスクリプトの読み込み順序問題は同じだ。フックで出力する位置を変えても、jQuery より前に呼ばれるリスクは残る。フックを使う場合でも、スクリプト部分は wp_enqueue_script に任せ、フックにはマークアップだけを出力する形が堅実だ。

Elementor Pro の「カスタムコード」機能を使っているなら、その中に script タグを書くのではなく、同様に子テーマのファイルとして切り出してハンドル登録するほうが制御できる。どうしても直書きが必要なら、カスタムコードの「場所」設定を「本文の終了タグ直前」にし、さらにコード内で jQuery を明示的に使う($ を使わない)ことでエラーを減らせる。

よくある質問

コンソールに「$ is not defined」と出るがどう直せばいいか

jQuery が読み込まれる前に $ を使っているか、noConflict モードで $ が無効になっている。即時関数で (function($) { ... })(jQuery); とラップし、すべての $ をこのスコープ内に収めれば解決する。

functions.php を編集せずに直す方法はあるか

「WPCode」などのコードスニペット管理プラグインを使えば、管理画面から wp_enqueue_script のコードを登録できる。functions.php を直接触りたくない場合の現実的な代替手段だ。スニペットの実行場所を「フロントエンドのみ」に設定するのを忘れないようにする。

キャッシュを削除しても直らないのはなぜか

ブラウザキャッシュだけを消していて、サーバー側のページキャッシュや CDN キャッシュが残っているケースが多い。WordPress のキャッシュプラグインの「すべてのキャッシュを削除」を実行し、さらに CDN を使っている場合はその管理画面からもパージする。シークレットウィンドウで確認するとブラウザキャッシュの影響を除外できる。

スライダーのマークアップだけ残して script を外したら表示が消えた

新しく作った JS ファイルが正しく読み込まれていない。ブラウザの開発者ツールの「ネットワーク」タブで testimonial-slider.js が 200 番で返っているか確認する。404 ならパスが間違っている。読み込まれているのに動かない場合は、コンソールに別のエラーが出ていないか調べる。

この記事のポイント

  • ログアウト時だけ JavaScript が動かない原因は、jQuery の依存切れとキャッシュ最適化の複合
  • HTML ブロックへの script 直書きは読み込み順序を制御できず、根本対策にならない
  • wp_enqueue_script で jQuery 依存を明示し、外部ファイルとして切り出すのが正攻法
  • 即時関数で $ の衝突を防ぎ、キャッシュプラグインでは独自スクリプトを除外対象に追加する
  • Elementor やテーマフックを使う場合も、スクリプトだけは enqueue に任せる設計が堅実
佐々木 太陽