Gatsby SEO and Meta Tags — Search Engine Optimization with React Helmet
Learn how to optimize Gatsby sites for search engines using gatsby-plugin-react-helmet, meta tags, Open Graph, and structured data for better rankings.
In this lesson, you'll understand how to add SEO to Gatsby pages, create reusable SEO components, and implement structured data.
What You'll Learn
How to install and configure gatsby-plugin-react-helmet, create a reusable SEO component, add Open Graph tags, and implement JSON-LD structured data.
Why It Matters
SEO determines whether users find your site. Proper meta tags, structured data, and social sharing previews directly impact search rankings and click-through rates.
flowchart LR
A[SEO Component] --> B[Title Tag]
A --> C[Meta Description]
A --> D[Open Graph]
A --> E[Twitter Card]
A --> F[JSON-LD Schema]
B --> G[Search Results]
D --> H[Social Shares]
F --> I[Rich Snippets]
style A fill:#639,color:#fff
Installation
npm install gatsby-plugin-react-helmet react-helmet
// gatsby-config.js
module.exports = {
plugins: ['gatsby-plugin-react-helmet']
};
Basic SEO Component
// src/components/SEO.js
import React from 'react';
import { Helmet } from 'react-helmet';
import { graphql, useStaticQuery } from 'gatsby';
export default function SEO({ title, description, image, pathname, article }) {
const { site } = useStaticQuery(graphql`
query SEOQuery {
site {
siteMetadata {
title
description
siteUrl
author
}
}
}
`);
const seo = {
title: title || site.siteMetadata.title,
description: description || site.siteMetadata.description,
image: image ? `${site.siteMetadata.siteUrl}${image}` : null,
url: `${site.siteMetadata.siteUrl}${pathname || '/'}`
};
return (
<Helmet title={seo.title} titleTemplate={`%s | ${site.siteMetadata.title}`}>
<meta name="description" content={seo.description} />
<meta name="author" content={site.siteMetadata.author} />
{seo.image && <meta name="image" content={seo.image} />}
{/* Open Graph */}
<meta property="og:title" content={seo.title} />
<meta property="og:description" content={seo.description} />
<meta property="og:url" content={seo.url} />
<meta property="og:type" content={article ? 'article' : 'website'} />
{seo.image && <meta property="og:image" content={seo.image} />}
{/* Twitter */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={seo.title} />
<meta name="twitter:description" content={seo.description} />
{seo.image && <meta name="twitter:image" content={seo.image} />}
</Helmet>
);
}
Output: Every page with <SEO title="..." description="..." /> gets proper meta tags, Open Graph, and Twitter card markup.
Using SEO in Pages
// src/pages/blog.js
import React from 'react';
import SEO from '../components/SEO';
export default function BlogPage() {
return (
<>
<SEO
title="Blog"
description="Read the latest articles about web development and Gatsby."
pathname="/blog/"
/>
<h1>Blog</h1>
{/* ... */}
</>
);
}
SEO in Templates
Pass frontmatter data to SEO:
// src/templates/blog-post.js
import SEO from '../components/SEO';
export default function BlogPost({ data }) {
const post = data.markdownRemark;
const image = post.frontmatter.image?.childImageSharp?.original?.src;
return (
<>
<SEO
title={post.frontmatter.title}
description={post.excerpt}
image={image}
pathname={post.fields.slug}
article
/>
<article>
<h1>{post.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</article>
</>
);
}
JSON-LD Structured Data
Add schema markup for rich snippets:
// src/components/SEO.js — add inside <Helmet>
<script type="application/ld+json">
{JSON.stringify({
'@context': 'https://schema.org',
'@type': article ? 'Article' : 'WebPage',
headline: seo.title,
description: seo.description,
image: seo.image,
url: seo.url,
author: {
'@type': 'Person',
name: site.siteMetadata.author
},
datePublished: article?.datePublished,
dateModified: article?.dateModified
})}
</script>
Output: Search engines see structured data, enabling rich snippets with author, publish date, and images in search results.
Common Mistakes
- Not setting
titleTemplate: Without it, all pages show the same title format. UsetitleTemplate={%s | Site Name}in the SEO component. - Missing Open Graph image: Social shares without images look unprofessional. Always provide an OG image.
- Using relative URLs for OG image: Open Graph requires absolute URLs. Prepend the
siteUrlto the image path. - Not adding
langattribute: Set<html lang="en">inHelmetfor Accessibility and SEO. - Duplicate canonical URLs: Every page should have a
<link rel="canonical" href={url} />to prevent duplicate content issues.
Practice Questions
What plugin adds React Helmet support to Gatsby? Answer:
gatsby-plugin-react-helmet. It ensures Helmet data is extracted during the build.What is Open Graph used for? Answer: It controls how pages appear when shared on social media platforms (Facebook, LinkedIn, Discord).
Why use absolute URLs for OG images? Answer: Social media crawlers need absolute URLs to fetch images. Relative paths don't resolve correctly from the crawler's perspective.
What does JSON-LD structured data enable? Answer: Rich search results with star ratings, author info, publish dates, images, and FAQ sections.
Challenge
Create an SEO component that accepts optional breadcrumbs and faq props to generate breadcrumb JSON-LD and FAQPage schema. Test with Google's Rich Results Test tool.
Mini Project
Implement full SEO across a Gatsby blog: a reusable SEO component with all meta tags, Open Graph, Twitter cards, JSON-LD Article schema, breadcrumb trails, and canonical URLs.
FAQ
What's Next
Learn about Gatsby Sitemap and RSS to generate XML sitemaps and RSS feeds for better search engine discovery.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro