てくすた

ピクスタ株式会社のエンジニア・デザイナーがつづるよもやまテクニカルブログです

大規模なサイトマップのインデックスファイルを分割した話

はじめに

こんにちは。PIXTA 検索基盤チームでエンジニアをしているアルバイトの村岡です。

今回は SEO 施策のひとつとして実施したサイトマップのインデックスファイル分割について紹介します。まず、そもそもサイトマップとは?インデックスファイルとは?という前提を共有し、その後、インデックスファイルを分割した理由やその実装面について書いていきます。

前提

そもそもサイトマップとは?

サイトマップとは特定のページを検索エンジンに通知して検索結果に登録してもらう仕組みです。ページ数の多くない通常のウェブサイトであれば、サイトマップがなくても自動的に検索エンジンがクロールし、検索結果に登録してくれます。

しかし、PIXTA の総ページ数は 5,000 万以上。さらに日々新たな素材が登録され、ページ数も増え続けています。そのため、PIXTA ではサイトマップを作成し、サイトに関する情報を検索エンジンに伝えています。

インデックスファイルとは?

サイトマップには 1 つのファイルにつき、50,000 URL 以下かつ 50MB 以下1という制限があります。そのため、大規模なサイトではサイトマップを分割し、それらをまとめたインデックスファイルを作成することが必要となります。

PIXTA も先に述べたようにページ数が非常に多いため、それぞれのサイトマップが制限内に収まるよう分割し、インデックスファイルを作成しています。

インデックスファイルの分割とその理由

PIXTA ではインデックスファイルをさらにカテゴリ別に分割しました。

以下の例は、2020 年 10 月現在の robots.txt の一部を抜粋したものです。クローラーにサイトマップの URL を伝えるための記述ですが、複数のインデックスファイルを記載していることが分かります。

Sitemap: https://pixta.jp/sitemaps/static-index.xml.gz
Sitemap: https://pixta.jp/sitemaps/tag-popular-index.xml.gz
Sitemap: https://pixta.jp/sitemaps/item-click-index.xml.gz
Sitemap: https://pixta.jp/sitemaps/item-sentence-index.xml.gz

分割以前はひとまとめに生成されていたサイトマップが、そのカテゴリごとに分割されるようになりました。生成されるファイルを比較すると以下のようになります。

分割前

sitemap-index.xml.gz
sitemap1.xml.gz
sitemap2.xml.gz
sitemap3.xml.gz
sitemap4.xml.gz
...

分割後

static-index.xml.gz
static1.xml.gz
static2.xml.gz
...
tag-popular-index.xml.gz
tag-popular1.xml.gz
tag-popular2.xml.gz
tag-popular3.xml.gz
...
item-click-index.xml.gz
item-click1.xml.gz
item-click2.xml.gz
item-click3.xml.gz
...

分割の理由

ではなぜインデックスファイルを分割したのでしょうか? ひとことで言うと、大規模なサイトマップの状態を観測可能にし、施策と検証のサイクルを回すことを可能にするためです。

ピクスタでは主に、マーケティング部が Google Search Console を利用し、サイトマップの状態を観測しています。この Search Console では、サイトマップがそのインデックスファイル単位で集計されます。

そのため、インデックスファイル分割以前の PIXTA は、サイトマップに記載されている全てのページがひとまとめに集計・レポートされてしまうという状態でした。この状態では、サイトマップの一部に変更を加えたとしても、その効果を検証することが難しくなってしまいます。

サイトマップ関連の施策を行うにあたって上記の課題を解決し、サイトマップを個々のカテゴリごとに観測可能な状態にすることを目的として、インデックスファイルを分割することが決まりました。

実装面

ここからは、インデックスファイル分割の実装面について。どのようにして既存のシステムに組み込んでいったのかを説明します。

サイトマップの更新はバッチ処理として実装されており、gem である sitemap_generator を内部的に利用しています。

求められる要件と修正以前の構成

前述したように、PIXTA では素材数の増加とともに膨大なページ(URL)が新たに作られているため、その全てをサイトマップに載せることはできません。そのため、マーケテイング部が意図を持って選別したページをサイトマップに載せています。

また、PIXTA では画像素材はもちろん動画素材も販売されており、個々の素材ページをサイトマップに載せる際には画像サイトマップ、動画サイトマップと呼ばれる形式で記述しており、それぞれ異なる要素が必要とされます。

以下がインデックスファイル分割前のディレクトリ構成です(簡略化しています)。

upload_sitemaps/
┣ sitemap_target_generators
    ┣ static
        ┣ ...
    ┣ items
        ┣ photos
            ┣ ...
        ┣ videos
            ┣ ...
        ┣ ...
    ┣ ...
┣ upload_sitemaps.rb
┣ sitemap_assembler.rb
┣ …

詳細は割愛しますが、 それぞれの責務について軽く説明しておきます。

  • upload_sitemaps.rb: エントリーポイント
  • sitemap_target_generators: 載せるページ毎の url やオプションを持つインスタンスを生成する
  • sitemap_assembler.rb: sitemap_target_generators によって作成されたインスタンスをまとめ、ファイルの生成とアップロードを行う

sitemap_target_generators 以下も関心毎にディレクトリが分けられており、それぞれのファイルが単一の責任を負っています。

インデックスファイル分割のための実装

upload_sitemaps/
┣ sitemap_groups
    ┣ カテゴリ1
    ┣ カテゴリ2
    ┣ ...
┣ sitemap_target_generators
    ┣ static
        ┣ ...
    ┣ items
        ┣ photos
            ┣ ...
        ┣ videos
            ┣ ...
        ┣ ...
    ┣ ...
┣ upload_sitemaps.rb
┣ sitemap_assembler.rb
┣ …

サイトマップインデックスを分割するため、新たに sitemap_groups というネームスペースを作成しました。このネームスペース以下の sitemap_group が最終的なアウトプットとなるカテゴリに含まれる複数の sitemap_target_generators をまとめる役割を担います。また、この sitemap_group 毎に sitemap_assembler を複数回実行するように変更しました。

sitemap_group という概念の導入により、開発側の実装都合で作られている sitemap_target_generators にはほとんど手を加えることなく、それらをビジネス都合で自由に組み合わせて、ひとつのカテゴリのサイトマップとして公開できるようになりました。

また、これらの変更により、以下のような副次的なメリットも生まれました。

  • 生成処理がカテゴリ単位となったことで、例外エラー時の影響範囲が狭く、原因の特定も容易に
  • サイトマップの内容変更時に、相当するカテゴリ(sitemap_group)だけを意識できるように

おわりに

今回は、サイトマップのインデックスファイル分割に至った理由やその実装例を紹介しました。サイトマップをうまく活用し、サービスを成長させていきたい方の参考になれば幸いです。


ピクスタでは、SEO にも関わっていきたいエンジニアを募集しています!

recruit.pixta.co.jp