Skip to content

WooCommerce schema markup: what your store outputs and how to fill the gaps

WooCommerce prints product structured data on its own, with the name, price, stock status and rating. Test a product page with Google's Rich Results Test, fix any error, then add what is missing, such as a GTIN, a brand, and shipping and return details. Markup does not guarantee a rich result.

By
WP Ministry
Published

In short

  • WooCommerce adds Product markup to a product page that has a price or a rated review. No plugin is needed for that.
  • An error in Google's Rich Results Test makes the item invalid. A warning leaves it valid.
  • The usual gaps are a GTIN, a brand, reviews, and shipping and return details.
  • Fill a gap in WooCommerce's own fields first, then with a plugin, then with the woocommerce_structured_data_product filter.
  • Mark up only what a visitor can see on the page. Never add a rating the page does not show.
  • Markup makes a page eligible for a rich result. Google does not guarantee one.

WooCommerce already puts structured data on a product page. It is a block of JSON-LD that names the product as a schema.org Product and gives its price, its stock status and, when customers have rated it, its rating. That is what Google reads to show a product rich result, so the work is to check what your store prints and to fill in what is missing.

Markup makes a page eligible for a rich result. Google says plainly that it does not guarantee one, and its documentation for product markup promises nothing about where the page ranks.

What a product rich result is

A rich result is a search result that shows more than a title and a description. For products, Google's documentation describes two kinds.

  • A product snippet is a text result with extra product information, such as ratings, review information, price and availability.
  • A merchant listing is for a page where a shopper can buy the product. It can show price, availability, and shipping and return information, in places such as the shopping knowledge panel, Google Images and popular product results.

A store's product page can qualify for both. Google notes that a page with the properties a merchant listing requires can be eligible for product snippets too. Only a page about one product, or the variants of one product, qualifies. A category page does not.

Product snippetMerchant listing
Requiredname, and one of review, aggregateRating or offersname, image and offers, with a price and a priceCurrency in the offer
Recommended, among othersaggregateRating, review, and in the offer availability, priceCurrency and priceValidUntilbrand.name, a GTIN, mpn, sku, description, aggregateRating, review, and in the offer availability, shippingDetails, hasMerchantReturnPolicy and itemCondition

What WooCommerce outputs on its own

WooCommerce builds the markup while it draws the product page and prints it near the end of the page, in the footer. To see it, open a product page, view the page source, and search for application/ld+json.

html
<script type="application/ld+json">{"@context":"https://schema.org/","@type":"Product", ... }</script>

The block is part of the HTML the server sends, which is where Google recommends a store put its product markup. On some pages the Product sits inside an @graph list beside a BreadcrumbList.

This is what WooCommerce 11.1 puts in the Product, and where each value comes from.

PropertyComes fromLeft out when
name, urlThe product's name and addressNever
description"Product short description", or the main description if that is emptyNever, though it can be empty
imageThe product imageThe product has no image
skuThe SKU field. If it is empty, WooCommerce uses the product's ID numberNever
gtinThe "GTIN, UPC, EAN, or ISBN" field on the Inventory tabThe value is not 8, 12, 13 or 14 digits long
brandThe brand assigned to the product. With more than one, the first by nameNo brand is assigned
offersThe price, the store's currency and the stock status. WooCommerce adds priceValidUntil and names the store as sellerThe product has no price
aggregateRating, reviewThe average rating, the number of reviews, and the five most recent rated reviewsNo customer has rated the product, or reviews or star ratings are switched off
  • A product with no price and no rated review gets no Product block at all.
  • A variable product whose variations differ in price gets an AggregateOffer with the lowest and highest price.
  • WooCommerce's product markup has no mpn, shipping details, return policy or item condition.

If a product page has a price and still shows no Product block, look at its template. WooCommerce gathers the data on an action its own product template runs, woocommerce_single_product_summary. A custom template that never runs it leaves WooCommerce nothing to print.

Test one product page

