クローラーに見せる情報をSSRで補完する

クライアント描画だけでは伝わらない見出し・説明・内部リンクをサーバー側で出力する手法

SSRクローラーsr-only内部リンクレンダリング
読了時間: 12分

はじめに

ブラウザで開けば商品名も説明もきちんと表示されているのに、検索結果にはなかなか出てこない。ヘッドレス構成のECでSEOが伸び悩むとき、原因のかなりの割合を占めるのが「サーバーが最初に返すHTMLに、肝心の中身が入っていない」という状態です。

この食い違いは開発中に気づきにくく、表示速度やちらつきの対策に力を入れているサイトほど起きやすいという性質があります。

この記事では、モーターサイクル用品を扱うECサイトで、クローラー(検索エンジンがページを読みに来るプログラム)に届いていなかった情報を、サーバーサイドレンダリング(SSR。サーバー側でHTMLを組み立ててから返す方式)でどう補ったのかを解説します。画面の見た目は変えずに、検索エンジンへの伝わり方だけを改善する方法です。

初期HTMLが空になる理由

表示のなめらかさを優先すると中身が減る

ページを開いた瞬間に文字や画像がガタつく現象は、ユーザー体験としてかなり嫌われます。これを避ける定番の作り方が、読み込み中は骨組みだけの灰色のブロック(スケルトン)を表示しておき、画面幅や端末の判定が終わってから本体を描画する方式です。

ところが、この「判定が終わるまで待つ」という条件がサーバー側の描画にも効いてしまうと、サーバーが返すHTMLにはスケルトンしか含まれません。判定に使う画面幅はブラウザでしか分からないので、サーバー上では常に「まだ分からない」状態のまま出力されるためです。表示をなめらかにするほど初期HTMLの情報量が減っていく、という関係になっていました。

キャッシュに空のHTMLが保存される

さらに影響が大きいのが、この構成をISR(一度作ったHTMLを一定時間キャッシュして使い回す仕組み)と組み合わせた場合です。中身の入っていないHTMLがそのままキャッシュに保存され、次に来たクローラーにも同じ空のHTMLが配られ続けます。

人間のユーザーはJavaScriptが実行されれば普通に見られるので、画面上は何の問題もありません。一方のクローラーは、JavaScriptの実行を待たずに空のHTMLだけを見て次のページへ移ることがある。「画面には出ているのに、検索エンジンには存在しないのと同じ」という状態が、ここで生まれます。

初期HTMLに情報を載せるかどうか
BEFORE
クライアント描画のみ

サーバーが返すHTMLは骨組みだけ。クローラーが中身を読めないことがある

AFTER
SSRで初期出力

見出し・説明・リンクが最初から入っており、確実に読み取られる

図にすると、違いは「最初に届くHTMLに中身が入っているかどうか」の一点です。

クローラーに届ける情報を選ぶ

商品名の見出しと商品説明

まず外せないのが、そのページの主役を示すh1(ページで最も重要な見出し)と商品説明です。h1はページが何について書かれているかをクローラーに伝える要素なので、必ずサーバー側で出力します。商品説明も、ユーザーに見せている本文と同じものをHTMLに含めました。長い場合は先頭2,000字程度で区切っています。

ここを省くと、デザインをどれだけ作り込んでも検索エンジンには「何のページか分からない」と判定されかねません。目立たない部分ですが、最優先で押さえたいところ。

関連商品への内部リンク

もう一つ重視したのが、関連商品やあわせて使うアイテムへの内部リンクです。内部リンクはクローラーがサイト内を巡回する経路になり、ページ同士の関連性も伝えます。関連商品のブロックをサーバー側で出力しておくと、クローラーが商品ページの間を辿りやすくなります。

商品名とそのページへのリンク、そしてブランド名。この3つを初期HTMLに載せておくだけで、1ページあたりの情報量と回遊の経路が同時に増えます。

SSRページ生成の流れ
リクエスト受信

サーバーが商品ページのリクエストを受け取る

データ取得

