2026年5月20日
2026年5月20日
WordPressのwp_head・wp_footerフックの使い方:メタタグ・GTM・インラインスクリプトの追加
wp_head、wp_body_open、wp_footer は、テーマが HTML の決まった位置で呼ぶ関数(wp_head() など)が実行するアクションフックです。WordPress 本体やプラグインは、ここに CSS・JavaScript・メタタグなどを出力します。自分でコードを追加するときも、テンプレートを直接書き換えずにこのフックを使うと、テーマを更新しても消えません。
この記事の優先度の値や関数は、2026年11月時点の WordPress 6.9 のソースコード(wp-includes/default-filters.php など)で確かめています。
3つのフックが出力される位置
| 関数(テーマが呼ぶ) | テーマで呼ぶ位置 | 主に出力されるもの |
|---|---|---|
wp_head() |
</head> の直前 |
<title>、CSS、head に置くスクリプト、canonical、サイトアイコン |
wp_body_open() |
<body> の直後(WordPress 5.2 以降) |
管理バー(Google タグマネージャーの noscript もここに追加する) |
wp_footer() |
</body> の直前 |
フッターに置くスクリプト |
ブロックテーマ(Twenty Twenty-Five など)では、WordPress がこの3つを自動で呼ぶので、テーマ側で書く必要はありません。
クラシックテーマを自作する場合は、header.php と footer.php にこれらを書きます。wp_head() や wp_footer() が無いと、プラグインの CSS・JavaScript や管理バーが出なくなります。
header.php の例です。
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
footer.php の例です。
<?php wp_footer(); ?>
</body>
</html>
<title> を自分で書かず、functions.php で add_theme_support( 'title-tag' ); を指定すると、WordPress が wp_head で <title> を出力します。
CSS と JavaScript のファイルは wp_enqueue_scripts で読み込む
CSS や JavaScript のファイルを wp_head に <script src="…"> と直接書くのは避けます。wp_enqueue_scripts フックで登録すると、WordPress が重複を防ぎ、依存関係の順に並べて、wp_head() か wp_footer() の中で出力します。
<?php
add_action( 'wp_enqueue_scripts', function () {
// 投稿の個別ページだけで読み込む
if ( is_singular( 'post' ) ) {
wp_enqueue_script(
'mytheme-share',
get_theme_file_uri( 'js/share.js' ),
array(),
'1.0.0',
array(
'in_footer' => true, // wp_footer() で出力する
'strategy' => 'defer', // defer 属性を付ける(WordPress 6.3 以降)
)
);
}
} );
5つ目の引数に true だけを渡すと、フッターで出力する指定になります。配列で strategy を指定する書き方は WordPress 6.3 で追加されました。
wp_head や wp_footer に直接書くのは、ファイルとして読み込めないもの(メタタグ、外部サービスが指定するタグ、ページごとに値が変わる小さなスクリプト)に限ると、管理しやすくなります。
優先度で出力する順番を決める
add_action() の3つ目の引数が優先度です。小さいほど先に実行されます(指定しなければ 10)。WordPress 本体が wp_head に登録している主な処理は次のとおりです。
| 優先度 | 処理 |
|---|---|
| 1 | <title> の出力、wp_enqueue_scripts の実行、robots メタタグ |
| 8 | CSS の出力(wp_print_styles) |
| 9 | head に置くスクリプトの出力(wp_print_head_scripts) |
| 10 | canonical など |
| 99 | サイトアイコン |
| 101 | 「追加 CSS」の出力 |
wp_footer では、フッターに置くスクリプトが優先度 20 で出力されます。そのため、フッターのスクリプトより先に出したいものは 20 より小さく、あとに出したいものは 20 より大きくします。
head にメタタグを追加する(OGP の例)
<?php
add_action( 'wp_head', function () {
if ( ! is_singular() ) {
return;
}
$post_id = get_queried_object_id();
$description = wp_strip_all_tags( get_the_excerpt( $post_id ) );
$image = get_the_post_thumbnail_url( $post_id, 'large' );
if ( ! $image ) {
$image = get_site_icon_url( 512 );
}
?>
<meta property="og:title" content="<?php echo esc_attr( get_the_title( $post_id ) ); ?>">
<meta property="og:description" content="<?php echo esc_attr( $description ); ?>">
<meta property="og:url" content="<?php echo esc_url( get_permalink( $post_id ) ); ?>">
<meta property="og:type" content="article">
<?php if ( $image ) : ?>
<meta property="og:image" content="<?php echo esc_url( $image ); ?>">
<?php endif; ?>
<?php
}, 5 );
get_the_excerpt()は、抜粋が入力されていなければ本文から自動で作ります。- Yoast SEO、All in One SEO、Rank Math などの SEO プラグインは OGP を出力するので、使っている場合はこのコードを入れると重複します。ページのソースで
og:titleが2回出ていないか確かめてください。
Google タグマネージャーを追加する
Google タグマネージャーは、管理画面に表示されるコードを head のできるだけ上と、<body> の直後の2か所に置くよう案内しています。wp_head と wp_body_open で出力します。GTM-XXXXXXX は自分のコンテナ ID に置き換えます。
<?php
define( 'MYTHEME_GTM_ID', 'GTM-XXXXXXX' );
// head のできるだけ上に出力する
add_action( 'wp_head', function () {
?>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<?php echo esc_js( MYTHEME_GTM_ID ); ?>');</script>
<!-- End Google Tag Manager -->
<?php
}, 1 );
// <body> の直後に出力する
add_action( 'wp_body_open', function () {
?>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=<?php echo esc_attr( MYTHEME_GTM_ID ); ?>"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<?php
} );
- 優先度 1 の処理はほかにもあるため、head の一番上になるとは限りません。同じ優先度の中では登録した順に実行されるため、テーマのコードは本体の処理より後になります。より前に出したい場合は優先度を 0 にします。
- テーマが
wp_body_open()を呼んでいないと noscript の部分は出力されません。 - 自分のアクセスを計測から外したい場合は、各関数の先頭で
if ( current_user_can( 'manage_options' ) ) { return; }として管理者のときは出力しない方法があります。
インラインスクリプトで値を渡す
PHP の値(Ajax の URL や nonce など)を JavaScript に渡すときは、wp_add_inline_script() を使うと、対象のスクリプトの直前に出力されます。
<?php
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script(
'mytheme-main',
get_theme_file_uri( 'js/main.js' ),
array(),
'1.0.0',
true
);
$data = array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'mytheme_nonce' ),
);
wp_add_inline_script(
'mytheme-main',
'const mythemeData = ' . wp_json_encode( $data ) . ';',
'before' // main.js の前に出力する
);
} );
スクリプトが読み込まれないページでは、インラインスクリプトも出力されないので、無駄がありません。どうしても wp_footer に直接書く場合も、値は wp_json_encode() で JSON にしてから埋め込みます。文字列をそのまま echo すると、引用符や </script> を含む値でスクリプトが壊れたり、XSS の原因になったりします。
出力されたか確かめる
- ログアウトした状態(またはシークレットウィンドウ)でページを開き、ページのソースを表示します(Windows は Ctrl+U)。
- 追加したタグを検索し、
</head>の前、<body>の直後、</body>の前のどこに出ているかを確かめます。 - 何も出ていない場合は、テーマに
wp_head()・wp_body_open()・wp_footer()があるか、キャッシュのプラグインやサーバーのキャッシュが古い HTML を返していないかを確かめます。
まとめ
wp_headは</head>の直前、wp_body_openは<body>の直後、wp_footerは</body>の直前に出力するフックです。- CSS・JavaScript のファイルは
wp_enqueue_scriptsで登録し、直接書くのはメタタグや外部サービスのタグに限ります。 - 出力の順番は優先度で決めます。CSS は 8、head のスクリプトは 9、フッターのスクリプトは 20 です。
- PHP の値を JavaScript に渡すときは
wp_add_inline_script()とwp_json_encode()を使います。