Search

Adding Schema & Structured Data to WordPress

Structured data or schema are essentially HTML attributes or scripts that help search engines interpret the structure of specific content and understand how to display it correctly and prominently in search results (SERP’s).

Structured data is the standard format that search engines operate with, and they provide information about a specific page, helping search engines understand how to categorize that page.

For example, on a specific cooking recipe page, the information could include the ingredients, cooking time, desired temperature, calorie count, and more.

So, many of us have worked on WordPress websites or other projects where technical SEO was the first requirement, even before performing the process of On-page SEO.

These structured data are included in the execution of technical SEO for a website and can be crucial from this perspective, ultimately leading to better optimization and SEO performance.

Considering that not many bother to implement structured data on their websites, if done correctly, and assuming search engines decide to display them, you will have a certain advantage over your competitors – whether you’re managing a blog, selling products, advertising jobs, and so on.

In this guide, we will explain the concept behind structured data, look at possible formats, mention the advantages of using them, and then show how to add different types of data to WordPress websites without using plugins.

What are Structured Data?

Structured Data can be thought of as a treasury of words composed of attributes and values of HTML or scripts that succinctly describe the content of the document or page and even add specific details that might not appear to the visitor.

At its core, structured data is simply information that provides the lexicon and hierarchy, adding structure and details to the HTML Markup. That Markup goes into your website’s code and helps search engines crawl, index, and parse your site.

The idea of this lexicon, named Schema.org, was created through collaboration between Google, Microsoft, Yahoo, Yandex, and has been maintained by them as well as additional individuals from the W3C community.

You can actually see and participate in this community activity on the open community page.

I assume that you’ve likely encountered the term structured data when you’ve come across discussions about schema, as “structured data” is the most accurate expression to describe how those schemas work. So if you encounter the term structured data, know that it essentially refers to those schemas.

So, What Are Rich Snippets?

It might get a bit confusing, but to put it simply – schema or schema markup is the code that enables many of the features you see in search results when rich snippets are a prominent example of these features. In other words, rich snippets are essentially the result of using schema markup.

If Google’s algorithm feels that presenting additional information could be helpful for a specific search query, it will add or emphasize that information. This information is called rich snippets and is implemented by embedding schema on your site.

Here’s an example of search results with rich snippets, one displaying recipes and the other books:

Recipe Schema Example
Books Schema Example - Structured Data

Types of Schema Formats

Schemas can be presented in three ways: Microdata, JSON-LD, and RDFa. In this guide, we’ll focus on Microdata and JSON-LD since they are the most common. In fact, as we delve into examples and see how to add schema markup to your WordPress pages, we’ll concentrate solely on JSON-LD.

Let’s see how the code differs between Microdata and JSON-LD for a specific business displaying its opening hours. Before we present the differences, see an example of a Google search result for this business (not necessarily relevant to the time of writing this article):

Local Business Schema Markup

Notice how the address, phone number, and business hours appear in the search results. So here’s an example of how it’s done in both formats, noting that it’s just for demonstration purposes to show the code differences between the formats.

Using Microdata:

<div itemscope itemtype="http://schema.org/Pharmacy">
  <h1 itemprop="name">Philippa's Pharmacy</h1>
  <p itemprop="description">
    A superb collection of fine pharmaceuticals.
  </p>
  <p>Open: 
    <span itemprop="openingHours" content="Mo,Tu,We,Th 09:00-12:00">
      Monday-Thursday 9am-noon
    </span>
  </p>
</div>

Similarly, this can be done using JSON-LD:

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "Pharmacy",
  "name": "Philippa's Pharmacy",
  "description": "A superb collection of fine pharmaceuticals.",
  "openingHours": "Mo,Tu,We,Th 09:00-12:00"
}
</script>

Choosing Which Format to Use

The decision of which schema format to use is entirely individual preference, but if you look at Google’s documentation on structured data, you’ll find that it revolves largely around using JSON-LD.

So if you’re looking for higher potential to impact Google search results, using JSON-LD is likely a better starting point, and that’s also Google’s recommendation…

How Does Schema Affect SEO and Your Site’s Promotion?

We’re discussing schema because we care about how search engines interpret our site’s content. Hence, the question arises: does schema have a direct impact on our site’s ranking in search engines?

I think the answer isn’t exactly clear. Some experts who work at Google have in the past confirmed that schema doesn’t have a direct impact on your site’s ranking.

“If you add the relevant markup to your site pages, it doesn’t mean you’ll experience an improvement in your site’s ranking – but it helps Google and search engines understand your content better.”

At the same time, if Google better understands your content, it’s likely that you might appear in specific queries that you wouldn’t have without that schema. Furthermore, if your site’s link to a post or recipe is displayed differently or highlighted in search results due to schema usage, your click-through rate (CTR) is likely to be higher.

Therefore, I say that the answer is not unambiguous. Either way, the proper implementation of schema will not harm you and will likely improve the user experience. See in the following video what Matt Cutts has to say about the topic – he surely understands better than me:

What information can appear in structured data?

In Google’s guide to structured data, you’ll find the most extensive information on the subject. You can discover which types of data can be structured and even examples of how to do it.

Speaking of examples, for those who aren’t familiar with code, know that you can always use the Structured Data Markup Helper to mark up structured data directly on your site and get the appropriate code based on your markup.

Anyway, let’s try to summarize the possible types of data, and it’s worth mentioning that schema categorizes content by types. Here are most of the content types that Google identifies as of the time of writing this article:

  • Articles
  • Books
  • Courses
  • Datasets
  • Events
  • Job Posting
  • Local Businesses
  • Music
  • Podcasts
  • Products
  • Recipes
  • Reviews
  • TV & Movies
  • Fact Check

In addition to these content types, Google also checks structured data that enhances the user interface:

  • Breadcrumbs
  • Sitelinks Search Box
  • Corporate Contact Information
  • Logos
  • Social Profile Links
  • Carousels

You can certainly see that there are plenty of opportunities to influence search results, how they are displayed, and what is actually displayed.

How to Add Schema Markup to WordPress Sites

We’ve discussed the concept of schema and structured data so far and have seen how they contribute to optimization in search engines. But how do you work with them in practice and how do you add this structured data?

In this section, we’ll see how to add structured data using code, and the best way to demonstrate this is with live and concrete examples from this blog.

By the way, I assume some may wonder why not use SEO plugins that allow you to manage specific schema like Yoast or the Schema plugin. The truth is there are many other WordPress plugins that allow you to do this and these are legitimate options in many cases.

However, I’ve concluded that it’s not straightforward to achieve the required level of precision for specific content types in certain projects, such as business opening hours, local business contact details, etc.

Moreover, I always prefer to have complete control over what happens on sites I develop and not rely on plugins or external services (as much as possible). But I reiterate that this is entirely individual, and how you choose to do this is up to you.

By the way, it’s reasonable to assume that for each of those schemas I’m adding in this blog, there are plenty of possible parameters. Also, the schema and/or parameters I’ve chosen may not necessarily be relevant to you, so consult with an expert if needed…

It’s also important to adding structured data is merely a recommendation for search engines, and when you consider adding structured data to a particular page and wonder whether to add this information, consider this – if the same structured data were the only information the user saw on that page, would it contribute to them in any way?

Let’s see some examples. I’m not going to elaborate on why I’m adding them, but I assume that a look at the code will guide you and perhaps help you understand how to add schema to WordPress sites.

Adding BlogPosting Schema for Articles in the Blog

Here are examples of how I’m adding schema for various elements in the Savvy Blog. We’ll start with the BlogPosting schema, which is a more specific schema under the Article schema and is intended for all articles on this blog.

The way I do this is by adding JSON-LD to the head of the page in the following manner:

