A Complete, Dead-Simple Guide to SEO for Static Site Generators

Posted by Soham Kamani on October 4, 2023


What is a static site generator? Static site generators (SSGs) are tools to convert dynamic templates into static HTML pages. SSGs like Gatsby, Jekyll, and Hugo have been gaining popularity because they allow you to use templates and represent your blog as a series of components, which is often much more efficient.

In this post, we'll focus on some popular SSGs that use the React framework. If you're looking for information about Angular SEO, look here as well. 

One of the most appealing things about SSGs is that, compared to regular web pages, they provide better support for Search Engine Optimization (SEO). This is one reason why you should use a static site generator. SEO allows your website to have greater visibility on search engines, which brings in more traffic to your site from relevant audiences. SSGs allow you to easily incorporate common SEO patterns into your site by using the appropriate SEO components.

In this post we will be looking into some strategies for developing these SEO-specific components. We will then look at how to implement these strategies with some popular static site generator frameworks.


Static Site Generator SEO Challenges

Although SSGs are better for SEO in the long run, there are a few challenges that we have to overcome compared to working with static sites:

  1. Creating SEO templates — On static sites, we can add the required titles and meta tags for each page individually. For SSGs, we need to create a template for these tags so they can be auto-generated for each page.
  2. Generating sitemaps — For a static site, we can manually update our sitemap once we add new pages. In the case of SSGs, since new pages are generated dynamically, sitemaps will in turn need to be generated automatically when building our site.
  3. Source code verification — The HTML source code for a site plays a huge role in SEO. For static sites, you know the source code that will finally appear on the website. In the case of SSGs, however, there are normally so many components and templates that you'll need to verify the source code once the website is generated.

Although these seem like challenges at first, they can be treated as benefits as well. For example, automating SEO templates and generating the sitemap do require initial effort to set up, but they will actually reduce the time and effort you spend on SEO every time you add a new page.

Static Site Generator SEO strategies

Let's discuss some strategies and concepts common to most static site generators for enabling and optimizing SEO on your site. Everyone has their own opinion about their favorite static site generator so there isn't necessarily one best static site generator; instead, we'll cover SEO strategies for the most popular static site generators.

Adding titles and descriptions

Every webpage needs to have meta tags to describe their title and description. Here's an example from the ButterCMS Angular CMS page:

<title>Angular CMS - #1 Headless CMS for Angular | ButterCMS</title>

<meta name="description" content="ButterCMS is an API-based CMS for Angular apps. Add marketing pages, blog and more to your Angular app in minutes.">

The title and meta description tags give search engines a brief overview about the content of the page. They are also sometimes used by search engines in their results page, showing users a short snippet of what the web page is about.

For SSGs, we will need to insert these tags as templates that need to be filled in for each page:

<title>{page title}</title>

<meta name="description" content="{page description}">

Open Graph image and summary tags

When we paste some links on Twitter, it displays a summary card with an image and description, like this:

This is made possible by the Twitter and Open Graph meta tags:

<meta property="og:type" content="article" />

<meta property="og:url" content="" />

<meta property="og:title" content="Building your own content management UI with ButterCMS" />

<meta property="og:image" content="" />

<meta property="og:description" content="Build your own custom content management UI dashboard and easily integrate it with a few simple javascript tools" />

<meta name="twitter:card" content="summary_large_image">

<meta name="twitter:site" content="@ButterCMS">

<meta name="twitter:creator" content="@ButterCMS">

<meta name="twitter:title" content="Building your own content management UI with ButterCMS" />

<meta name="twitter:description" content="Build your own custom content management UI dashboard and easily integrate it with a few simple javascript tools" />

<meta name="twitter:image" content="" />


  • The twitter:card tag tells Twitter about the type of card preview to be shown when someone pastes a link on their tweet.
  • The twitter:image tag provides the URL of the image to display on the card.
  • The twitter:title and twitter:description tags describe the title and summary text on the card, respectively.

The og tags are specified by the Open Graph Protocol and are used by other sites like Facebook and Google's rich snippets. With them, you can control exactly how you want links to appear when shared on social media.

To support SSGs, each value of these tags needs to be templatized.

The twitter:card, twitter:site, and twitter:creator tags would remain the same for every page on a website, while the twitter:title, twitter:description and twitter:image tags would change for each page:

