WooCommerce Schema Markup: Products, Reviews & Rich Results

Last Updated: February 25, 2026 · 14 min read

WooCommerce ships with basic Product schema out of the box — but "basic" is the key word. The default output misses star ratings from native reviews, shippingDetails, merchant return policies, and correct handling of variable products. This guide shows exactly what WooCommerce includes by default, what's missing, and how to fix every gap.

⚠️ WooCommerce default schema has critical gaps

✅ What WooCommerce includes

  • • Product name, description, image
  • • Price and currency
  • • SKU
  • • Basic availability

❌ What WooCommerce misses

  • • AggregateRating (star ratings)
  • • shippingDetails (delivery time/cost)
  • • hasMerchantReturnPolicy
  • • priceValidUntil
  • • Brand and GTIN/MPN

1. Adding the Missing Properties

1. Star Ratings (AggregateRating)

WooCommerce collects product reviews but does not add AggregateRating schema by default. Add this to your functions.php:

add_filter( 'woocommerce_structured_data_product', function( $markup, $product ) {
  $review_count = $product->get_review_count();
  $rating       = $product->get_average_rating();

  if ( $review_count > 0 && $rating > 0 ) {
    $markup['aggregateRating'] = array(
      '@type'       => 'AggregateRating',
      'ratingValue' => number_format( (float) $rating, 1 ),
      'reviewCount' => $review_count,
      'bestRating'  => '5',
      'worstRating' => '1',
    );
  }
  return $markup;
}, 10, 2 );

2. Shipping Details

Google's product rich results increasingly show delivery estimates. Add shippingDetails to surface this in search:

add_filter( 'woocommerce_structured_data_product', function( $markup, $product ) {
  $markup['offers']['shippingDetails'] = array(
    '@type'       => 'OfferShippingDetails',
    'shippingRate' => array(
      '@type'    => 'MonetaryAmount',
      'value'    => '0',
      'currency' => get_woocommerce_currency(),
    ),
    'shippingDestination' => array(
      '@type'          => 'DefinedRegion',
      'addressCountry' => 'US',
    ),
    'deliveryTime' => array(
      '@type'        => 'ShippingDeliveryTime',
      'handlingTime' => array(
        '@type'    => 'QuantitativeValue',
        'minValue' => 0,
        'maxValue' => 1,
        'unitCode' => 'DAY',
      ),
      'transitTime' => array(
        '@type'    => 'QuantitativeValue',
        'minValue' => 3,
        'maxValue' => 7,
        'unitCode' => 'DAY',
      ),
    ),
  );
  return $markup;
}, 10, 2 );

3. Variable Products

Variable product challenge

WooCommerce outputs different prices for variable products ("from £19.99") which Google may flag as ambiguous. Best practice: output a single AggregateOffer with lowPrice and highPrice.

// For variable products, replace offers with AggregateOffer
if ( $product->is_type( 'variable' ) ) {
  $markup['offers'] = array(
    '@type'         => 'AggregateOffer',
    'lowPrice'      => wc_format_decimal( $product->get_variation_price( 'min' ) ),
    'highPrice'     => wc_format_decimal( $product->get_variation_price( 'max' ) ),
    'priceCurrency' => get_woocommerce_currency(),
    'offerCount'    => count( $product->get_available_variations() ),
  );
}

2. WooCommerce Schema Plugins Compared

PluginStar RatingsShippingDetailsReturn PolicyPrice
WooCommerce (default)Free
Yoast SEO + WooCommerce⚠️ PartialFree / £79 yr
RankMath Pro$59/yr
Schema Pro$79/yr
Structured Data for WooCommerce⚠️ Partial$49/yr

3. Return Policy Schema for WooCommerce

Google’s product rich results include return policy information when present. This information helps buyers make purchase decisions directly in the SERP. Add it to your WooCommerce product schema:

add_filter( 'woocommerce_structured_data_product', function( $markup, $product ) {
  $markup['offers']['hasMerchantReturnPolicy'] = array(
    '@type'                    => 'MerchantReturnPolicy',
    'applicableCountry'        => 'US',
    'returnPolicyCategory'     =>
      'https://schema.org/MerchantReturnFiniteReturnWindow',
    'merchantReturnDays'       => 30,
    'returnMethod'             =>
      'https://schema.org/ReturnByMail',
    'returnFees'               =>
      'https://schema.org/FreeReturn',
  );
  return $markup;
}, 10, 2 );

4. Testing WooCommerce Schema After Implementation

1