function json_ld_article() {
	
	// Schema.org JSON for BlogPosting

	// Only on single Posts & Snippets 
	if ( is_singular( 'post') || is_singular('snippet') ) {
		
		// We need access to the post
		global $post;
		setup_postdata($post);

		// Variables
		$logo = get_template_directory_uri() . '/images/site-logo.png';
		$logo_width = 82;
		$logo_height = 60; // must be 60px and width <=600
		$excerpt = get_the_excerpt();
		$image = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'full');

		// Open script
		$html = '<script type="application/ld+json">';

		$html .= '{';
		$html .= '"@context": "http://schema.org",';
		$html .= '"@type": "BlogPosting",';


		$html .= '"mainEntityOfPage": {';
			$html .= '"@type": "WebPage",';
			$html .= '"@id": "' . get_permalink() . '"';
		$html .= '},';

		// ... (rest of the schema markup)

		$html .= '}';

		// Close script
		$html .= '</script>';

		echo $html;
	}
}
add_action('wp_footer', 'json_ld_article');

Notice that for every schema we add, there will be the @type parameter indicating the type of schema being used. You can also see that I’m using basic WordPress functions to specify the image, link, title, author of the article, date, and more.

I don’t intend to elaborate beyond the code’s essence, but note that there is a condition at the beginning stating that this code will be added only to posts and snippets on the site using the is_single() function.

If I haven’t mentioned, there is also a certain validity to how you write the schema and the format of the data you input, such as the size of the image you’re adding or the way you display elements of a specific recipe. Help is also available in this case from Google’s built-in data guide.

It’s also possible that the code I’m presenting in the guide is not perfect, so if you have comments, corrections, and improvement ideas, I’d appreciate it if you shared them in the comments below. We learn from your feedback just as much…

Adding Person Schema

This is a Person schema describing my name and several links to my social networks (referring to me personally as an individual and not as a company). This is just an example and is not implemented in this blog. Here’s the code you can use:

function json_ld_person() {

	// Schema.org JSON for Person

	$html = '<script type="application/ld+json">';

	$html .= '{';
	$html .= '"@context": "http://schema.org",';
	$html .= '"@type": "Person",';
	$html .= '"name": "Roee Yossef",';
	$html .= '"url": "' . home_url() . '",';
	$html .= '"sameAs" : [';
	$html .= '"https://www.facebook.com/roee.yossef/",';
	$html .= '"https://twitter.com/RoeeYossef",';
	$html .= '"https://plus.google.com/+RoeeYossef",';
	$html .= '"https://www.linkedin.com/in/roeeyossef/"';
	$html .= ']}';

	// Close script
	$html .= '</script>';

	echo $html;
}
add_action('wp_head', 'json_ld_person');

Adding Organization Schema

This schema is of type Organization and relates to the company’s blog. Similar to Person, in this code, I specify the links to the social networks of the company’s blog as well as the logo and the blog’s name.

The choice of whether to add a Person or Organization schema depends on your website’s nature and is up to you. As far as I know, the correct approach is to add only one of the two options. If you are familiar with Yoast, you probably know that it also allows you to choose only one option, either a company or an individual.

function json_ld_organization() {

	// Schema.org JSON for Organization

	$logo = get_template_directory_uri() . '/images/site-logo.png';
	$logo_width = 82;
	$logo_height = 60;
	// Open script
	$html = '<script type="application/ld+json">';

	$html .= '{';
	$html .= '"@context" : "http://schema.org",';
	$html .= '"@type" : "Organization",';
	$html .= '"name" : "' . get_bloginfo( 'name' ) . '",';
	$html .= '"url" : "' . home_url() . '",';
	$html .= '"logo": {';
	$html .= '"@type": "ImageObject",';
	$html .= '"url": "' . $logo . '",';
	$html .= '"width": ' . $logo_width . ',';
	$html .= '"height": ' . $logo_height;
	$html .= '},';
	$html .= '"sameAs" : [';
	$html .= '"https://www.facebook.com/savvy.wordpress/",';
	$html .= '"https://twitter.com/Wordpress_Savvy",';
	$html .= '"https://plus.google.com/b/105571002353816264757/+SavvyCoIlSite"';
	$html .= ']}';

	// Close script
	$html .= '</script>';

	echo $html;
}
add_action('wp_head', 'json_ld_organization');

Note that Organization schema should not be embedded on every page.

Adding WebSite Schema

This is a WebSite schema describing the website’s name (Savvy Blog), an alternative name, and its URL. This schema is broad and covers the entire site.

