Headless WordPress and SEO

One of the main reasons for using WordPress for a site is SEO, next to ease of content editing. With the help of plugins like Yoast you can easily add seo for your content per page basis. 

Context

For my project I’m using WordPress as my CMS and Yoast for SEO, using WpGraphql for data fetching and NextJS as my frontend stack.

With the help of WPGraphQL for Yoast SEO plugin. Huge shout out to Ash Hitchcock for this. You can get the Yoast SEO data in WPGraphQL and use it in your frontend.

Get SEO data via graphql

If you ever used WpGraphql this will look very familiar to you. For any page, post or any other custom post type you have all have this SEO field and with in that all the fields provided by Yoast.

query PageQuery {
  page(id: "/", idType: URI) {
    title
    uri
    seo {
      title
      metaDesc
      canonical
      metaKeywords
      metaRobotsNofollow
      opengraphModifiedTime
      ....
    }
  }
}

This is great now you can take this info and put it in your frontend sites head.

Easiest way to get the full SEO info

The above step is fine but what if we want all the SEO tags that Yoast generates/adds in each WordPress page. There is a field called fullHead that gives the raw SEO as a string for each page/post. We can use this in our sites head and this even have the structured data or application/ld+json included in it.

query PageQuery {
  page(id: "/", idType: URI) {
    title
    uri
    seo {
      title
      fullHead
    }
  }
}

Only one small problem

There is just one small problem with the above approach, If you check the string returned by fullHead closely you will see it points to the WordPress site not your frontend url. So if we can find a way to replace the WordPress urls with our frontend urls but not the media urls then we can use this and we dont have to manually add each tags.

The solution

Lets break down the problem so we know clearly what we have to do.

  1. Replace all the wordpress urls with our frontend url.
  2. We want to keep the media urls (eg: og:image) same.
let wpUrl = 'https://yourwpsite.com';
let siteUrl = 'https://frontendsite.com';
export default function seoStringParser(data) {
  data = data.replaceAll(wpUrl, () => siteUrl);
  data = data.replaceAll(`${siteUrl}/wp-content`, 
  () => `${wpUrl}/wp-content`);
  return data;
}

The above function is going to recive the SEO string and we are going to do two replaces. First replaceAll is going to just replace the wp url with fronend url, this solves one problem, all the links are now pointing correctly except the media urls now they are wrong. So we have a second replaceAll that will select ${siteUrl}/wp-content (here /wp-content in the end will help us to select only the media items) and replace it back with the wordpress url.

Add the Yoast data in your nextJS site

Finally, Now if you check the string its ready to put in our frontend sites head.

import Head from "next/head";
import parse from "html-react-parser";
import seoStringParser from "~/utils/seoStringParser"

export default function PageSEO({ seoData }) {
  let { title, fullHead } = seoData;
  return (
    <Head>
      <title>{title}</title>
      {parse(seoStringParser(fullHead))}
    </Head>
  );
}

Feel free to reach out to me if you have any questions.

Dipankar Maikap

Dipankar Maikap

I'm a freelance web developer. I work out of Kolkata, India. My favorite number is 77.

Leave a Reply