<meta name="twitter:card" content="summary_large_image">

<meta name="twitter:site" content="@ButterCMS">

<meta name="twitter:creator" content="@ButterCMS">

<meta name="twitter:title" content="{page title}" />

<meta name="twitter:description" content="{page description}" />

<meta name="twitter:image" content="{link to page banner image}" />

Verifying the source code of web pages

Once your website is generated by the SSG, you will need some way to verify if the SEO-related tags have actually been rendered as required. The easiest way to do this is by viewing the page source of your generated page.

This can be done by going to the browser, right clicking on a page, and selecting the "View Page Source" option. CTRL + U is a common shortcut for this.

This will take you to another page where the source code of the page can be seen.

Here, you can verify if the various meta tags were generated without error. This is the easiest and most fool-proof way to verify the SEO-related tags since this source code is the exact same information that is viewed by search engines when they crawl your site.

SEO strategies for React Static Site Generators

SSGs like Gatsby and Next.js use React as the templating library in addition to the application logic. 

For these frameworks, the initial page’s HTML is generated on the server side, and the React library and application code is loaded later. We can’t just place an HTML head element in our React components since a component may be rendered multiple times depending on your application code. This could lead to duplicate changes if each component needs to manipulate the page’s head element differently.

Using libraries like React Helmet or next/head saves you the trouble of maintaining code for these cases, and it takes care of updating the document head via any of your React components without duplication.


You can use the next/head submodule to encapsulate modifications to the head element. Normally, you would have an SEO React component that would do this for you:

// components/seo.js
import React from 'react'
import PropTypes from 'prop-types'
import Helmet from 'react-helmet'
import Head from 'next/head'