商品情報と関連商品をサーバー側でまとめて取得

HTML組み立て

見出し・説明・内部リンクを含むHTMLを生成

初期HTMLを返却

クローラーもユーザーも中身入りのHTMLを受け取る

この4段階を踏むと、ブラウザ側の処理を待たずに中身のあるHTMLが届く、という流れです。

画面に出さずにHTMLへ含める

「クローラーには伝えたいけれど、デザイン上は画面に出したくない」情報もあります。そんなときに使うのが、sr-onlyと呼ばれる書き方です。もともとは目の見えない方が使う読み上げソフト(スクリーンリーダー)向けの補足テキストを置くための手法で、CSSで表示領域をほぼゼロにしているだけなので、HTMLとしては通常どおり存在します。クローラーにも読み上げソフトにも普通に届く、という仕組みです。

スケルトン表示の段階からこれらを出力しておけば、画面幅の判定が終わる前にクローラーが読み取っても、中身のあるHTMLが届きます。判定が終わったあとは、通常の見える要素に置き換わる作りです。

h1をページに1つだけ保つ

カテゴリ専用ページとの重複を避ける

実装していて手間取ったのが、h1の扱いでした。ページの主役を示すh1は、原則としてページに1つ。ところがヘッドレス構成ではカテゴリごとに専用のヒーロー画像やレイアウトを用意することが多く、そちらが独自にh1を持っているケースが出てきます。SEO用のh1を機械的に足すと、ページによってはh1が2つになってしまう。

そこで、表示される大見出しがあるページはそれに任せ、無いページだけ見えない見出しで補う、という条件分けにしました。

どちらのページでも、h1の数は常に1つに保たれます。

表示用ラベルと検索用タイトルを分ける

パンくず(ホーム > カテゴリ > 商品 のように現在地を示すナビゲーション)の名前も、同じ考え方で揃えました。検索結果向けのタイトルは検索語を含む長めの文言になりがちで、それをそのままナビゲーションのラベルに使うと画面が読みにくくなります。

そこで表示用のラベルと検索用のタイトルを別々に持ち、パンくず・構造化データ・商品ページからカテゴリへ戻る導線では、すべて表示用ラベルを使う形に統一しました。同じ場所を指す名前が3か所でバラバラになる状態を避けるためです。

カテゴリページのSSRがいちばん効いた

先頭24件をHTMLに載せる

商品ページ以上に効果が大きかったのが、カテゴリ一覧ページのSSRでした。カテゴリページはサイト内の回遊の起点であり、クローラーが個々の商品ページへ辿っていく通り道でもあります。ここが空のHTMLだと、その先の商品ページまで発見されにくくなってしまう。

出力しているのは、カテゴリ名の見出し、カテゴリを説明するリード文、そして先頭24件ぶんの商品名・説明の抜粋・商品ページへのリンクです。24件という数は、ページを開いたときに最初に表示される商品数とそろえてあります。

可視と不可視で同じ値を使う

商品説明の抜粋も、画面上のカードに表示している120字と同じ切り出し方にしました。細かい部分ですが、可視と不可視で同じ値を使うことを徹底しておくと、あとから見直すときの判断が楽になります。

「画面に出ている内容を、前倒しでHTMLに出しているだけ」。この一点を守っていれば、クローキングを疑われる余地もありません。検索エンジン向けに別のコンテンツを用意しているわけではない、と説明できる状態を保つのが目的です。

まとめ

ヘッドレスECでクローラーに情報が届かない問題の多くは、表示を良くするための実装が初期HTMLを空にしていることに起因します。対処は、見出し・商品説明・内部リンクをサーバー側で出力し、画面に出したくないものはsr-onlyで補うこと。ただし出力するテキストは、画面に表示される内容と必ずそろえること。

画面の見た目を一切変えずに、検索エンジンへの伝わり方だけを改善できるのがこの方法の利点です。次は、こうして届けた情報に意味を添える構造化データと、ページの入口そのものを知らせるsitemapの話に続きます。