A photo of Shane

Shane Chaffe

2 min read ⏳

So you want to use Contentful to achieve your SEO Goals but are not sure where to start, firstly understanding that Contentful works on the premise of using content models to build data structures is key. The same concept is shared between content models and React components, so if you're familiar with React components you should be able to pick the patters for Content Modelling relatively quickly.

Creating a Content Model

In my example, I wanted to use a specific content model to manage my SEO Data so I can maintain a clean working interface and group data cleanly following the principle of KISS: Keep It Simple Stupid.

Depending on how granular you want to get, you can create as many fields as you like to be used within your content but for me, I opted for a content model that looks like this:

SEO Content Model

This is pretty barebones you might think, and you're probably right. I handle the rest of the tags at a code level so in this case it's wise to note that you should manage all of this inside Contentful if you expect editors to manage your SEO or people who aren't comfortable with code.

Using a Reference Field to reference your SEO data

When configuring your content model for another piece of content, let's say an Article content model, you'll want to include a reference to a single entry so that you can create an entry that is explicitly for SEO. This is what it would look like:

Reference field

Now that you've referenced your SEO Metadata and populated the data required, you're done, right? Well, that's what the editor thinks at least. The rest of the work happens under the hood.

Slack

Consuming Contentful data to populate your SEO

Since your SEO data is now rooted inside of a content model that belongs to a Article, it will always be referencing that article or page or however your set up looks like, the point is that it will be available on the API under the key of the field name. I named my field SEO Metadata, that means in the response there will be a key waiting for me to consume under `seoMetadata`.

In your Next.js project it would be wise to create a component that has all the tags you wish to populate, an example that I configured that satisfies all platforms is this:

import Head from "next/head";
import React from "react";

const SeoData = ({
  title,
  description,
  image,
  keywords,
  url,
  publishedTime,
  updatedTime,
}) => {
  return (
    <Head>
      {/* Primary Meta Tags */}
      <title>{title}</title>
      <meta name="description" content={description} key="desc" />
      <meta name="keywords" content={keywords} />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta charSet="utf-8" />
      <meta name="robots" content="index, follow" />
      <meta name="googlebot" content="index, follow" />
      {/* Open Graph / Facebook */}
      <meta property="og:site_name" content="Coffee Reviews" />
      <meta property="og:title" content={title} />
      <meta property="og:description" content={description} />
      <meta property="og:type" content="website" />
      <meta property="og:url" content={url} />
      <meta property="og:image" content={image} />
      <meta property="og:image:alt" content={title} />
      <meta property="og:image:type" content="image/png" />
      <meta property="og:image:width" content="1200" />
      <meta property="og:image:height" content="630" />
      <meta property="article:published_time" content={publishedTime} />
      <meta property="article:modified_time" content={updatedTime} />
      {/* Twitter */}
      <meta name="twitter:card" content="summary_large_image" />
      <meta name="twitter:title" content={title} />
      <meta name="twitter:description" content={description} />
      <meta name="twitter:image" content={image} />
      <meta name="twitter:image:alt" content={title} />
      <meta name="twitter:site" content="@CoffeeReviews" />
      <meta name="twitter:creator" content="@ShaneChaffe" />
    </Head>
  );
};

export default SeoData;

You can see clearly from my code comments and the imports as well as the props, what data I require in order to make this all work. Ensuring you have all of these populated and that you pass the props is what will ensure you succeed in reaching your SEO goals using Contentful. This pattern is indeed a best practice.

You can validate how it would look on each platform if you're using Vercel by using the Open Graph tab:

Twitter:

Twitter

Slack:

Slack

Facebook:

Facebook

Using this approach gives you nice previews and it's worth noting that Slack relies on the data from the og tags to satisfy their unfurling requirements.

This image describes it perfectly:

Anatomy of a URL

Technology used:

ContentfulNext.jsSEOPages RouterVercelMeta Tags