WordPress5.5から追加されたサイトマップ(sitemap.xml)作成機能のカスタマイズを行います。
凝りに凝ればむずかしくなってしまいますが、最低限のことだけをするならかんたん。
カスタマイズしないとショボい
WordPress標準のサイトマップは、デフォルトだとURLリストしか表示しません。
更新日時すらない。デフォルトのサイトマップを表示してみます。
"https://(domain)/sitemap.xml" は、"https://(domain)/wp-sitemap.xml" にリダイレクトされる。
wp-sitemap-posts-post-1 | 投稿ページ |
wp-sitemap-posts-page-1 | 固定ページ サイトホーム |
wp-sitemap-posts-cta-1 wp-sitemap-posts-lp-1 | カスタム投稿ページ (テスト環境ではcta, lp) |
wp-sitemap-taxonomies-category-1 | カテゴリ内の投稿一覧ページ |
wp-sitemap-taxonomies-post_tag-1 | タグ内の投稿一覧ページ |
wp-sitemap-taxonomies-category_group-1 wp-sitemap-taxonomies-page_form-1 | カスタム・タクソノミー内の投稿一覧ページ (テスト環境ではcategory_group, page_form) |
wp-sitemap-users-1 | ユーザーページ |
サイトマップを作成するプラグインより優れているところは、サイトマップが分割されているところだけでしょう。
ちなみに、All in One SEO Packプラグインが作るサイトマップはこんな内容です。
Imagesの意味が分かりませんが、更新頻度や更新日時などすべての項目が入ってます。
(管理画面で個別設定可。)
ただ、ひとつのsitemap.xmlに入っているところはキツイかな?
なぜカスタマイズが必要か?
サイトマップはGoogleなどの検索エンジンのクローラーにサイトの概要を知ってもらうためのものです。
WordPres標準のサイトマップはURLのリストだけなので、クローラーに見てもらう情報としてはかなり薄い。
Googleは『標準のサイトマッププロトコルを使用してください』と言っているので、URLロケーションだけでは足りないでしょう。
(それで十分という人もいるが。)
またサイトマップには、1ファイルのサイズ、ロケーションの数に上限があります。
1ファイルの条件 | |
---|---|
サイズ (非圧縮) | 50MB以下 |
ロケーション数 (URL数) | 50,000件 |
そしてもうひとつは、サイトマップにURLを登録する / しない のコントロールができないこと。
WordPress標準のサイトマップはそのままだとないない尽くしです。ただカスタマイズするための機能はたくさん用意されています。
(『まともなものが欲しければ自分で作りな。』と言っているように感じる。)
エントリ項目の追加
『作れるものならやってみな。』と言われてしまったので、やっちゃいましょう。
まずは、内容の薄さを直します。エントリ項目の追加します。
add_filter( 'wp_sitemaps_posts_entry', function( $sitemap_entry, $post, $post_type ) {
$sitemap_entry['lastmod'] = $post->post_modified_gmt;
$sitemap_entry['changefreq'] = 'daily';
$sitemap_entry['priority'] = 0.7;
return $sitemap_entry;
}, 10, 3 );
add_filter( 'wp_sitemaps_taxonomies_entry', function( $sitemap_entry, $term, $taxonomy ) {
$sitemap_entry['changefreq'] = 'weekly';
$sitemap_entry['priority'] = 0.5;
return $sitemap_entry;
}, 10, 3 );
add_filter( 'wp_sitemaps_users_entry', function( $sitemap_entry, $user ) {
$sitemap_entry['changefreq'] = 'monthly';
$sitemap_entry['priority'] = 0.1;
return $sitemap_entry;
}, 10, 2 );
タクソノミーとユーザーページでは更新日時を設定できません。タクソノミーはカテゴリやタグの検索結果ページなので分かりますが、ユーザーページはあってもいいと思う。
今後の修正に期待しましょう。
またサンプルではやっていませんが、$post, $term, $userはクラスオブジェクトでIDを持っているので、ページごとの設定も可能です。
($post_typeと$taxonomyもあるので、投稿ページ、固定ページ、カテゴリごとにもできる。)
テーマのfunctions.phpなどに追加する。ただしfunctions.phpには、必要最低限のものしか書かないのがテーマファイルのコーディング規約なのでオススメしない。
(WPのコーディング規約では、機能を追加・変更・削除するものはプラグイン化することになっている。)
エントリ項目の追加 - トップページ
WordPress標準サイトマップで、『トップページ(https://(domain)/)のURLがない?』と思ったのですが、固定ページの中に入っています。
そしてトップページは、さっきの 'wp_sitemaps_posts_entry' フィルターでエントリ項目は追加されません。トップページ用のフィルターを使います。
add_filter( 'wp_sitemaps_posts_show_on_front_entry', function( $sitemap_entry ) {
$time = current_datetime();
$time = DateTime::createFromImmutable( $time );
$time->setTimezone( new DateTimeZone( 'UTC' ) );
$sitemap_entry['lastmod'] = $time->format('Y-m-d H:i:s');
$sitemap_entry['changefreq'] = 'always';
$sitemap_entry['priority'] = 1.0;
return $sitemap_entry;
} );
トップページは更新日時がないので、sitemap.xmlにクローラーがアクセスしたときの日時を設定しました。
何やらごちゃごちゃ書いているのは、タイムゾーンをUTC(GMT)に変換しているため。
サイトマップのURL数を変更
ひとつのサイトマップファイルに登録されるURLのデフォルト件数は2000です。これを変更します。
(テスト用なのでわざと小さい値に変更。)
add_filter( 'wp_sitemaps_max_urls', function( $max_urls, $object_type ) {
$max_urls = 10;
return $max_urls;
}, 10, 2 );
キャプチャでお見せしませんが、"https://(domain)/wp-sitemap.xml" のまとめリストでファイル名の後ろが 2, 3, 4, ... と複数のサイトマップが作成されてました。
また、オブジェクトタイプ毎に件数を指定できます。
add_filter( 'wp_sitemaps_max_urls', function( $max_urls, $object_type ) {
if ( 'post' === $object_type ) {
$max_urls = 50;
} else if ( 'term' === $object_type ) {
$max_urls = 20;
} else if ( 'user' === $object_tyle ) {
$max_urls = 2;
}
return $max_urls;
}, 10, 2 );
'post' | 投稿ページ 固定ページ カスタム投稿ページ |
'term' | カテゴリページ タグページ カスタム・タクソノミーページ |
'user' | ユーザーページ |
2000件で不都合なことは、1ファイルのサイズが50MBより大きくなるときなので、あまり使うことはなさそうです。
(たいがいはデフォルト2000で事足りるはず。)
最大URL数を取得する関数も用意されています。
$sitemap_post_max_urls = wp_sitemaps_get_max_urls( 'post' );
$sitemap_term_max_urls = wp_sitemaps_get_max_urls( 'term' );
$sitemap_user_max_urls = wp_sitemaps_get_max_urls( 'user' );
引数の省略はできません。(必須)
タイプ別に出力を除外
出力したくないものをコントロールします。
add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {
return ( $name == 'users' ) ? false : $provider;
}, 10, 2 );
$name | 対象ページ |
---|---|
'posts' | 投稿ページ 固定ページ カスタム投稿ページ |
'taxonomies' | カテゴリページ タグページ カスタム・タクソノミーページ |
'users' | ユーザーページ |
ユーザーページはユーザー名がurlに含まれるので見せたくないこともあるでしょう。
気になるのは、URL数制限のオブジェクトタイプとプロバイダ名がちがうこと。
このフィルターの本当の目的は、サイトマップのプロバイダ(機能を提供するクラスオブジェクト)を追加するものです。
じっさいは、WP_Sitemaps_Providerクラスの子クラスを作ってプロバイダをカスタマイズします。
今回のサンプルでは、プロバイダにfalseを指定して無効化しました。
(プロバイダ未指定 = 出力なし)
中身を見たところ個別サイトマップファイル名を変える以外、使いみちはなさそうです。
高度なカスタマイズでは、カスタムプロバイダの作成が中心になるんじゃないかな?
WordPress.orgリファレンス
細かいタイプ別出力の除外
プロバイダでの出力制限は細かいタイプを設定できません。固定ページを出力しないとか。
細かいものをコントロールする別のフィルターが用意されています。
投稿タイプの出力制限
すべての投稿タイプを除外する設定をします。
(テスト用。全部消すならプロバイダの無効化のほうがいい。)
add_filter( 'wp_sitemaps_post_types', function( $post_types ) {
unset( $post_types['post'] );
unset( $post_types['page'] );
unset( $post_types['cta'] );
unset( $post_types['lp'] );
return $post_types;
} );
$post_types パラメータ | 投稿タイプ |
---|---|
post | 投稿ページ |
page | 固定ページ |
カスタム投稿 (name) | カスタム投稿ページ サンプルでは 'cta', 'lp' 。 |
$post_typesのパラメータに出力したくないものを指定してunsetすればOK。
タクソノミーの出力制限
すべてのタクソノミーを除外する設定をします。
(テスト用。全部消すならプロバイダの無効化のほうがいい。)
add_filter( 'wp_sitemaps_taxonomies', function( $taxonomies ) {
unset( $taxonomies['category'] );
unset( $taxonomies['post_tag'] );
unset( $taxonomies['category_group'] );
return $taxonomies;
} );
$taxonomies パラメータ | 投稿タイプ |
---|---|
category | カテゴリページ |
post_tag | タグページ |
カスタム・タクソノミー (name) | カスタム・タクソノミーページ サンプルでは 'category_group' 。 |
$taxonomiesのパラメータに出力したくないものを指定してunsetすればOK。
ひとつのロケーションをピンポイントで除外
『グループじゃなくてピンポイントで除外したい』ときのフィルターも用意されています。
投稿、タクソノミー、ユーザーのIDを指定します。
投稿の除外
add_filter( 'wp_sitemaps_posts_query_args', function( $args, $post_type ) {
if ( 'post' === $post_type ) {
$args['post__not_in'] = isset( $args['post__not_in'] ) ? $args['post__not_in'] : [];
$args['post__not_in'][] = 1479; // 1479 is the ID of the post to exclude.
}
return $args;
}, 10, 2 );
タクソノミーの除外
add_filter( 'wp_sitemaps_taxonomies_query_args', function( $args, $taxonomy ) {
if ( 'category' === $taxonomy ) {
$args['exclude'] = isset( $args['exclude'] ) ? $args['exclude'] : [];
$args['exclude'][] = 5; // 5 is the ID of the category to exclude.
}
return $args;
}, 10, 2 );
ユーザーの除外
add_filter( 'wp_sitemaps_users_query_args', function( $args ) {
$args['exclude'] = isset( $args['exclude'] ) ? $args['exclude'] : [];
$args['exclude'][] = 32; // 32 is the ID of the user to exclude.
return $args;
}, );
処理としてはかんたんですが、投稿の除外のパラメータだけ 'post__not_in' なのが気になります。'exclude' に統一して欲しい。
標準サイトマップの無効化
自分が使っているプラグインのサイトマップが標準のサイトマップで上書きされるなど、標準サイトマップを使いたくないときがあります。
無効化フィルターも用意されています。
add_filter( 'wp_sitemaps_enabled', '__return_false' );
WordPress5.5以降に対応しているプラグインであれば、この処理が入ってるはず。暫定対応として使いましょう。
管理画面を作ったほうが便利
これまで説明したフィルターを使えば、プラグイン並みのサイトマップが作れるでしょう。
PHPプログラムでフィルター処理を書いていくのが一番かんたんですが、IDを探すのも、いちいち追加していくのも面倒です。
それなら管理画面で条件を設定できるようにしたほうが後々楽になります。それほどむずかしくありません。
管理画面を作る。(条件を選んでDBに保存。)
保存した設定データを使ってフィルターを実装。
これでできるでしょう。誰かがプラグインを作ってくれそうな気もするので、それまで待つのもあり。
All in One SEOプラグインは対応できています。
ただし、ver.4.0.11以上を使うようにしてください。4.0.10まではバグで、リンク先のサイトマップが表示されます。
(エラーが発生してサイトホームにジャンプする。)
Images / Videos のサイトマップは今のところ未対応です。
将来的にはフィルターを追加するかも? と言っていますが、現状、プラグインに頼ってるとも言っています。
詳細を見きったわけではない初見ですが、Images と Videos用のプロバイダクラスを用意して、そのプロバイダを登録すればできるんじゃないかと思う。