ScreenshotNeo

BlogHow-to

How to Add Open Graph Images to Pages in a Gatsby Site

Add an Open Graph image to Gatsby pages with the Head API, using a static default image or generating unique images at build time.

By the ScreenshotNeo team4 October 20268 min read

To add an Open Graph image to a Gatsby page, export a named Head function from the page or page template and render a <meta property="og:image"> tag whose content is the image’s absolute public URL. Put a shared image in Gatsby’s static directory; for page-specific artwork, generate an image during page creation and pass its path to the page through pageContext.

Gatsby’s Head API is available from gatsby@4.19.0. It adds metadata to generated static HTML and can use page query data and pageContext. The Head export belongs in a page or page template, including templates used with createPage; it is not a replacement for metadata rendered only inside an ordinary reusable component. Gatsby Head API documentation

1. Add a shared Open Graph image

Use this route when most pages can share one prepared image. Save the image at static/social/default-share.png. Files in static are served from the site root, so this file’s public path is /social/default-share.png.

Set the deployed site origin in gatsby-config.js so metadata can build absolute URLs:

// gatsby-config.js
module.exports = {
  siteMetadata: {
    siteUrl: "https://www.example.com",
    title: "Example site",
  },
};

Then add a named Head export to a page, for example src/pages/about.js:

// src/pages/about.js
import * as React from "react";

export default function AboutPage() {
  return <main><h1>About</h1></main>;
}

export function Head() {
  const siteUrl = "https://www.example.com";
  const imageUrl = `${siteUrl}/social/default-share.png`;

  return (
    <>
      <meta property="og:image" content={imageUrl} />
    </>
  );
}

Replace the example domain with the production origin and make sure the file exists at the matching path. Gatsby’s SEO guide recommends storing stable site information in siteMetadata and using the deployed siteUrl to construct absolute metadata URLs. Its static-image pattern expects the image to exist in static with the referenced filename and extension. Gatsby SEO guide

2. Use page data and a site-wide fallback

For content pages, query a page’s image path and use it when present, with a default image as a fallback. Keep the Head export in the page or template so Gatsby can render its tags into that page’s HTML.

// Example page template
import * as React from "react";
import { graphql } from "gatsby";

export default function ArticleTemplate({ data }) {
  const article = data.markdownRemark;
  return <article><h1>{article.frontmatter.title}</h1></article>;
}

export function Head({ data }) {
  const article = data.markdownRemark;
  const siteUrl = "https://www.example.com";
  const imagePath = article.frontmatter.socialImage || "/social/default-share.png";
  const imageUrl = new URL(imagePath, siteUrl).toString();

  return (
    <>
      <title>{article.frontmatter.title}</title>
      <meta property="og:title" content={article.frontmatter.title} />
      <meta property="og:image" content={imageUrl} />
    </>
  );
}

export const query = graphql`
  query ArticleHead($id: String!) {
    markdownRemark(id: { eq: $id }) {
      frontmatter {
        title
        socialImage
      }
    }
  }
`;

The example assumes socialImage is a root-relative public path such as /social/article-one.png. If your content model returns another shape, adapt the query and field access. Ensure a missing or empty per-page value resolves to a real fallback; otherwise the metadata can be absent or invalid.

3. Generate a different image for each page

If every article needs artwork composed from its title or other content, a build-time image plugin can create images while Gatsby creates pages. This adds a plugin dependency and build configuration; use it only if generated per-page artwork is useful for the site.

The documented flow for gatsby-plugin-open-graph-images is: configure the plugin, call createOpenGraphImage() from gatsby-node.js, provide a React component and page data, pass the generated image metadata in pageContext, and read ogImage.imagePath in the page template’s Head export. The plugin documents a default canvas of 1200 × 630 pixels and requires an id in the context to distinguish generated images. Check its current compatibility with your Gatsby version before adopting it. Plugin documentation

// Conceptual page-template usage after gatsby-node.js supplies ogImage
export function Head({ pageContext }) {
  const siteUrl = "https://www.example.com";
  const imageUrl = new URL(pageContext.ogImage.imagePath, siteUrl).toString();

  return <meta property="og:image" content={imageUrl} />;
}

