A Simplified Guide to SEO with GraphCMS

It's relatively simple to ensure you're not sacrificing any SEO best practices when using a Headless CMS.

Ronak Ganatra
Ronak Ganatra
Guide to Headless CMS and SEO with GraphCMS

In previous articles we've covered the general Headless CMS and SEO Best Practices, as well as the Best Practices for Technical SEO when using a Headless CMS.

Here we'll dive into a more hands-on approach of how SEO is handled for our own website at GraphCMS, and what some common solutions could be for marketers and content creators to ensure a strong foundation for operational SEO.

We currently maintain all the content for our website from within GraphCMS itself. We build our site using a Static Site Generator (Gatsby), and deploy to Netlify using webhooks.

SEO as a ModelAnchor

Since the concept of simple plug-and-play plugins like Yoast don't exist in the Headless world, we opted to run our operational SEO as a model within GraphCMS. All the required fields are set as an SEO model, which can have relations to a variety of pages, posts, and resources.

In practice, this is what our SEO Schema currently looks like:

SEO Model.png

Using this approach, we enforce correct SEO attributes are in place by defining the meta-data as a requirement in our data model when content creators create or edit new data.

The meta title, description, and focus keywords are taken as text strings to reflect accordingly when the website is crawled and indexed.

The OG Image field allows content editors to add custom OG images for Facebook, Twitter, LinkedIn, etc. on the fly; although these could be generated programmatically using a service like Zeit's OG Image as a Service.

Pages and posts can be connected to this SEO model as required, ensuring that every piece of content has its corresponding SEO attributes attached.

For certain pages (especially resources behind a lead wall), having a Boolean field for a _noindex tag (or a _nofollow, or any other SEO attributes as required) allow content editors to exercise greater control on the content they're publishing.

For context, an enriched SEO model for a blog post such as this one could look similar to this:

SEO Connect.png

Taking this approach at GraphCMS allows us to make sure all SEO attributes for content are easy to create, edit, and modify on the fly, and might resemble the familiarity of adding SEO attributes via plugins in the majority of legacy CMS platforms.

To simply take the page title, description, and keywords from the post rather than creating individual SEO updates each time, the frontend can simply have a fallback to inherit the properties from the page if an SEO model isn't connected to a new content piece.

On the frontend, the added attributes are then compiled on the next website build prior to deploying as part of an "SEO" component.

import React from 'react';
import Helmet from 'react-helmet';
import useSiteMetadata from '../hooks/useSiteMetadata';
const SEO = ({ children, title, subTitle, meta }) => {
const {
description: metaDescription,
keywords: metaKeywords,
noindex,
title: metaTitle,
image,
} = meta || {};
const {
keywords,
title: siteTitle,
titleTemplate,
siteUrl,
defaultImage,
twitter,
} = useSiteMetadata();
const pageTitle = metaTitle || title;
const pageDescription = metaDescription || subTitle;
const pageKeywords = metaKeywords || keywords;
const ogImage = image?.url || defaultImage;
return (
<Helmet
htmlAttributes={{ lang: 'en' }}
defaultTitle={siteTitle}
titleTemplate={titleTemplate}
>
<title>{pageTitle}</title>
<meta name="description" content={pageDescription} />
<meta name="keywords" content={pageKeywords} />
<meta property="image" content={ogImage} />
<meta property="og:url" content={siteUrl} />
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={pageDescription} />
<meta property="og:site_name" content={siteTitle} />
<meta property="og:image" content={ogImage} />
<meta name="og:type" content="website" />
<meta name="twitter:site" content={`@${twitter}`} />
<meta name="twitter:title" content={pageTitle || siteTitle} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image:src" content={ogImage} />
{!!noindex && <meta name="robots" content="noindex" />}
{children}
</Helmet>
);
};
export default SEO;

And finally, when the time comes to build pages prior to deploying, the job is done for us with pages requesting any added meta attributes before our sitemap is updated using the Gatsby Sitemap Plugin.

meta: seo {
...seoData
}

To learn more about using GraphCMS to deliver better SEO in general, we've covered the Headless CMS and SEO Best Practices, as well as the Best Practices for Technical SEO when using a Headless CMS.

It's Easy To Get Started

GraphCMS plans are flexibly suited to accommodate your growth. Get started for free, or request a demo to discuss larger projects with more complex needs