How to implement person and organisation schema in JSON-LD in WordPress

Richard Baxter

First, a brief history of structured data for SEO

Microformats

For a time, we had Microformats. Those times were simple, and good.

Implementing Microformats would lead to interesting things, like review ratings in Google’s search results. You could have your events listed, recipes indexed, and all sorts of contact details marked up as critical data points for a crawler to parse.

I really liked compound Microformats. They were simple to implement sets of attributes; added to the HTML containers surrounding useful data, like class="postal-code". Initially, web developers weren’t keen to add additional attributes to their markup, but over time, we’d get small wins, like having class="hreview-aggregate" become integrated with the stylesheet, tackling presentation and information in one go.

Then came RDFa

I never really bonded with RDFa. It was complicated, it was XML, and all we used it for was an extremely over engineered solution to gain rich snippets in Google’s search results. RDFa, an XML based extension to HTML5 was a much more powerful, but complexly structured solution compared to Microformats.

For most digital marketers, RDFa was too complex a thing to just work with. Front end web developers were especially reluctant to implement RDFa, although at the time, those that were made to just got on with it. The crippling blow to RDFa from the marketing community was that support from search engines was inconsistent and therefore the extra complexity was difficult to justify.

Schema.org ended all of this with microdata

Today I doubt you’ll meet any front end focused SEOs today that would recommend Microformats (unless they ask for a rel="nofollow" attribute adding to a link) or RDFa based markup. That’s because of Schema.org.

Schema.org: a common vocabulary for structured data markup on web pages

In June 2011, Google, Yahoo and Bing “got together” to announce Schema.org. Despite offering support for legacy RDFa and Microformats implementations, our community were immediately advised to implement Schema. It made sense, owing to wider support for other data types “including movies, music, organizations, TV shows, products, places and more”.

Schema is based on Microdata types and properties (for example: itemtype="http://schema.org/Movie") and extends quite well, with further extensibility and new types in Schema 2.0.

Dan wrote a very complete guide to all aspects of Schema Markup currently supported by Google. Wisely, he included the equivalent JSON-LD schemas, too.

This is already a lot of structured data, and you haven’t even got to the point of your post!

Here’s my point. Structured data is important, really important.

I think you should know a little structured data history too. I also think you should stay on top of what’s coming next, because it’s interesting and it will impact the future of search.

I think all of the future of structured data is JSON-LD, and I think that’s what we should all be implementing in our technical releases from now.

Staying on top of the topic of structured data

A really, really good way to stay on top of ideas relevant to digital marketers and SEOs in the structured data community is to follow Aaron Bradley‘s SEOSkeptic.com.

It was a post by Aaron that really helped the penny drop on the real importance of JSON-LD. Just the opening paragraph of “Zero Blue Links: Search After Traffic” is a real eye opener and one you should consume very carefully.

I reflected on the use of Schema, or more generally, structured markup (or JSON-LD for the future) is absolutely critical to apps like Google Now and its ability to pull a large majority of card results into the wrapper.

I predicted that Google’s mobile search results may soon look very much like Google Now, just in the browser, and that to maximise the opportunity a search marketer should make the best possible use of structured data and the knowledge graph, now.

I’ve since refined that view somewhat. I’m beginning to conclude that “search” for us may soon be about something more technically diverse. We’ll be staying on top of new search interfaces that require our content to be re-purposed in an alternative presentation layer to enable access.

Think about your site’s data layer and your site’s presentation layer as separate things. Think about your website as an API endpoint that can serve a JSON data payload to search engines. Think about how a search engine may choose (even, prefer for some applications) to consume your content on that API endpoint.

I can’t help but feel that eventually we’ll be doing exactly this to make sure we have visibility across a broad range of devices; organic and social channels, like answer boxes, instant articles and cards.

So to that end, I’m pretty sure (hopeful) Aaron would agree with me.

My take on using schema and why I’m writing this post

My take on using Schema Markup (Microdata) is this: I don’t want to implement it.

