GatsbyのSEO
Gatsbyサイトを検索向けに最適化する方法を解説します。Gatsbyの4つのレンダリング方式(SSG、DSG、SSR、クライアント専用)、クロール可能性、最新のHead APIと従来のreact-helmet、サイトマップ、canonical、画像SEO、ReactバンドルによるCore Web Vitalsのコスト、Netlify時代のメンテナンスリスクを扱います。
このページには証拠シグナルが1件あります
- 関連するライブツールCanonicalization Checker
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は既定で、訪問者が来る前にページを完成済みHTMLへ構築します(この方式をSSGと呼びます)。そのためGoogleがアクセスした時点でコンテンツはページ内にあり、JavaScriptを待つ必要がありません。これはSEOの強い出発点です。Gatsbyには、後で生成するページやリクエストごとのデータを使うページ向けに、ほかのレンダリング方式もあります。利用している場合は理解が必要です。ただし、大きなReactバンドルをブラウザーへ送るためページが遅くなる可能性があり、metaタグ、サイトマップ、canonical、画像altテキストは自分で設定しなければなりません。
Gatsbyとは何か
GatsbyはReactを基盤とするウェブサイトフレームワークです。一般的なReactアプリはJavaScriptの読み込み後にブラウザー内でページを組み立てるため、検索エンジンが最初に取得するHTMLがほぼ空になる場合があります。Gatsbyは既定で逆の方式を採用します。gatsby buildを実行すると、多くのページを事前に完全なHTMLファイルへ変換します。そのためGoogle、Bing、読者がページを要求した時点で、コンテンツはすでにHTMLに含まれています。 この主張の根拠 Gatsby creates static HTML files during its production build. 対象範囲: Gatsby static generation; client-side behavior can still be added. 信頼度: 高 · 検証日: Gatsby: Builds and deploys
この既定方式により、Gatsbyは静的サイトジェネレーター(SSG)になります。一般的なReactアプリよりはるかに強く、初期状態からSEOに適している理由です。Gatsbyではページ単位で、初回リクエスト時に生成、サーバーでリクエストごとに生成、ブラウザーだけでレンダリングという3方式も選べます。クローラーが実際に見る内容が方式ごとに変わるため、Advancedタブで説明します。
GatsbyとSEOを心配する理由(多くの場合は心配不要)
最も一般的な誤解は、“Gatsby is bad for SEO because it uses React.” (翻訳)「GatsbyはReactを使うのでSEOに悪い」というものですが、誤りです。React部分はページの構築と配信が終わった後に動き、操作性を加えるだけです。検索エンジンが重視するテキスト、リンク、見出しは最初からHTMLに含まれています。
したがってGatsbyは最大の障害を自動的に越えます。ただし、SEOのすべてを代行するわけではありません。
それでも必要な設定
Gatsbyサイトが自動的に最適化されるわけではありません。次の設定が必要です。
- 各ページへtitleタグとmeta descriptionを追加する(現代的な方法は組み込みのGatsby Head API)。 この主張の根拠 Gatsby's Head API lets pages export document-head metadata. 対象範囲: Gatsby Head API. 信頼度: 高 · 検証日: Gatsby: Head API
gatsby-plugin-sitemapでサイトマップを生成する。- ページの重複版を競合させないようcanonical URLを設定する。
- 画像のaltテキストを書く。 Gatsbyの画像ツールは自動的にリサイズと最適化を行いますが、altテキストは書きません。
多くの人を驚かせる点
Gatsbyは各ページで完全なReactランタイム(約200KB以上)をブラウザーへ送ります。HTMLはすでに完成しているためインデックス登録には影響しませんが、ページを遅くし、Core Web Vitals(Googleのページエクスペリエンス速度指標)へ影響する可能性があります。Astroのような軽量フレームワークは、比較するとほとんどJavaScriptを送りません。
現在Gatsbyを選ぶなら、もう一つ知るべき点があります。Netlifyは2023年にGatsbyを買収し、その後の活発な開発は大幅に鈍化しました。 既存Gatsbyサイトなら問題ありませんが、新規プロジェクトでは検討材料になります。
Head APIと旧react-helmetプラグイン、サイトマップとcanonicalの落とし穴、ReactバンドルとCWVのトレードオフ、Gatsbyの将来性を含む技術版はAdvancedタブで説明します。
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クエリは
datapropをHeadexportへ直接渡し、追加接続は不要。 - 標準パターンは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つあります。
- **
gatsby-plugin-canonical-urls**は各ページへ<link rel="canonical">を追加します。/blog?tag=fooと/blogが別々のcanonicalページとして扱われないようstripQueryString: trueを設定します。大半のサイトに推奨します。 - 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で最も重要な比較です。
| 観点 | Gatsby | Astro |
|---|---|---|
| ブラウザーへ送るJS | 200KB以上(完全な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へ
Headexportのタグが入るか確認する。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でよくある誤り
gatsby-plugin-react-helmetを使い続ける。 旧式なのでHead APIへ移行する。- DevToolsにはmetaタグがあるがページソースにはない。 SEOコンポーネントがクライアント側でレンダリングされている。DevToolsではなく
view-source:を確認する。 - 下書きがサイトマップへ入る。 Reactコンポーネントではなく
gatsby-node.jsのGraphQLで除外する。 src/pagesから孤立ページが生まれる。 Gatsbyはそこにあるものをすべて自動ルーティングするため、古いファイルも構築されサイトマップへ入る。- 二重canonical。
gatsby-plugin-canonical-urlsとreact-helmetが両方動く。 - 末尾スラッシュの不整合。
<Link>のクライアントルーティングがサーバー側の末尾スラッシュredirectを迂回する。 - canonicalからquery stringを除いていない。
stripQueryString: trueを設定する。 GatsbyImageのaltテキスト不足。 自動生成されない。/sitemap.xmlを送信する。 実際のファイルは/sitemap-index.xml。gatsby developでサイトマップをテストする。gatsby build時だけ生成される。- React stateでnoindexを切り替える。 Googleはすでに生HTMLを処理している可能性があり、生HTMLに
noindexがある場合はレンダリングを完全に省略することもあります。noindex判断は静的HTMLまたはサーバーヘッダーへ置きます。
背景にあるJavaScriptレンダリングの基礎は、親のJavaScript SEO ハブを参照してください。
AI要約
Advanced版の要点です。
- GatsbyにはSSG、DSG、SSR、クライアント専用ルートという4つのレンダリング経路がある。 既定のSSGでは
gatsby buildがページを静的HTMLへ事前レンダリングするため、クローラーは最初の取得で完全なコンテンツを受け取ります。レンダリングキュー不要で、最も強いインデックス可能性の基準です。DSGは初回要求まで生成を遅延し、SSRは要求ごとに生成し、クライアント専用ルートはブラウザーでJavaScriptが動くまでルート固有の内容を描画しません。これは純粋なクライアント側Reactアプリと同じです。経路ごとに本番HTMLを検証します。正常なgatsby buildが証明するのはSSGだけです。 - Reactバンドルのコストはクロール可能性ではなくパフォーマンスで、すべての経路に当てはまる。 Gatsbyはクライアント側で完全なReactランタイム(約200KB以上)をハイドレーションし、Core Web Vitalsへ影響します。JavaScriptを送らないHugo、Jekyll、Eleventyにはなく、Astroはislandで約5KBを送ります。
- Gatsby Head API(v4.19+)を使う。 ページ/テンプレートからの名前付き
Headexportでtitle/meta/canonical/JSON-LDを管理します。4経路すべてで機能し、旧gatsby-plugin-react-helmetを置き換えます。ページ/テンプレートだけで使え、idで重複排除します。 - 経路別の本番チェック: 生HTML、Head exportのメタデータ、HTTP status、キャッシュ、失敗/空状態を、そのルートが使う経路ごとに5項目すべて確認する。サイトマップ生成と除外が本番ビルドだけで正しいことも確認する。
- サイトマップ:
gatsby-plugin-sitemapはsitemap-index.xmlを生成するため、/sitemap.xmlではなくそれを送信します。gatsby build時だけ動き、devでは動きません。Googleは<priority>/<changefreq>を無視するため<lastmod>を重視します。下書きはgatsby-node.jsで除外します。DSG、SSR、クライアント専用ルートは、SSGと同じ前提にせず個別の掲載判断が必要です。 - canonical: Head APIと
location.pathname、またはstripQueryString: true付きgatsby-plugin-canonical-urlsのどちらかを使い、併用しない(二重canonical不具合)。 - 画像:
gatsby-plugin-imageはサイズ、WebP、遅延読み込みを処理してCLSを防ぎますが、altテキストは書かないため手動です。 - 「DevToolsにはあるがview-sourceにはない」不具合は、SEOコンポーネントが
Headexportではなくクライアント側でレンダリングされていることを示す。 - 保守リスク: Netlifyが2023年にGatsbyを買収後、活動が鈍化しました(React 19未対応、ロードマップ未達)。既存サイトには問題ありませんが、新規プロジェクトではAstro/Next.jsと比較します。
公式ドキュメント
GatsbyとGoogleが公開する一次資料です。
Gatsby
- レンダリング方式 — SSG、DSG、SSR、クライアント専用ルートという4経路の概要。
- Deferred Static Generationの利用 — DSGの初回要求時生成。
- Server-Side Renderingの利用 — Gatsby FunctionsによるSSR要求時出力。
- クライアント専用ルートとユーザー認証 — 初期HTMLにルート固有内容がない理由。
- SEOコンポーネントの追加 — 推奨SEOコンポーネントパターン。
- Gatsby Head APIリファレンス — headタグを管理する現代的な組み込み方式。
- Gatsby Head APIの紹介 — react-helmetを置き換えた理由。
- gatsby-plugin-sitemap — 本番ビルド限定のサイトマップ生成。
- gatsby-plugin-image —
StaticImage/GatsbyImage、形式、CLS防止。 - gatsby-plugin-robots-txt — 環境対応robots.txt。
- gatsby-plugin-canonical-urls — サイト全体のcanonicalと
stripQueryString。 - gatsby-plugin-react-helmet — 旧式メタデータ方式。
- gatsby-plugin-next-seo — 構築済みJSON-LD/schemaコンポーネント。
- GatsbyのReactハイドレーション — 静的HTMLが対話可能になる仕組み。
- JavaScript SEOの基礎を理解する — クロール → レンダリング → インデックス登録の段階と事前レンダリングの利点。
情報源からの引用
Gatsbyの構造へ直接当てはまる公式発言です。GatsbyはJavaScript SSGなので、関連する一次資料はGoogleのJavaScriptレンダリング案内と同じ主題に関するGoogle担当者の発言です。
Google Search Central — JavaScript SEOの基礎
- “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がビルド時に行うことの根拠。
- “The page may stay on this queue for a few seconds, but it can take longer than that.” (翻訳)「ページはこのキューに数秒とどまる場合があり、それ以上かかることもあります。」— 事前レンダリングHTMLなら回避できるレンダリングキューについて。
Martin Splitt(Google Developer Advocate)
- “Even though Googlebot can render JavaScript, we don’t want to rely on that.” (翻訳)「GooglebotはJavaScriptをレンダリングできますが、それに依存したくありません。」— SSG/SSRを選ぶ原則(SEJ/Botifyの報道経由)。
- “A lot of people are still looking at view source. That is not what we use for indexing. We use the rendered HTML.” (翻訳)「今も多くの人がview sourceを見ていますが、インデックス登録に使うのはそれではなくレンダリング済みHTMLです。」— Gatsbyの「DevToolsとview-source」不具合が混乱を招く正確な理由(SEJ経由)。
- “The median time in the render queue is only five seconds.” (翻訳)「レンダリングキューの時間の中央値はわずか5秒です。」— 中央値であり、裾の遅延ははるかに長い可能性がある点に注意(BrightonSEO、SEJ経由)。
John Mueller(Google Search Advocate)
- “Server-side rendering is not a requirement there. We can render JavaScript-based pages for the most part.” (翻訳)「サーバーサイドレンダリングは必須ではありません。大半のJavaScriptベースページはレンダリングできます。」— SSR/SSGはベストプラクティスですが厳密な必須条件ではなく、Googleは最終的にCSRコンテンツをレンダリングするという文脈(SEJ経由)。
Gatsby SEOチェックリスト
Gatsbyビルドが実際に検索向けになっているか確認します。
- 主要コンテンツがDevToolsだけでなくView Source(生HTML)にあり、クライアント側だけでなく事前レンダリング済みだと確認できる。
- 新規実装では旧react-helmetでなく、ページ/テンプレートの
HeadexportによるGatsby Head APIでメタデータを設定する。 - すべてのページにビルド時の固有な
<title>とmeta descriptionがあり、siteMetadataのフォールバックを持つ。 - canonicalタグはHead APIまたは
gatsby-plugin-canonical-urlsの一方だけで設定し、二重canonicalを避ける。 - query-string版がcanonicalを分散させないよう
stripQueryString: trueを設定する。 -
gatsby-plugin-sitemapを導入し、devでは動かないためgatsby build && gatsby serveで出力を確認する。 - Search Consoleへ
/sitemap.xmlではなく**/sitemap-index.xml**を送信する。 - 下書きがサイトマップへ入らないよう
gatsby-node.js(GraphQL)で除外する。 - 自動ルートになる
src/pagesに古い/孤立ファイルがない。 -
robots.txtでNetlify preview/branchデプロイをブロックし、本番は開放する。 - 各
GatsbyImage/StaticImageに明示的なaltテキストがある。 - JS/CSSアセットを
robots.txtでブロックしていない。 - 末尾スラッシュ形式を決め、
<Link>だけでなくホスト/CDNで強制する。 -
noindex判断をReact stateではなく静的HTMLまたはサーバーヘッダーへ置く。 - Core Web Vitalsを確認する。Reactバンドルが主な負担になりやすく、可能なら部分ハイドレーションを検討する。
- 使用する全レンダリング経路(SSG、DSG、SSR、クライアント専用)で、ローカル
gatsby buildログだけでなく本番の生HTML、メタデータ、HTTP status、キャッシュ、失敗/空状態を確認する。 - DSG、SSR、クライアント専用ルートごとに明示的で検証済みのサイトマップ判断があり、SSGページと同じ前提にしていない。
考え方の枠組み
1. クロール可能性とパフォーマンスは別々の評価軸。 Gatsbyは事前レンダリングHTMLでクロール可能性に優れる一方、Reactバンドルでパフォーマンスコストを負います。混同しないでください。「ReactだからGatsbyはSEOに悪い」は2つを取り違えています。コンテンツは問題なくインデックスされ、JSの負担はCore Web Vitalsに現れます。
2. HTMLが早く存在するほど、問題は起きにくい。 SSGは最も安全なビルド時にHTMLを確定します。Gatsbyの既定ページはSSGなので、インデックス可能性のレンダリング範囲(おおむね危険から安全へ、クライアント専用 → SSR → DSG → SSG)の安全側です。ただしGatsbyは複数方式を持ち、ページがDSG、SSR、クライアント専用の場合もあります。各ルートの実際の方式を確認してから、安全側だと判断します。
3. 既定はHead API、react-helmetは継承コードだけ。
新規実装の答えはGatsby Head APIです。react-helmetは選ぶものではなく移行で外すものです。タグが生HTMLへ出ない場合、最初に「Head export内にあるか、コンポーネント内に閉じ込められているか」を確認します。
4. canonical機構は正確に1つ選ぶ。
Head APIのcanonicalまたはgatsby-plugin-canonical-urlsであり、併用しません。2機構 = 2つのcanonicalタグ = 二重canonical不具合です。<head>へ書くすべての要素も同様に、タグごとに信頼できる唯一の情報源を決めます。
5. Gatsbyは見つけたものをすべて構築するため、フィルターは自分の仕事。
下書き、古いsrc/pagesファイル、query-string版をGatsbyが編集判断してくれることはありません。gatsby-node.js、canonical設定、サイトマップoptionで除外しなければ、配信されクロールされます。
6. 新規プロジェクトか既存サイトかで保守判断が変わる。 既存Gatsbyサイトは機能するため維持します。新規プロジェクトでは、保守鈍化とエコシステム劣化のリスクが実際の判断材料です。採用前にAstro/Next.jsと比較します。
Gatsby SEO早見表
メタデータ: どの方式を使うか
| 方式 | 状態 | 使用場面 |
|---|---|---|
Gatsby Head API(Head export) | 現行(v4.19+) | すべての新規実装。ページ/テンプレートのみ |
gatsby-plugin-react-helmet | 旧式 | 移行待ちの既存サイト |
プラグイン一覧
| プラグイン | 機能 | SEOの注意点 |
|---|---|---|
gatsby-plugin-sitemap | sitemap-index.xmlを生成 | 本番ビルドのみ。index URLを送信 |
gatsby-plugin-image | サイズ、WebP/AVIF、遅延読み込み、CLS防止 | altテキストは自動生成しない |
gatsby-plugin-canonical-urls | サイト全体のcanonical | react-helmetのcanonicalと併用しない |
gatsby-plugin-robots-txt | ビルド時robots.txt | 環境規則でpreviewデプロイをブロック |
gatsby-plugin-next-seo | 構築済みJSON-LDコンポーネント | — |
gatsby-plugin-manifest | PWAマニフェスト(アイコン/テーマ) | 構造化データではない |
要点
- サイトマップは
/sitemap.xmlではなく**/sitemap-index.xml**。 - サイトマップは**
gatsby developでは生成されない**ため、gatsby build && gatsby serveを使う。 - Googleは
<priority>/<changefreq>を無視するため、正確な<lastmod>だけを重視する。 - Reactバンドルはページあたり約200KB以上(完全ハイドレーション)。クロールではなくCWVのコスト。
- Astroは比較上約5KB(islandのみ)。
gatsby develop≠ 本番。サイトマップ、robots、一部の最適化が異なる。- Netlifyは2023年2月にGatsbyを買収し、保守は鈍化(React 19未対応)。
2行のSEO用Head export
export const Head = ({ data, location }) => (
<>
<title>{data.post.title}</title>
<link rel="canonical" href={`https://example.com${location.pathname}`} />
</>
) Gatsbyの本番成果物を確認する
gatsby developではなく、gatsby buildの後に実行します。
find public -name '*.html' -type f | while IFS= read -r file; do
title_count=$(grep -Eio '<title>[^<]*</title>' "$file" | wc -l | tr -d ' ')
canonical_count=$(grep -Eio '<link[^>]+rel=["'"']canonical["'"'][^>]*>' "$file" | wc -l | tr -d ' ')
robots=$(grep -Eio '<meta[^>]+name=["'"']robots["'"'][^>]*>' "$file" | head -1)
if [ "$title_count" -ne 1 ] || [ "$canonical_count" -ne 1 ]; then
printf '%s\ttitles=%s\tcanonicals=%s\t%s\n' "$file" "$title_count" "$canonical_count" "$robots"
fi
doneHead APIとプラグインの重複機構による欠落または重複出力を検出します。値とサイトマップ掲載は別々に確認してください。
Gatsby SEOのツール
- Gatsby Head API(組み込み、v4.19+)— 依存関係なしでページ/テンプレートごとの
<title>、meta、canonical、JSON-LDを管理する。 gatsby-plugin-sitemap— 本番ビルドでsitemap-index.xmlを生成する。gatsby-plugin-image—StaticImage/GatsbyImage、レスポンシブサイズ、WebP/AVIF、遅延読み込み、CLS防止プレースホルダー。gatsby-plugin-canonical-urls—stripQueryString対応のサイト全体canonical。gatsby-plugin-robots-txt— 環境対応robots.txt(previewデプロイをブロック)。gatsby-plugin-next-seo— 手書きを避ける場合の構築済みJSON-LD/schemaコンポーネント。view-source:/GSC URL検査 — hydrated DOMを示すDevToolsではなく、「コンテンツとメタデータが生HTMLにあるか」の基準。- Lighthouse/PageSpeed Insights — ReactバンドルのCore Web Vitalsコストと部分ハイドレーションの価値を確認する。
gatsby build && gatsby serve— サイトマップ、robots.txt、本番限定の最適化をローカルテストする唯一の方法。
Gatsbyサイトで避けること
Gatsbyサイトの構築と配信で実際に起きる具体的な誤りです。診断ではなく予防の観点で整理します。
新規実装でgatsby-plugin-react-helmetを使い続ける
誤り: 古いGatsbyチュートリアルに載っているため、新規ページや新規プロジェクトでも習慣でreact-helmetを選ぶ。
誤りである理由: react-helmetにはReact Hooksと並行レンダリングに関する既知の問題があり、defer={false}で直すバックグラウンドタブのtitle不具合もあります。不要になったサードパーティーバンドルとProviderラッパーでもあります。
代わりに行うこと: 組み込みのGatsby Head API(v4.19+)、つまりページまたはテンプレートからの名前付きHead exportを使います。react-helmetは未移行の既存コードだけに残します。
2つのcanonical機構を同時に動かす
誤り: 同じページでgatsby-plugin-canonical-urlsとreact-helmet(またはHead API)のcanonicalタグを両方設定する。
誤りである理由: 両方が動き、ページから2つの<link rel="canonical">タグが配信されます。意図したcanonical URLを曖昧にする既知のGatsby障害です。
代わりに行うこと: サイト全体でHead API、またはstripQueryString: true付きプラグインの正確に1つを選び、もう一方を完全に外します。
ビルド時ではなくReactコンポーネント内で下書きを除外する
誤り: クライアント側の確認(例: if (!post.published) return null)で未公開コンテンツを隠し、検索にも出ないと考える。
誤りである理由: Gatsbyはコンポーネントがブラウザーで動く前に、見つけたものをすべて静的HTMLへ構築します。Reactの確認が動く時点で、下書きページはすでに構築され、サイトマップにも載っています。
代わりに行うこと: gatsby-node.jsのGraphQLクエリで、公開日がない項目を除外するなどして下書きをフィルターし、最初から構築も掲載もされないようにします。
altテキストなしでGatsbyImageを配信する
誤り: gatsby-plugin-imageがサイズ、形式、プレースホルダーを自動生成するため、画像SEO全体も処理すると信頼する。
誤りである理由: プラグインが最適化するのは配信であり、altテキストは書きません。ほかの画像処理が済んで見えるからこそ、GatsbyImage/StaticImageのalt不足はGatsby SEOで最も一般的な見落としの一つです。
代わりに行うこと: すべての画像コンポーネントで毎回altテキストを必須項目にします。Gatsbyが完全に利用者へ残す唯一の画像SEO要素です。
gatsby developで本番SEO出力を確認できると考える
誤り: gatsby developでサイトマップ、robots.txt、noindexの挙動を確認し、何も表示されないため壊れていると判断する。
誤りである理由: gatsby-plugin-sitemapなど複数のビルド時処理は開発モードでは動きません。不具合ではなく、dev modeが仕様どおり動いているだけです。
代わりに行うこと: サイトマップ、robots.txt、本番限定の最適化について結論を出す前にgatsby build && gatsby serveを実行します。
<Link>のクライアントルーティングで末尾スラッシュ不整合が隠れる
誤り: サーバー側の末尾スラッシュredirect規則がアプリ内ナビゲーションを含むすべての場所へ適用されると考える。
誤りである理由: Gatsbyの<Link>コンポーネントはクライアント側History APIルーティングを使い、通常末尾スラッシュ正規化に頼るサーバー側301を迂回します。そのため内部リンクがredirect規則を一度も通らず、静かに「誤った」形式を配信できます。
代わりに行うこと: 末尾スラッシュ形式を1つ決めてホスト/CDN層で強制し、ページへの到達方法にかかわらずcanonicalを一致させます。
Gatsby SEOでよくある問題
実際にGatsbyサイトで観測している症状から、原因と修正を引けるようにします。
DevToolsにはmetaタグがあるがview-sourceにはない
症状: Chrome DevToolsでtitle/meta descriptionは正しく見えるが、view-source:(または生のcurl)では欠落しているか汎用値になっている。
考えられる原因: SEOコンポーネントがクライアント側でレンダリングされています。ページのHead exportとして、またはその内部で使わず一般コンポーネントとして使っているため、ハイドレーション後のDOMにだけ現れます。
修正: タグをページまたはテンプレートの名前付きHead exportへ移動します。ハイドレーション済みDOMを示すDevToolsではなく、クローラーが生取得で見るものを示すview-source:またはcurl -s <url>で確認します。
サイトマップがない、または空
症状: /sitemap-index.xmlへアクセスするかSearch Consoleを確認しても何もない、または一覧が不完全。
考えられる原因: ほぼ常に、gatsby-plugin-sitemapがまったく動かないgatsby developでテストしたことです。まれに、プラグインがgatsby-config.jsへインストール/設定されていません。
修正: gatsby build && gatsby serveを実行して再確認します。それでもなければgatsby-config.jsにプラグインがあるか確認します。/sitemap-index.xmlを直接要求して検証してください。/sitemap.xmlではなくindex URLです。
1ページにcanonicalタグが2つある
症状: ソース表示(またはschema/タグ監査)で、同じページに2つの<link rel="canonical">要素がある。
考えられる原因: 同じページでgatsby-plugin-canonical-urlsとreact-helmet(またはHead API)のcanonicalが両方動いています。
修正: 片方を外し、1つの情報源だけがcanonicalを設定するようにします。ソースを再確認し、PatrickのCanonical Tag Checker で正確に1つのcanonicalが解決されることを確認します。
下書きまたは孤立ページがサイトマップへ入る
症状: サイトマップ(またはSearch Consoleのカバレッジ)に、下書き投稿やsrc/pagesの古いファイルなど公開予定のないURLが載る。
考えられる原因: Gatsbyは見つけたものをすべて自動構築、自動ルーティングします。フィルターされない未公開GraphQL項目やsrc/pagesの残存ファイルが、実際の静的ページとして構築され、ほかのページと同様に掲載されます。
修正: gatsby-node.jsのGraphQLクエリで、公開日がない項目を除外するなどして下書きをフィルターし、構築されないようにします。孤立したsrc/pagesファイルは古いファイルを削除します。ページがすでに構築された後なので、コンポーネント内のフィルターでは遅すぎます。
ページのquery-string版が重複としてインデックスされる
症状: Search Consoleで/blogと/blog?tag=fooのような重複に近いURLが両方インデックスされる、または重複コンテンツとして指摘される。
考えられる原因: gatsby-plugin-canonical-urlsがstripQueryString: trueなしで動き、query-string版がクリーンURLではなく自分自身へcanonical化されています。
修正: プラグイン設定へstripQueryString: trueを追加して再構築し、query-string URLのcanonicalタグを再確認します。クリーンなパスを指すはずです。
noindexにしたページが検索結果へ残る
症状: ページをnoindexに設定したが、数週間後もインデックスされたまま、またはSearch Consoleがタグに反してインデックス済みと表示する。
考えられる原因: noindexディレクティブを静的HTMLまたはサーバーヘッダーへ組み込まず、React stateで切り替えています。Googleはnoindexなしの生HTMLをすでに処理した可能性があります。クライアントレンダリング後にだけnoindexを見る場合、ページの再レンダリングを完全に省略することもあります。
修正: 条件付きReactロジックではなく、ビルド時のHead exportによる静的HTMLまたはHTTPヘッダーへnoindex判断を移します。view-source:で生レスポンスにタグがあることを再確認します。
確認クイズ: Gatsby SEO
Gatsbyサイトを検索向けに最適化する5問です。各問の回答を選び、確認してください。
有用なリソース
関連する私の記事
- JavaScript SEO: A Definitive Guide — レンダリング、DOMの同等性、Gatsbyのような静的/事前レンダリング出力が低リスク側にある理由。
- The Beginner’s Guide to Technical SEO — レンダリング構造を技術SEO全体へ位置付ける。
私の講演
- How Search Works (SlideShare)— クロール、レンダリング、インデックス登録、ランキングの解説。(継続的な免責事項: “This is my understanding of systems… not going to be 100% complete or accurate.” (翻訳)「これは私のシステム理解であり、100%完全または正確とは限りません。」)
業界資料
- Gatsby Head API reference — 現代的なメタデータ方式の一次資料。
- Introducing the Gatsby Head API — react-helmetを置き換えた理由に関するGatsby自身の説明。
- Google Search Central — JavaScript SEO basics — Gatsbyビルドならコンテンツについて省略できるクロール → レンダリング → インデックス登録の段階。
- Gatsby is joining Netlify — 保守状況の背景となる2023年の買収発表。
- Netlify acquires frontend platform Gatsby (TechCrunch)— 買収に関する独立報道。
- “Is GatsbyJS abandoned?” discussion #39062 — Gatsbyの現在の保守状態を扱うコミュニティ議論。
- SEO comparison of Gatsby vs Next vs Astro (Vaihe)— JSペイロードとクロールバジェットの比較。
- Understanding partial hydration in Gatsby 5 (LogRocket)— CWVに関係する部分ハイドレーションの改善と制約。
変更履歴
2026年8月23日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年8月3日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年7月18日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。