function json_ld_website() {

	// Schema.org JSON for WebSite

	$html = '<script type="application/ld+json">';

	$html .= '{';
	$html .= '"@context": "http://schema.org",';
	$html .= '"@type": "WebSite",';
	$html .= '"name": "' . get_bloginfo( 'name' ) . '",';
	$html .= '"alternateName": "Savvy Blog",';
	$html .= '"url": "' . home_url() . '"';
	$html .= '}';

	// Close script
	$html .= '</script>';

	echo $html;
}
add_action('wp_head', 'json_ld_website');

Adding BreadCrumbs Schema

This is a BreadCrumbs schema responsible for the breadcrumbs displayed when a result from this blog appears in search engines.

BreadCrumbs Savvy BlogThe code in this case is slightly different from the code necessary for category breadcrumbs as in this case we use a different taxonomy.

function json_ld_breadcrumbs() {

	// Schema.org JSON for breadcrumbs

	if ( is_singular( 'post') || is_singular('snippet') ) {

		global $post;
		$post_terms = wp_get_object_terms($post->ID, 'taxonomy', array('fields'=>'ids'));
		$term_name = get_term( $post_terms[0], 'taxonomy') ;

		$html = '<script type="application/ld+json">';

		$html .= '{';
		$html .= '"@context": "http://schema.org",';
		$html .= '"@type": "BreadcrumbList",';
		$html .= '"itemListElement": [';
		$html .= '{';
		$html .= '"@type": "ListItem",';
		$html .= '"position": "1",';
		$html .= '"item" : {';
		$html .= '"@id" : "' . get_site_url() . '",';
		$html .= '"name": "' . get_bloginfo( 'name' ) . '"';
		$html .= '}},';
		$html .= '{';
		$html .= '"@type": "ListItem",';
		$html .= '"position": "2",';
		$html .= '"item" : {';
		$html .= '"@id" : "' . $term_name->term_id . '",';
		$html .= '"name" : "' . $term_name->name . '"';
		$html .= '}},';
		$html .= '{';
		$html .= '"@type": "ListItem",';
		$html .= '"position": "3",';
		$html .= '"item" : {';
		$html .= '"@id" : "' . get_permalink() . '",';
		$html .= '"name" : "' . get_the_title() . '"';
		$html .= '}}]}';
		// Close script
		$html .= '</script>';

		echo $html;
	}

}

add_action( 'wp_head', 'json_ld_breadcrumbs' );

Please note that since I use Yoast on Savvy Blog, and since Yoast automatically adds schema markup (according to the settings you define in the plugin), I had to filter the JSON-LD code that the Yoast plugin adds.

For Yoast versions below 11.0, you can remove the schema using the following filter:

function savvy_remove_yoast_json($data){
	$data = array();
	return $data;
}
add_filter('wpseo_json_ld_output', 'savvy_remove_yoast_json', 10, 1);

For Yoast versions higher than 11.0, you can use this filter:

add_filter( 'wpseo_json_ld_output', '__return_false' );

With that, we’re done. If you’d like, check one of the posts on this blog with the Structured Data Testing Tool to see those schemas mentioned in this guide…

Summary

The choice of how and which built-in data / schema to add to your site is relevant to your site’s content and is up to you.

You can do this through plugins, using code as demonstrated in this guide, and I’ve even seen those using Advanced Custom Fields to allow clients to edit that built-in data easily (which is very true in the case of a recipe site, for example).

Either way, I believe this guide sheds some light on built-in data, schema, and Rich Snippets on WordPress sites, and I’m sure I’ll expand on this topic in the future.

So, get to work, help search engines, and provide a better user experience for your visitors.

If you have a recipe site, take a look at the next post describing how and why to add built-in data for recipe sites.

I’d be happy if you shared the post in relevant places, and of course, I’d love to hear comments and suggestions, especially on the SEO experts’ side… 🙂

Roee Yossef
Roee Yossef

I develop websites & custom WordPress themes by design. I love typography, colors & everything between, and aim to provide high performance, seo optimized websites with a clean & semantic code.

0 Comments...

Leave a Comment

Quick Navigation

Up!
Blog