GatsbyのSEO

Gatsbyサイトを検索向けに最適化する方法を解説します。Gatsbyの4つのレンダリング方式(SSG、DSG、SSR、クライアント専用)、クロール可能性、最新のHead APIと従来のreact-helmet、サイトマップ、canonical、画像SEO、ReactバンドルによるCore Web Vitalsのコスト、Netlify時代のメンテナンスリスクを扱います。

初回公開:2026年6月26日 · 最終更新:2026年8月23日 · 上級者向け
このページには証拠シグナルが1件あります

Gatsbyには4つのレンダリング方式があります。SSG(デフォルト)はgatsby buildでページを静的HTMLに事前レンダリングし、DSGは最初の要求時に遅延静的生成を行い、SSRはGatsby Functionsで要求ごとにサーバーサイドレンダリングを行い、クライアント専用ルートはブラウザーだけで描画します。多くのGatsbyサイトはSSGを使い、最初の取得でクローラーに完全なHTMLを渡せるため、純粋なクライアント側Reactアプリより強いSEOの基盤になります。ただしDSGとSSRはビルド手順の外でHTMLを生成し、クライアント専用ルートは初期HTMLにルート固有のコンテンツを出すとは限らないため、本番確認が必要です。どの方式でもGatsbyは完全なReactランタイム(約200KB以上)を送り、クライアント側でハイドレーションします。これはクロール可能性ではなくCore Web Vitalsのコストです。メタデータには組み込みのGatsby Head API(v4.19+)を使います。主な落とし穴はcanonicalの二重化、下書きや孤立ページのサイトマップ流入、altテキスト不足、本番のみのサイトマップ、方式ごとの本番挙動確認、そしてNetlifyによる2023年の買収後にメンテナンスが大幅に鈍化したことです。

TL;DR — Gatsbyには4つのレンダリング方式、既定のSSG、DSG、SSR、クライアント専用ルートがあり、すべてが同じように生HTMLへコンテンツを入れるわけではありません。SSGはビルド時(gatsby build)に静的HTMLを事前生成するため、最初のクローラー要求より前に生HTMLへコンテンツがあり、Web Rendering Serviceもレンダリングキューも不要です。DSGは初回要求まで生成を遅延し、SSRはサーバーで要求ごとに生成し、クライアント専用ルートはブラウザーがJavaScriptを実行するまでルート固有の内容を描画しません。どの経路でもGatsbyはクライアント側で完全なReactバンドル(約200KB以上)をハイドレーションします。これはクロール可能性ではなくCore Web Vitalsのコストです。現在のメタデータ方式は組み込みのGatsby Head API(v4.19+)で、4経路すべてに対応し、gatsby-plugin-react-helmetを置き換えます。繰り返される障害は、Head APIとreact-helmetが同時に動く二重canonical、下書き/孤立ページのサイトマップ流入、本番でしか生成されないサイトマップ、GatsbyImageのalt不足、末尾スラッシュの不整合、本番確認されていないDSG/SSR/クライアント専用ルートです。さらにNetlifyによる2023年の買収後、Gatsbyの保守は大きく鈍化しています。

Gatsbyの4つのレンダリング方式とSEOへの影響

GoogleはJavaScriptページをクロール、レンダリング、インデックス登録の3段階で処理し、レンダリングはheadless Chromiumを使うキューから別の処理として行われます。依存すべきでない理由について、Google自身は明確です。“Server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript.” (翻訳)「サーバーサイドレンダリングや事前レンダリングは、ユーザーとクローラーにとってサイトを高速化し、すべてのbotがJavaScriptを実行できるわけではないため、今も優れた方法です。」

Gatsbyサイトが常にビルド時の静的HTMLになるわけではありません。ページまたはテンプレート単位で選ぶ4つのレンダリング経路があります。 この主張の根拠 gatsby build writes production output, including generated HTML, to the public directory. 対象範囲: Gatsby production builds. 信頼度: 高 · 検証日: Gatsby CLI: build

  • SSG(Static Site Generation)— 既定。 gatsby buildがページの完全にレンダリングされた静的HTMLを/publicへ出力します。Googlebotが最初に取得する生HTMLに、テキスト、リンク、メタデータを含む完全なコンテンツがあります。安全で低リスクの経路であり、多くのGatsbyページが使います。
  • DSG(Deferred Static Generation)。 すべてのページをビルド時に生成せず、各ページの初回要求まで生成を遅らせます。全件ビルドが遅くなるほど多数の低トラフィックページを持つサイトに有用です。ビルドだけではクローラーが見るものは分かりません。何かが要求するまでページHTMLが存在しないため、ビルドログだけでなく初回要求とキャッシュ後の挙動を確認します。
  • SSR(Server-Side Rendering)。 Gatsby Functionsを介し、要求時データを使って要求ごとにページをレンダリングします。要求時に動くため、SSRページにはビルド時ページにはない本番確認が必要です。レスポンス状態、キャッシュヘッダー、タイムアウト、空またはエラー応答でクローラーが見るものは、成功したローカルビルドからは分かりません。
  • クライアント専用ルート。 ブラウザー内だけでレンダリングし、初期HTMLにはルート固有のコンテンツがありません。純粋なクライアント側Reactアプリと同じ特性です。JavaScriptが動くまでGoogleや他のクローラーがページ固有の内容を見ると想定しないでください。設計上JS依存として扱います。認証済み/ゲート付きコンテンツには適しますが、内容とともにインデックス登録したいページには不適切です。