Pick a product that has a price, an image and at least one review, so that every part of the markup is present.

  1. Step 1: Run the page through the Rich Results Test

    Open Google's Rich Results Test and enter the full address of the product page. The page has to be reachable without logging in. To check a change before it is live, choose "Code" in place of "URL" and paste the markup.

  2. Step 2: Read which results were found

    The test lists each kind of rich result it found on the page, and the items under each. For a store you should see product snippets and merchant listings. A status such as "N valid item(s) detected" means nothing blocks the item.

  3. Step 3: Fix errors first

    An item with an error is invalid. Search Console calls this a critical issue, and an invalid item cannot appear as a rich result. Open the item to see which property is at fault. With WooCommerce's own markup, look at the product before the code: a merchant listing requires an image, for example, and WooCommerce leaves image out when the product has none.

  4. Step 4: Then weigh the warnings

    An item with warnings is still valid. A warning names a recommended property that is absent. Google's advice is that a few complete and accurate recommended properties are worth more than every possible one.

  5. Step 5: Compare the values with the page

    Check that the price, the stock status and the rating in the markup are the ones a visitor sees. Google requires structured data to be a true representation of the page.

Once Google has crawled the store, Search Console shows two reports under Shopping, one for product snippets and one for merchant listings. Each has a table named "Why items are invalid" and one named "Improve item appearance". A report appears only after Google has found valid markup of that kind, and it shows a sample of items, not every one.

Fill in what is missing

Work in this order: a field WooCommerce already has, then a plugin, then code.

A GTIN, a brand and a part number

  • GTIN. Edit the product, open the Inventory tab and fill in "GTIN, UPC, EAN, or ISBN" with the number from the barcode. WooCommerce strips everything but digits and adds the value to the markup only if 8, 12, 13 or 14 digits remain.
  • Brand. Go to Products > Brands to create the brand, then choose it in the "Product brands" panel when you edit the product. Brands are part of WooCommerce itself. Google asks for at most one brand name, and where a product has more than one, WooCommerce's markup takes the one whose name comes first in the alphabet.
  • Part number. WooCommerce has no field that feeds mpn. A plugin or the filter below can add it.

If a product has no GTIN, leave the field empty. Do not invent a number.

Ratings and reviews

Rating markup appears when three things are true: "Enable product reviews" and "Enable star rating on reviews" are both selected under WooCommerce > Settings > Products, and at least one customer has rated the product.

A product with a price and no reviews is still eligible for a product snippet, because Google requires only one of review, aggregateRating and offers. Its documentation says the test may show a warning in that case. The answer is real reviews from customers, never a rating written into the markup.

Shipping and returns

Google recommends stating these once for the whole business and not on every product. There are three ways to do it.

  • Settings in Search Console. Under Settings > Shopping > Shipping and returns you can enter delivery times, shipping costs, the return window and return costs. Google approves shipping details automatically and verifies a return policy by hand, so a new return policy waits as pending first.
  • Google Merchant Center, if the store has an account.
  • Markup on one page. Put the shipping and return policy under Organization markup on the page that describes your policy. Google says it does not need to be on every page.

Where more than one is present, Google puts settings in Merchant Center or Search Console ahead of markup on the site. Use shippingDetails or hasMerchantReturnPolicy on a single offer only for a product whose terms differ from the store's standard ones.

What an SEO plugin adds

Some SEO plugins build on WooCommerce's markup instead of writing a second set. Yoast's add-on for stores, Yoast WooCommerce SEO, is one example. Its documentation says it alters the Product piece, applies its own validation to each value WooCommerce supplies, sets brand and manufacturer from taxonomies you choose, and stitches the offers, reviews and rating into the graph Yoast SEO outputs. It also adds fields for product identifiers on a Yoast SEO tab in the product data box.

Before you install a plugin for this, read its documentation for two things: which properties it adds, and whether it works with WooCommerce's markup or beside it. WordPress vs Shopify for SEO covers what an SEO plugin does for the rest of a store.

Add a property with code

WooCommerce passes the finished Product array through a filter, woocommerce_structured_data_product, with the product as the second argument. Its own Brands feature uses the same filter to add brand.

This example adds mpn. It reads the value from a product attribute named MPN, so add that attribute to the product first and select "Visible on the product page". The part number is then on the page for visitors as well as in the markup.

