WordPress Logo WordPress XMLサイトマップ wp-sitemap.xml のカスタマイズ

WordPress の標準のXMLサイトマップ(プラグインなし)の基本的な使い方やデフォルトで出力される wp-sitemap.xml のカスタマイズ方法について。

更新日:2024年08月01日

作成日:2024年7月21日

XMLサイトマップ生成機能

WordPress のバージョン5.5 以上は標準で「XMLサイトマップ生成機能」が搭載されています。

パーマリンク設定に応じて XML サイトマップには以下でアクセスできます。

パーマリンク設定 URL
基本(?p=123) https://ドメイン名/?sitemap=index
その他(基本以外)の設定 https://ドメイン名/wp-sitemap.xml

また、独自の sitemap.xml を配置していない場合は、https://ドメイン名/sitemap.xml にアクセスすると、wp-sitemap.xml にリダイレクトされるようです。

アクセスすると以下のようなサイトマップインデックスが出力されます。

デフォルトでは投稿と固定ページ、カテゴリー、タグとユーザーのアーカイブのサイトマップへの URL が出力されます(カスタム投稿タイプを作成している場合は、それらも出力されます)。

https://ドメイン名/wp-sitemap-posts-post-1.xml (投稿)
https://ドメイン名/wp-sitemap-posts-page-1.xml (固定ページ)
https://ドメイン名/wp-sitemap-taxonomies-category-1.xml (カテゴリー)
https://ドメイン名/wp-sitemap-taxonomies-post_tag-1.xml (タグ)
https://ドメイン名/wp-sitemap-users-1.xml (ユーザー)

例えば、wp-sitemap-posts-post-1.xml をクリックすると、以下のような投稿の URL と最終更新日から成るサイトマップが表示されます。

上記のソースを確認すると、以下のようになっています。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://localhost/wp-sample/wp-sitemap.xsl"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://localhost/wp-sample/template-paginated/</loc>
    <lastmod>2012-01-09T02:00:20+09:00</lastmod>
  </url>
  <url>
    <loc>http://localhost/wp-sample/template-sticky/</loc>
    <lastmod>2012-01-07T23:07:21+09:00</lastmod>
  </url>
  <url>
    <loc>http://localhost/wp-sample/template-excerpt-generated/</loc>
    <lastmod>2012-03-15T01:49:22+09:00</lastmod>
  </url>
  <url>
    <loc>http://localhost/wp-sample/edge-case-nested-and-mixed-lists/</loc>
    <lastmod>2009-05-16T06:48:32+09:00</lastmod>
  </url>
  <url>
    <loc>http://localhost/wp-sample/edge-case-many-tags/</loc>
    <lastmod>2009-06-01T17:00:34+09:00</lastmod>
  </url>
  <url>
    <loc>http://localhost/wp-sample/post-format-standard/</loc>
    <lastmod>2010-10-05T16:27:25+09:00</lastmod>
  </url>
  ・・・中略・・・
</urlset>

標準XMLサイトマップが生成されない

functions.php で無効化されていたり、別のサイトマッププラグインで上書きされていると WordPress の標準XMLサイトマップは生成されません。また、以下の場合も生成されません。

検索エンジンがサイトをインデックスしないようにしている場合

設定→表示設定の「検索エンジンでの表示」で「検索エンジンがサイトをインデックスしないようにする」にチェックを入れている場合、サイトマップは生成されず、wp-sitemap.xml にアクセスすると、「ページが見つかりません」となります。

サイトマップが現在有効になっているかどうかは以下で確認できます。

wp_sitemaps_get_server()->sitemaps_enabled()

XMLサイトマップの出力を停止(無効化)

wp_sitemaps_enabled フィルターを使用してXMLサイトマップの生成を停止することができます。

標準XMLサイトマップの生成をすべて停止したい場合は、以下を functions.php に記述します。

add_filter( 'wp_sitemaps_enabled', '__return_false' );

XML Sitemap Generator for Google や Yoast SEO などのプラグインでサイトマップを出力している場合は、プラグインを有効化すると XML サイトマップ機能が無効化されるので、自分で上記を記述する必要はありません。

生成されるサイトマップをカスタマイズ

フィルターフックを使ってサイトマップをカスタマイズすることができます。

以下のページに詳しい解説があります。

New XML Sitemaps Functionality in WordPress 5.5

以下の URL でサイトマップ関連のドキュメントへのリンクをリスト表示することができます。

https://developer.wordpress.org/?s=sitemap

また、以下のサイトが参考になります。