After installing a plugin or adding functions.php code, clear your cache fully (page cache, object cache, CDN cache). Cached responses will serve the old schema.

2

Paste a specific product page URL into SchemaValidator.org. Confirm that AggregateRating, shippingDetails, and hasMerchantReturnPolicy are detected as separate entities within the Product schema.

3

Run the same URL through Google's Rich Results Test. Look for the 'Product' rich result preview showing star ratings and price. If stars don't appear, AggregateRating is missing or has a validation error.

4

Submit the product URL to Google Search Console via URL Inspection → Request indexing. This accelerates Googlebot picking up the new schema.

5

After 2–3 weeks, check GSC → Enhancements → Product errors. The count of valid products should match your product catalogue size.

5. WooCommerce Schema and Google Merchant Center

⚠️ Schema ≠ Google Merchant Center feed

WooCommerce product schema helps with organic Product rich results, but it is separate from Google Merchant Center (GMC), which powers Google Shopping ads and free product listings. You need both:

Schema markup does:

  • • Enables Product rich results in organic search
  • • Shows star ratings in SERP
  • • Supports AI Overview product citations

Google Merchant Center does:

  • • Powers Google Shopping carousel
  • • Enables free product listings across Google
  • • Feeds Google Ads product campaigns

Frequently Asked Questions

Does WooCommerce automatically output valid Product schema?

WooCommerce outputs basic Product schema that covers name, description, image, price, and availability. However, this is insufficient for Google's full Product rich result. Critical fields like AggregateRating (star ratings), shippingDetails, hasMerchantReturnPolicy, priceValidUntil, Brand, and GTIN/MPN are all missing by default. You need either a schema plugin or custom functions.php code to fill these gaps.

Why aren't my WooCommerce star ratings appearing in search results?

Because WooCommerce does not output AggregateRating schema by default, even though it collects product reviews. Google cannot infer ratings from on-page display — the data must be explicitly in the structured data. You need to either add the functions.php filter shown in this guide, use a plugin like RankMath Pro or Schema Pro, or install the Structured Data for WooCommerce plugin.

What is the difference between WooCommerce schema and a Google Merchant Center feed?

They serve different purposes. WooCommerce Product schema enables organic Product rich results in regular Google Search (showing stars, prices, availability below your link). Google Merchant Center (GMC) is a separate data feed that powers Google Shopping carousel, free product listings across Google surfaces, and Google Ads shopping campaigns. You need both independently — schema does not feed GMC and GMC data does not create rich results in organic search.

Do I need a premium plugin or can I just use functions.php?

For sites with a developer, functions.php is free and gives you precise control over exactly what schema is output. The code examples in this guide cover the main gaps. For non-developers or large catalogues with complex logic, a plugin like RankMath Pro ($59/yr) or Schema Pro ($79/yr) is faster and handles edge cases like variable products, sale prices, and conditional shipping automatically.

How do I handle variable products with multiple price points in schema?

Replace the standard Offer with AggregateOffer using lowPrice and highPrice. This tells Google the price range rather than a single ambiguous price. Include offerCount to convey the number of variants. Avoid outputting a single price for variable products — Google may flag this as misleading if a user sees a different price on the page depending on which variant they select.

Why does Google Search Console report a missing field: priceValidUntil for my products?

GSC flags this as a recommended (not required) field. Google uses priceValidUntil to determine whether a price is current — without it, Google may treat the price as potentially stale and display it less prominently in product rich results. Set it to a reasonable date in the future (e.g. end of current year or 90 days out). For products with permanently valid pricing, set it 1–2 years ahead and update periodically.

Can I run both Yoast WooCommerce and RankMath Pro for product schema simultaneously?

No — running two SEO plugins that both output Product schema will create duplicate structured data blocks on the page, which can confuse Google and may cause validation errors. Choose one plugin and disable the schema output of the other. In Yoast, you can disable specific schema types under SEO → Search Appearance → Schema. In RankMath, you can set per-post-type schema rules.

How do I verify that my WooCommerce schema changes are actually working?

Paste a specific product page URL into SchemaValidator.org and look for AggregateRating, shippingDetails, and hasMerchantReturnPolicy nested within the Product object. Then run the same URL through Google's Rich Results Test and look for a Product rich result preview with star display. Finally, check Google Search Console → Enhancements → Products after 2–3 weeks to see if the count of valid product URLs matches your catalogue.

Validate Your WooCommerce Product Schema

Check your product pages for missing AggregateRating, shippingDetails, and rich result eligibility.

Validate Product Schema →