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 snippet | Merchant listing | |
|---|---|---|
| Required | name, and one of review, aggregateRating or offers | name, image and offers, with a price and a priceCurrency in the offer |
| Recommended, among others | aggregateRating, review, and in the offer availability, priceCurrency and priceValidUntil | brand.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.
<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.
| Property | Comes from | Left out when |
|---|---|---|
name, url | The product's name and address | Never |
description | "Product short description", or the main description if that is empty | Never, though it can be empty |
image | The product image | The product has no image |
sku | The SKU field. If it is empty, WooCommerce uses the product's ID number | Never |
gtin | The "GTIN, UPC, EAN, or ISBN" field on the Inventory tab | The value is not 8, 12, 13 or 14 digits long |
brand | The brand assigned to the product. With more than one, the first by name | No brand is assigned |
offers | The price, the store's currency and the stock status. WooCommerce adds priceValidUntil and names the store as seller | The product has no price |
aggregateRating, review | The average rating, the number of reviews, and the five most recent rated reviews | No customer has rated the product, or reviews or star ratings are switched off |
- A product with no price and no rated review gets no
Productblock at all. - A variable product whose variations differ in price gets an
AggregateOfferwith 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.
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.
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.
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
imageout when the product has none.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.
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
Organizationmarkup 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.
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;
}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
Productwith the filter that decides which types go on a page.
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' ) );
}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.
- ResourceWooCommerce checkout is down: a runbook
- Cost guideWooCommerce maintenance cost: why a store costs more, and what the extra should buy
- ResourceWooCommerce sale readiness checklist: Black Friday or any big sale
- Error fixHow to fix WooCommerce payment gateway errors
- Error fixHow to fix a WooCommerce checkout that is not working
- GuideHow to speed up a WooCommerce store