It messes with my presentation layer. Getting it implemented is slow, really really slow. You have to “get buy in” to win the resource via the front end development team who don’t want to mess up their HTML to accommodate the SEO team and this crappy code. Once you have it in, *then* you have to monitor it, checking every time a release is put live. Hoping that it hasn’t broken something. Which it often has. Which means more change requests, more communicating and more hassle.

All is not lost, however. JSON-LD’s keys and values match the attribute names set out in Schema.org – so you’re actually changing very little. Just compare the Microdata markup in Organization to its JSON-LD version in Dan’s Schema guide.

JSON-LD is where it’s at

JSON-LD is where it’s at, friends. Here’s why I think this:

I’ve had a few objections to this, namely; it feels “weird” to duplicate data on the webpage and support is limited (breadcrumbs won’t work).

I’ve reflected on those points for hours and I think the advantages in faster release outweigh any concerns. Sure – duplication. Specifically, the ArticleBody value for in-depth articles, for example. I still don’t think that’s a problem.

Implementing JSON-LD in WordPress

So, on that note let’s get to the point of the post. I had a lot of fun implementing JSON-LD across our homepage, author pages and posts.

Take a look in the head of my author page.


<script type="application/ld+json">
// <![CDATA[
{ 
  "@context":"http:\/\/schema.org\/", 
  "name":"Richard Baxter", 
  "@type":"Person",
  "email":"richard@builtvisible.com",
  "sameAs":[ 
    "https:\/\/twitter.com\/richardbaxter",
    "http:\/\/builtvisible.com\/",
    "https:\/\/www.facebook.com\/richardbaxterseo",
    "https:\/\/plus.google.com\/+RichardBaxterSEO\/",
    "http:\/\/uk.linkedin.com\/in\/richardbaxterseo",
    "http:\/\/www.slideshare.net\/richardbaxterseo" 
  ]
}
//]]>
</script>

Which validates in the rich snippets testing tool as follows:

person-json-ld

Our homepage uses Organization as follows:

<script type="application/ld+json">// <![CDATA[
{
  "@context": "http:\/\/schema.org\/",
  "name": "Builtvisible",
  "@type": "Organization",
  "logo": "https:\/\/builtvisible.com\/wp-content\/uploads\/2018\/09\/builtvisible-logo.png",
  "url": "http:\/\/builtvisible.com\/",
  "sameAs": [
    "https:\/\/twitter.com\/builtvisible", 
    "https:\/\/www.facebook.com\/builtvisible",
    "https:\/\/www.linkedin.com\/company\/builtvisible",
    "https:\/\/plus.google.com\/+SEOgadget\/posts"
  ],
  "contactPoint": [{
    "@type": "ContactPoint",
    "telephone": "+44 20 7148 0453",
    "email": "hello@builtvisible.com",
    "contactType": "sales"
  }]
}
// ]]>
</script>

Again, validating nicely:

organization-json-ld

And finally, an article:


<script type="application/ld+json">
// <![CDATA[ 
{ 
  "@context":"http:\/\/schema.org\/", 
  "name":"Implementing JSON-LD in WordPress", 
  "@type":"Article",
  "author":"Richard Baxter", 
  "ArticleSection":"Technical", 
  "datePublished":"2015-05-18 18:37:17", 
  "Publisher":"Builtvisible", 
  "url":"http:\/\/builtvisible.com\/implementing-json-ld-wordpress/" 
} 
// ]]>
</script>

Which validates nicely, here:

article-json-ld

Implementation

Save the following code as json-ld.php in your theme directory:

