Customizing Yoast SEO's structured data with schema API part 1

Peter Jacxsens - Jun 4 '22 - - Dev Community

One of the features of Yoast SEO for Wordpress is structured data/schema. But, how do you customize this data. What if for example you would like to add a phone number or a sponsor to the Organization schema? Or maybe you don't want to use gravatars in the Person schema? This is what this series is about.

This first part gives an introduction on how Yoast implemented structured data. This is important because you need to understand the structure of the json-ld before you can alter it. Parts 2 to 4 will deal with actual customization.

A sidenote: this article assumes you know about structured data/schema, json-ld, yoast SEO and wordpress. But, we take our time to explain the code.

Interlinked pieces

The team at yoast implemented a modular and flexible approach to json-ld. They pulled apart all the structured data into single reusable schemas (modular) called a pieces. These pieces are linked to each other through ID's (flexible) and get outputted as inline json.

<script type="application/ld+json" class="yoast-schema-graph">
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://www.mycompany.com/#Organization",
      "url": "https://www.mycompany.com/",
      "name": "My Company"
    }
  ]
}
</script>
Enter fullscreen mode Exit fullscreen mode

The "@graph" property is an array that holds all of the different pieces. Currently it holds only one piece, an Organization (simplified example):

Let's add 2 more pieces: Website and Webpage:

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://www.mycompany.com/#Organization",
      "url": "https://www.mycompany.com/",
      "name": "My Company"
    },
    {
      "@type": "Website",
      "@id": "https://www.mycompany.com/#Website",
      "url": "https://www.mycompany.com/",
      "name": "My Company",
      "publisher": {
        "@id": "https://www.mycompany.com/#Organization"
      }
    },
    {
      "@type": "Webpage",
      "@id": "https://www.mycompany.com/page1/",
      "url": "https://www.mycompany.com/page1/",
      "name": "Page 1",
      "description": "Page 1 description",
      "isPartOf": {
        "@id": "https://www.mycompany.com/#Website"
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Both Website and Webpage have their own @types and IDs. Crucial to notice here are the properties that link these pieces together. Website has a property "publisher" which refers to the id of the Organization. Webpage has a property "isPartOf" that refers to the Website id.

Webpage refers to Website. Website refers to Organization. This is a clever but not obvious solution. Referring is not obvious because there is no official way of doing this. Json-ld is messy, it's not clearly documented.

A solution without referring would involve having to repeat entire schemas, nested inside other schemas.

  • Organization
  • Website
    • publisher: Organization all over again
  • Webpage
    • isPartOf: Website all over again
    • publisher: Organization all over again

It would be a bloated mess. Yoast solved this for us by using IDs. But, this also means that the json-ld is interconnected and you should be carefull before altering it.

The basic schemas

The second thing you need to understand about structured data in Yoast SEO is that it uses 3 basic pieces on every page, post, taxonomy, custom post type,... These 3 pieces are the ones we already used as examples:

  • Organization (or a subtype like Corporation, LocalBusiness or a subsubtype like Store, Restaurant,...)
  • Website
  • Webpage

I have to admit. When I first saw these basic schemas I thought Website and Webpage were unnecessary and my first instinct was to remove them. I was wrong. They don't seem very important on their own but are needed to hold everything together.

Let's take a look at a simplified Article piece as an example:

{
  "@type": "Article",
  "@id": "https://www.mycompany.com/blog/hello-world/#article",
  "isPartOf": {
      "@id": "https://www.mycompany.com/blog/hello-world/#webpage"
  },
  "author": {
      "@id": "https://www.mycompany.com/#/schema/person/2fa9055e7ef234fa04dd717e6aaed799"
  },
  "headline": "Hello world!",
  "publisher": {
      "@id": "https://www.mycompany.com/#Organization"
  }
},
Enter fullscreen mode Exit fullscreen mode

You can see that Article has a lot of referrals. It's linked to WebPage, Organization and a Person piece. But, it is not directly linked to Website.

Yoast has thought this through for us and came up with this structure. It might seem a bit overwhelming at first but it works. Simply removing a piece would break the chain of referrals and leave us with 404 Piece not Found situations.

Summary

When you first look into the json-ld that Yoast SEO renders onto the page it may be a bit confusing. The structured data is modular: different pieces are linked using IDs.

The second thing that may be confusing is that every page uses the same 3 basic pieces: Organization (or a subtype), Website and Webpage. Accept this basic structure because it ties in with other pieces that Yoast SEO outputs and you can also use it for your own custom pieces.

Now that you understand this we can talk about customizing. Part 2 of this series covers adding, changing or removing piece properties and removing a piece. Part 3 and part 4 will show you how to add a piece.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .