WordPress投稿にSEOタイトル・メタディスクリプション欄を自作する方法|カスタムフィールド実装ガイド


WordPress投稿のSEOカスタムフィールドとは、各記事ごとのSEOタイトル・メタディスクリプションを投稿編集画面で個別入力・保存し、wp_head で出力する仕組みです。AIOSEOやYoast SEOといった専用プラグインを使わず、WordPress標準の postmeta API とフックだけで実装できます。

この記事では、前回のWordPressのSEOを自作するメリット・デメリットで挙げた「必須実装要素①: title/meta管理」を深掘りし、メタボックスの追加から保存・出力・REST API連携まで、WordPress公式APIだけで完結する最小実装をステップごとに解説します。コード例はすべて公式の汎用形式で、コピペで動く構成にしています。


WordPress投稿のSEOカスタムフィールドとは(定義と仕組み)

SEOカスタムフィールドは、postmeta テーブルに「SEOタイトル」「メタディスクリプション」専用のキーを用意し、記事ごとに個別の値を保存する仕組みです。WordPress標準ではこの2項目は post_titlepost_excerpt しか持っていないため、SEO最適化のために別フィールドを追加します。

代表的な実装パターンは次の3層に分かれます。

  1. 入力UI:投稿編集画面に add_meta_box でメタボックスを追加
  2. 保存処理save_post アクションで update_post_meta を呼び、postmetaに格納
  3. 出力処理wp_headget_post_meta から読み出し、<title><meta name="description"> として出力

この3層を自分のテーマ(または機能プラグイン)に実装すれば、SEOプラグインを入れずにページ単位のSEO最適化が可能になります。


カスタムフィールド自作 vs SEOプラグイン vs ACFの比較

SEOメタの管理方法には主に3つの選択肢があります。それぞれの特徴を整理した上で判断するのが安全です。

項目自作(postmeta)SEOプラグインACF
導入コスト実装が必要インストールのみプラグイン+設定
表示速度への影響最小(必要な機能だけ)不要機能も読み込まれがち中程度
カスタマイズ自由度高いプラグインの設計に依存UIは強いが出力は自作
UI管理画面自前で実装充実したUI標準装備強力なフィールドUI
メンテナンスWP本体APIのみ追随プラグイン更新追随プラグイン+自作出力
向いている人個人開発者・自社運用編集者多数の組織サイトカスタムフィールド多用サイト

SEOメタ用途だけを自作する場合、必要な関数は4つ程度(add_meta_box / update_post_meta / get_post_meta / register_meta)で、合計100行ほどの実装に収まります。プラグインを増やしたくない個人開発者・自社メディア運営者に最も向いています。


実装の全体像(4ステップ)

SEOカスタムフィールドの実装は次の4ステップで完成します。

  1. ステップ1:投稿編集画面にメタボックスを追加する(入力欄を表示)
  2. ステップ2:入力された値を postmeta に保存する(nonce検証・サニタイズ込み)
  3. ステップ3wp_head でフロントの <title> と <meta name=”description”> に出力する
  4. ステップ4:(任意)register_meta でREST APIに公開し、Gutenberg・外部ツールから参照可能にする

ステップ1〜3が必須、ステップ4は任意です。以下、各ステップを WordPress 公式APIの最小サンプルで順に見ていきます。コードは functions.php またはテーマ内の任意のPHPファイルにそのまま貼って動作確認できます。


ステップ1:投稿編集画面にメタボックスを追加する

add_meta_boxadd_meta_boxes アクションで呼ぶと、投稿編集画面の任意の位置にカスタム入力欄を追加できます。

<?php
add_action( 'add_meta_boxes', 'my_seo_add_meta_box' );

function my_seo_add_meta_box() {
    add_meta_box(
        'my_seo_meta_box',          // メタボックスのID
        'SEO設定',                  // タイトル
        'my_seo_render_meta_box',   // コールバック関数名
        'post',                     // 表示する投稿タイプ
        'side',                     // 表示位置(normal/side/advanced)
        'high'                      // 表示優先度(high/core/default/low)
    );
}