Reactのハイドレーション(ReactDOMClient.hydrateRoot())は、どの経路がHTMLを生成しても、その上で操作性を加えるためクライアント側で行われます。レンダリング経路にかかわらず同じ処理であり、ページをどの経路が生成したかとは別の問題です(ハイドレーションのコストは後述します)。

SSG/DSG/SSRと、空の<div id="root">を返してブラウザー(またはレンダラー)にページ構築を依存する純粋なクライアント側Reactアプリを比較してください。多くのGatsbyページは既定で意味のあるHTMLを配信します。これは実際のインデックス可能性の利点ですが、フレームワーク全体の保証ではなくページ単位の性質です。レンダリング方式や画像ツールだけでCore Web Vitals、インデックス登録、順位が保証されることはありません。ルートが使う経路の本番出力を確認します。

SSG/DSG/SSRに共通する注意点はクロール可能性ではなくパフォーマンスです。Gatsbyは完全なReactランタイムを各ページへ送り、再ハイドレーションします。その影響とAstroとの比較は後述します。

Gatsby Head APIとgatsby-plugin-react-helmet

Gatsby SEOで最重要なのは、「現代的な方法で実装しているか」という問いです。

旧式の方法 — gatsby-plugin-react-helmet。 長年、<title>、meta description、その他のheadタグにはreact-helmetライブラリとこのプラグインを使うのが標準でした。プラグインの役割はreact-helmetにSSR対応を加えることです。なければtitle/metaタグはJS実行後にしか現れず、生HTMLに含まれないため目的を損ないます。機能はしますが、React Hooksや並行レンダリングに関する既知の問題、defer={false}で回避するバックグラウンドタブのtitle不具合があります。

現代的な方法 — Gatsby Head API(v4.19+)。 Gatsbyには現在、任意のページまたはテンプレートファイルから名前付きHead exportを行い、head要素を追加する組み込み方式があります。 この主張の根拠 Gatsby pages and templates can export a named Head function to add head elements. 対象範囲: Gatsby Head API. 信頼度: 高 · 検証日: Gatsby: Head API

export const Head = () => (
  <>
    <title>Page Title</title>
    <meta name="description" content="..." />
  </>
)

location.pathname、params、ページのGraphQLクエリから渡るdata、pageContextなどのpropsを受け取ります。同じid propを持つタグは重複排除され、最後のものが優先されます。ただしHead APIと残存するreact-helmet呼び出しなど、異なるheadタグ機構を同時に動かすと、重複排除があっても競合します。機能するのはページファイルとテンプレートだけで、任意のコンポーネントではありません。react-helmetに比べ、サードパーティーバンドル不要、Providerラッパー不要、React 18ストリーミングで決定的なタグ順序という利点があります。新規プロジェクトではHead APIを使い、既存サイトは移行を計画してください。

Head APIはSSG、DSG、SSR、クライアント専用ルートの4経路すべてで同じように利用できます。異なるのは、クローラーが取得できるHTMLへ出力される時期です。SSGではビルド時、DSGでは初回要求時、SSRでは要求ごとに生成され、クライアント専用ルートでは初期HTMLに入りません。「Head exportを追加した」と「すべてのルートの生HTMLにある」を同一視しないでください。代表ページ1件だけでなく、各ルートが使う経路の本番出力をview-source:またはcurlで確認します。

「DevToolsにはmetaタグがあるがソースにはない」不具合。 Gatsby SEOの典型的な症状で、Chrome DevToolsではtitle/metaタグが見えるのにview-source:にはありません。DevToolsはJS実行後のハイドレーション済みDOMを表示し、view-sourceは生HTMLを表示するためです。DevToolsにしかタグがない場合、SEOコンポーネントはGatsbyの静的出力へ組み込まれずクライアント側でレンダリングされています。通常はページのHead exportとして、またはその内部で使わず、一般コンポーネントとして使ったことが原因です。必ずDevToolsではなく生HTMLで確認します。