Use the exact field names and setup documented by the plugin version you install. The snippet shows the metadata handoff, not a complete plugin configuration: the plugin’s API and configuration are maintained by its authors and can change. If sitemap tooling would otherwise include the plugin’s generated output directory (documented default: __og-image), configure that tooling to exclude it.

Do not copy metadata examples that repeat og:image:width for both dimensions. If you choose to emit dimensions, use the appropriate property name and the actual output dimensions. The plugin documentation examples noted in the research dossier contain this apparent duplication.

4. Choose the image workflow

Need Suitable approach Considerations
One image works for the whole site Place it under static and reference its absolute URL No image-generation plugin; update the file when the shared artwork changes.
A few pages need different prepared images Store a public path per page and use a fallback Keep paths valid and available in the deployed build.
Many pages need artwork composed from page data Generate images during page creation Add plugin configuration, check compatibility, inspect output, and handle sitemap exclusion if needed.

This is a maintenance choice, not a documented performance comparison: the available sources establish the static asset and build-time generation workflows but do not quantify their build cost or runtime speed.

5. Check the generated page and deployed image

  1. Confirm your installed Gatsby version is at least 4.19.0 for the built-in Head API.
  2. Build the site using its normal production build process.
  3. Inspect the generated HTML for the target page and confirm it contains one intended og:image tag with the final absolute URL.
  4. Open the image URL on the deployed site and confirm it serves the intended image without requiring authentication.
  5. If images are generated, confirm the file exists in the build output and that sitemap processing excludes its output directory when appropriate.

These checks verify your Gatsby output and public asset path. The cited Gatsby sources do not establish social-platform crawler rules or cache-refresh behavior, so confirm platform-specific requirements with the relevant platform documentation if those details matter.

6. Troubleshooting

Symptom Likely cause Fix
No Open Graph image appears in generated HTML Head is missing, is not a named export, or is defined only in an ordinary component. Export Head by name from the page or page template. Verify the Gatsby version supports the API.
The image URL starts with a local path or has the wrong host The metadata uses a relative path or an incorrect production siteUrl. Build an absolute URL from the production origin and the public image path.
The URL is correct but the image is missing The file is not in static, the filename or extension differs, or the deployed build omits generated output. Match the path exactly to the deployed asset and inspect the build output.
Some pages have an empty image value Page data has no image and there is no fallback. Use a valid per-page image when available, otherwise use a site-wide default.
Generated images collide or replace one another The generation context does not uniquely identify each image. Supply the required unique id and follow the plugin’s documented page-creation flow.
Generated image files appear in a sitemap Sitemap tooling is scanning the generation output directory. Exclude the generated directory, such as the documented default __og-image, where appropriate.

Performance, reliability, and cost

A static image avoids adding an image-generation plugin and its build configuration. Build-generated art can reduce manual per-page asset maintenance when many pages need unique compositions, but it adds build-time work and another dependency. The sources provide no quantitative performance or cost measurements, so evaluate build duration and maintenance in your own project rather than relying on a benchmark.

For reliability, treat the public URL and actual built image as part of the page metadata contract. A correct tag pointing to a missing or private asset cannot provide the intended preview. When adopting a community plugin, review its documentation and compatibility for the installed Gatsby version; the presence of a plugin directory entry does not establish current maintenance status.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. For the Gatsby page itself, its API can capture a rendered URL; it does not replace setting the page’s og:image metadata. A single GET request returns an image or PDF, and its API documentation describes the available options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://www.example.com/about -o shot.webp

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://www.example.com/about"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://www.example.com/about'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
  • Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers report the page verdict and billing status.
  • An MCP server lets AI agents, including Claude and Cursor, use screenshot tools.
  • The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

FAQ

Can I put the Open Graph image tag in a shared SEO component?

A shared component can help organize metadata, but Gatsby’s named Head export must be on a page or page template. Have that export render or call the shared metadata logic.

Does every Gatsby page need a unique image?

No. A shared default image is suitable when one preview works across pages. Use per-page paths or build-generated images when the content benefits from distinct artwork.

Should I add image width and height tags?

Add them only when you know the actual output dimensions, and use the correct property names. The dynamic plugin’s example appears to repeat the width property, so do not copy it verbatim.

What if my site uses Gatsby earlier than 4.19.0?

The built-in Head API described here starts with Gatsby 4.19.0. Upgrade Gatsby or consult the metadata approach supported by the version you run before using this page-level API.