Customizing Yoast SEO's structured data with schema API part 2
Tags: wordpress, yoast, schemaapi
Published: 2022-06-04 15:12:58

In the [first part](https://dev.to/peterlidee/customizing-yoast-seos-structured-data-with-schema-api-part-1-1p76) of this series I explained how [Yoast SEO](https://yoast.com/wordpress/plugins/seo/) implements structured data. Now, we will have a look some basic ways to customize the schemas.  

## Schema API

Yoast SEO has a build in api for altering it's schema output: [Schema API](https://developer.yoast.com/features/schema/api/). This is what we will be using.

To make development in this mode easier, yoast also provided a little snippet that turns on dev mode for structured data. This will print the json-ld un-minified, so you can easely read it. Just drop this in your `functions.php`. (don't use this in production)

```php
add_filter( 'yoast_seo_development_mode', '__return_true' );
```

## Customize schema props

To change a property of a piece (a single schema), we use the `wpseo_schema_<class>` filter. The `<class>` refers to the schema you want to change. So, for `Article` you would use `wpseo_schema_article`.

### **Example 1** Add property "email" to `Organization`:

```php
// functions.php

add_filter( 'wpseo_schema_organization', 'add_email_to_organization' );
function add_email_to_organization( $data ) {
  $data['email'] = get_option('company-email');
  return $data;
}
```

This would result in: (simplified example)

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://www.mycompany.com/#Organization",
      "url": "https://www.mycompany.com/",
      "name": "My Company",
      "email": "info@mycompany.com"
    }
  ]
}
```

The `$data` object holds all the properties: "@type", "id", ... All we have to do is add a new property and then return `$data`.

In case you are confused by `get_option`. That is not schema API but [WordPress settings API](https://developer.wordpress.org/plugins/settings/settings-api/). It allows you to customize WordPress settings and preferences. The `get_option` function is then used to retrieve the content. You can use `get_option` to retrieve data you're familiar with like `get_option("blogname")` or `get_option("siteurl")`. In the above example we retrieve a custom field "company-email".

### **Example 2** Change an existing property:

```php
// functions.php

add_filter( 'wpseo_schema_organization', 'change_name_of_organization' );
function change_name_of_organization( $data ) {
  $data['name'] = "A custom name";
  return $data;
}
```

This would result in: (simplified example)

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://www.mycompany.com/#Organization",
      "url": "https://www.mycompany.com/",
      "name": "A custom name"
    }
  ]
}
```

As you can see, adding or editing (overwriting) a property is pretty much the same.

### **Example 3** remove property "potentialAction" from `Article`:

```php
// functions.php

add_filter( 'wpseo_schema_article', 'remove_potentialAction_property_from_article', 11, 1 );
function remove_potentialAction_property_from_article( $data ) {
  if (array_key_exists("potentialAction", $data)) {
      unset($data['potentialAction']);
  }
  return $data;
}
```

The code seems pretty self explanatory. If the property "potentialAction" exists, remove it.

### **Example 4** Conditionally add "award" to `Article`. 

It is important to note that you can use all of WordPress' conditional logic in these functions. Let's say you received an award for a certain blog post and would like to add that to your structured data.

```php
// functions.php

add_filter('wpseo_schema_article', 'conditionally_add_award_to_article');
function conditionally_add_award_to_article( $data ){
  if ( ! is_single( 123 ) ) {
    return $data;
  }
  $data['award'] = 'Some Fancy Award';
  return $data;
}
```

## Remove an entire piece

To remove a piece we use the `wpseo_schema_graph_pieces` filter. Let's say we want to remove the `Breadcrumb` schema from the website.

```php
// functions.php

add_filter( 'wpseo_schema_graph_pieces', 'remove_breadcrumbs_from_schema', 11, 2 );
/**
* Removes the breadcrumb graph pieces from the schema collector.
*
* @param array  $pieces  The current graph pieces.
* @param string $context The current context.
*
* @return array The remaining graph pieces.
*/
function remove_breadcrumbs_from_schema( $pieces, $context ) {
    return \array_filter( $pieces, function( $piece ) {
        return ! $piece instanceof \Yoast\WP\SEO\Generators\Schema\Breadcrumb;
    });
}
```

As the comments say, we remove `Breadcrumb` from the schema collector. So the function that renders the `Breadcrumb` piece doesn't get called. 

But, as we saw in [part 1](https://dev.to/peterlidee/customizing-yoast-seos-structured-data-with-schema-api-part-1-1p76), this leaves us with a problem. All the pieces are linked. After removing `Breadcrumb`, `Webpage` is still referring `Breadcrumb`.

```json
{
  "@type": "WebPage",
  "@id": "https://www.mycompany.com/page1/#webpage",
  "url": "https://www.mycompany.com/page1/",
  "name": "Page 1",
  "isPartOf": {
    "@id": "https://www.mycompany.com/#website"
  },
  "breadcrumb": {
    "@id": "https://www.mycompany.com/page1/#breadcrumb"
  }
}
```

Luckily, we already know how to remove a property from a schema piece:

```php
// functions.php

add_filter( 'wpseo_schema_webpage', 'remove_breadcrumbs_property_from_webpage', 11, 1 );
function remove_breadcrumbs_property_from_webpage( $data ) {
  if (array_key_exists('breadcrumb', $data)) {
    unset($data['breadcrumb']);
  }
  return $data;
}
```

## Summary

You now know how to add, change or remove properties from a single piece. We've also shown an example of removing a piece. An important note here is to look for links before you edit or remove things. Make sure not to break the chain.

On a last note I need to mention this is only an introduction. There are more filters and possibilities available. So you should really invest some time reading the [schema API docs](https://developer.yoast.com/features/schema/api/). Don't worry, they are short.

In the [third](https://dev.to/peterlidee/customizing-yoast-seos-structured-data-with-schema-api-part-3-1i7d) and [fourth parts](https://dev.to/peterlidee/customizing-yoast-seos-structured-data-with-schema-api-part-4-2bdf) of this series, we will look into adding custom pieces.