投稿者別(ユーザー)アーカイブを除外

投稿者別(ユーザー)アーカイブのサイトマップ出力を停止するには、wp_sitemaps_add_provider フィルターを使用できます。以下のように $name が users の場合は false を返します。

add_filter('wp_sitemaps_add_provider', function ($provider, $name) {
  if ('users' === $name) {
    return false;
  }

  return $provider;
}, 10, 2);

特定のユーザーのアーカイブを除外

特定のユーザーの投稿者別アーカイブを除外するには wp_sitemaps_users_entry フィルターを使います。

$user->data->user_login が特定のユーザー名の場合は空の配列を返します。

add_filter('wp_sitemaps_users_entry', function ($sitemap_entry, $user) {
  if ('ユーザー名' === $user->data->user_login) {
    return [];
  }

  return $sitemap_entry;
}, 10, 2);

特定のページを除外

特定の投稿や固定ページを除外する場合は wp_sitemaps_posts_query_args フィルターを使います。

$args['post__not_in'] の配列に除外する投稿や固定ページの ID を追加します。以下は ID が 1140 の投稿を除外する場合の例です(2〜5行目は省略可能)。

add_filter('wp_sitemaps_posts_query_args', function ($args, $post_type) {
  if ('post' !== $post_type) {
    // 投稿ページ以外の場合は何もしない
    return $args;
  }

  $args['post__not_in'] = isset($args['post__not_in']) ? $args['post__not_in'] : array();
  $args['post__not_in'][] = 1140; // 除外する投稿の ID を $args['post__not_in'] に追加して除外
  return $args;
}, 10, 2);

以下はお問い合わせフォームの確認ページ(confirm)と完了ページ(complete)を除外する例です。

この例では固定ページの ID をスラッグから取得する関数を別途定義して使っています。

// 投稿や固定ページのスラッグから ID を取得する関数
if (!function_exists('get_id_by_post_name')) {
  function get_id_by_post_name($post_name) {
    global $wpdb;
    $id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_name = '" . $post_name . "'");
    return esc_html($id);
  }
}

// sitemap に confirm と complete の固定ページをを含めない
add_filter('wp_sitemaps_posts_query_args', function ($args, $post_type) {
  // 固定ページ以外の場合は何もしない
  if ('page' !== $post_type) {
    return $args;
  }
  $args['post__not_in'] = isset($args['post__not_in']) ? $args['post__not_in'] : array();
  $args['post__not_in'][] = get_id_by_post_name('confirm'); // 確認ページ(confirm)を除外
  $args['post__not_in'][] = get_id_by_post_name('complete'); // 完了ページ(complete)を除外
  return $args;
}, 10, 2);

以下は上記をまとめて指定する場合の例です(12〜14行目は省略可能)。

// 投稿や固定ページのスラッグから ID を取得する関数
if (!function_exists('get_id_by_post_name')) {
  function get_id_by_post_name($post_name) {
    global $wpdb;
    $id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_name = '" . $post_name . "'");
    return esc_html($id);
  }
}

add_filter('wp_sitemaps_posts_query_args', function ($args, $post_type) {
  // 固定ページや投稿以外の場合は何もしない
  if ('post' !== $post_type && 'page' !== $post_type ) {
    return $args;
  }
  $args['post__not_in'] = isset($args['post__not_in']) ? $args['post__not_in'] : array();
  $args['post__not_in'][] = get_id_by_post_name('confirm');
  $args['post__not_in'][] = get_id_by_post_name('complete');
  $args['post__not_in'][] = get_id_by_post_name('投稿のスラッグ');
  return $args;
}, 10, 2);

特定の投稿タイプを除外

特定の投稿タイプを除外する場合は wp_sitemaps_post_types フィルターを使います。

以下は、投稿と固定ページ、及び news というカスタム投稿タイプを除外する例です。

add_filter('wp_sitemaps_post_types', function ($post_types) {
  unset($post_types['post']); // 投稿を除外
  unset($post_types['page']); // 固定ページを除外
  unset( $post_types['news'] ); // news というスラッグのカスタム投稿タイプを除外
  return $post_types;
});

特定のタクソノミーを除外

特定のタクソノミーを除外する場合は wp_sitemaps_taxonomies フィルターを使います。

「カテゴリー」は category、「タグ」は post_tag、カスタムタクソノミーはスラッグを指定します。

以下はタグとカテゴリー、および news-category というカスタムタクソノミーを除外する例です。

