SEO handling in Strapi [Building Personal Blog Website Part 7]
Tags: strapi, seo, headless, nextjs
Published: 2022-12-12 14:55:50

There are two approaches for SEO in Strapi - you can create a SEO component by hand or use a SEO plugin which provides an extensive component. In this guide you’ll use the plugin, but you’ll edit the component a bit so it has only the relevant (for us) data.

Open your Strapi repository and install SEO plugin:

```bash
yarn add @strapi/plugin-seo
yarn build
yarn develop
```

Now log in to admin panel locally and click on the SEO panel on the left hand side - this should initialize the plugin:

![Blog-7-1.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_1_186c23f992.jpg)

Go back to Content-type builder - there should be two new components created:

![Blog-7-2.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_2_c57f517884.jpg)

You’ll use only SEO one, you’ll get rid of the `MetaSocial` component. Why? This component assumes you’ll use a different image, title and description for each social media, while in reality the title and description will stay the same and the image used for Facebook and LinkedIn would be the same. Only for Twitter you’d need another image - and you’ll make the change to the SEO component so it allows you to upload this as well. Start with deleting `metaSocial` from `Seo` component.

![Blog-7-3.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_3_3370c09088.jpg)

Now add a new field for `metaTwitterImage`:

![Blog-7-4.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_4_32e69728ef.jpg)

And just to keep your CMS clean - Edit `MetaSocial` component and press Delete - you’ll not need it anymore.

![Blog-7-5.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_5_09a8e83f71.jpg)

It’s time to add `Seo` component to your Posts. Still in Content-type builder open Post collection type and add another field:

![Blog-7-6.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238055/Blog_7_6_967cecd165.jpg)

Select *Component* and *Use an existing component*

![Blog-7-7.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_7_ef82884ce7.jpg)

Now select `seo` component, put a name (preferrably `seo`) and select *Single component*. Then save the Post model and you’ll be set.

![Blog-7-8.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_8_853a60b7c9.jpg)

Now in VSCode (or Terminal) commit all the files and publish changes to GitHub and Railway.

When it rebuilds, log in to admin panel on your hosted Strapi. Go to the content manager, open any of your posts and there you should be able to add SEO. Provide `title`, `description`, `metaImage` (preferably 1200x630 since this is a fitting size for both Facebook and LinkedIn) and `metaTwitterImage` (here use 560x300). If you’d like - provide SEO for all your posts. If you’re done - you can go to VSCode and open your Next.js app.

You need to do three things here:

1. Update GraphQL query in `[slug].js` so it fetch also SEO data.
2. Use `next/head` to add proper meta tags
3. Validate if SEO data actually exists - SEO is optional in your CMS. 

Let’s start with the first task. Open `[slug].js` and in GraphQL query in `getStaticProps` method add the following fields to be fetched:

```bash
SEO {
  metaTitle
  metaDescription
  metaImage {
    data {
      attributes {
        url
      }
    }
  }
  metaTwitterImage {
    data {
      attributes {
        url
      }
    }
  }
}
```

Now it’s time to use the SEO data that you have. Update your Post component as follows:

```bash
export default function Post({ postData }) {
  return (
    <>
      <Head>
        <title>{postData.attributes.title}</title>
        {postData.attributes.SEO && (
          <>
            <meta
              name="description"
              content={postData.attributes.SEO.metaDescription}
            />
            <meta property="og:title" content={postData.attributes.title} />
            <meta property="og:type" content="article" />
            <meta
              property="og:image"
              content={postData.attributes.SEO.metaImage.data.attributes.url}
            />
            <meta
              property="twitter:image"
              content={
                postData.attributes.SEO.metaTwitterImage.data.attributes.url
              }
            />
            <meta property="twitter:card" content="summary_large_image" />
          </>
        )}
      </Head>
      <ReactMarkdown className="prose prose-sm md:prose-lg lg:prose-xl xl:prose-2xl prose-slate w-11/12 mx-4 my-8">
        {postData.attributes.content}
      </ReactMarkdown>
    </>
  );
}
```

The `{postData.attributes.SEO && (` ensures that you’ll render meta tags only when the SEO data is actually provided. You should aim to provide it for every post as this not only helps with Google ranking, but also with properly displaying the relevant data while sharing posts on social media.

When that’s done rebuild your app locally to check if everything is OK. If it is - commit your changes and push them to GitHub. When the app rebuilds on Netlify open any of the posts that you provided SEO data for. First of all you should notice that on the browser bar there is an actual title of the post. 

![Blog-7-9.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_9_fc5760cd11.jpg)

For the rest of the metadata you’ll need to go to [https://developers.facebook.com/tools/debug/](https://developers.facebook.com/tools/debug/) and enter URL to your post and click Debug:

![Blog-7-10.jpg](https://res.cloudinary.com/dvrqjaeju/image/upload/v1670238054/Blog_7_10_881e84a188.jpg)

You should get a similar result. You see the link preview - everything looks fine. There are also warnings that you are missing `og:url` and `og:description` metatags - add those on your own if you want. Let this be my challenge for you :)

One more thing while you’re at it. Add some meta tags to your `_app.js` file - this will ensure that every page on your site has at least the basic metadata in place:

```bash
function MyApp({ Component, pageProps }) {
  return (
    <div className="flex flex-col items-center bg-white">
      <Head>
        <meta charset="UTF-8" />
        <meta name="author" content="YOUR NAME" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      </Head>
      <Navbar />
      <Component {...pageProps} />
      <Footer />
    </div>
  );
}
```

Charset, author and viewport are a nice addition to your SEO. Title and description should be provided per page so just use the snippet below and add it to all of the pages(`[slug].js`, `index.js` etc.) -  you can also extract it to a separate component and use it this way - your choice:

```bash
<Head>
  <title>YOUR TITLE</title>
  <meta name="description" content="YOUR_DESCRIPTION" />
</Head>
```

And that’s all! Now you have a basic SEO provided on your website. In the next part we’ll dive deep into pagination, topic which will be extremely useful when the blog post count grows.