Guide Gatsby SEO

Comment optimize a Gatsby site pour recherche — Gatsby's four rendu paths (SSG, DSG, SSR, client-seulement) et ce que chaque signifie pour crawlability, le modern Head API vs legacy react-helmet, sitemaps, canonicals, image SEO, le React-bundle CWV coût, et le Netlify-era maintenance risque.

Première publication : 26 juin 2026 · Dernière mise à jour : 3 août 2026 · Avancé
1 indice probant sur cette page

Gatsby a four rendu options: SSG (le par défaut — pages pre-rendu à static HTML à gatsby construire), DSG (deferred static generation on premier requête), SSR (rendu côté serveur per requête via Gatsby Functions), et client-seulement routes (rendu entirely dans le navigateur). La plupart Gatsby sites lean on SSG, qui donne robots d’exploration entièrement rendu HTML on le premier récupérer avec aucun rendu queue à wait on — a strong SEO baseline, far meilleur que a pure client-side React app. Mais que baseline n’est pas universal: DSG et SSR pages generate HTML à l’extérieur le construire étape et besoin leur propre production vérifications, et client-seulement routes ne devrait pas être assumed à expose route-spécifique contenu dans le initial HTML à tout. Whichever chemin sert une page, Gatsby encore ships le complet React runtime (~200KB+) et hydrates il client-side — a Core Web Vitals coût, pas a crawlability un. Le actuel façon à manage metadata est le built-dans Gatsby Head API (v4.19+), qui fonctionne à travers tout four rendu paths et remplace gatsby-plugin-react-helmet. Le recurring pitfalls sont double balise canonicals, draft/orphan pages leaking dans sitemaps, manquant texte alternatif, le production-seulement sitemap gotcha, DSG/SSR/client-seulement routes needing explicit sitemap et production-behavior vérifications, et a framework whose maintenance a slowed sharply since Netlify's 2023 acquisition.

TL;DR — Gatsby a four rendu options — SSG (le par défaut), DSG, SSR, et client-seulement routes — et ils ne pas tout put contenu dans le raw HTML le même façon. SSG pre-renders à static HTML à construire temps (gatsby build), donc contenu est dans le raw HTML avant le premier robot d’exploration requête — aucun Web Rendu Service, aucun rendu queue. DSG defers generation à le premier requête; SSR generates per requête on a serveur; client-seulement routes rendre rien route-spécifique jusqu’à le navigateur exécute le JavaScript. Whichever chemin sert une page, Gatsby hydrates a complet React bundle (~200KB+) on le client, qui est a Core Web Vitals coût, pas a crawlability un. Le actuel metadata approche est le built-dans Gatsby Head API (v4.19+), qui fonctionne à travers tout four rendu paths et remplace gatsby-plugin-react-helmet. Le recurring échec modes sont double canonical balises (Head API + react-helmet les deux firing), draft/orphan pages leaking dans sitemaps, le production-seulement sitemap gotcha, manquant texte alternatif on GatsbyImage, trailing-slash inconsistency, et DSG/SSR/client-seulement routes que jamais obtenu a production vérifier. Et le elephant dans le room: since Netlify’s 2023 acquisition, Gatsby’s maintenance a slowed sharply.

Gatsby’s four rendu options — et pourquoi ils matter pour le SEO

Google processes JavaScript pages dans three phases — exploration, alors rendu, alors indexation — et rendu se produit dans a séparé réussir depuis a queue en utilisant headless Chromium. Google’s propre guidance est blunt à propos de pourquoi vous devezn’t lean on que: “Serveur-side or pre-rendu est encore a great idea parce que il rend votre site web faster pour utilisateurs et robots d’exploration, et pas tout bots peut exécuter JavaScript.”