SEOコンポーネントへ接続する(GraphQLデータ層)

Gatsbyのデータ層はGraphQLであり、ページへメタデータを渡す仕組みです。

  • useStaticQueryはgatsby-config.jsで定義したsiteMetadata(title、description、siteUrl)から全体の既定値を取得する。
  • ページ単位のGraphQLクエリはdata propをHead exportへ直接渡し、追加接続は不要。
  • 標準パターンはprop || siteMetadataのフォールバックで、ページ値があれば使い、なければサイト既定値を使う。

ページデータを受け取るHead exportは次のようになります。

export const Head = ({ data }) => (
  <>
    <title>{data.post.title}</title>
    <meta name="description" content={data.post.excerpt} />
  </>
)

サイトマップ: gatsby-plugin-sitemapと落とし穴

gatsby-plugin-sitemapをインストールし、gatsby-config.jsで設定します。よくある注意点があります。

  • 生成するのはsitemap-index.xmlであり、/sitemap.xmlではない。 Google Search Consoleへindex URLを送信します。/sitemap.xmlを送って解決を期待しないでください。
  • 本番ビルドでしか動かない。 gatsby developでは何もしません。gatsby build && gatsby serveでテストします。「サイトマップがない」という報告の多くは「本番ビルドを一度も実行していない」という意味です。
  • 既定の**createLinkInHead: true**により、サイトマップ参照がHTML headへ自動追加される。
  • /dev-404-page、/404、/offline-plugin-app-shell-fallbackは常に除外される。
  • <priority>と<changefreq>はGoogleに無視される。 プラグイン文書にも明記されています。正確な<lastmod>を重視します。
  • entryLimitの既定値は1ファイル45 000 URL。

下書きの除外は自分で行います。 Gatsbyは見つけたものをすべて構築するため、フィルターしなければ下書きもサイトマップへ入ります。公開日がない項目を除外するなど、gatsby-node.jsのGraphQLフィルターで除外してください。Reactコンポーネント内で隠してはいけません。その時点ではすでに構築され、掲載されています。

DSG、SSR、クライアント専用ルートには明示的なサイトマップ判断が必要です。 gatsby-plugin-sitemapはビルド時に見えるものを反映します。SSGページは静的ファイルとして存在するため単純です。DSGページは初回要求までHTMLがなく、SSRページには固定HTMLがなく、クライアント専用ルートにはそもそもインデックス対象のルート固有コンテンツがありません。ルートが存在するだけでサイトマップに入る、または入れるべきだと想定しないでください。ページごとに判断し、生成されたsitemap-index.xmlがビルド時の推測ではなく判断どおりか検証します。

robots.txt: gatsby-plugin-robots-txt

gatsby-plugin-robots-txtはビルド時にrobots.txtを生成します。SEOで有用なのは環境認識です。process.env.GATSBY_ACTIVE_ENV、次にprocess.env.NODE_ENVを読み、環境ごとに異なる規則を配信できます。典型的な用途は、本番を開放したままNetlifyのpreview/branchデプロイでクローラーをブロックし、ステージングURLの誤インデックスを防ぐことです。

canonical URLと二重canonical不具合

有効な方法は2つあります。

  1. **gatsby-plugin-canonical-urls**は各ページへ<link rel="canonical">を追加します。/blog?tag=fooと/blogが別々のcanonicalページとして扱われないようstripQueryString: trueを設定します。大半のサイトに推奨します。
  2. Head APIでlocation.pathnameからcanonicalを自分で設定します。
export const Head = ({ location }) => (
  <link rel="canonical" href={`https://example.com${location.pathname}`} />
)

二重canonical不具合。 既知で起こりやすい問題です。gatsby-plugin-canonical-urlsとreact-helmetのcanonicalタグを同時に使うと、<link rel="canonical">が2つ出力されます。機構は1つにします。react-helmetを使う場合はgatsby-plugin-react-helmet-canonical-urlsがhelmet対応の選択肢です。Head APIではcanonicalをその中で設定し、プラグインを外します。

末尾スラッシュ。 Gatsbyページは末尾スラッシュの有無どちらでも到達でき、Gatsbyの<Link>コンポーネントはクライアント側のHistory APIルーティングを使います。通常、末尾スラッシュを正規化するサーバー側301を迂回します。形式を1つ決め、ホスト/CDN層で強制し、canonicalも一致させます。

