search

How to Add Schema & Structured Data to Your WordPress Site

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 Is Structured Data?

Structured data is a vocabulary of HTML attributes and values (or JSON scripts) that describe page content in a format search engines can parse. This markup goes into your site’s code and helps search engines crawl, index, and understand your content.

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.

The terms “structured data” and “schema” are often used interchangeably. Schema.org defines the vocabulary, while structured data is the broader concept of marking up content in a machine-readable format.

So, What Are Rich Snippets?

Schema markup is the code that powers enhanced search result features. Rich snippets are the visible result of using schema markup – they appear when Google decides that extra information would help users for a specific query.

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

Schema Formats: Microdata vs JSON-LD

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

Google’s structured data documentation recommends JSON-LD as the preferred format. JSON-LD is easier to maintain because it lives in a separate <script> tag and does not mix with your HTML markup.

How Schema Affects SEO

Does schema directly improve rankings? The answer is nuanced. Google has stated that structured data is not a direct ranking factor.

“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.”

However, schema helps Google surface your content in rich results, which can significantly increase your click-through rate (CTR). Pages with rich results can see CTR increases of 20-40%. Proper schema implementation will not hurt your rankings and is likely to improve visibility and user experience.

Supported Schema Types

The Google Search Gallery lists all supported schema types with implementation examples. You can also use the Structured Data Markup Helper to generate markup visually.

Here are the main content types Google supports:

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

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

Adding Schema Markup to WordPress

Below are code examples showing how to add JSON-LD schema to WordPress using PHP. These examples are from this blog and demonstrate the approach for different schema types.

SEO plugins like Yoast handle schema automatically and are a valid option for most sites. However, custom code gives you full control over the output – useful when you need precision for specific content types like local business hours or custom post types.

Note: The parameters shown below may not be relevant to your site. Consult the Google Search Gallery for the full list of supported properties for each schema type.

Structured data is a recommendation for search engines, not a guarantee of display. When deciding what to mark up, ask yourself: if this structured data were the only information a user saw, would it be useful?

Here are the code examples:

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');

Each schema uses the @type parameter to specify its type. The code uses standard WordPress functions like get_the_title(), get_permalink(), and get_the_author() to populate the schema dynamically. The is_singular() condition ensures the markup only loads on the relevant pages.

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://x.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://x.com/Wordpress_Savvy"';
	$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 Blog

The 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' );
Important: If you use Yoast SEO (or any SEO plugin that generates schema), you may need to disable its built-in schema output to avoid duplicate or conflicting markup. Yoast versions 11.0 and above use a different API.

Since Yoast automatically adds schema markup based on your plugin settings, you may need to filter its JSON-LD output.

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, the code examples are complete. You can validate your schema using the Rich Results Test or the Schema Markup Validator.

FAQs

Which schema format should I use - JSON-LD or Microdata?
JSON-LD is recommended by Google and is easier to implement and maintain. It lives in a separate script tag, so it does not mix with your HTML markup. Microdata still works, but JSON-LD is the industry standard for new implementations.
Does structured data directly improve search rankings?
Structured data is not a direct ranking factor according to Google. However, it enables rich results (star ratings, FAQ dropdowns, recipe cards) that increase click-through rates by 20-40%. Higher CTR can indirectly signal relevance and improve rankings over time.
Should I use a plugin or custom code for schema?
For most sites, an SEO plugin like Yoast handles common schema types automatically. Custom code is better when you need precise control over the output - for example, local business hours, custom post type mappings, or specific properties that plugins do not support.
How do I test if my schema markup is correct?
Use the Google Rich Results Test (search.google.com/test/rich-results) to check which rich result types your page qualifies for. For full schema validation, use the Schema Markup Validator (validator.schema.org). Also monitor the Enhancements section in Google Search Console for ongoing issues.
Can I have multiple schema types on the same page?
Yes. A single page can include multiple schema types - for example, Article, BreadcrumbList, and FAQPage on a blog post. Each can be in its own JSON-LD script tag. Just make sure each schema accurately describes content that actually exists on the page.

Summary

Structured data helps search engines understand your content and can unlock rich results that boost CTR. JSON-LD is the recommended format and can be added to WordPress using PHP functions hooked to wp_head or wp_footer.

Start with the essentials – Article, Organization, BreadcrumbList, and WebSite schema – then expand to content-specific types like FAQPage, HowTo, or Product as needed. Use the Rich Results Test to validate your markup.

For recipe-specific schema, see our guide on adding structured data to recipe sites. You can also use Advanced Custom Fields to let clients edit schema properties through the WordPress admin.

Schema is also becoming critical for AI search. To learn which types matter most for AI Overviews and generative search engines, see my guide on schema markup for AI search.

Join the Discussion
0 Comments  ]

Leave a Comment

To add code, use the buttons below. For instance, click the PHP button to insert PHP code within the shortcode. If you notice any typos, please let us know!

Savvy WordPress Development official logo