<?php 
// JSON-LD for WordPress Home Articles and Author Pages 
 // Stuff for any page 
 function get_post_data() { 
    global $post; 
    return $post; 
  } 
  // This has all the data of the post/page etc 
  $payload["@context"] = "http://schema.org/"; 
  // Stuff for any page, if it exists 
  $post_data = get_post_data(); 
  // Stuff for specific pages 
  $category = get_the_category(); 
  // This gets the data for the user who wrote that particular item 
  if (is_single()) { 
    $author_data = get_userdata($post_data->post_author); 
    $post_url = get_permalink(); 
    $post_thumb = wp_get_attachment_url(get_post_thumbnail_id($post->ID)); 
    $payload["@type"] = "Article"; 
    $payload["url"] = $post_url; 
    $payload["author"] = array( "@type" => "Person", "name" => 
    $author_data->display_name, ); 
    $payload["headline"] = $post_data->post_title; 
    $payload["datePublished"] = $post_data->post_date; 
    $payload["image"] = $post_thumb; 
    $payload["ArticleSection"] = $category[0]->cat_name; 
    $payload["Publisher"] = "Builtvisible"; 
  } 

  // We do all this separately so we keep the right things for organization together 
  if (is_front_page()) { 
    $payload["@type"] = "Organization"; 
    $payload["name"] = "Builtvisible"; 
    $payload["logo"] = "https:\/\/builtvisible.com\/wp-content\/uploads\/2018\/09\/builtvisible-logo.png"; 
    $payload["url"] = "http:\/\/builtvisible.com\/"; 
    $payload["sameAs"] = [
      "https:\/\/twitter.com\/builtvisible", 
      "https:\/\/www.facebook.com\/builtvisible", 
      "https:\/\/www.linkedin.com\/company\/builtvisible", 
      "https:\/\/plus.google.com\/+SEOgadget\/"
    ]; 
    $payload["contactPoint"] = [
      ["@type" => "ContactPoint", 
        "telephone" => "+44 20 7148 0453",
        "email" => "hello@builtvisible.com",
        "contactType" => "sales"
      ]
    ]; 
  }  
  // This gets the data for the user who wrote that particular item 
  if (is_author()) { 
  // Some of you may not have all of these data points in your user profiles - delete as appropriate 
  // fetch twitter from author meta and concatenate with full twitter URL 
    $author_data = get_userdata($post_data->post_author);
    $twitter_url = " https:\/\/twitter.com/"; 
    $twitterHandle = get_the_author_meta('twitter'); 
    $twitterHandleURL = $twitter_url . $twitterHandle; 
    $websiteHandle = get_the_author_meta('url'); 
    $facebookHandle = get_the_author_meta('facebook'); 
    $gplusHandle = get_the_author_meta('googleplus'); 
    $linkedinHandle = get_the_author_meta('linkedin'); 
    $slideshareHandle = get_the_author_meta('slideshare'); 
    $payload["@type"] = "Person"; 
    $payload["name"] = $author_data->display_name; 
    $payload["email"] = $author_data->user_email; 
    $payload["sameAs"] = array($twitterHandleURL, $websiteHandle, $facebookHandle, $gplusHandle, $linkedinHandle, $slideshareHandle); 
  } 
?>

Obviously you’ll have to edit our details out and yours in.

Also the usual disclaimers apply, use our work, but we can’t be held responsible for anything that breaks. Do check what data you have in your author_meta – we’ve added some extra user profile fields.

Then, add the following two lines of code in header.php as follows:


<?php include('json-ld.php'); ?>
<script type="application/ld+json">
// <![CDATA[
<?php echo json_encode($payload); ?>
// ]]
</script> 

So wonderful. My data is kept well away from my presentation layer. I’m a very happy man.


With all the new search result formats and devices, “search” for us may soon be about staying on top of new interfaces that require our content to be re-purposed in an alternative presentation layer. Think about that: Apple Watch doesn’t have a browser.

Our own websites may become end points that need an accessible data payload to be useful to search engines. I can’t help but feel that eventually we’ll be supplying our entire site content as JSON to make sure we still have access to a broad range of devices and organic and social channels, like answer boxes, instant articles and cards.

At Builtvisible, we’ve got a sense that the JSON-LD spec might be extended to include popular actions outside of Gmail and that publishers like ourselves will be expected to make the consumption of our content entirely possible without ever visiting the site. With actions like “buy” coming to the paid shopping model, it’s only a matter of time before the same options are presented to organic search users, and HTML begins to become an option, not a prerequisite to performing well in search.

Comments are closed.


Join the Inner Circle

Industry leading insights direct to your inbox every month.