画像SEO: gatsby-plugin-image

gatsby-plugin-imageはGatsbyの本当の強みの一つです。コンポーネントは2つあります。

  • StaticImage — パスが既知でビルド時にハードコードする画像向け。
  • GatsbyImage — GraphQLから渡る動的画像向け。

複数サイズ、WebP/AVIF形式、遅延読み込み、ブレークポイント(750/1080/1366/1920px)を自動処理します。また、スペースを予約してCore Web Vitals指標のCumulative Layout Shiftを防ぐプレースホルダー(ぼかし、主要色、トレースSVG)も生成します。寸法指定でCLSを避け、現代的な形式と遅延読み込みがLCPを改善します。

ただしaltテキストは書きません。 毎回、自分で用意します。GatsbyImageのalt不足はGatsby SEOで最も一般的な見落としの一つです。(旧gatsby-imageパッケージからの移行にはnpx gatsby-codemods gatsby-plugin-imageというcodemodがあります。)

構造化データ(JSON-LD)

Googleが推奨する構造化データ形式はJSON-LDです。現代的なGatsbyでは、Head APIのscriptタグで追加するのが明確です。

export const Head = ({ data }) => (
  <script type="application/ld+json">
    {JSON.stringify({
      "@context": "https://schema.org",
      "@type": "Article",
      "headline": data.post.title,
    })}
  </script>
)

手書きを避けたい場合、gatsby-plugin-next-seoに構築済みJSON-LDコンポーネントがあります。よくある混同を解消すると、gatsby-plugin-manifestは構造化データ用プラグインではありません。 PWA Webアプリマニフェスト(アイコン、テーマ色)を生成するもので、schemaとは無関係です。

ReactバンドルとCore Web Vitals

ここが、JavaScriptを送らないジェネレーターと比べたGatsbyの本当の弱点です。

  • 完全ハイドレーション(Gatsby 1〜4の既定)はReactツリー全体をハイドレーションし、各ページへ200KB以上のReactランタイムを送ります。HTMLは事前レンダリングされるためクロール可能性には影響しませんが、読み込み速度とCWVには確実に影響します。
  • **部分ハイドレーション(Gatsby 5、実験的)**は"use client"付きコンポーネントだけをハイドレーションし、残りを静的HTMLにします。配信JSを減らし、TTIとCWVを直接改善します。ただし本番ビルド限定、beta段階、emotion、styled-components、gatsby-plugin-offlineと非互換という実際の制約があります。

要点は、GatsbyのJSペイロードがインデックス可能性ではなくパフォーマンスの問題だということです。Googlebotはページエクスペリエンスシグナルを評価するためJSもレンダリングするので、コンテンツが正しくインデックスされてもバンドルがCWVのコストになります。

GatsbyとAstroのSEO比較

現在静的フレームワークを選ぶなら、SEOで最も重要な比較です。

観点GatsbyAstro
ブラウザーへ送るJS200KB以上(完全なReactランタイム)約5KB(対話型islandのみ)
レンダリングモデルSSG → SPA(完全ハイドレーション)SSG → MPA(既定でハイドレーションなし)
ビルド速度(40ページ)2〜3分10秒未満
SEOプラグインエコシステム成熟(gatsby-plugin-*)成長中
クロールバジェットへの影響高い(GoogleがレンダリングするJSが多い)低い
フレームワークの将来不確実(Netlify所有、活動鈍化)活発、成長中

どちらもインデックス可能なHTMLを事前レンダリングするため、この点は同等です。違いはJSの負担です。Astroのislandが送るJavaScriptは一部にすぎず、Vaiheの比較では*“Reduced JavaScript execution conserves crawl budget and accelerates page scanning.”* (翻訳)「JavaScript実行を減らすとクロールバジェットを節約し、ページの走査を高速化する」と表現されています。(反対側の歴史的注意点として、比較当時のAstro画像処理にはwidth/heightの自動指定がなく、Lighthouse警告が出ていました。現在は解決している可能性があるため、最新のAstro文書を確認してください。)

分野全体の比較は静的サイトジェネレーター ハブを参照してください。

現実的な話: Gatsbyの保守動向

美化も悲観もしません。

