After installing a Gatsby SEO plugin, verify the pages your production site actually serves: their main content, page-specific metadata, canonical URLs, crawl and indexing rules, discovery paths and performance. A successful build is a useful starting point, but the public response needs its own check.
These ten Gatsby SEO checks connect each configuration choice to evidence you can inspect before and after a release. They apply to an existing Gatsby site; the Head example below targets Gatsby 5.5 or later. Work through a representative content page, a nested page and any distinct templates rather than checking only the homepage.
1. Fetch the document that search engines receive
Start with a fresh request to a real production page. Save its headers and HTML:
curl --fail --silent --show-error --dump-header page.headers --output page.html https://example.com/gatsby-seo-checklist/
Use curl.exe on Windows if curl resolves to a PowerShell alias. If the headers show a redirect, inspect its final destination before diagnosing rendering. Open the saved HTML and find the page’s actual heading, a distinctive sentence from its main content and its navigation links. Seeing only a loading message deserves investigation.
This avoids a common diagnostic mistake: inspecting a client-side navigation request for page-data.json and assuming that JSON is everything a fresh visitor or crawler receives. Fetch the page URL directly to inspect the document response.
Check the route’s rendering model too. Gatsby supports static generation, deferred static generation and server-side rendering. Client-only routes have different output behavior and should be treated deliberately. Important public landing pages need an appropriate content-rendering path; data fetched only after mounting can leave their initial HTML incomplete.
If the content is missing, trace the page query, template and data-loading code before adding more metadata. A Head export changes the document head; it does not populate the page body. Google can render JavaScript, but rendering is another part of processing a page. Our JavaScript crawlability guide explains those boundaries.
2. Put each page’s metadata in the correct Head export
Check the installed Gatsby version, for example with npm ls gatsby, before copying a metadata recipe. The Gatsby Head API was introduced in 4.19.0. Support for setting html and body attributes through Head arrived in 5.5.0.
For Gatsby 5.5 or later, this complete example can live at src/pages/gatsby-seo-checklist.jsx in a site deployed at the domain root:
import * as React from "react";
export default function GatsbySeoChecklistPage() {
return (
<main>
<h1>Gatsby SEO checklist</h1>
<p>Check the HTML, metadata and public URLs before publishing.</p>
</main>
);
}
export function Head() {
return (
<>
<html lang="en" />
<title>Gatsby SEO Checklist | Example Studio</title>
<meta
name="description"
content="Review the HTML, metadata and public URLs of a Gatsby site before publishing."
/>
<link
id="canonical"
rel="canonical"
href="https://example.com/gatsby-seo-checklist/"
/>
</>
);
}
Replace the illustrative brand, text and URL with the page’s real details. For CMS-driven templates, use that page’s queried content or pageContext rather than giving every route the same homepage title and description.
The named Head export belongs in a page or a page template used by createPage. A reusable metadata component can supply JSX, but exporting Head only from an ordinary component does not register it as a page export.
Inspect the built and public HTML for one intended title, description and canonical. Check for competing Helmet and Head output during migrations. Gatsby documents id-based deduplication within Head, but that is not a substitute for choosing a clear metadata owner. Each page should define what it needs because Head content is cleared when that page unmounts.
3. Align canonical URLs with real deployment paths
For the example page, the public URL, canonical and internal links should agree on https://example.com/gatsby-seo-checklist/. Check the final hostname, HTTPS, path prefix and trailing slash.
Your existing gatsby-config.js might include these settings for a domain-root site:
module.exports = {
siteMetadata: {
siteUrl: "https://example.com"
},
trailingSlash: "always"
};
Merge the relevant fields into your current configuration, preserving other metadata and plugins. This fragment records the production origin and slash policy; it does not automatically add a canonical to every page.
Gatsby’s configuration reference defines always, never and ignore. The hosting layer must serve or redirect those variants consistently. A configuration value alone does not prove the deployed redirect works.
For a deployment beneath /blog/, account for Gatsby’s pathPrefix and the actual host mount. Check for a missing prefix or an accidental /blog/blog/ in manually assembled canonicals. The root-deployment example above is not a universal subdirectory recipe.
Open a nested page and a URL with tracking parameters. Confirm that the canonical identifies its intended preferred page rather than blindly copying the request URL or pointing everything to the homepage. A canonical expresses a preference; it does not redirect visitors or protect private content. See our canonical-tag guide for duplicate-URL diagnosis.
4. Separate crawl access from indexing rules
Inspect both the page’s HTML and its response headers. A leftover preview rule can affect a production page even when its content and canonical look correct.
For a public page that should stay out of search, an indexing directive can be supplied in HTML:
<meta name="robots" content="noindex">
Or through the HTTP response:
X-Robots-Tag: noindex
These are examples for deliberately excluded pages, not settings to paste across your production site. For pages you want indexed, investigate any unintended noindex from the page template, build environment or host.
Check robots.txt separately. Google needs access to crawl a page to see its noindex rule. Blocking the URL in robots.txt can prevent that rule from being discovered; a robots disallow is not a reliable instruction to remove a URL from search. Google’s noindex documentation explains the distinction.
Private account areas and confidential previews need access controls. A canonical, sitemap exclusion or robots directive does not provide privacy. Preview deployment protection should be intentional, while the production release should expose the pages and resources you actually want crawled.
Keep an expected indexing policy for each page type. A thank-you page, a public article and an authenticated dashboard need different decisions; plugin defaults cannot infer all of them.
5. Verify deep links, redirects and missing-page status
Request a nested page directly, without first navigating through the homepage. Then request a path that definitely does not exist:
curl --silent --show-error --dump-header nested.headers --output nested.html https://example.com/guides/deployment/
curl --silent --show-error --dump-header missing.headers --output missing.html https://example.com/this-page-does-not-exist-7f3b/
The real page should deliver its intended content and a suitable successful response. The invented URL should return a genuine missing-page response, normally 404, rather than your homepage or a thin error screen with status 200. For removed content, choose an appropriate 404 or 410 response unless a relevant replacement warrants a redirect.
Creating src/pages/404.js controls the error-page content. Verify how your host serves it; the component does not establish every deployment platform’s HTTP behavior.
Test any expected permanent redirect as well. Check its destination and status, then inspect the final page. Redirecting every retired URL to the homepage can hide broken paths while sending visitors somewhere unrelated.
Gatsby’s client-only routing guide explains why those routes need host handling for direct visits. A valid authenticated app shell can be appropriate there. Keep its routing rules scoped so they do not turn every unknown public URL into a successful app-shell response.
If navigation works but a direct request fails, investigate the host’s route mapping before changing page metadata.
6. Reconcile internal links and sitemap discovery
Compare your intended public-page inventory with the pages visitors can reach from navigation, category pages and contextual links. Check a recently published page and a page several levels into the content hierarchy.
For Gatsby-managed internal pages, a link can look like this:
import { Link } from "gatsby";
<Link to="/guides/deployment/">Deployment guide</Link>
Gatsby’s Link component handles internal navigation and configured path prefixes. Use a normal <a href="..."> for external destinations, downloads or pages outside the Gatsby application. Inspect the resulting HTML for real destinations and descriptive link text; a click handler alone is not a dependable crawlable link.
Then fetch your actual sitemap entry point. The current official sitemap plugin documentation describes production-build output at sitemap-index.xml, with child files such as sitemap-0.xml. Custom settings can change the location. Do not mark a sitemap missing merely because /sitemap.xml returns 404.
Follow the index’s child URLs and compare the listed pages with your intended inventory. A successful XML response can still omit a newly created page or contain a preview hostname. Check any sitemap reference in the domain’s robots.txt against the real deployed address.
Omitting a URL from a sitemap does not prevent its crawling or indexing. Keep discovery, canonical selection and indexing directives consistent; our XML sitemap guide covers that broader review.
7. Check image sources, layout and loading behavior
Inspect the images actually delivered by a representative template. Check their displayed size, downloaded size, alternative text and the space reserved before they load.
Gatsby provides two different image components: StaticImage for a source known when the component is built, and GatsbyImage for image data passed into the component, commonly from a CMS query. A dynamic CMS URL cannot simply be passed as an arbitrary prop into StaticImage; its source must be statically analyzable.
If the Gatsby image plugins are already configured and the referenced asset exists, an above-the-fold static hero might use:
import { StaticImage } from "gatsby-plugin-image";
<StaticImage
src="../images/deployment-guide.jpg"
alt="Deployment checklist beside a laptop"
layout="constrained"
width={1200}
loading="eager"
/>
Use alternative text that describes your real image. The example assumes a suitable local photograph; it is not a request to add that image to every page.
The image component reference recommends eager loading for above-the-fold images. Keep below-the-fold loading appropriate to their position instead of making every image eager. Check the generated responsive sources and layout rather than assuming the plugin configuration guarantees a good result.
For CMS-hosted images, verify the source plugin’s supported transformations. Existing plain images can also be valid when their dimensions, responsive delivery, loading and alternative text meet the page’s needs.
8. Measure the pages users actually experience
A fast starter page does not establish the performance of a content-heavy article, product page or search interface. Review representative templates on mobile, including their real images, consent interface, fonts and third-party scripts.
Use the current Core Web Vitals definitions: Largest Contentful Paint (LCP), Interaction to Next Paint (INP) and Cumulative Layout Shift (CLS). Field assessment uses the 75th percentile of page loads. A local or lab run is diagnostic evidence, while field data describes observed users over its reporting period.
| Signal | What to investigate on a Gatsby page | Evidence to keep |
|---|---|---|
| Slow LCP | Hero-image discovery, font rendering and server response | The identified LCP element and its loading sequence |
| Poor INP | Expensive event handlers, hydration work and third-party scripts | The affected interaction and main-thread work |
| Layout shifts | Missing image space, late banners and changing content | The element that moves and what caused the shift |
Change the identified cause, then repeat the relevant measurement under comparable conditions. Removing unused scripts is useful when those scripts contribute to the problem; changing image settings will not solve every interaction delay.
If page-level field data is unavailable, record that limitation. A broad origin-level result or one lab score does not prove that a particular Gatsby template passes. Avoid treating a perfect audit score as a publication requirement or a promise of higher rankings.
9. Match structured data to the visible page
If your Gatsby template emits JSON-LD, inspect the application/ld+json script in the saved public HTML. Parse the JSON, then check its meaning against the page.
For an article, verify the real headline, author, publication date and relevant image. For a product, verify the actual product and offer information. Do not copy article markup onto every route or insert ratings, reviews or credentials the page cannot substantiate.
Gatsby Head accepts data-block scripts, so the mechanism can live alongside page metadata. The schema type and required properties still depend on the content and the search feature you are targeting. Reusing a component does not make its default values true for every page.
Use the relevant Google feature documentation and Rich Results Test when the page targets a supported rich result. A syntax pass establishes that the JSON can be read; it does not verify the truth of its fields or every eligibility requirement.
Google’s structured-data policies require representative, accurate content and do not guarantee rich-result appearance. Fix contradictory dates, unsupported claims and duplicate entities at their source rather than adding more markup to compensate.
10. Recheck the exact release after content changes
Make a known content change and follow it through your publishing pipeline. Record the page URL, the intended update and the release that should contain it. Then fetch the public document again and look for the changed sentence and metadata.
For statically generated pages, publishing a CMS record does not by itself prove that a new HTML build reached the host. Confirm the build trigger and release output. For SSR, DSG or cached responses, verify the relevant generation and invalidation behavior instead of assuming every route refreshes in the same way.
Gatsby also caches resources during client navigation. Compare a fresh document request with an already open session when diagnosing stale content; a single open tab is not complete release evidence. Check any offline/service-worker setup if it is part of your actual site.
Use a small release worksheet to keep evidence attached to each check. Save the following as gatsby-seo-release.csv and replace the illustrative URLs with your own. “Not checked” is a starting value, not an observed result:
check,url,evidence_to_capture,result,next_action
1,https://example.com/gatsby-seo-checklist/,Fresh document HTML and main-content sentence,Not checked,
2,https://example.com/gatsby-seo-checklist/,Public title description and page Head ownership,Not checked,
3,https://example.com/gatsby-seo-checklist/,Final URL canonical and slash policy,Not checked,
4,https://example.com/gatsby-seo-checklist/,Robots access plus HTML and header indexing rules,Not checked,
5,https://example.com/guides/deployment/,Deep-link response plus missing-page and redirect checks,Not checked,
6,https://example.com/gatsby-seo-checklist/,Incoming internal link and actual sitemap child entry,Not checked,
7,https://example.com/gatsby-seo-checklist/,Image source dimensions alt and loading,Not checked,
8,https://example.com/gatsby-seo-checklist/,Template performance evidence with field or lab scope,Not checked,
9,https://example.com/gatsby-seo-checklist/,Relevant structured data and visible-content agreement,Not checked,
10,https://example.com/gatsby-seo-checklist/,Published content marker and release identity,Not checked,
Add separate rows for templates or locales that behave differently. For each failure, record the responsible content source, template or hosting rule and the smallest correction needed.
Repeat the affected checks after the fix. Treat the release as verified when the intended public content and signals agree, while keeping performance or indexing outcomes separate from the fact that a build completed.