WordPressでプラグインなしで記事ごとにnoindexを設定する方法

個別記事ごとにnoindexを設定したい場合のコードです。 add_meta_box()を使ってカスタムフィールドをサイドバーに追加します。

投稿の設定の場合、wp_postmetaテーブルにデータを入れることが多いと思いますが、投稿IDの配列だけ保存できれば良いので「ブログのトップに固定(sticky_posts)」と同様にwp_optionsテーブルに保存します。

<?php

class Noindex_Settings
{
    public function __construct()
    {
        add_action('add_meta_boxes', [$this, 'custom_meta_boxes']);
        add_action('save_post', [$this, 'update']);
    }

    /**
     * カスタムフィールドのボックスを追加する
     */
    function custom_meta_boxes()
    {
        global $post_type;

        add_meta_box(
            'noindex_setting',
            '検索エンジン設定',
            [$this, 'insert_fields'],
            'post',
            'side',
            'high'
        );
    }

    /**
     * カスタムフィールドの入力エリアを設定する
     */
    function insert_fields()
    {
        global $post;

        $noindex_posts = get_option('noindex_posts');
        $checked = '';

        if (is_array($noindex_posts)) {
            $noindex_posts = array_unique(array_map('intval', $noindex_posts));

            if (in_array($post->ID, $noindex_posts, true)) {
                $checked = 'checked';
            }
        }

        echo '<label>
    <input type="checkbox" name="noindex_posts" value="checked" ' .
            $checked .
            '> 検索エンジンに登録しない(noindex)</label>';
    }

    /**
     * save_postフックでカスタムフィールドの値を保存
     * @param int $post_id
     */
    function update($post_id)
    {
        //自動保存ならアップデートしない
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }

        $post_id = (int) $post_id;
        $noindex_posts = get_option('noindex_posts');

        if ($_POST['noindex_posts']) {
            //noindex_postsにpost_idを追加
            if (!is_array($noindex_posts)) {
                $noindex_posts = [$post_id];
            } else {
                $noindex_posts = array_unique(
                    array_map('intval', $noindex_posts)
                );
            }

            if (!in_array($post_id, $noindex_posts, true)) {
                $noindex_posts[] = $post_id;
            }

            update_option('noindex_posts', array_values($noindex_posts));
        } else {
            //noindex_postsからpost_idを削除
            if (!is_array($noindex_posts)) {
                return;
            }

            $noindex_posts = array_values(
                array_unique(array_map('intval', $noindex_posts))
            );

            if (!in_array($post_id, $noindex_posts, true)) {
                return;
            }

            $offset = array_search($post_id, $noindex_posts, true);
            if (false === $offset) {
                return;
            }

            array_splice($noindex_posts, $offset, 1);
            update_option('noindex_posts', $noindex_posts);
        }
    }
}

new Noindex_Settings();

あとはnoindexかを判定する関数を作って、metaタグでnoindex設定すればOKです。

<?php

/**
 * noindexにするページを判定する関数
 *
 * @return boolean
 */
function is_noindex()
{
    $post_id = get_the_ID();
    $noindex_posts = get_option('noindex_posts');

    if (is_array($noindex_posts)) {
        $noindex_posts = array_map('intval', $noindex_posts);
        $is_noindex = in_array($post_id, $noindex_posts, true);
    } else {
        $is_noindex = false;
    }

    //アーカイブや404もnoindex判定に追加
    if (
        $is_noindex ||
        is_date() ||
        is_404() ||
        is_search() ||
        is_author() ||
        is_paged() ||
        is_attachment()
    ) {
        return true;
    } else {
        return false;
    }
}
<?php if (is_noindex()): ?>
    <meta name="robots" content="noindex">
<?php endif; ?>