Netlifyは2023年2月にGatsby Inc.を買収しました。 Gatsby Cloudは終了し、顧客はNetlifyへ移行しました。Netlifyは買収が「Gatsby JSに影響しない」と述べましたが、その後の活動は大幅に鈍化しています。広く読まれたGitHubコミュニティ議論(#39062)では、Gatsbyは事実上放棄されたと論じられています。コミットはわずかでReact 19に未対応、2024年ロードマップは未達、テレメトリーサービスは終了しました。保守担当者は現在の状態を、セキュリティ修正、限定的な依存関係更新、容易な不具合修正と説明しています。

SEOチームへの意味。 既存Gatsbyサイトなら緊急事態ではありません。構築でき、インデックスされ、動作します。リスクは時間とともに進むエコシステムの劣化です。SEOはgatsby-plugin-sitemap、画像、canonical-urlsなどのプラグインへ依存し、古いプラグイン(API廃止に直面するgatsby-source-shopifyなど)は、静かにインデックス登録を損なう壊れ方をする可能性があります。新規プロジェクトでは重く考慮してください。移行先として選ばれているのはAstroとNext.jsです。

本番チェックリスト: すべてのレンダリング経路を検証する

ローカルのgatsby developや正常なgatsby buildログだけでは、クローラーが実際に受け取るものを証明できません。SSG、DSG、SSR、クライアント専用ルートはHTML生成方法が異なるため、代表ページ1件で全体を推測せず、経路ごとに本番挙動を確認します。

  • 生HTMLのコンテンツ。 使用中の各レンダリング経路について、DevToolsではなくcurl -s <url>またはview-source:で実際の本番URLを取得し、クローラーが見るコンテンツ、title、metaタグが存在するか確認する。
  • メタデータ(Head exportの出力)。 対象経路の生HTMLへHead exportのタグが入るか確認する。DSG/SSRがSSGと最も異なる点です。ソースにはタグがあっても、本番取得で初めてレスポンスへの出力を証明できます。
  • HTTP状態。 本番レスポンスのstatus codeを確認する。特にSSR/DSGは、ローカルで正常にレンダリングできても、初回要求や負荷時に本番で500になる場合があり、ビルドでは分かりません。
  • キャッシュ挙動。 SSG出力は予測可能にキャッシュされる静的ファイルです。DSGは初回要求後にキャッシュされるため、初回だけでなく2回目も高速で正しいか確認します。SSRレスポンスはキャッシュヘッダーとホスティング層に依存します。古い内容や要求ごとの内容が誤った訪問者へ配信されないか検証します。
  • 失敗時と空状態。 要求時または初回要求時データを使うSSR/DSGページで、データ取得失敗または空返却時にクローラーが見るものを確認します。処理されないエラー状態は、正常データでローカルテストしたページと同じではありません。
  • サイトマップ生成と除外。 本番ビルド(gatsby build && gatsby serve)でのみ行われ、gatsby developではないことを再確認します。下書き、クライアント専用ルート、掲載しないと判断したページが、意図だけでなく生成済みsitemap-index.xmlから実際に除外されているか確認します。

各レンダリング経路で、どれも省略できません。正常なgatsby buildが証明するのはSSG出力であり、DSG、SSR、クライアント専用挙動ではありません。

Gatsby SEOでよくある誤り

  1. gatsby-plugin-react-helmetを使い続ける。 旧式なのでHead APIへ移行する。
  2. DevToolsにはmetaタグがあるがページソースにはない。 SEOコンポーネントがクライアント側でレンダリングされている。DevToolsではなくview-source:を確認する。
  3. 下書きがサイトマップへ入る。 Reactコンポーネントではなくgatsby-node.jsのGraphQLで除外する。
  4. src/pagesから孤立ページが生まれる。 Gatsbyはそこにあるものをすべて自動ルーティングするため、古いファイルも構築されサイトマップへ入る。
  5. 二重canonical。 gatsby-plugin-canonical-urlsとreact-helmetが両方動く。
  6. 末尾スラッシュの不整合。 <Link>のクライアントルーティングがサーバー側の末尾スラッシュredirectを迂回する。
  7. canonicalからquery stringを除いていない。 stripQueryString: trueを設定する。
  8. GatsbyImageのaltテキスト不足。 自動生成されない。
  9. /sitemap.xmlを送信する。 実際のファイルは/sitemap-index.xml。
  10. gatsby developでサイトマップをテストする。 gatsby build時だけ生成される。
  11. React stateでnoindexを切り替える。 Googleはすでに生HTMLを処理している可能性があり、生HTMLにnoindexがある場合はレンダリングを完全に省略することもあります。noindex判断は静的HTMLまたはサーバーヘッダーへ置きます。

背景にあるJavaScriptレンダリングの基礎は、親のJavaScript SEO ハブを参照してください。

専門家メモを追加

専門家の引用を固定

新しい人物ですか?まず、 /admin/experts/ → 専門家の引用を固定 から未登録プロフィールを作成してください。