functions.php
add_filter( 'woocommerce_structured_data_product', 'example_add_mpn_to_product_markup', 10, 2 );

function example_add_mpn_to_product_markup( $markup, $product ) {
	if ( ! $product instanceof WC_Product ) {
		return $markup;
	}

	$mpn = $product->get_attribute( 'MPN' );

	if ( '' !== $mpn && empty( $markup['mpn'] ) ) {
		$markup['mpn'] = $mpn;
	}

	return $markup;
}
Goes in a child theme's functions.php, or in a small plugin of your own.

Give the attribute one value. If it holds several, WooCommerce returns them joined by commas, and that is not a part number.

Put the code in a child theme so that a theme update does not remove it. How to create a WordPress child theme shows how to make one. A mistake in functions.php can stop the whole site from loading, so make the change on a staging copy first, or be ready to remove the lines over SFTP. If you would rather not edit code, our WooCommerce maintenance service is a care plan for a store that includes 5 hours a month of fixes and edits.

To check it, clear any page cache, reload the product page, and look for "mpn" in the JSON-LD block. Then run the page through the test again. To undo it, delete the lines.

Two sets of markup for one product

A second plugin or the theme can write its own Product block beside WooCommerce's. A reviews plugin or a schema plugin may do this. The two blocks then describe one product twice, and they can disagree: one has the price, the other has the rating, or each has a different price.

To find it, search the page source for "@type":"Product" and count the matches, allowing for spaces around the colon. The Rich Results Test shows the same thing as two items under one result type, each with its own errors and warnings.

To fix it, keep one set.

  • Look for a setting first. If one of the two plugins has a switch for its product markup, turn off the block that is less complete.
  • Do not strip WooCommerce's markup from under a plugin that builds on it. A plugin of that kind, as Yoast WooCommerce SEO describes itself, works from those values.
  • If the other plugin writes a complete block of its own and has no switch, you can stop WooCommerce printing its Product with the filter that decides which types go on a page.
functions.php
add_filter( 'woocommerce_structured_data_type_for_page', 'example_remove_wc_product_markup' );

function example_remove_wc_product_markup( $types ) {
	return array_diff( $types, array( 'product' ) );
}
Removes WooCommerce's own Product markup. Its breadcrumb markup stays.

Run the test afterwards. It should show one product item, with the price and rating a visitor sees.

What structured data cannot do

  • It does not guarantee a rich result. Google's guidelines say structured data enables a feature and does not guarantee that it appears.
  • It is not a way to move up the results. Google's product documentation describes what a result can show and says nothing about position. Where its guidelines do mention ranking, it is to say that a manual action for structured data costs a page its rich results and does not affect how it ranks.
  • It cannot describe what the page does not show. Google's rule is not to mark up content that is not visible to readers. A rating in the markup has to be on the page, with the reviews behind it.
  • It cannot borrow reviews. Google says not to aggregate reviews or ratings from other websites, and not to include fake reviews or ones written for a reward that is not disclosed. Breaking these rules can bring a manual action.
  • It does not fix a slow or broken product page. How to speed up a WooCommerce store covers the first of those.

Common questions

Does schema markup improve my rankings?

Google's documentation for product markup does not say so. It describes markup as a way to make a page eligible for a richer result, and it does not guarantee that result. Treat markup as a way to describe your products accurately, not as a ranking method.

The test warns that my product has no review or rating. Is that a problem?

No. A product snippet needs only one of a review, a rating or an offer, and a product with a price has an offer. The warning goes away when customers leave rated reviews. Do not add a rating by hand to clear it.

Can reviews on my own product pages earn stars?

They can be marked up, and WooCommerce does it for you. Google's rule against reviews that a business controls about itself applies to LocalBusiness and Organization markup, which is a rating of the business. A customer's review of a product is a different thing. Stars remain Google's decision either way.

Do I need Google Merchant Center as well?

Not for the markup to work. Google says that providing both structured data on your pages and a Merchant Center feed gives a store the most ways to be eligible, and that some results combine the two. A store can start with markup alone.

More on this subject

Not sure what is wrong?

Tell us what you see. We reply with the cause and a fixed quote, and the diagnosis is free.