広告

【WordPress】sitemap.xmlを動的に出力する

WordPress

SEO対策のひとつとして、サーチエンジンにサイトストラクチャや構成ページなどを通知するsitemap.xml。

WordPressの最新バージョンではデフォルトでsitemap.xmlが出力されるようになったほか、sitemap.xmlを自動生成するプラグインやテーマも多く存在するため、通常直接sitemap.xmlをカスタマイズすることは少なくなりました。

ここでは、これらのプラグインなどによるsitemap.xmlとは別に、sitemap.xml(のフォーマットのxml)を動的に出力する方法について解説します。

WordPressでsitemap.xmlを自力で出力する方法

WordPressでsitemap.xmlを出力する方法はいくつか考えられますが、大きく「サイトの更新時にファイルを静的に書き出しておく」方法と、「検索エンジンなどがアクセスしたタイミングで動的に内容を出力する」方法などが考えられます。

サイトの更新時にsitemap.xmlファイルを静的に書き出す

投稿や固定ページなどの更新に合わせて自前でsitemap.xmlを出力するサンプルコードです。

<?php
function generate_static_sitemap_xml()
{
  $allPosts = get_posts(array(
    'numberposts' => -1,
    'orderby' => 'modified',
    'post_type'  => array('post', 'page'),
    'order'    => 'DESC'
  ));

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

  foreach ($allPosts as $post) {
    setup_postdata($post);

    $postdate = explode(" ", $post->post_modified);

    $xml .= '<url>' .
      '<loc>' . get_permalink($post->ID) . '</loc>' .
      '<lastmod>' . $postdate[0] . '</lastmod>' .
      '<changefreq>monthly</changefreq>' .
      '</url>';
  }

  $xml .= '</urlset>';

  $fp = fopen(ABSPATH . "ext-static-sitemap.xml", 'w');
  fwrite($fp, $xml);
  fclose($fp);
}

add_action("publish_post", array($this, "generate_static_sitemap_xml"));
add_action("publish_page", array($this, "generate_static_sitemap_xml"));
?>

こちらでは、publish_postpublish_pageのアクションフックを使って、投稿などが公開されるタイミングですべての投稿データを一覧にしたxmlをext-static-sitemap.xmlファイルに書き込む形で機能を実現します。

generate_static_sitemap_xmlではすべての投稿と固定ページを取得して、ループですべてを出力するようにしているので、投稿の数が膨大になると書き出しの処理に時間がかかったりなど問題が起きる場合があります。

また、このsitemap.xmlは投稿者がコンテンツを公開した時に更新されるため、動的にURLが生成されるようなサイトの場合、それらのURLを反映させることはできません。

動的にsitemap.xmlを出力する

ユーザーによってページが作られるCGMや、外部のAPIと連携して自動的にページを生成するWebサービスなど、編集者の投稿などとは別のタイミングで動的にURLが発行されるようなカスタマイズがされているような場合、上記の静的なsitemap.xmlの出力ではリアルタイムに検索エンジンにサイト構成の変更を通知させることができません。

また、プラグインやテーマを使った場合でも前述のような自動生成のURLは登録できない(yoast seoなどにはそれっぽいアクションフックがある?)ので、これらの生成されたページを自動的にsitemap.xmlに反映したいような場合、sitemap.xmlの内容を動的に返す必要があります。

以下はsitemap.xmlの内容を動的に返すコードの例です。

<?php
function generate_dynamic_sitemap_xml()
{
  $allPosts = get_posts(array(
    'numberposts' => -1,
    'orderby' => 'modified',
    'post_type'  => array('post', 'page'),
    'order'    => 'DESC'
  ));

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

  foreach ($allPosts as $post) {
    setup_postdata($post);

    $postdate = explode(" ", $post->post_modified);

    $xml .= '<url>' .
      '<loc>' . get_permalink($post->ID) . '</loc>' .
      '<lastmod>' . $postdate[0] . '</lastmod>' .
      '<changefreq>monthly</changefreq>' .
      '</url>';
  }

  $xml .= '</urlset>';
  header('Content-Type: application/rss+xml; charset=UTF-8');

  echo $xml;
}

function init_generate_dynamic_sitemap_xml()
{
  add_action('do_feed_ext-sitemap', 'generate_dynamic_sitemap_xml');
  add_rewrite_rule('ext-sitemap.xml', 'index.php?feed=ext-sitemap', 'top');
}

add_action('init', 'init_generate_dynamic_sitemap_xml');
?>

こちらの例では、add_rewrite_ruledo_feed_*のアクションフック使って、サイトマップフィードにリアルタイムでアクセスされたときの処理関数を追加しています。

do_feed_*アクションフックはxmlフィードにアクセスされたときに発生するアクションフックで、do_feed_に続く文字列でフィード名を指定することができます。

上記の例ではdo_feed_ext-sitemapと指定しており、これによってhttps://(サイト)/index.php?feed=ext-sitemapのURLからオリジナルのフィードにアクセスできるようになっています。

また、add_rewrite_ruleはURLのリライトルールを指定するもので、これにより上記のURLに加えてhttps://(サイト)/ext-sitemap.xmlからも同ページにアクセスできるように設定しています。(GoogleサーチコンソールにはURL形式の制限などはないので、SEO上は/index.php?feed=ext-sitemapのまま登録しても特に問題ありません。)

サンプルコードでは静的な出力方法と同じく投稿と固定ページを出力する例になっていますが、こちらの場合はGoogleクローラーなどのアクセスのタイミングでコードが実行されるため、動的ページのURLや通常の投稿やタクソノミー以外のURLなどを出力して最新のサイト構造を検索エンジンに伝えることも可能です。

サンプルではgenerate_dynamic_sitemap_xml()関数内で作ったxmlのコードをechoで出力しています。この中で$xmlの本文を作ることで自由にsitemap.xmlを返すことが可能です。

実際はこのまま動かしてしまうとサーバーの負荷が大きくなってしまうことがあるので、キャッシュ関連の処理も組み合わせると安心ですね。

コメント

タイトルとURLをコピーしました