Gatsby v5 Open Graph Meta Tags: Add OG with gatsby-plugin-react-helmet
Set og:title, og:image, og:description in Gatsby v5 using Head API, gatsby-plugin-react-helmet-async, and Gatsby Cloud OG image generation.
Gatsby v5 Head API vs react-helmet
Gatsby v5 introduced the built-in Head API — a first-class way to add <head> elements without any plugin. This replaces the older gatsby-plugin-react-helmet approach that was standard in Gatsby v4 and earlier. Both methods still work in v5, but the Head API is the recommended path going forward.
Both approaches render metadata during Gatsby's server-side rendering (or static generation), so Open Graph tags are present in the HTML that social crawlers parse.
Method 1: Gatsby v5 Head API (recommended)
Export a named Head component from any page or template. Gatsby automatically hoists its content into the document <head>:
// src/pages/index.tsx
import type { HeadFC } from "gatsby";
export const Head: HeadFC = () => (
<>
<title>My Gatsby Site — Fast Static Sites</title>
<meta name="description" content="Built with Gatsby v5 for blazing performance." />
{/* Open Graph */}
<meta property="og:type" content="website" />
<meta property="og:title" content="My Gatsby Site — Fast Static Sites" />
<meta property="og:description" content="Built with Gatsby v5 for blazing performance." />
<meta property="og:image" content="https://yourdomain.com/og/home.png" />
<meta property="og:url" content="https://yourdomain.com/" />
{/* Twitter Card */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="My Gatsby Site — Fast Static Sites" />
<meta name="twitter:description" content="Built with Gatsby v5 for blazing performance." />
<meta name="twitter:image" content="https://yourdomain.com/og/home.png" />
</>
);
export default function IndexPage() {
return <main><h1>Welcome</h1></main>;
}Dynamic OG tags in Gatsby templates
For blog posts or product pages generated via createPage, pass page context to the Head component via pageContext or a GraphQL page query:
// src/templates/blog-post.tsx
import { graphql, type HeadProps, type PageProps } from "gatsby";
interface PostData {
mdx: {
frontmatter: {
title: string;
description: string;
slug: string;
ogImage?: { publicURL: string };
};
};
}
export const Head = ({ data }: HeadProps<PostData>) => {
const { title, description, slug, ogImage } = data.mdx.frontmatter;
const image = ogImage?.publicURL
?? `https://yourdomain.com/api/og?title=${encodeURIComponent(title)}`;
return (
<>
<title>{title} | My Blog</title>
<meta name="description" content={description} />
<meta property="og:type" content="article" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<meta property="og:url" content={`https://yourdomain.com/blog/${slug}`} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={image} />
</>
);
};
export const query = graphql`
query BlogPostById($id: String!) {
mdx(id: { eq: $id }) {
frontmatter {
title
description
slug
ogImage { publicURL }
}
}
}
`;
export default function BlogPostTemplate({ data }: PageProps<PostData>) {
const { title, description } = data.mdx.frontmatter;
return (
<article>
<h1>{title}</h1>
<p>{description}</p>
</article>
);
}Method 2: gatsby-plugin-react-helmet-async
If you're maintaining an older Gatsby codebase or prefer react-helmet, use gatsby-plugin-react-helmet-async (the async-safe version for Gatsby v4/v5):
// Install
// npm install gatsby-plugin-react-helmet-async react-helmet-async
// gatsby-config.js
module.exports = {
plugins: ["gatsby-plugin-react-helmet-async"],
};
// src/components/seo.tsx
import React from "react";
import { Helmet } from "react-helmet-async";
interface SeoProps {
title: string;
description: string;
image?: string;
url?: string;
}
export function Seo({ title, description, image, url }: SeoProps) {
const ogImage = image ?? "https://yourdomain.com/og/default.png";
return (
<Helmet>
<title>{title}</title>
<meta name="description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={ogImage} />
{url && <meta property="og:url" content={url} />}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={ogImage} />
</Helmet>
);
}Gatsby Cloud OG image generation
Gatsby Cloud (and Gatsby v5 with the Functions feature) supports serverless functions. You can add a function at src/api/og.ts that generates PNG images using Satori or Puppeteer — and reference them as the og:image URL for dynamic pages. The function endpoint is available at /api/og?title=... during development and on Gatsby Cloud.
Preview your Gatsby OG tags
Paste any Gatsby page URL into OGFixer to see instant previews on Twitter, LinkedIn, Discord, and Slack.