add_filter('wp_sitemaps_taxonomies', function ($taxonomies) {
  unset($taxonomies['post_tag']); // タグページを除外
  unset($taxonomies['category']); // カテゴリーページを除外
  unset( $taxonomies['news-category'] ); // news-category というカスタムタクソノミーを除外
  return $taxonomies;
});

優先順位や更新頻度を追加

必要であれば、wp_sitemaps_posts_entry を使って、優先順位(priority)や更新頻度(changefreq)を追加することもできます。

以下は優先順位と更新頻度を追加する例です(固定ページでトップページを設定している場合)。

add_filter('wp_sitemaps_posts_entry', function ($sitemap_entry, $post, $post_type) {
  // 固定ページ
  if ('page' === $post_type) {
    // トップページを設定している場合(home または front-page ※設定による)
    if ('home' === $post->post_name) {
      $sitemap_entry['changefreq'] = 'daily';  // 更新頻度
      $sitemap_entry['priority'] = 1.0;  // 優先順位
    } elseif ('product' === $post->post_name) {
      $sitemap_entry['changefreq'] = 'weekly';
      $sitemap_entry['priority'] = 0.9;
    } else {
      $sitemap_entry['changefreq'] = 'monthly';
      $sitemap_entry['priority'] = 0.5;
    }
  }
  // 投稿やカスタム投稿タイプなど(固定ページ以外)
  else {
    $sitemap_entry['changefreq'] = 'weekly';
    $sitemap_entry['priority'] = 0.7;
  }
  return $sitemap_entry;
}, 10, 3);

トップページが投稿の場合

フロントページの表示が「最新の投稿」のテーマでは(例:テーマ Twenty Twenty Four など)、wp_sitemaps_posts_show_on_front_entry フックを利用できます。

参考サイト:https://wp-kama.com (wp_sitemaps_posts_show_on_front_entry)

// 「設定」→「表示設定」ホームページの表示が「最新の投稿」のテーマの場合
add_filter('wp_sitemaps_posts_show_on_front_entry', function ($sitemap_entry) {
  $sitemap_entry['changefreq'] = 'daily';  // 更新頻度
  $sitemap_entry['priority'] = 1.0;  // 優先順位
  return $sitemap_entry;
}, 10, 1);

add_filter('wp_sitemaps_posts_entry', function ($sitemap_entry, $post, $post_type) {
  // 固定ページ
  if ('page' === $post_type) {
    // スラッグが product の場合
    if ('product' === $post->post_name) {
      $sitemap_entry['changefreq'] = 'weekly';
      $sitemap_entry['priority'] = 0.9;
    } else {
      $sitemap_entry['changefreq'] = 'monthly';
      $sitemap_entry['priority'] = 0.5;
    }
  }
  // 投稿やカスタム投稿タイプなど(固定ページ以外)
  else {
    $sitemap_entry['changefreq'] = 'weekly';
    $sitemap_entry['priority'] = 0.7;
  }
  return $sitemap_entry;
}, 10, 3);

上記を記述すると、wp-sitemap-posts-page-1.xml は例えば以下のように出力されます。

XML タグ定義

以下は XML タグ定義の例です。

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

  <url>
    <loc>http://www.example.com/</loc>
    <lastmod>2024-01-01</lastmod>
    <changefreq>monthly</changefreq>
    <priority>1.0</priority>
  </url>

</urlset>

以下は使用できるタグです。loc のみが必須で、その他はオプションです。

タグ 説明
loc ページの URL。(必須)
lastmod ファイルの最終更新日。 この日付は W3C Datetime 形式で記述。
changefreq ページの更新頻度。以下が有効な値です。
  • always
  • hourly
  • daily
  • weekly
  • monthly
  • yearly
  • never
priority 優先度。0.0 から 1.0 までの値を指定できます。

詳細:https://www.sitemaps.org/ja/protocol.html

サイトマップにページを追加

サイトマップに出力されていないページやWordPress で管理していないページをサイトマップに含めたい場合は、WP_Sitemaps_Provider というサイトマッププロバイダーを拡張するための基本クラスが用意されているので利用できます。

以下はサイト直下の sample ディレクトリ内の2つの WordPress で管理しないページ(index.html と foo.html)をサイトマップに含める例です。この例では wp_register_sitemap_provider() を使ってサイトマッププロバイダーを登録しています。

lastmod や priority、changefreq はオプションなので省略可能です。

