Skip to content

Gatsby SEO and Meta Tags — Search Engine Optimization with React Helmet

DodaTech Updated 2026-06-28 4 min read

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

  1. Not setting titleTemplate: Without it, all pages show the same title format. Use titleTemplate={%s | Site Name} in the SEO component.
  2. Missing Open Graph image: Social shares without images look unprofessional. Always provide an OG image.
  3. Using relative URLs for OG image: Open Graph requires absolute URLs. Prepend the siteUrl to the image path.
  4. Not adding lang attribute: Set <html lang="en"> in Helmet for Accessibility and SEO.
  5. Duplicate canonical URLs: Every page should have a <link rel="canonical" href={url} /> to prevent duplicate content issues.

Practice Questions

  1. What plugin adds React Helmet support to Gatsby? Answer: gatsby-plugin-react-helmet. It ensures Helmet data is extracted during the build.

  2. What is Open Graph used for? Answer: It controls how pages appear when shared on social media platforms (Facebook, LinkedIn, Discord).

  3. 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.

  4. 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

Does Gatsby automatically generate a sitemap?

: No. Use gatsby-plugin-sitemap to auto-generate sitemap.xml from your pages.

How do I add Google Analytics?

: Use gatsby-plugin-google-analytics or gatsby-plugin-google-gtag with your tracking ID.

Can I add custom meta tags per page?

: Yes. Pass additional children to Helmet: <SEO title="Page"><meta name="robots" content="noindex" /></SEO>.

How do I test my SEO implementation?

: Use Google's Rich Results Test, Facebook Sharing Debugger, Twitter Card Validator, and Lighthouse SEO audit.

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