function my_seo_render_meta_box( $post ) {
    // nonceフィールドを出力(保存時の検証に使う)
    wp_nonce_field( 'my_seo_save_meta', 'my_seo_meta_nonce' );

    $seo_title = get_post_meta( $post->ID, '_my_seo_title', true );
    $seo_desc  = get_post_meta( $post->ID, '_my_seo_description', true );
    ?>
    <p>
        <label for="my_seo_title"><strong>SEOタイトル</strong></label>
        <input type="text" id="my_seo_title" name="my_seo_title"
               value="<?php echo esc_attr( $seo_title ); ?>"
               style="width:100%;" />
    </p>
    <p>
        <label for="my_seo_description"><strong>メタディスクリプション</strong></label>
        <textarea id="my_seo_description" name="my_seo_description"
                  rows="4" style="width:100%;"><?php echo esc_textarea( $seo_desc ); ?></textarea>
    </p>
    <?php
}

ポイントは メタキーの先頭にアンダースコアを付けること(例:_my_seo_title)。アンダースコア始まりのメタキーは「保護されたメタ」として扱われ、投稿編集画面の標準カスタムフィールドUIに表示されなくなります。SEO専用フィールドが標準UIに二重表示されるのを防ぐ目的で、SEOプラグイン各種もこの命名規則を採用しています。


ステップ2:入力値を postmeta に保存する

save_post アクションで投稿が保存されたタイミングをフックし、update_post_meta でpostmetaテーブルに値を格納します。ここで nonce検証・自動保存除外・権限チェック・サニタイズ の4点セットを必ず実装します。

<?php
add_action( 'save_post', 'my_seo_save_meta' );

function my_seo_save_meta( $post_id ) {
    // 1. nonce検証
    if ( ! isset( $_POST['my_seo_meta_nonce'] )
        || ! wp_verify_nonce( $_POST['my_seo_meta_nonce'], 'my_seo_save_meta' ) ) {
        return;
    }

    // 2. 自動保存はスキップ
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    // 3. 編集権限チェック
    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    // 4. サニタイズして保存
    if ( isset( $_POST['my_seo_title'] ) ) {
        update_post_meta(
            $post_id,
            '_my_seo_title',
            sanitize_text_field( wp_unslash( $_POST['my_seo_title'] ) )
        );
    }

    if ( isset( $_POST['my_seo_description'] ) ) {
        update_post_meta(
            $post_id,
            '_my_seo_description',
            sanitize_textarea_field( wp_unslash( $_POST['my_seo_description'] ) )
        );
    }
}

wp_unslash は WordPress が自動付与するエスケープを除去する関数で、サニタイズ前に必ず通します。タイトルは sanitize_text_field、複数行のメタディスクリプションは sanitize_textarea_field を使い分けるのがWordPress公式の作法です。

4つのチェックのうち nonce検証を省略するとCSRF攻撃で他ユーザーの投稿メタを書き換えられる可能性があり、権限チェックを省略すると低権限ユーザーが管理者投稿を編集できる脆弱性になります。どちらも公開サイトでは必須です。


ステップ3:wp_headでフロントに出力する(フォールバック設計)

保存した値を <title> タグと <meta name="description"> として出力します。ここで肝心なのは postmetaが空のときのフォールバックです。全記事に毎回SEOタイトルを書くのは現実的ではないため、空のときは post_titlepost_excerpt に自動で切り替える設計が必須になります。

<title>タグの上書き

WordPress 4.4以降、テーマが add_theme_support( "title-tag" ) を宣言していると、<title>pre_get_document_title フィルタで上書きできます。

<?php
add_filter( 'pre_get_document_title', 'my_seo_filter_title' );

function my_seo_filter_title( $title ) {
    if ( ! is_singular( 'post' ) ) {
        return $title;
    }

    $post_id   = get_queried_object_id();
    $seo_title = get_post_meta( $post_id, '_my_seo_title', true );

    if ( ! empty( $seo_title ) ) {
        return $seo_title;
    }

    // フォールバック:post_title をそのまま使う
    return $title;
}

meta description の出力

メタディスクリプションは wp_head アクションでHTMLを直接出力します。こちらも空欄時は get_the_excerpt でフォールバックさせます。

<?php
add_action( 'wp_head', 'my_seo_output_meta_description' );

