2026年8月8日
2026年8月8日
WordPressでwp_head()が二重に呼ばれてスクリプトが重複するときの調べ方と直し方
ページのソースを見ると同じスクリプトやタグが2回出ている場合、原因は「wp_head() が本当に2回実行されている」か、「同じものが別々の経路から1回ずつ出力されている」かのどちらかです。両者は直し方がまったく違うため、まずどちらなのかを見分けることが近道になります。この記事では、その見分け方と、原因ごとの確認方法・修正方法を説明します。
重複していると何が困るのか
同じスクリプトが2回読み込まれると、ページの表示が遅くなるだけでなく、動作にも影響が出ます。アクセス解析のタグが2回出ればページビューが二重に計測され、スライダーやモーダルのスクリプトなら、同じ処理が2回登録されてボタンが2回反応する、といった不具合になります。<title> やcanonicalなどのメタタグが重複すると、検索エンジンへの伝わり方も不安定になります。
まず重複の出どころを見分ける
ブラウザーでページを開き、ソースを表示して(多くのブラウザーで Ctrl+U)、重複しているスクリプトのファイル名で検索します。見るべきなのは、wp_enqueue_script() で読み込まれたスクリプトに付く id 属性です。WordPressは、登録されたスクリプトのタグに「ハンドル名-js」という形の id を付けます。
<script src="https://example.com/wp-content/plugins/foo/slider.js?ver=2.1" id="foo-slider-js"></script>
<script src="https://example.com/wp-content/themes/bar/js/slider.js?ver=1.0" id="bar-slider-js"></script>
この例のように id が違えば、テーマとプラグインがそれぞれ別のハンドル名で同じライブラリーを読み込んでいます。id が無いタグは、header.php に直接書かれているか、プラグインが wp_head フックで直接出力しているものです。
wp_enqueue_script() で登録したスクリプトは、WordPressが出力済みかどうかを記録しているため、仮に wp_head() が2回呼ばれても、同じハンドルのスクリプトは通常2回は出ません。一方で、wp_head フックで直接 echo しているタグ(解析タグ、メタタグ、インラインのスタイルなど)は、呼ばれた回数だけ出力されます。「enqueueしたスクリプトは1回なのに、解析タグやメタタグだけが2回ある」なら、wp_head() の二重実行を疑います。
wp_head() が何回実行されたかを確かめる
二重実行かどうかは、did_action() で確かめられます。この関数は、指定したアクションがそれまでに何回実行されたかを返します。ステージング環境で、子テーマの functions.php か、mu-plugins に置いたファイルに次のコードを一時的に追加します。
add_action( 'wp_head', function () {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
// 何回目の wp_head かと、どこから呼ばれたかを debug.log に残す
error_log( 'wp_head run #' . did_action( 'wp_head' ) . ' : ' . wp_debug_backtrace_summary() );
}, 1 );
wp-config.php で WP_DEBUG と WP_DEBUG_LOG を true にしておくと、wp-content/debug.log に記録されます。管理者でログインしてページを1回開き、ログに「run #2」が出ていれば二重実行です。wp_debug_backtrace_summary() の出力には呼び出し元のファイルと関数が並ぶため、どのテンプレートから2回目が呼ばれたかが分かります。確認が終わったら、このコードは削除してください。
原因1: 同じライブラリーを別のハンドルで読み込んでいる
最も多いのがこのケースです。テーマが独自のハンドルでライブラリーを読み込み、プラグインも別のハンドルで同じものを読み込むと、WordPressからは別物に見えるため両方が出力されます。どちらを残すかを決め、もう一方を外します。外すのは、元の登録より後に動くように優先度を大きくした wp_enqueue_scripts の中で行います。
add_action( 'wp_enqueue_scripts', function () {
// テーマ側で読み込んでいる重複ライブラリーを外す(ハンドル名はソースの id から "-js" を除いたもの)
wp_dequeue_script( 'bar-slider' );
}, 100 );
外したほうのスクリプトに依存している処理が無いかを、外したあとにブラウザーのコンソールで確認します。jQueryのようにWordPress本体に同梱されているライブラリーを、テーマが外部から別ハンドルで読み込んでいる場合は、本体の jquery ハンドルを使う形にそろえるのが安全です。
原因2: 解析タグや同じ機能を複数の場所で設定している
アクセス解析のタグは、テーマの設定欄、SEO系プラグイン、Site Kit by Google のような専用プラグイン、タグマネージャーなど、入れられる場所が多いため重複しやすい項目です。過去に別の方法で入れたタグを消し忘れているケースもよくあります。ソースで計測IDを検索して出現回数を数え、設定している場所を1か所にまとめます。
プラグインが wp_head に直接出力しているタグを止めたい場合は、まずそのプラグインの設定で出力を止められないかを確認します。設定が無い場合は remove_action() で外せますが、登録時と同じ関数名と優先度を指定しないと外れません。
add_action( 'init', function () {
// 'foo_print_tracking' と 10 は、プラグインが add_action した際の値に合わせる
remove_action( 'wp_head', 'foo_print_tracking', 10 );
} );
クラスのメソッドで登録されている場合はこの書き方では外れないため、プラグイン側の設定で止めるほうが確実性が高く、更新にも強くなります。
原因3: テーマの中で wp_head() が2回呼ばれている
did_action() の確認で二重実行が分かった場合は、テーマのテンプレートを調べます。よくあるのは次のパターンです。
header.phpの中にwp_head();が2回書かれている(カスタマイズの際に貼り付けが重なった)- テンプレートの中で
get_header()が2回呼ばれている、またはヘッダー部分を読み込むテンプレートパーツが重複している - ページビルダーや独自テンプレートが、自前の
<head>を出力しつつテーマのヘッダーも読み込んでいる
テーマのフォルダー内で検索すると、該当箇所が見つかります。
grep -rn "wp_head()" wp-content/themes/your-theme
wp_head() は </head> の直前に1回だけ置くのが正しい形です。修正は親テーマを直接編集せず、該当テンプレートを子テーマにコピーして行います。ブロックテーマには通常 header.php が無く、wp_head() はWordPress本体が呼ぶため、ブロックテーマで二重実行が起きているなら、プラグインが独自に呼んでいる可能性が高くなります。
原因4: 最適化系プラグインの結合とキャッシュ
スクリプトを結合・遅延読み込みするキャッシュ系プラグインを使っていると、元のタグと結合後のファイルの両方に同じ処理が入ったり、設定変更前の古いキャッシュが残ったりして重複に見えることがあります。最適化機能を一時的に止めてキャッシュを削除し、ソースを確認し直して、重複が消えるかを確かめます。
作業前の注意
テーマやfunctions.phpの変更は、ファイルのバックアップを取ってからステージング環境で試し、表示と動作を確認してから本番に反映してください。本番で WP_DEBUG_LOG を有効にした場合は、確認後に元へ戻します。ここで紹介した関数やフックは、現行のWordPressで使えるものです(2026年10月現在)。
まとめ
- ソースの
id="ハンドル名-js"を見て、別ハンドルの重複か、直接出力の重複かを見分ける - enqueueしたスクリプトは
wp_head()が2回呼ばれても通常は重複せず、直接出力のタグだけが重複する - 二重実行の有無は
did_action( 'wp_head' )とwp_debug_backtrace_summary()で確かめる - 別ハンドルの重複は
wp_dequeue_script()、直接出力は設定かremove_action()で外す - テンプレートの修正は子テーマで行い、
wp_head()は</head>の直前に1回だけにする