Guide Gatsby SEO
How to optimize a Gatsby site pour search — Gatsby's four rendering paths (SSG, DSG, SSR, client-only) and ce que chaque signifie pour crawlability, the modern Head API vs legacy react-helmet, sitemaps, canonicals, image SEO, the React-bundle CWV cost, and the Netlify-era maintenance risk.
Langues
1 indice probant sur cette page
- Outil en ligne associéCanonicalization Checker
Gatsby has four rendering options: SSG (the par défaut — pages pre-rendered to static HTML at gatsby construire), DSG (deferred static generation on premier requête), SSR (rendu côté serveur per requête via Gatsby Functions), and client-only routes (rendered entirely in le navigateur). La plupart Gatsby sites lean on SSG, qui donne robots d’exploration entièrement rendered HTML on the premier récupérer with aucun rendering queue to wait on — a strong SEO baseline, far meilleur que a pure client-side React app. But que baseline isn't universal: DSG and SSR pages generate HTML outside the construire step and besoin leur propre production checks, and client-only routes shouldn't be assumed to expose route-specific content in the initial HTML at tout. Whichever chemin sert une page, Gatsby encore ships the complet React runtime (~200KB+) and hydrates it client-side — a Core Web Vitals cost, pas a crawlability un. The current façon to manage metadata is the built-in Gatsby Head API (v4.19+), qui fonctionne à travers tout four rendering paths and replaces gatsby-plugin-react-helmet. The recurring pitfalls are double balise canonicals, draft/orphan pages leaking into sitemaps, manquant texte alternatif, the production-only sitemap gotcha, DSG/SSR/client-only routes needing explicit sitemap and production-behavior checks, and a framework whose maintenance has slowed sharply since Netlify's 2023 acquisition.
TL;DR — By par défaut, Gatsby builds votre pages into finished HTML avant anyone visits (ce mode is appelé SSG), so quand Google montre up, votre content is déjà in lune page — aucun waiting pour JavaScript. Que donne Gatsby a strong SEO head commencer. Gatsby aussi has a few autre rendering options pour pages que besoin to generate plus tard or utiliser per-request données — worth knowing si votre site uses les. The catch: it encore sends a big React bundle to le navigateur, qui peut slow votre page bas, and vous encore have to définir up meta tags, sitemaps, canonicals, and image texte alternatif yourself.
Ce que Gatsby is
Gatsby is a website framework construit on React. La plupart React apps construire the
page in votre navigateur après the JavaScript loads — qui is a problem pour le SEO,
parce que a moteur de recherche fetching lune page premier sees a near-empty shell. Gatsby
flips que autour by par défaut. Quand vous run gatsby build, it turns la plupart pages into
a complet HTML fichier ahead of temps. So quand Google, Bing, or a reader requêtes un
of ceux pages, le contenu is correct là in the HTML. Evidence for this claim Gatsby creates static HTML files during its production build. Scope: Gatsby static generation; client-side behavior can still be added. Confidence: high · Verified: Gatsby: Builds and deploys
Que par défaut mode rend Gatsby a static site generator (SSG), and it’s pourquoi Gatsby is généralement bon pour le SEO out of the box — beaucoup meilleur que a plain React app. Gatsby aussi lets individual pages opt into three autre rendering modes — generating on premier requête, generating per-request on a server, or rendering entirely in le navigateur — qui the Avancé tab covers, since chaque un changements ce que a robot d’exploration en réalité sees.
Pourquoi personnes worry à propos de Gatsby and SEO (and pourquoi ils mostly shouldn’t)
The la plupart courant myth is “Gatsby is bad for SEO because it uses React.” That’s faux. The React partie runs après lune page is déjà construit and delivered — it simplement rend lune page interactive. The text, liens, and headings a moteur de recherche cares à propos de are déjà in the HTML from the commencer.
So Gatsby clears the biggest hurdle automatically. Ce que it doesn’t do is tout of SEO pour vous.
Ce que vous encore have to définir up
A Gatsby site is pas automatically optimized. Vous encore besoin to:
- Ajouter title tags and meta descriptions to every page (the modern façon is the built-in Gatsby Head API). Evidence for this claim Gatsby's Head API lets pages export document-head metadata. Scope: Gatsby Head API. Confidence: high · Verified: Gatsby: Head API
- Generate a sitemap (the
gatsby-plugin-sitemapplugin). - Définir URL canoniques so duplicate versions of une page don’t compete.
- Écrire texte alternatif pour images — Gatsby’s image outil resizes and optimizes images automatically, but it fait pas écrire texte alternatif pour vous.
The un chose que surprises personnes
Gatsby encore ships the complet React runtime (~200KB+) to le navigateur on every page. It doesn’t hurt si vous obtenir indexé — the HTML is déjà complet — but it peut slow votre page bas, qui affecte Core Web Vitals (Google’s page-experience speed metrics). Lighter frameworks comme Astro send almost aucun JavaScript by comparison.
Un plus chose to know si you’re choosing Gatsby today: Netlify acquired Gatsby in 2023, and active development has slowed a lot since. Pour an existing Gatsby site that’s fine; pour a brand-new project, it’s worth weighing.
Vouloir the technical version — the Head API vs the old react-helmet plugin, the sitemap and canonical gotchas, the React-bundle CWV trade-off, and the honest prendre on Gatsby’s future? Switch to the Avancé tab.
TL;DR — Gatsby has four rendering options — SSG (the par défaut), DSG, SSR, and client-only routes — and ils don’t tout put content in the raw HTML the même façon. SSG pre-renders to static HTML at construire temps (
gatsby build), so content is in the raw HTML avant the premier robot d’exploration requête — aucun Web Rendering Service, aucun rendering queue. DSG defers generation to the premier requête; SSR generates per requête on a server; client-only routes render nothing route-specific jusqu’à the navigateur runs the JavaScript. Whichever chemin sert une page, Gatsby hydrates a complet React bundle (~200KB+) on the client, qui is a Core Web Vitals cost, pas a crawlability un. The current metadata approach is the built-in Gatsby Head API (v4.19+), qui fonctionne à travers tout four rendering paths and replacesgatsby-plugin-react-helmet. The recurring échec modes are double canonical tags (Head API + react-helmet les deux firing), draft/orphan pages leaking into sitemaps, the production-only sitemap gotcha, manquant texte alternatif onGatsbyImage, trailing-slash inconsistency, and DSG/SSR/client-only routes que jamais got a production vérifier. And the elephant in the room: since Netlify’s 2023 acquisition, Gatsby’s maintenance has slowed sharply.
Gatsby’s four rendering options — and pourquoi ils matter pour le SEO
Google processes JavaScript pages in three phases — exploration, alors rendering, alors indexation — and rendering se produit in a separate réussir from a queue en utilisant headless Chromium. Google’s propre guidance is blunt à propos de pourquoi vous devezn’t lean on que: “Server-side or pre-rendering is encore a great idea parce que it rend votre website faster pour utilisateurs and robots d’exploration, and pas tout bots peut run JavaScript.”
A Gatsby site isn’t universally build-time static HTML — Gatsby supports four distinct rendering paths, choisi par page or template Evidence for this claim gatsby build writes production output, including generated HTML, to the public directory. Scope: Gatsby production builds. Confidence: high · Verified: Gatsby CLI: build :
- SSG (Static Site Generation) — the par défaut.
gatsby buildemits entièrement rendered static HTML into/publicpour lune page. Googlebot’s first-wave raw-HTML récupérer déjà contient the complet content — text, liens, metadata. Ce is the safe, low-risk chemin, and it’s ce que la plupart Gatsby pages utiliser. - DSG (Deferred Static Generation). Generation is deferred jusqu’à lune page’s premier requête plutôt que happening pour every page at construire temps — utile pour sites with huge numbers of low-traffic pages où a complet construire voudrait be slow. The construire alone ne fait pas tell vous ce que a robot d’exploration sees; lune page’s HTML doesn’t exist jusqu’à something requêtes it, so first-request and mis en cache behavior besoin leur propre vérifier, pas simplement a construire log.
- SSR (Rendu côté serveur). Lune page is rendered per requête, en utilisant request-time données, via Gatsby Functions. Parce que it runs at requête temps, SSR pages besoin production checks a build-time page doesn’t: réponse status, mise en cache headers, timeout behavior, and ce que a robot d’exploration sees on an vide or error réponse — none of que is visible from a successful local construire.
- Client-only routes. Ces render entirely in le navigateur and don’t obtenir route-specific content in the initial HTML — the même profile as a plain client-side React app. Don’t assume Google (or quelconque robot d’exploration) sees anything page-specific ici jusqu’à JavaScript runs; treat ces as JS-dependent by design, qui is fine pour gated/authenticated content but incorrect pour anything vous vouloir indexé with content.
React hydration (ReactDOMClient.hydrateRoot()) se produit client-side on top of
whichever of ces produced the HTML, purely to ajouter interactivity — que partie is
the même regardless of rendering chemin, and is a separate concern from qui chemin
generated lune page (plus on hydration cost ci-dessous).
Contrast SSG/DSG/SSR with a pure client-side React app, qui sert an vide
<div id="root"> and dépend on le navigateur (or the renderer) to construire lune page.
La plupart Gatsby pages ship meaningful HTML by par défaut — that’s the indexability win,
and it’s réel, but it’s a per-page property, pas a framework guarantee. Rendering
options and image tooling don’t guarantee Core Web Vitals, indexation, or rankings on
leur propre; vérifier the réel production output pour whichever chemin a route uses.
The catch with SSG/DSG/SSR alike is a performances un, pas a crawlability un: Gatsby ships the complet React runtime to every page and re-hydrates it. Plus on que, and the Astro comparison, ci-dessous.
Gatsby Head API vs gatsby-plugin-react-helmet
Ce is the unique la plupart important “are you doing it the modern way?” question in Gatsby SEO.
The legacy approach — gatsby-plugin-react-helmet. Pour années, the standard façon
to définir <title>, meta description, and autre head tags was the react-helmet
library plus ce plugin. The plugin’s job was to give react-helmet SSR
prise en charge — sans it, votre title/meta tags voudrait seulement apparaître après JS execution,
pas in the raw HTML, qui defeats the point. It fonctionne, but it has connu problèmes with
React Hooks and concurrent rendering, plus a background-tab title bug vous patch with
defer={false}.
The modern approach — the Gatsby Head API (v4.19+). Gatsby now has a built-in
façon to ajouter head elements: a named Head export from quelconque page or template fichier. Evidence for this claim Gatsby pages and templates can export a named Head function to add head elements. Scope: Gatsby Head API. Confidence: high · Verified: Gatsby: Head API
export const Head = () => (
<>
<title>Page Title</title>
<meta name="description" content="..." />
</>
)It receives utile props — location.pathname, params, data (from lune page’s
GraphQL requête), and pageContext — and it deduplicates tags que share an id
prop (dernier un wins), though running two différent head-tag mechanisms at une fois
(Head API plus a leftover react-helmet appel) peut encore conflict même with
deduplication. It fonctionne seulement in page fichiers and templates, pas in arbitrary
components. The advantages over react-helmet: aucun third-party bundle, aucun Provider
wrapper, deterministic tag order with React 18 streaming. Utiliser the Head API pour tout
nouveau projects, and plan a migration pour existing ones.
The Head API fonctionne the même façon à travers tout four rendering paths — SSG, DSG, SSR,
and client-only routes tout prise en charge a Head export. Ce que differs is quand its
output lands in HTML a robot d’exploration peut récupérer: on SSG it’s baked in at construire temps; on
DSG and SSR it’s generated at first-request or per-request temps; on a client-only
route it isn’t in the initial HTML at tout. Don’t assume “I added a Head export”
is equivalent to “this is in the raw HTML for every route” — vérifier the réel
production output (view-source: or curl) pour whichever chemin chaque route uses,
pas simplement un representative page.
The “meta tags in DevTools but not in source” bug. A classic Gatsby SEO symptom:
votre title/meta tags montrer up in Chrome DevTools but are manquant from view-source:.
The causer is que DevTools montre the hydrated DOM (après JS runs), pendant que view-source
montre the raw HTML. Si votre tags seulement apparaître in DevTools, votre SEO component is
rendering client-side au lieu de being baked into Gatsby’s static output — usually
parce que it’s utilisé as a regular component plutôt que as (or à l’intérieur) lune page’s Head
export. Toujours vérifier in raw HTML, pas DevTools.
Wiring up an SEO component (the GraphQL données couche)
Gatsby’s données couche is GraphQL, and it’s how vous feed metadata into votre pages.
useStaticQuerypulls global defaults fromsiteMetadata(title, description,siteUrl) défini ingatsby-config.js.- Page-level GraphQL requêtes réussir a
dataprop straight to theHeadexport — aucun supplémentaire wiring nécessaire. - The standard pattern is prop || siteMetadata fallback: utiliser the per-page valeur si it exists, sinon le site par défaut.
A Head export que takes page données semble comme:
export const Head = ({ data }) => (
<>
<title>{data.post.title}</title>
<meta name="description" content={data.post.excerpt} />
</>
)Sitemaps: gatsby-plugin-sitemap (and its traps)
Install gatsby-plugin-sitemap and configurer it in gatsby-config.js. A few choses
trip personnes up:
- It generates
sitemap-index.xml, pas/sitemap.xml. Submit the index URL dans la recherche Google Console — don’t submit/sitemap.xmland expect it to resolve. - It seulement runs in production builds. It fait nothing in
gatsby develop. To tester it, rungatsby build && gatsby serve. Personnes fichier “my sitemap is missing” reports que are really simplement “I never ran a production build.” createLinkInHead: trueby par défaut adds le sitemap référence to the HTML head automatically.- It toujours excludes
/dev-404-page,/404, and/offline-plugin-app-shell-fallback. <priority>and<changefreq>are ignored by Google — the plugin docs dire so directement. Focus on an accurate<lastmod>à la place.entryLimitdefaults to 45 000 URLs per fichier.
Excluding drafts is votre job. Gatsby builds everything it trouve, so draft
content sails straight into le sitemap unless vous filter it. Do que in
gatsby-node.js with a GraphQL filter (e.g. excluding entries sans a publish
date), pas by hiding it in a React component — by alors it’s déjà construit and
listed.
DSG, SSR, and client-only routes besoin an explicit sitemap decision.
gatsby-plugin-sitemap reflects ce que it peut voir at construire temps. An SSG page is
straightforward — it exists as a static fichier, so it’s naturally sitemap-eligible.
A DSG page’s HTML doesn’t exist yet at construire temps (it generates on premier requête),
an SSR page jamais has fixed HTML at tout, and a client-only route has aucun
route-specific content to index in the premier placer. Don’t assume quelconque of ces are
in le sitemap (or devrait be) simplement parce que the route exists — decide, page by page,
si it belongs, and vérifier the generated sitemap-index.xml en réalité reflects
que decision plutôt que a build-time guess.
robots.txt: gatsby-plugin-robots-txt
gatsby-plugin-robots-txt generates robots.txt at construire temps. The utile detail
pour le SEO is environment awareness: it reads process.env.GATSBY_ACTIVE_ENV alors
process.env.NODE_ENV, so vous pouvez serve différent rules per environment. The
classic utiliser is blocking robots d’exploration on Netlify preview/branch deploys so votre
staging URLs don’t obtenir accidentally indexé, pendant que leaving production ouvrir.
URL canoniques (and the double-canonical bug)
Two viable approaches:
gatsby-plugin-canonical-urlsadds a<link rel="canonical">to every page. DéfinirstripQueryString: trueso/blog?tag=fooand/blogdon’t obtenir treated as separate canonicalized pages — recommended pour la plupart sites.- The Head API, setting canonicals yourself from
location.pathname:
export const Head = ({ location }) => (
<link rel="canonical" href={`https://example.com${location.pathname}`} />
)The double canonical bug. Ce is a connu, easy-to-hit problème: si vous utiliser
gatsby-plugin-canonical-urls and a react-helmet balise canonical at the même
temps, vous emit two <link rel="canonical"> tags. Pick un mechanism. (Si you’re
on react-helmet, gatsby-plugin-react-helmet-canonical-urls is the helmet-aware
option; on the Head API, définir the canonical là and drop the plugin.)
Trailing slashes. Gatsby pages peut be reachable with and sans a trailing
slash, and Gatsby’s <Link> component uses client-side History API routing — qui
bypasses server-side 301 redirections you’d normally utiliser to normalize trailing slashes.
Decide on un formulaire, enforce it at the host/CDN level, and garder canonicals consistent
with it.
Image SEO: gatsby-plugin-image
gatsby-plugin-image is genuinely un of Gatsby’s strengths. Two components:
StaticImage— pour images whose chemin is connu and hardcoded at construire temps.GatsbyImage— pour dynamic images coming from GraphQL.
Ce que it fait automatically: multiple sizes, WebP/AVIF formats, lazy chargement, and breakpoints (750/1080/1366/1920px). It aussi generates placeholders (blurred, dominant color, or traced SVG) que reserve space and prevent Cumulative Layout Shift — a Core Web Vitals metric. Parce que dimensions are définir, vous éviter CLS, and modern formats plus lazy chargement aider LCP.
The un chose it ne fait pas do is écrire texte alternatif. That’s on vous, every temps —
manquant texte alternatif on GatsbyImage is un of the la plupart courant Gatsby SEO oversights.
(Migrating from the old gatsby-image package? There’s a codemod:
npx gatsby-codemods gatsby-plugin-image.)
Données structurées (JSON-LD)
Google’s preferred structured-data format is JSON-LD, and the clean façon to ajouter it in modern Gatsby is via the Head API with a script tag:
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 offers pre-built JSON-LD components si you’d plutôt pas
hand-roll les. Un frequent confusion to clair up: gatsby-plugin-manifest is
pas a structured-data plugin — it generates the PWA web app manifest (icons,
theme color), nothing to do with schema.
The React bundle and Core Web Vitals
Here’s Gatsby’s réel weakness relative to the zero-JS generators.
- Complet hydration (the Gatsby 1–4 par défaut) hydrates the entier React tree and ships a 200KB+ React runtime to every page. The HTML is pre-rendered, so ce doesn’t hurt crawlability — but it absolutely affecte charger speed and CWV.
- Partial hydration (Gatsby 5, experimental) hydrates seulement components marked
"use client"and leaves the rest as static HTML, cutting the JS shipped and directement improving TTI and CWV. The limitations are réel: production builds seulement, encore beta, and incompatible with emotion, styled-components, andgatsby-plugin-offline.
The takeaway: Gatsby’s JS payload is a performances problem, pas an indexability un. Googlebot encore renders JS to assess page-experience signals, so the bundle peut cost vous on CWV même though votre content indexes fine.
Gatsby vs Astro pour le SEO
Si you’re choosing a static framework today, ce is the comparison que matters la plupart pour le SEO.
| Dimension | Gatsby | Astro |
|---|---|---|
| JS shipped to navigateur | 200KB+ (complet React runtime) | ~5KB (interactive islands seulement) |
| Rendering model | SSG → SPA (complet hydration) | SSG → MPA (zero hydration by par défaut) |
| Construire speed (40 pages) | 2–3 minutes | Sous 10 seconds |
| SEO plugin ecosystem | Mature (gatsby-plugin-*) | Growing |
| Crawl-budget impact | Plus élevé (plus JS pour Google to render) | Lower |
| Framework future | Uncertain (Netlify ownership, slowed activity) | Active, growing |
Les deux pre-render indexable HTML — that’s a wash. The difference is the JS tax: Astro’s islands ship a fraction of the JavaScript, qui a Vaihe comparison frames as “Reduced JavaScript execution conserves budget d’exploration and accelerates page scanning.” (Un historical caveat on the autre side: Astro’s image handling lacked automatic width/height at the temps of que comparison, qui produced Lighthouse warnings — vérifier current Astro docs, as it may be resolved.)
Pour context on how the whole field compares, voir the static site generators hub.
The honest partie: Gatsby’s maintenance trajectory
I won’t sugarcoat ce, and I won’t catastrophize it soit.
Netlify acquired Gatsby Inc. in February 2023. Gatsby Cloud was sunset and customers were déplacé to Netlify; Netlify stated the acquisition voudrait “pas impact Gatsby JS.” Since alors, activity has slowed markedly. A widely-read community GitHub discussion (#39062) argues Gatsby is effectively abandoned — minimal commits, aucun React 19 prise en charge, a 2024 roadmap que wasn’t delivered, and the telemetry service shut bas. Maintainers have framed the current state as security fixes, limited dependency updates, and low-hanging-fruit bug fixes.
Ce que que signifie pour le SEO teams. Pour an existing Gatsby site, none of ce is
an emergency — it builds, it indexes, it fonctionne. The risk is ecosystem decay over
temps: SEO dépend on plugins (gatsby-plugin-sitemap, image, canonical-urls), and
aging plugins (e.g. gatsby-source-shopify facing API deprecation) peut eventually
break in façons que quietly degrade indexation. Pour a nouveau project, weigh que
seriously — the frameworks personnes are migrating to are Astro and Suivant.js.
Production checklist: vérifier every rendering chemin
A local gatsby develop session or même a clean gatsby build log doesn’t prove
ce que a robot d’exploration en réalité receives. Parce que SSG, DSG, SSR, and client-only routes
chaque generate HTML differently, vérifier production behavior per chemin plutôt que
assuming un representative page covers tout of les:
- Raw HTML content. Pour chaque rendering chemin in utiliser, récupérer a réel production
URL with
curl -s <url>orview-source:— pas DevTools — and confirmer the content, title, and meta tags a robot d’exploration voudrait voir are en réalité là. - Metadata (Head export output). Confirmer the
Headexport’s tags land in que raw HTML pour the chemin in question. Ce is où DSG/SSR differ la plupart from SSG: the tags exist in votre source soit façon, but seulement a production récupérer proves ils made it into la réponse. - HTTP status. Vérifier la réponse code d’état on production, surtout pour SSR and DSG routes — une page que renders fine locally peut 500 in production on premier requête or sous charger in façons a construire jamais surfaces.
- Mise en cache behavior. SSG output is a static fichier with predictable mise en cache. DSG caches après the premier requête — confirmer the second requête is fast and correct, pas simplement the premier. SSR réponses depend on votre mise en cache headers and hosting couche; vérifier stale or per-request content isn’t served to the incorrect visitor.
- Échec and empty-state behavior. Pour SSR and DSG pages backed by request-time or first-request données, vérifier ce que a robot d’exploration sees si que données récupérer fails or renvoie vide — an unhandled error state n’est pas the même page vous testé locally with bon données.
- Sitemap generation and exclusions. Re-confirm ce seulement se produit on a
production construire (
gatsby build && gatsby serve, jamaisgatsby develop), and que the exclusions vous expect — drafts, client-only routes, anything vous decided shouldn’t be listed — are en réalité absent from the generatedsitemap-index.xml, pas simplement absent from votre intent.
None of ce is optional per rendering chemin — a working gatsby build proves SSG
output, pas DSG, SSR, or client-only behavior.
Courant Gatsby SEO mistakes
- Encore en utilisant
gatsby-plugin-react-helmet— legacy; migrate to the Head API. - Meta tags in DevTools but pas in page source — the SEO component is rendering
client-side; vérifier
view-source:, pas DevTools. - Draft content in sitemaps — filter drafts in
gatsby-node.jswith GraphQL, pas in a React component. - Orphan pages from
src/pages— Gatsby auto-routes everything là; stale fichiers construire and land in le sitemap. - Double balise canonicals —
gatsby-plugin-canonical-urls+ react-helmet les deux firing. - Trailing-slash inconsistency —
<Link>client-routing bypasses server-side trailing-slash redirections. - Pas stripping requête strings from canonicals — définir
stripQueryString: true. - Texte alternatif omitted on
GatsbyImage— it isn’t auto-generated. - Submitting
/sitemap.xml— the réel fichier is/sitemap-index.xml. - Testing le sitemap in
gatsby develop— it seulement generates ongatsby build. - Noindex toggled by React state — Google may have déjà processed the raw
HTML; and quand it sees
noindexin raw HTML it may skip rendering entirely. Garder noindex decisions in static HTML or server headers.
Pour the JavaScript-rendering fundamentals behind tout of ce, voir the parent JavaScript SEO hub.
AI summary
A condensed prendre on the Avancé version:
- Gatsby has four rendering paths — SSG, DSG, SSR, and client-only routes.
SSG is the par défaut:
gatsby buildpre-renders lune page to static HTML, so robots d’exploration obtenir complet content on the premier récupérer — aucun rendering queue, and the strongest indexability baseline. DSG defers generation to the premier requête; SSR generates per requête; client-only routes render nothing route-specific jusqu’à JavaScript runs in le navigateur (même profile as a plain client-side React app). Vérifier production HTML per chemin — a successfulgatsby buildseulement proves SSG behavior. - The React-bundle cost is performances, pas crawlability, and s’applique regardless of rendering chemin. Gatsby hydrates a complet React runtime (~200KB+) on the client, qui hits Core Web Vitals. The zero-JS generators (Hugo, Jekyll, Eleventy) don’t have ce; Astro ships ~5KB via islands.
- Utiliser the Gatsby Head API (v4.19+), a named
Headexport from page/template fichiers, pour titles/meta/canonical/JSON-LD. It fonctionne à travers tout four rendering paths and replaces the legacygatsby-plugin-react-helmet. It fonctionne seulement in pages/templates and dedupes byid. - Production checklist per chemin: raw HTML content, Head-export metadata, HTTP status, mise en cache behavior, and échec/empty-state handling — vérifier tout five pour whichever rendering chemin a route en réalité uses, plus confirmer sitemap generation and exclusions seulement on a production construire.
- Sitemaps:
gatsby-plugin-sitemapgeneratessitemap-index.xml(submit que, pas/sitemap.xml) and seulement runs ongatsby build, pas in dev. Google ignores<priority>/<changefreq>— focus on<lastmod>. Filter drafts ingatsby-node.js. DSG, SSR, and client-only routes chaque besoin an explicit sitemap-inclusion decision — don’t assume they’re covered the même façon an SSG page is. - Canonicals: Head API +
location.pathname, orgatsby-plugin-canonical-urlswithstripQueryString: true— jamais les deux (double canonical bug). - Images:
gatsby-plugin-imageauto-handles sizes/WebP/lazy-load and empêche CLS, but ne fait pas écrire texte alternatif — that’s manual. - The “DevTools but not view-source” bug = SEO component rendering client-side
au lieu de via the
Headexport. - Maintenance risk: Netlify acquired Gatsby in 2023; activity has slowed (aucun React 19, undelivered roadmap). Fine pour existing sites; pour nouveau projects weigh Astro/Suivant.js.
Documentation officielle
Primary-source documentation from Gatsby and from Google.
Gatsby
- Rendering options — the overview of Gatsby’s four rendering paths: SSG, DSG, SSR, and client-only routes.
- En utilisant Deferred Static Generation — DSG’s first-request generation behavior.
- En utilisant Rendu côté serveur — SSR’s request-time output via Gatsby Functions.
- Client-only routes and utilisateur authentication — pourquoi client-only routes don’t expose route-specific content in the initial HTML.
- Ajout an SEO component — the recommended SEO-component pattern.
- Gatsby Head API référence — the modern, built-in façon to manage head tags.
- Introducing the Gatsby Head API — pourquoi it replaced react-helmet.
- gatsby-plugin-sitemap — sitemap generation (production builds seulement).
- gatsby-plugin-image —
StaticImage/GatsbyImage, formats, CLS prevention. - gatsby-plugin-robots-txt — environment-aware robots.txt.
- gatsby-plugin-canonical-urls — site-wide balise canonicals and
stripQueryString. - gatsby-plugin-react-helmet — the legacy metadata approach.
- gatsby-plugin-next-seo — pre-built JSON-LD/schema components.
- React hydration in Gatsby — how the static HTML becomes interactive.
- Comprendre the JavaScript SEO basics — the explorer → render → index phases, and pourquoi pre-rendering helps.
Quotes from the source
On-the-record statements que appliquer directement to Gatsby’s architecture. Gatsby is a JavaScript SSG, so the relevant principal sources are Google’s JavaScript-rendering guidance and Google reps on the même.
Recherche Google Central — JavaScript SEO basics
- “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.” — the cas pour exactly ce que Gatsby fait at construire temps.
- “The page may stay on this queue for a few seconds, but it can take longer than that.” — on the rendering queue que pre-rendered HTML lets vous skip.
Martin Splitt, Google (Developer Advocate)
- “Even though Googlebot can render JavaScript, we don’t want to rely on that.” — the principle behind preferring SSG/SSR. (Via SEJ / Botify coverage.)
- “A lot of people are still looking at view source. That is not what we use for indexing. We use the rendered HTML.” — the exact raison the “DevTools vs view-source” Gatsby bug confuses personnes. (Via SEJ.)
- “The median time in the render queue is only five seconds.” — remarque ce is the median; tail latency peut be far plus long. (BrightonSEO, via SEJ.)
John Mueller, Google (Search Advocate)
- “Server-side rendering is not a requirement there. We can render JavaScript-based pages for the most part.” — context: SSR/SSG is meilleur pratique, pas strictly requis; Google va eventually render CSR content. (Via SEJ.)
Gatsby SEO checklist
A réussir to confirmer a Gatsby construire is en réalité search-friendly:
- Principal content apparaît in View Source (raw HTML), pas simplement in DevTools — confirms it’s pre-rendered, pas client-side seulement.
- Metadata is définir via the Gatsby Head API (
Headexport from pages/ templates), pas legacy react-helmet on nouveau fonctionner. - Every page has a unique, build-time
<title>and meta description, with asiteMetadatafallback. - Balise canonicals are définir un façon seulement — Head API or
gatsby-plugin-canonical-urls, jamais les deux (avoids the double-canonical bug). -
stripQueryString: trueis définir so query-string variants don’t fragment canonicals. -
gatsby-plugin-sitemapis installed; vous verified the output withgatsby build && gatsby serve(it doesn’t run in dev). - Vous submitted
/sitemap-index.xml(pas/sitemap.xml) in Search Console. - Draft content is filtered out in
gatsby-node.js(GraphQL), so it jamais enters le sitemap. - Aucun stale/orphan fichiers in
src/pagesque auto-build into routes. -
robots.txtblocks Netlify preview/branch deploys but leaves production ouvrir. - Every
GatsbyImage/StaticImagehas explicit texte alternatif. - JS/CSS assets aren’t blocked in
robots.txt. - Trailing-slash formulaire is decided and enforced at the host/CDN (pas simplement via
<Link>). -
noindexdecisions live in static HTML or server headers, pas React state. - Core Web Vitals vérifié — the React bundle is the probable drag; considérer partial hydration où viable.
- Pour every rendering chemin in utiliser (SSG, DSG, SSR, client-only), vous vérifié
production raw HTML, metadata, HTTP status, mise en cache behavior, and
échec/empty-state handling — pas simplement a local
gatsby buildlog. - DSG, SSR, and client-only routes chaque have an explicit, verified sitemap decision — none of les are covered by the même assumption as an SSG page.
The mental models
1. Crawlability vs performances are two separate scorecards. Gatsby aces crawlability (HTML is pre-rendered) but pays on performances (the React bundle). Don’t conflate les — “Gatsby is bad for SEO because React” mixes up the two. Votre content indexes fine; votre Core Web Vitals are où the JS tax montre up.
2. The précédent the HTML exists, the moins peut go incorrect. SSG decides HTML at construire temps — the safest point. Gatsby’s par défaut page is an SSG, so it’s on the safe fin of the rendering spectrum (client-only → SSR → DSG → SSG, roughly riskiest to safest pour indexability). But Gatsby is a multi-mode framework — a donné page pourrait be DSG, SSR, or client-only à la place, chaque earning its propre placer on que spectrum. Know qui mode chaque route en réalité uses avant assuming it’s on the safe fin.
3. Head API by par défaut; react-helmet seulement by inheritance.
Pour anything nouveau, the decision is made: Gatsby Head API. react-helmet is a chose vous
migrate off of, pas something vous reach pour. Si a tag isn’t showing in raw HTML,
the premier question is “is this in a Head export, or stuck in a component?”
4. Pick exactly un canonical mechanism.
Head API canonical or gatsby-plugin-canonical-urls — jamais les deux. Two mechanisms =
two balise canonicals = the double-canonical bug. Même discipline pour anything que
writes to <head>: un source of truth per tag.
5. Gatsby builds everything it trouve — so filtering is votre job.
Drafts, stale src/pages fichiers, query-string variants: Gatsby doesn’t editorialize.
Si vous don’t exclude it (in gatsby-node.js, in canonical config, in sitemap
options), it ships and obtient crawled.
6. Nouveau project vs existing site changements the maintenance calculus. Existing Gatsby site: garder it, it fonctionne. Nouveau project: the slowed maintenance and ecosystem-decay risk are réel inputs — weigh Astro/Suivant.js avant committing.
Gatsby SEO — cheat sheet
Metadata: qui approach
| Approach | Status | Utiliser it quand |
|---|---|---|
Gatsby Head API (Head export) | Current (v4.19+) | Tout nouveau fonctionner; pages/templates seulement |
gatsby-plugin-react-helmet | Legacy | Existing sites pending migration |
Plugins En un coup d’œil
| Plugin | Fait | SEO gotcha |
|---|---|---|
gatsby-plugin-sitemap | Generates sitemap-index.xml | Production construire seulement; submit the index URL |
gatsby-plugin-image | Sizes, WebP/AVIF, lazy-load, CLS-safe | Aucun auto texte alternatif |
gatsby-plugin-canonical-urls | Site-wide balise canonicals | Don’t pair with react-helmet canonicals |
gatsby-plugin-robots-txt | Build-time robots.txt | Utiliser env rules to block preview deploys |
gatsby-plugin-next-seo | Pre-built JSON-LD components | — |
gatsby-plugin-manifest | PWA manifest (icons/theme) | Pas données structurées |
Fast facts
- Sitemap fichier is
/sitemap-index.xml, pas/sitemap.xml. - Sitemap doesn’t generate in
gatsby develop— utilisergatsby build && gatsby serve. - Google ignores
<priority>/<changefreq>— accurate<lastmod>seulement. - React bundle ≈ 200KB+ par page (complet hydration); a CWV cost, pas a explorer un.
- Astro ships ~5KB by comparison (islands seulement).
gatsby develop≠ production: sitemap, robots, and some optimizations differ.- Netlify acquired Gatsby Feb 2023; maintenance has slowed (aucun React 19 yet).
Two-line SEO Head export
export const Head = ({ data, location }) => (
<>
<title>{data.post.title}</title>
<link rel="canonical" href={`https://example.com${location.pathname}`} />
</>
) Vérifier Gatsby’s production artifacts
Run ce après gatsby build, pas contre gatsby develop:
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
doneCe catches manquant or duplicate output from overlapping Head API/plugin mechanisms. Examiner the valeurs and sitemap membership separately.
Outils pour Gatsby SEO
- Gatsby Head API (built-in, v4.19+) — the no-dependency façon to manage
<title>, meta, canonical, and JSON-LD par page/template. gatsby-plugin-sitemap— generatessitemap-index.xmlon production builds.gatsby-plugin-image—StaticImage/GatsbyImage, responsive sizes, WebP/AVIF, lazy chargement, CLS-preventing placeholders.gatsby-plugin-canonical-urls— site-wide balise canonicals withstripQueryString.gatsby-plugin-robots-txt— environment-aware robots.txt (block preview deploys).gatsby-plugin-next-seo— pre-built JSON-LD/schema components si vous don’t vouloir to hand-roll données structurées.view-source:/ GSC Inspection d’URL — the ground truth pour “is my content and metadata in the raw HTML?” (pas DevTools, qui montre the hydrated DOM).- Lighthouse / PageSpeed Insights — to voir the Core Web Vitals cost of the React bundle and si partial hydration is worth pursuing.
gatsby build && gatsby serve— the seulement façon to tester sitemap, robots.txt, and production-only optimizations locally.
Ce que pas to do on a Gatsby site
Concrete mistakes personnes en réalité faire building and shipping Gatsby sites — prevention, pas diagnosis.
Keeping gatsby-plugin-react-helmet on nouveau fonctionner
The mistake: reaching pour react-helmet by habit on nouveau pages or a nouveau project, parce que that’s ce que older Gatsby tutorials encore montrer.
Pourquoi it’s incorrect: react-helmet has connu problèmes with React Hooks and concurrent rendering, plus a background-tab title bug vous have to patch with defer={false}. It’s aussi a third-party bundle and Provider wrapper vous don’t besoin anymore.
Que faire à la place: utiliser the built-in Gatsby Head API (v4.19+) — a named Head export from lune page or template fichier. Reserve react-helmet pour existing code vous haven’t migrated yet.
Running two canonical mechanisms at une fois
The mistake: setting a canonical via gatsby-plugin-canonical-urls and a react-helmet (or Head API) balise canonical on the même page.
Pourquoi it’s incorrect: les deux fire, and lune page ships two <link rel="canonical"> tags — a well-known Gatsby échec mode que muddies qui URL vous en réalité intended as canonical.
Que faire à la place: pick exactly un mechanism site-wide (the Head API, or the plugin with stripQueryString: true) and drop the autre entirely.
Filtering drafts in a React component au lieu de at construire temps
The mistake: hiding unpublished content with a client-side vérifier (e.g. if (!post.published) return null) and assuming que garde it out of search.
Pourquoi it’s incorrect: Gatsby builds everything it trouve into static HTML avant que component ever runs in le navigateur — the draft page is déjà construit and déjà listed in le sitemap by the temps votre React vérifier executes.
Que faire à la place: filter drafts in gatsby-node.js with a GraphQL requête (e.g. excluding entries sans a publish date) so ils jamais obtenir construit or listed in the premier placer.
Shipping GatsbyImage sans texte alternatif
The mistake: trusting gatsby-plugin-image to handle image SEO end-to-end parce que it auto-generates sizes, formats, and placeholders.
Pourquoi it’s incorrect: the plugin optimizes delivery — it ne fait pas écrire texte alternatif. Manquant texte alternatif on GatsbyImage/StaticImage is un of the la plupart courant Gatsby SEO oversights precisely parce que everything sinon à propos de the image semble handled.
Que faire à la place: treat texte alternatif as a requis field on every image component, every temps — it’s the un piece of image SEO Gatsby leaves entirely to vous.
Assuming gatsby develop montre vous production SEO output
The mistake: checking le sitemap, robots.txt, or noindex behavior in gatsby develop and concluding it’s broken parce que nothing montre up.
Pourquoi it’s incorrect: gatsby-plugin-sitemap and several autre build-time behaviors simply don’t run in development mode — you’re pas looking at a bug, you’re looking at dev mode doing ce que dev mode fait.
Que faire à la place: run gatsby build && gatsby serve avant drawing quelconque conclusion à propos de sitemap, robots.txt, or production-only optimizations.
Letting <Link> client-routing hide trailing-slash inconsistency
The mistake: assuming votre serveur-side trailing-slash redirection rules appliquer everywhere, notamment in-app navigation.
Pourquoi it’s incorrect: Gatsby’s <Link> component uses client-side History API routing, qui bypasses le serveur-side 301 redirections you’d normally rely on to normalize trailing slashes — so lien internes peut quietly serve the “wrong” formulaire sans ever hitting votre redirection rule.
Que faire à la place: decide on un trailing-slash formulaire, enforce it at the host/CDN level, and assurez-vous canonicals are consistent with it regardless of how a donné page was reached.
Courant Gatsby SEO problèmes
Symptom-first lookup pour problems you’re actively seeing on a Gatsby site — commencer from ce que vous observe.
Meta tags montrer up in DevTools but are manquant from view-source
Symptom: vous inspect lune page in Chrome DevTools and the title/meta description regarder correct, but view-source: (or a raw curl) montre les manquant or generic.
Probable causer: the SEO component is rendering client-side — it’s utilisé as a regular component plutôt que as (or à l’intérieur) lune page’s Head export, so it seulement apparaît in the DOM après hydration.
Fix: déplacer the tags into lune page or template’s named Head export. Confirmer with view-source: or curl -s <url> — pas DevTools, qui montre the hydrated DOM, pas ce que a crawler’s raw récupérer sees.
Le sitemap is manquant or vide
Symptom: vous visit /sitemap-index.xml (or vérifier Search Console) and obtenir nothing, or an incomplete liste.
Probable causer: almost toujours que vous testé in gatsby develop, où gatsby-plugin-sitemap doesn’t run at tout. Moins commonly, the plugin isn’t installed/configuré in gatsby-config.js.
Fix: run gatsby build && gatsby serve and vérifier à nouveau. Si it’s encore manquant, vérifier the plugin is présent in gatsby-config.js. Confirmer by requesting /sitemap-index.xml directement — remember it’s the index URL, pas /sitemap.xml.
Une page has two balise canonicals
Symptom: viewing source (or running a schema/tag audit) montre two <link rel="canonical"> elements on the même page.
Probable causer: gatsby-plugin-canonical-urls and a react-helmet (or Head API) canonical are les deux firing pour the même page.
Fix: supprimer un mechanism so seulement a unique source sets the canonical. Confirmer by viewing source à nouveau and checking with Patrick’s Balise canonical Checker que exactly un canonical resolves.
Draft or orphan pages apparaître in le sitemap
Symptom: le sitemap (or Search Console coverage) listes URLs vous jamais meant to publish — draft posts, or stale fichiers sous src/pages.
Probable causer: Gatsby auto-builds and auto-routes everything it trouve — an unpublished GraphQL entry que isn’t filtered, or a leftover fichier in src/pages, obtient construit into a réel static page and listed comme quelconque autre.
Fix: filter drafts in gatsby-node.js with a GraphQL requête (e.g. excluding entries sans a publish date) so they’re jamais construit. Pour orphan src/pages fichiers, delete the stale fichier — filtering in a component is aussi late, since lune page is déjà construit by alors.
Query-string variants of une page are getting indexé as duplicates
Symptom: Search Console montre near-duplicate URLs comme /blog and /blog?tag=foo les deux indexé, or flagged as contenu dupliqué.
Probable causer: gatsby-plugin-canonical-urls is running sans stripQueryString: true, so query-string variants are canonicalized to themselves au lieu de the clean URL.
Fix: définir stripQueryString: true in the plugin config, rebuild, and re-check the balise canonical on a query-string URL — it devrait now point to the clean chemin.
Une page vous intended to noindex is encore showing up in search
Symptom: vous définir une page to noindex, but it’s encore indexé weeks plus tard, or Search Console montre it as indexé despite the tag.
Probable causer: the noindex directive was toggled via React state plutôt que baked into static HTML or server headers — Google may have déjà processed the raw HTML (sans the noindex) and, quand it fait voir noindex seulement in a client-rendered réussir, peut skip rendering lune page à nouveau entirely.
Fix: déplacer the noindex decision into static HTML (via the Head export at construire temps) or an HTTP header, pas conditional React logic. Recheck with view-source: to confirmer the tag is présent in the raw réponse.
Testez vos connaissances: Gatsby SEO
Five rapide questions on optimizing a Gatsby site pour search. Pick an réponse pour chaque, alors vérifier.
Ressources utiles
My connexe writing
- JavaScript SEO: A Definitive Guide — rendering, DOM parity, and pourquoi static/prerendered output (comme Gatsby’s) is the low-risk fin of the spectrum.
- The Beginner’s Guide to SEO technique — où rendering architecture fits in the bigger picture.
My speaking
- How Search Fonctionne (SlideShare) — my walkthrough of exploration, rendering, indexation, and ranking. (My standing disclaimer s’applique: “This is my understanding of systems… not going to be 100% complete or accurate.”)
From autour the industry
- Gatsby Head API référence — the principal source pour the modern metadata approach.
- Introducing the Gatsby Head API — Gatsby’s propre explanation of pourquoi it replaced react-helmet.
- Recherche Google Central — JavaScript SEO basics — the explorer → render → index phases Gatsby’s construire lets vous skip pour content.
- Gatsby is joining Netlify — the 2023 acquisition announcement, pour context on maintenance.
- Netlify acquires frontend platform Gatsby (TechCrunch) — independent coverage of the acquisition.
- “Is GatsbyJS abandoned?” discussion #39062 — the community thread on Gatsby’s current maintenance state.
- SEO comparison of Gatsby vs Suivant vs Astro (Vaihe) — the JS-payload and crawl-budget comparison.
- Understanding partial hydration in Gatsby 5 (LogRocket) — the CWV-relevant hydration improvement and its limites.
Journal des modifications
Mis à jour le 18 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.