function my_seo_output_meta_description() {
    if ( ! is_singular( 'post' ) ) {
        return;
    }

    $post_id  = get_queried_object_id();
    $seo_desc = get_post_meta( $post_id, '_my_seo_description', true );

    if ( empty( $seo_desc ) ) {
        // フォールバック:抜粋から自動生成
        $seo_desc = get_the_excerpt( $post_id );
        $seo_desc = wp_strip_all_tags( $seo_desc );
        $seo_desc = mb_substr( $seo_desc, 0, 160 );
    }

    if ( ! empty( $seo_desc ) ) {
        printf(
            '<meta name="description" content="%s" />' . "\n",
            esc_attr( $seo_desc )
        );
    }
}

出力時には esc_attr または esc_html を必ず通すのがWordPressの作法です。これを省くとメタ情報経由でHTMLが注入され、XSSの原因になります。フォールバック側でも wp_strip_all_tags でHTMLタグを除去してから文字数を切ることで、安全な出力になります。


ステップ4:register_metaでREST API公開(Gutenberg/AI連携)

ここまでで postmeta への保存と出力は完成していますが、register_meta を追加するとそのメタキーが REST API経由で取得・更新可能になります。Gutenbergのサイドバーから操作したり、外部AIツール・記事一括管理スクリプトから読み書きしたい場合に有効です。

<?php
add_action( 'init', 'my_seo_register_meta' );

function my_seo_register_meta() {
    register_post_meta( 'post', '_my_seo_title', array(
        'show_in_rest'  => true,
        'single'        => true,
        'type'          => 'string',
        'auth_callback' => function() {
            return current_user_can( 'edit_posts' );
        },
    ) );

    register_post_meta( 'post', '_my_seo_description', array(
        'show_in_rest'  => true,
        'single'        => true,
        'type'          => 'string',
        'auth_callback' => function() {
            return current_user_can( 'edit_posts' );
        },
    ) );
}

auth_callback を省略すると、アンダースコア始まりの保護メタは REST API経由で書き込めません。編集権限を持つユーザーだけが更新できるよう、上記のように current_user_can( "edit_posts" ) を返すようにします。

登録後は GET /wp-json/wp/v2/posts/{id} のレスポンス内 meta オブジェクトに _my_seo_title_my_seo_description が含まれるようになります。AI記事一括メンテや、Gutenbergサイドバーパネルへの拡張に応用できます。


よくある実装ミス5つと回避策

自作実装でよく見かける典型的なミスと、その回避方法を5つ挙げます。公開前のチェックリストとして使ってください。

ミス症状回避策
nonce検証を省略CSRFで他ユーザーが投稿メタを改変可能wp_nonce_fieldwp_verify_nonceを必ずセットで使う
権限チェックを省略低権限ユーザーが管理者投稿のメタを編集可能current_user_can("edit_post", $post_id)を入れる
出力時のエスケープ忘れメタ経由でHTML/JS注入(XSS)が成立必ずesc_attrまたはesc_htmlを通す
フォールバック未設計postmeta未入力ページが空titleで配信される空のときpost_title/get_the_excerptに切り替え
自動保存除外を忘れる編集中の意図しないタイミングで上書きが走るDOING_AUTOSAVE定数で早期return

特に「フォールバック未設計」は古い投稿で空タイトル配信される事故の主因です。実装直後は問題が見えづらいため、SEOスコア無料診断ツールなどで本番URLを実際にチェックし、<title><meta name="description">が両方出力されているか確認してください。


SEOプラグインから移行する場合の注意点

既にAIOSEOやYoast SEOを使っているサイトが自作実装に切り替える場合、旧プラグインが残したpostmetaを引き継ぐか・破棄するかを最初に決める必要があります。代表的なメタキーは以下です。

プラグインSEOタイトルのメタキーメタディスクリプションのメタキー
Yoast SEO_yoast_wpseo_title_yoast_wpseo_metadesc
All in One SEO(AIOSEO)専用テーブル wp_aioseo_posts に格納同左
Rank Mathrank_math_titlerank_math_description

既存値を活かしたい場合は、get_post_meta で旧キーから読み、update_post_meta で自作キー(例:_my_seo_title)に書き写すマイグレーションスクリプトを書きます。AIOSEOのように専用テーブルを持つプラグインは、$wpdb 経由で別途SELECT文を組む必要があります。