A Gatsby site isn’t universally build-time static HTML — Gatsby supports four distinct rendering paths, choisi par page or template Preuve à l’appui de cette affirmation gatsby build writes production output, including generated HTML, to the public directory. Portée : Gatsby production builds. Niveau de confiance : élevé · Vérifié : Gatsby CLI: build :

  • SSG (Static Site Generation) — le par défaut. gatsby build emits entièrement rendu static HTML dans /public pour lune page. Googlebot’s premier-wave raw-HTML récupérer déjà contient le complet contenu — texte, liens, metadata. Ce est le sûr, faible-risque chemin, et c’est ce que la plupart Gatsby pages utiliser.
  • DSG (Deferred Static Generation). Generation est deferred jusqu’à lune page’s premier requête plutôt que happening pour chaque page à construire temps — utile pour sites avec huge numbers de faible-traffic pages où a complet construire voudrait être lent. Le construire alone ne fait pas tell vous ce que a robot d’exploration voit; lune page’s HTML ne fait pas exist jusqu’à quelque chose requêtes il, donc premier-requête et mis en cache behavior besoin leur propre vérifier, pas simplement a construire log.
  • SSR (Rendu côté serveur). Lune page est rendu per requête, en utilisant requête-time données, via Gatsby Functions. Parce que il exécute à requête temps, SSR pages besoin production vérifications a construire-time page ne fait pas: réponse status, mise en cache headers, timeout behavior, et ce que a robot d’exploration voit on an vide or erreur réponse — none de que est visible depuis a successful local construire.
  • Client-seulement routes. Ces rendre entirely dans le navigateur et ne pas obtenir route-spécifique contenu dans le initial HTML — le même profile as a plain client-side React app. ne pas assume Google (or quelconque robot d’exploration) voit n’importe quoi page-spécifique ici jusqu’à JavaScript exécute; treat ces as JS-dependent par design, qui est fine pour gated/authenticated contenu mais incorrect pour n’importe quoi vous vouloir indexé avec contenu.

React hydration (ReactDOMClient.hydrateRoot()) se produit client-side on top de whichever de ces produced le HTML, purely à ajouter interactivity — que partie est le même regardless de rendu chemin, et est a séparé concern depuis qui chemin generated lune page (plus on hydration coût ci-dessous).