add_action('init', function () {
  wp_register_sitemap_provider(
    'nonwp',  // サイトマッププロバイダーの名前
    new class extends WP_Sitemaps_Provider {
      public function __construct() {
        $this->name = 'nonwp'; // サイトマップ URL に使用される名前(サイトマッププロバイダーの名前)
      }
      public function get_url_list($page_num, $post_type = '') {
        // 各マップのリンクのリスト (XML <url> タグのデータのリスト) を返す
        return array(
          array(
            'loc' =>  site_url('/sample/'),
            'lastmod' => gmdate(DATE_W3C, filemtime(ABSPATH . '/sample/index.html')),
            'priority'   => 0.7,
            'changefreq' => 'monthly',
          ),
          array(
            'loc' =>  site_url('/sample/foo.html'),
            'lastmod' => gmdate(DATE_W3C, filemtime(ABSPATH . '/sample/foo.html')),
            'priority'   => 0.5,
            'changefreq' => 'monthly',
          ),
        );
      }
      public function get_max_num_pages($subtype = '') {
        return 1;  // 必要なサイトマップのページ数
      }
    }
  );
});

$this->name (6行目)

プロバイダーの名前。サイトマップ URL で使用され、一意である必要があります。wp_register_sitemap_provider() の第1引数と同じ。

※ 使用できる文字は a ~ z のみです。ダッシュ、スペース、大文字は使用できません。

ABSPATH

ABSPATH は WordPress がインストールされているディレクトリ(wp-config.php が存在しているディレクトリ)のフルパスが代入された定数です。

上記により、wp-sitemap-nonwp-1.xml という URL が追加されます。

wp-sitemap-nonwp-1.xml をクリックすると、追加したページが確認できます。

前述のコードは以下のように別途クラスを定義して記述することもできます。

// WP_Sitemaps_Provider(サイトマッププロバイダーの基本クラス)を拡張したクラスを定義
class Non_Wp_Sitemaps_Provider extends WP_Sitemaps_Provider {

  public function __construct() {
    $this->name = 'nonwp'; // サイトマップ URL に使用される名前(サイトマッププロバイダーの名前)
  }

  public function get_url_list($page_num, $object_subtype = '') {
    // 各マップのリンクのリスト (XML <url> タグのデータのリスト) を返す
    $url_list = array(
      array(
        'loc' =>  site_url('/sample/'),
        'lastmod' => gmdate(DATE_W3C, filemtime(ABSPATH . '/sample/index.html')),
        'priority'   => 0.7,
        'changefreq' => 'monthly',
      ),
      array(
        'loc' =>  site_url('/sample/foo.html'),
        'lastmod' => gmdate(DATE_W3C, filemtime(ABSPATH . '/sample/foo.html')),
        'priority'   => 0.5,
        'changefreq' => 'monthly',
      ),
    );
    return $url_list;
  }
  public function get_max_num_pages($object_subtype = '') {
    return 1; // 必要なサイトマップのページ数
  }
}

add_action('init', function () {
  // サイトマッププロバイダの名前とインスタンスを渡す
  wp_register_sitemap_provider('nonwp', new Non_Wp_Sitemaps_Provider());
});

または wp_sitemaps_init フックを使って以下のように記述することもできます(違いは最後の31〜34行目部分のみ)。

// WP_Sitemaps_Provider を拡張したクラスを定義
class Non_Wp_Sitemaps_Provider extends WP_Sitemaps_Provider {

  public function __construct() {
    $this->name = 'nonwp'; // サイトマップ URL に使用される名前(サイトマッププロバイダーの名前)
  }

  public function get_url_list($page_num, $object_subtype = '') {
    // 各マップのリンクのリスト (XML <url> タグのデータのリスト) を返す
    $url_list = array(
      array(
        'loc' =>  site_url('/sample/'),
        'lastmod' => gmdate(DATE_W3C, filemtime(ABSPATH . '/sample/index.html')),
        'priority'   => 0.7,
        'changefreq' => 'monthly',
      ),
      array(
        'loc' =>  site_url('/sample/foo.html'),
        'lastmod' => gmdate(DATE_W3C, filemtime(ABSPATH . '/sample/foo.html')),
        'priority'   => 0.5,
        'changefreq' => 'monthly',
      ),
    );
    return $url_list;
  }
  public function get_max_num_pages($object_subtype = '') {
    return 1; // 必要なサイトマップのページ数
  }
}

add_action('wp_sitemaps_init', function ($wp_sitemaps) {
  // サイトマッププロバイダの名前とインスタンスを渡す
  $wp_sitemaps->registry->add_provider('nonwp', new Non_Wp_Sitemaps_Provider());
});

参考サイト