マイグレーションが終わったらSEOプラグインを停止・削除し、自作実装のフォールバック動作と <title> / <meta name="description"> の出力をフロントで再確認します。


SEO設定が正しく出力されているか診断する

自作実装が完成したら、本番URLで実際の出力を確認するのが最重要です。WordPress公式ディレクトリで公開している無料プラグイン ORECTIC SEO CHECK は、ページ単位でSEOタイトル・メタディスクリプション・OGP・構造化データの設定状況を一覧表示します。プラグイン本体に管理画面UIだけ任せて、出力は自作のままにしておく「ハイブリッド運用」にも使えます。


よくある質問(FAQ)

Q. SEOプラグインを使う場合と比較してメリットは何ですか?

不要機能のロードを避けられるため表示速度(特にCore Web Vitals)が改善されやすく、UIも自分の運用に合わせて最小化できます。一方で実装・保守の責任は自分で持つ必要があり、編集者が複数いるサイトでは標準UIが充実したSEOプラグインの方が運用コストは低くなります。

Q. nonce検証は必須ですか?省略するとどうなりますか?

必須です。省略すると外部サイトに仕込まれたフォームから管理画面のセッションを利用して投稿メタを書き換えるCSRF攻撃が成立します。wp_nonce_fieldwp_verify_nonceは必ずセットで使ってください。

Q. register_metaは使わなくても動きますか?

入力UIと出力だけなら不要です。register_metaはREST API経由でメタを読み書きしたい場合(Gutenbergサイドバーパネルの自作・AI記事一括メンテ・外部スクリプトとの連携など)にのみ必要になります。

Q. ACFやSCFと併用できますか?

可能です。ACFで作ったフィールドのメタキーを get_post_meta で読み出して同じく wp_head で出力すれば、入力UIはACFに任せて出力だけ自作という構成にできます。

Q. postmetaが未入力の場合、フォールバックはどう設計すべきですか?

<title>はWordPress標準のpost_titleに、<meta name="description">get_the_excerptwp_strip_all_tagsmb_substrで抜粋から自動生成するのが基本パターンです。空文字を出力するくらいなら自動生成の方がSEO上ずっと安全です。

Q. 既存記事のSEOタイトルを一括で初期化したい場合は?

WP-CLIのwp post meta updateか、register_metaでREST APIに公開した上でPythonやNode.jsの管理スクリプトから一括PUTする方法があります。記事数が多い場合はWAFや負荷を考慮してバッチ実行してください。


まとめ:次は「タクソノミー編」へ

WordPress標準のpostmeta APIだけでSEOカスタムフィールドは実装できます。ポイントは「nonce・権限・サニタイズ・エスケープ・フォールバック」の5点セットを必ず守ることと、register_metaでREST APIに公開しておくと後の拡張が楽になることです。

投稿側のSEOメタが整ったら、次はカテゴリページ・タグページのSEOメタです。termmeta APIを使えば同じ考え方でタクソノミー側にもSEOタイトル・メタディスクリプションを追加できます。実装パターンは次の記事で解説予定です。

また、自作するかSEOプラグインを選ぶかの判断軸そのものを整理した記事は、WordPressのSEOを自作するメリット・デメリットにまとめています。導入判断段階で迷っている場合はこちらを先に確認してください。


関連記事

【P10倍】&【22,000円クーポン】【国内生… 【P10倍】&【22,000円クーポン】【国内生… ¥154,800 【楽天ランキング1位!】三年保証 パソコ… 【楽天ランキング1位!】三年保証 パソコ… ¥35,980 【ふるさと納税】液晶モニター31.5型ワイ… 【ふるさと納税】液晶モニター31.5型ワイ… ¥135,000 JAPANNEXT 31.5インチ VAパネル搭載 4K(38… JAPANNEXT 31.5インチ VAパネル搭載 4K(38… ¥39,980 【限定大特価】ロジクール ワイヤレス キ… 【限定大特価】ロジクール ワイヤレス キ… ¥13,481 【ふるさと納税】HHKB Professional HYBRI… 【ふるさと納税】HHKB Professional HYBRI… ¥130,000
Rakuten Web Service Center