«Contrast SSG/DSG/SSR with a pure client-side React app, which serves an empty <div id="root"> and depends on the browser (or the renderer) to build the page. Most Gatsby pages ship meaningful HTML by default — that’s the indexability win, and it’s real, but it’s a per-page property, not a framework guarantee. Rendering options and image tooling don’t guarantee Core Web Vitals, indexing, or rankings on their own; verify the actual production output for whichever path a route uses. » (Traduction) (Résumé en français de la section vingt-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Le catch avec SSG/DSG/SSR alike est a performances un, pas a crawlability un: Gatsby ships le complet React runtime à chaque page et re-hydrates il. Plus on que, et le Astro comparaison, ci-dessous.

«## Gatsby Head API vs gatsby-plugin-react-helmet » (Traduction) (Résumé en français de la section vingt-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«This is the single most important “are you doing it the modern way?” question in Gatsby SEO. » (Traduction) (Résumé en français de la section vingt-huit, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Le legacy approche — gatsby-plugin-react-helmet. Pour années, le standard façon à définir <title>, meta description, et autre head balises était le react-helmet library plus ce plugin. Le plugin’s job était à donner react-helmet SSR prise en charge — sans il, votre titre/meta balises voudrait seulement apparaître après JS execution, pas dans le raw HTML, qui defeats le point. Il fonctionne, mais il a connu problèmes avec React Hooks et concurrent rendu, plus a background-tab titre bug vous patch avec defer={false}.

Le modern approche — le Gatsby Head API (v4.19+). Gatsby maintenant a a built-dans façon à ajouter head elements: a named Head export depuis quelconque page or template fichier. Preuve à l’appui de cette affirmation Gatsby pages and templates can export a named Head function to add head elements. Portée : Gatsby Head API. Niveau de confiance : élevé · Vérifié : Gatsby: Head API

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

Il receives utile props — location.pathname, params, data (depuis lune page’s GraphQL requête), et pageContext — et il deduplicates balises que share an id prop (dernier un wins), though running deux différent head-balise mechanisms à une fois (Head API plus a leftover react-helmet appel) peut encore conflict même avec deduplication. Il fonctionne seulement dans page fichiers et templates, pas dans arbitrary components. Le advantages over react-helmet: aucun tiers bundle, aucun Provider wrapper, deterministic balise order avec React 18 streaming. Utiliser le Head API pour tout nouveau projects, et plan a migration pour existing ones.

Le Head API fonctionne le même façon à travers tout four rendu paths — SSG, DSG, SSR, et client-seulement routes tout prise en charge a Head export. Ce que differs est quand son sortie lands dans HTML a robot d’exploration peut récupérer: on SSG c’est baked dans à construire temps; on DSG et SSR c’est generated à premier-requête or per-requête temps; on a client-seulement route il n’est pas dans le initial HTML à tout. ne pas assume “Je ajouté a Head export” est equivalent à “ce est dans le raw HTML pour chaque route” — vérifier le réel production sortie (view-source: or curl) pour whichever chemin chaque route utilise, pas simplement un representative page.

Le “meta tags in DevTools but not in source” bug. A classic Gatsby SEO symptom: votre titre/meta balises montrer up dans Chrome DevTools mais sont manquant depuis view-source:. Le causer est que DevTools montre le hydrated DOM (après JS exécute), pendant que view-source montre le raw HTML. Si votre balises seulement apparaître dans DevTools, votre SEO component est rendu client-side au lieu de étant baked dans Gatsby’s static sortie — généralement parce que c’est utilisé as a regular component plutôt que as (or à l’intérieur) lune page’s Head export. Toujours vérifier dans raw HTML, pas DevTools.

Wiring up an SEO component (the GraphQL données couche)

Gatsby’s données couche est GraphQL, et c’est comment vous feed metadata dans votre pages.

  • useStaticQuery pulls mondial defaults depuis siteMetadata (titre, description, siteUrl) défini dans gatsby-config.js.
  • Page-level GraphQL requêtes réussir a data prop straight à le Head export — aucun supplémentaire wiring nécessaire.
  • Le standard modèle est prop || siteMetadata fallback: utiliser le per-page valeur si il 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 (et son traps)

Install gatsby-plugin-sitemap and configurer it in gatsby-config.js. A few choses trip personnes up:

«- It generates sitemap-index.xml, not /sitemap.xml. Submit the index URL in Google Search Console — don’t submit /sitemap.xml and expect it to resolve. » (Traduction) (Résumé en français de la section quarante-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- It only runs in production builds. It does nothing in gatsby develop. To test it, run gatsby build && gatsby serve. People file “my sitemap is missing” reports that are really just “I never ran a production build.” » (Traduction) (Résumé en français de la section quarante-trois, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- createLinkInHead: true by default adds the sitemap reference to the HTML head automatically. » (Traduction) (Résumé en français de la section quarante-trois, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- It always excludes /dev-404-page, /404, and /offline-plugin-app-shell-fallback. » (Traduction) (Résumé en français de la section quarante-trois, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.) «- <priority> and <changefreq> are ignored by Google — the plugin docs say so directly. Focus on an accurate <lastmod> instead. » (Traduction) (Résumé en français de la section quarante-trois, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.) «- entryLimit defaults to 45,000 URLs per file. » (Traduction) (Résumé en français de la section quarante-trois, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)

Excluding drafts est votre job. Gatsby construit tout il trouve, donc draft contenu sails straight dans le sitemap unless vous filter il. Faire que dans gatsby-node.js avec a GraphQL filter (e.g. excluding entries sans a publish date), pas par hiding il dans a React component — par alors c’est déjà construit et listed.

DSG, SSR, et client-seulement routes besoin an explicit sitemap décision. gatsby-plugin-sitemap reflects ce que il peut voir à construire temps. An SSG page est straightforward — il exists as a static fichier, donc c’est naturally sitemap-eligible. A DSG page’s HTML ne fait pas exist yet à construire temps (il generates on premier requête), an SSR page jamais a fixed HTML à tout, et a client-seulement route a aucun route-spécifique contenu à indexer dans le premier placer. ne pas assume quelconque de ces sont dans le sitemap (or devrait être) simplement parce que le route exists — decide, page par page, si il belongs, et vérifier le generated sitemap-index.xml en réalité reflects que décision plutôt que a construire-time guess.

robots.txt: gatsby-plugin-robots-txt

gatsby-plugin-robots-txt generates robots.txt à construire temps. Le utile detail pour le SEO est environment awareness: il lit process.env.GATSBY_ACTIVE_ENV alors process.env.NODE_ENV, donc vous pouvez servir différent règles per environment. Le classic utiliser est blocking robots d’exploration on Netlify preview/branch deploys donc votre staging URLs ne pas obtenir accidentally indexé, pendant que leaving production ouvrir.

«## Canonical URLs (and the double-canonical bug) » (Traduction) (Résumé en français de la section quarante-huit, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Two viable approaches:

  1. gatsby-plugin-canonical-urls ajoute a <link rel="canonical"> à chaque page. Définir stripQueryString: true donc /blog?tag=foo et /blog ne pas obtenir treated as séparé canonicalized pages — recommended pour la plupart sites.
  2. Le Head API, paramètre canonicals yourself depuis location.pathname:
export const Head = ({ location }) => (
  <link rel="canonical" href={`https://example.com${location.pathname}`} />
)

Le double canonical bug. Ce est a connu, facile-à-hit problème: si vous utiliser gatsby-plugin-canonical-urls et a react-helmet balise canonical à le même temps, vous emit deux <link rel="canonical"> balises. Pick un mechanism. (Si vous êtes on react-helmet, gatsby-plugin-react-helmet-canonical-urls est le helmet-aware option; on le Head API, définir le canonical là et drop le plugin.)

Trailing slashes. Gatsby pages peut être reachable avec et sans a trailing slash, et Gatsby’s <Link> component utilise client-side History API routing — qui bypasses serveur-side 301 redirections vous’d normally utiliser à normalize trailing slashes. Decide on un formulaire, enforce il à le host/CDN level, et garder canonicals consistent avec il.

Image SEO: gatsby-plugin-image

gatsby-plugin-image is genuinely un of Gatsby’s strengths. Two components:

  • StaticImage — pour images whose chemin est connu et hardcoded à construire temps.
  • GatsbyImage — pour dynamic images coming depuis GraphQL.

Ce que il fait automatiquement: plusieurs sizes, WebP/AVIF formats, lazy chargement, et breakpoints (750/1080/1366/1920px). Il aussi generates placeholders (blurred, dominant color, or traced SVG) que reserve space et empêcher Cumulative Layout Shift — a Core Web Vitals metric. Parce que dimensions sont définir, vous éviter CLS, et modern formats plus lazy chargement aider LCP.

Le un chose il ne fait pas faire est écrire texte alternatif. c’est on vous, chaque temps — manquant texte alternatif on GatsbyImage est un de le la plupart courant Gatsby SEO oversights. (Migrating depuis le old gatsby-image package? il y a a codemod: npx gatsby-codemods gatsby-plugin-image.)

Données structurées (JSON-LD)

Google’s preferred structured-données format est JSON-LD, et le clean façon à ajouter il dans modern Gatsby est via le Head API avec a script balise:

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 vous’d plutôt pas hand-roll les. Un frequent confusion à clair up: gatsby-plugin-manifest est pas a structured-données plugin — il generates le PWA web app manifest (icons, theme color), rien à faire avec schema.

Le React bundle et Core Web Vitals

Here’s Gatsby’s réel weakness relative to the zero-JS generators.

  • Complet hydration (le Gatsby 1–4 par défaut) hydrates le entier React tree et ships a 200KB+ React runtime à chaque page. Le HTML est pre-rendu, donc ce ne fait pas hurt crawlability — mais il absolutely affecte charger speed et CWV.
  • Partiel hydration (Gatsby 5, experimental) hydrates seulement components marked "use client" et laisse le rest as static HTML, cutting le JS shipped et directement improving TTI et CWV. Le limitations sont réel: production construit seulement, encore beta, et incompatible avec emotion, styled-components, et gatsby-plugin-offline.

Le takeaway: Gatsby’s JS payload est a performances problème, pas an indexability un. Googlebot encore renders JS à assess page-experience signaux, donc le bundle peut coût vous on CWV même though votre contenu indexes fine.

Gatsby vs Astro pour le SEO

Si vous êtes choosing a static framework aujourd’hui, ce est le comparaison que matters la plupart pour le SEO.

DimensionGatsbyAstro
JS shipped to navigateur200KB+ (complet React runtime)~5KB (interactive islands seulement)
Rendering modelSSG → SPA (complet hydration)SSG → MPA (zero hydration by par défaut)
Construire speed (40 pages)2–3 minutesSous 10 seconds
SEO plugin ecosystemMature (gatsby-plugin-*)Growing
Crawl-budget impactPlus élevé (plus JS pour Google to render)Lower
Framework futureUncertain (Netlify ownership, slowed activity)Active, growing

«Both pre-render indexable HTML — that’s a wash. The difference is the JS tax: Astro’s islands ship a fraction of the JavaScript, which a Vaihe comparison frames as “Reduced JavaScript execution conserves crawl budget and accelerates page scanning.” (One historical caveat on the other side: Astro’s image handling lacked automatic width/height at the time of that comparison, which produced Lighthouse warnings — check current Astro docs, as it may be resolved.) » (Traduction) (Résumé en français de la section soixante-dix, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«For context on how the whole field compares, see the static site generators hub. » (Traduction) (Résumé en français de la section soixante-onze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«## The honest part: Gatsby’s maintenance trajectory » (Traduction) (Résumé en français de la section soixante-douze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«I won’t sugarcoat this, and I won’t catastrophize it either. » (Traduction) (Résumé en français de la section soixante-treize, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Netlify acquired Gatsby Inc. dans February 2023. Gatsby Cloud était sunset et clients étaient déplacé à Netlify; Netlify stated le acquisition voudrait “pas impact Gatsby JS.” Since alors, activity a slowed markedly. A widely-lire community GitHub discussion (#39062) argues Gatsby est effectively abandoned — minimal commits, aucun React 19 prise en charge, a 2024 roadmap que n’était pas delivered, et le telemetry service shut bas. Maintainers ont framed le actuel state as security corrections, limited dependency mises à jour, et faible-hanging-fruit bug corrections.

«What that means for SEO teams. For an existing Gatsby site, none of this is an emergency — it builds, it indexes, it works. The risk is ecosystem decay over time: SEO depends on plugins (gatsby-plugin-sitemap, image, canonical-urls), and aging plugins (e.g. gatsby-source-shopify facing API deprecation) can eventually break in ways that quietly degrade indexing. For a new project, weigh that seriously — the frameworks people are migrating to are Astro and Next.js. » (Traduction) (Résumé en français de la section soixante-quinze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Production checklist: vérifier every rendering chemin

A local gatsby develop session or même a clean gatsby build log ne fait pas prove ce que a robot d’exploration en réalité receives. Parce que SSG, DSG, SSR, et client-seulement routes chaque generate HTML differently, vérifier production behavior per chemin plutôt que assuming un representative page covers tout de les:

  • Raw HTML contenu. Pour chaque rendu chemin dans utiliser, récupérer a réel production URL avec curl -s <url> or view-source: — pas DevTools — et confirmer le contenu, titre, et meta balises a robot d’exploration voudrait voir sont en réalité là.
  • Metadata (Head export sortie). Confirmer le Head export’s balises land dans que raw HTML pour le chemin dans question. Ce est où DSG/SSR differ la plupart depuis SSG: le balises exist dans votre source soit façon, mais seulement a production récupérer proves ils fait il dans la réponse.
  • HTTP status. Vérifier la réponse code d’état on production, surtout pour SSR et DSG routes — une page que renders fine locally peut 500 dans production on premier requête or sous charger dans façons a construire jamais surfaces.
  • Mise en cache behavior. SSG sortie est a static fichier avec predictable mise en cache. DSG caches après le premier requête — confirmer le deuxième requête est rapide et correct, pas simplement le premier. SSR réponses depend on votre mise en cache headers et hosting couche; vérifier stale or per-requête contenu n’est pas servi à le incorrect visitor.
  • Échec et empty-state behavior. Pour SSR et DSG pages backed par requête-time or premier-requête données, vérifier ce que a robot d’exploration voit si que données récupérer fails or renvoie vide — an unhandled erreur state n’est pas le même page vous testé locally avec bon données.
  • Sitemap generation et exclusions. Re-confirm ce seulement se produit on a production construire (gatsby build && gatsby serve, jamais gatsby develop), et que le exclusions vous expect — drafts, client-seulement routes, n’importe quoi vous decided ne devrait pas être listed — sont en réalité absent depuis le generated sitemap-index.xml, pas simplement absent depuis 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

  1. Encore en utilisant gatsby-plugin-react-helmet — legacy; migrate à le Head API.
  2. Meta balises dans DevTools mais pas dans page source — le SEO component est rendu client-side; vérifier view-source:, pas DevTools.
  3. Draft contenu dans sitemaps — filter drafts dans gatsby-node.js avec GraphQL, pas dans a React component.
  4. Orphan pages depuis src/pages — Gatsby auto-routes tout là; stale fichiers construire et land dans le sitemap.
  5. Double balise canonicals — gatsby-plugin-canonical-urls + react-helmet les deux firing.
  6. Trailing-slash inconsistency — <Link> client-routing bypasses serveur-side trailing-slash redirections.
  7. Pas stripping requête strings depuis canonicals — définir stripQueryString: true.
  8. Texte alternatif omitted on GatsbyImage — il n’est pas auto-generated.
  9. Submitting /sitemap.xml — le réel fichier est /sitemap-index.xml.
  10. Testing le sitemap dans gatsby develop — il seulement generates on gatsby build.
  11. Noindex toggled par React state — Google peut ont déjà processed le raw HTML; et quand il voit noindex dans raw HTML il peut skip rendu entirely. Garder noindex decisions dans static HTML or serveur headers.

Pour le JavaScript-rendu fundamentals behind tout de ce, voir le parent JavaScript SEO hub.

Ajouter une note d’expert

Épingler une citation d’expert

Nouvelle personne ? Créez son profil non revendiqué à /admin/experts/ → Épingler une citation d’expert d’abord.