function SEO ({ description, title }) {
  return (
      <meta name='description' content={description} />

      <meta name='og:type' content='website' />
      <meta name='og:title' content={title} />
      <meta name='og:description' content={description} />

      <meta name='twitter:card' content='summary' />
      <meta name='twitter:title' content={title} />
      <meta name='twitter:description' content={description} />

export default SEO

Next, we would use this component in each of our pages. We can add this anywhere in our page component:

// pages/index.js

import SEO from '../components/seo'

const Index = () => (


    <SEO title='sample title' description='sample description' />

    <p>Hello Next.js</p>



export default Index

This will result in the following output HTML for the generated index.html page:

<!-- ... -->


        <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />

        <meta charSet="utf-8" />

        <title>sample title</title>

        <meta name="description" content="sample description" />

        <meta name="og:type" content="website" />

        <meta name="og:title" content="sample title" />

        <meta name="og:description" content="sample description" />

        <meta name="twitter:card" content="summary" />

        <meta name="twitter:title" content="sample title" />

        <meta name="twitter:description" content="sample description" />

        <meta name="next-head-count" content="10" />

        <!-- ... -->


<!-- ... -->

You can verify the source code by running the commands:

npx next build

npm next export

The index.html page will be present in the out directory by default.

You can find the full source code for this example here.

Gatsby Static Site Generator

Things are much easier with Gatsby because the SEO component is already prepared for you with the standard Gatsby project structure in src/components/seo.js.

This component makes use of the React Helmet library to generate the head HTML tags:






    titleTemplate={`%s | ${site.siteMetadata.title}`}



        name: `description`,

        content: metaDescription



        property: `og:title`,

        content: title



        property: `og:description`,

        content: metaDescription



        property: `og:type`,

        content: `website`



        name: `twitter:card`,

        content: `summary`



        name: `twitter:creator`,




        name: `twitter:title`,

        content: title



        name: `twitter:description`,

        content: metaDescription




The SEO component can be used (and is, by default) in the src/pages/index.js file:

import React from "react"

// ...

import SEO from "../components/seo"

const IndexPage = () => (


    <SEO title="Home" />

    {/* ... */}



export default IndexPage

This will lead to a similar generated index.html , which you can verify by running npm run build and viewing the public/index.html file.

You can find the full source code for this example here.

SEO strategies for Jekyll Static Site Generators

Jekyll is a popular SSG that works using Embedded Ruby (ERB) templates and layouts to customize each page.

You can follow along the getting started tutorial to get a starter site up and running. In order to add SEO-specific tags to your Jekyll site, you will need to modify the default template.

Create the file _layouts/default.html that will contain the base template for all our pages:

<!doctype html>

<html lang="en">


        <meta charset="utf-8">

        <link rel="stylesheet" href="/css/style.css">

        <!-- We add the SEO tags here -->

        <title>{{ page.title }}</title>

        <meta name="description" content="{{ page.description }}" />

        <meta name="og:type" content="website" />

        <meta name="og:title" content="{{ page.title }}" />

        <meta name="og:description" content="{{ page.description }}" />

        <meta name="twitter:card" content="summary" />

        <meta name="twitter:title" content="{{ page.title }}" />

        <meta name="twitter:description" content="{{ page.description }}" />

        <meta name="next-head-count" content="10" />




                <a href="/">Home</a>

                <a href="/blog/">Blog</a>


        <h1>{{ page.title }}</h1>


                {{ content }}



                &copy; to me




In the above template, page.title and page.description are template variables and differ for each page. In Jekyll, each page is compiled from a markdown file. The header of the markdown file will contain the title and description variables that will be used in the template.

Let’s take a look at a sample markdown file in the _posts directory:


layout: post

title:  "Welcome to Jekyll!"

description: "Sample description"

date:   2019-08-28 00:22:09 +0530

categories: jekyll update


Some page content...




In Jekyll, the post layout mentioned in the header above inherits from the default layout we just defined. This would give us the required meta tags in our generated HTML:

<title>Welcome to Jekyll!</title>

<meta name="description" content="Sample description" />

<meta name="og:type" content="website" />

<meta name="og:title" content="Welcome to Jekyll!" />

<meta name="og:description" content="Sample description" />

<meta name="twitter:card" content="summary" />

<meta name="twitter:title" content="Welcome to Jekyll!" />

<meta name="twitter:description" content="Sample description" />

<meta name="next-head-count" content="10" />

If you want to view or verify the HTML on your Jekyll site, run the jekyll build command and view the respective HTML files within the _site folder.

You can find the full source code for this example here.

SEO strategies for Hugo Static Site Generators

The last SSG we’ll discuss here is Hugo. Hugo is one of the fastest SSGs, and is powered by Go (and consequently uses Go templating). If you follow along with the quick start guide, you should be able to get a basic site up and running.

Hugo has most of the SEO requirements built in, which means you won't have to set anything up to generate the title meta tags discussed for the previous SSGs.

You can generate a new page using this command:

hugo new posts/<post-title>.md

This should generate a markdown file with the header:


title: "My First Post"

date: 2019-08-28T01:29:26+05:30

draft: true


This will cover all the SEO tags except for the description tags. You can fill this in by adding a description key to the post header:


title: "My Sample Post"

date: 2019-08-28T01:29:26+05:30

description: "My Sample Description"

draft: true


In order to verify the source code, you can run hugo -D and see your posts HTML file in public/posts/<post-title>/index.html

You can find the full source code for this example here.

If you're interested in creating a blazing fast static website with Hugo and ButterCMS, we have an easy to follow guide for you.


In this article, we covered the basics of SEO and Static Site Generators and how to integrate SEO into your site.

We saw how to apply SEO to a variety of SSGs like Gatsby, Next, Jekyll, and Hugo, but know that this can be applied to any SSG of your choice. There are just two things you need to look out for:

  1. A way to modify the SSG’s HTML tags (specifically in the head).
  2. A way to change the HTML tags for individual pages while maintaining a common template.

I hope this post has helped you understand the importance of SEO and how to integrate it into any SSG. SSGs are extremely efficient tools by themselves, but now that you know about the SEO templating tools described in this article, you can drive even more visitors to your website.

What are your favorite SSGs, and what benefits have you found from using them? We’d love to hear your thoughts! 

Do you want your product or marketing team to test Butter CMS? We can set up a live demo to walk your team through the fast, easy-to-use interface.

Get the latest Static Site Generator SEO articles delivered straight to your inbox.
Soham Kamani

Soham is a full stack developer with experience in developing web applications at scale in a variety of technologies and frameworks.

ButterCMS is the #1 rated Headless CMS

G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award

Don’t miss a single post

Get our latest articles, stay updated!