Skip to main content

Schema - Integration guidelines


Integrating with Yoast's structured data framework is easy, and, we encourage all plugin/theme/software authors to consider adopting and extending our approach.

You should start by reading our specification, and making sure that you understand the core principles. Loosely, these are that:

  • We output a block of structured data on every page on a website, which describes the Organization, the WebSite, the WebPage and its primary entity using vocabulary.
  • Where we can, we enrich those 'pieces' with information which we know from the user or site settings (such as, the logo of the Organization, or the author of a WebPage.
  • This is output in a way which constructs a single, cohesive @graph object in JSON-LD. This can be read by search engines (and other software), and provides marketing/integration/discoverability benefits to the end user / site owner.
  • Our Schema API allows developers to alter or extend the output of the graph.
  • By adapting and extending our graph, we produce richer representations of web pages, which help consumers like Google, Facebook and others understand (and better expose) the content of those pages.

Migration guide

If you've made use of the WPSEO_Graph_Piece interface in the past, you may have noticed a deprecation message since upgrading to 14.0. In this release, we introduced a new abstract class to deal with custom graph pieces, that you need to migrate to. To quickly see what changed, make sure you check out our blogpost and adapt your own code, accordingly.

An example use-case

Yoast SEO software already creates a large, structured graph, but there are content types which we don't (currently) support. You might want to add support for a specific content type. For example, you might want to add Person output to team profile pages, like we have here at Yoast. To do that, you should output a custom Person piece and stitch it into the main graph.

Specifically, on a WebPage representing a single person, that person could be added as new piece, and defined as the mainEntityOfPage of the WebPage piece. Example code to achieve this might look something like the following.

First, we add the piece to the graph:

add_filter( 'wpseo_schema_graph_pieces', 'yoast_add_graph_pieces', 11, 2 );

* Adds Schema pieces to our output.
* @param array $pieces Graph pieces to output.
* @param \WPSEO_Schema_Context $context Object with context variables.
* @return array Graph pieces to output.
function yoast_add_graph_pieces( $pieces, $context ) {
$pieces[] = new Team_Member( $context );

return $pieces;

And then Team_Member is a "graph piece", so let's create it. We're going to create it by extending the existing Person class, as that saves us a lot of code.

* Class Team_Member
class Team_Member extends \Person {
* A value object with context variables.
* @var WPSEO_Schema_Context
public $context;

* Team_Member constructor.
* @param WPSEO_Schema_Context $context Value object with context variables.
public function __construct( WPSEO_Schema_Context $context ) {
$this->context = $context;

* Determines whether or not a piece should be added to the graph.
* @return bool Whether or not a piece should be added.
public function is_needed() {
if ( is_singular( 'yoast_team_member' ) ) {
return true;

return false;

* Adds our Team Member's Person piece of the graph.
* @return array Person Schema markup.
public function generate() {
$data = parent::generate();

$data['worksFor'] = [ '@id' => $this->context->site_url . \Schema_IDs::ORGANIZATION_HASH ];
$data['mainEntityOfPage'] = [ '@id' => $this->context->canonical . \Schema_IDs::WEBPAGE_HASH ];

$job_title = get_post_meta( $this->context->id, 'employees_function_title', true );
if ( ! empty( $job_title ) ) {
$data['jobTitle'] = $job_title;

$suffix = get_post_meta( $this->context->id, 'employees_honoric_suffix', true );
if ( ! empty( $suffix ) ) {
$data['honorificSuffix'] = $suffix;

return $data;

And that is all, now this code will be output on your team member post type!

Note: this will only work if a user is running the Yoast SEO plugin of version 14.0 or higher. Plugin/theme/third-party developers should determine whether the Yoast SEO plugin is running, and manage their output accordingly.

"My plugin/theme already outputs schema markup"

Unless you're already adding individual pieces to a @graph (and connecting those pieces via @id referencing), you may need to make some changes in order to integrate effectively. If you already use an ID-based approach, you should be able to 'stitch' your pieces into our graph by using our Schema API and by following our specification.

If you use a different approach (e.g., you output a structured JSON-LD tree, or use microdata), there's a risk that the various pieces might have conflicting information, and that the page isn't accurately represented.

In this case, we encourage you to adapt your code to follow our specification. The first step is to identify each individual 'piece' of schema markup which you produce, and to output them as top-level members in a @graph (and connect them via unique @id parameters, based on our our specification ).

Then, if the user is running Yoast SEO, you can filter and/or extend our output and connect your pieces to our graph via our Schema API. When correctly integrated, you should be able to disable your plugin/theme output (as our own logic will manage the construction and output of the completed graph).

If you detect that your user isn't running Yoast SEO and you want to maximize interoperability with other plugins, you can construct your own graph following our specification.