ShipworkSite inspection
Checks

Crawlability

PaginationAre paginated pages set up right?Internal searchIs site search eating crawl budget?URL parametersAre parameters creating duplicates?Log analyserWhat does Googlebot actually crawl?Robots builderNeed a robots.txt file?Soft 404sAre pages “not found” but returning 200?JavaScriptCan crawlers see it without running JS?FreshnessIs my site quietly going stale?Robots.txtDoes robots.txt say what I think?

Indexing

Sitemap lastmodAre my sitemap dates valid?SitemapIs my sitemap actually fetchable?IndexingIs Google allowed to index my pages?CanonicalsIs Google indexing the wrong URL?Index signalsDo sitemap and index signals agree?Sitemap generatorNeed a sitemap.xml for my site?Bulk URL statusWhere does each of these URLs really land?Redirect builderNeed the redirect rules?RedirectsAre my URLs answering directly, over HTTPS?

On-page

Keyword ideasWhat are people searching for?SERP previewHow does my page look in Google?Content qualityAre your pages too thin or too alike?Image weightAre images slowing the page?CannibalizationAre pages competing with each other?On-page checkDoes the page use its target phrase?ImagesAre my images accessible and loading?Meta tag builderWhat should my title and share tags say?DuplicatesDo my pages compete for one query?

Links

Orphan pagesWhich pages can no link reach?Link graphHow deep do your pages sit?Anchor textDo links say what they point at?Outbound linksAre external links still alive?Broken linksAre internal links sending visitors nowhere?

Structured data

Rich resultsIs my markup eligible for a rich result?Structured dataIs my product schema valid?Schema coverageDo my key pages carry structured data?Social previewHow does my page look when shared?Schema vs pageDoes markup match the page price?Schema builderNeed valid JSON-LD?

International

Hreflang sitemapDo page and sitemap hreflang agree?HreflangDo my language versions link back?Hreflang builderNeed the hreflang tags?Redirect planMy site has dead links — what redirects do I write?Sitemap diffIs anything missing from my sitemap?Robots simulatorWhat does my robots.txt actually block?Can Googlebot?Can Googlebot fetch this URL?
Every error, explainedGuides
Pricing Learn Error guides Run free audit
Sign in

Sign in free and get one more free check this month. Your account keeps your reports, watches and connections on any device.

Sign in with GoogleOpens your account, or creates a free one Sign in with work emailWe email you a 6-digit code PricingPlans and credit packs for the paid jobs

Product schema example: copyable JSON-LD for a real product page

A useful Product schema example should describe what shoppers can actually see and buy on that URL. Start with one Product and one truthful Offer; add shipping, returns and variants only when those details apply. The samples here are templates, not values to paste unchanged: replace every URL, currency, policy and stock status with the page’s real information.

Published

A basic Product and Offer

For a product page where customers can purchase the item, Google recommends merchant listing markup. The Offer price, currency, availability and URL should agree with the visible page and checkout. Place the JSON inside a <script type="application/ld+json"> element in the product page HTML. This compact sample deliberately omits reviews and ratings rather than inventing them:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Trail mug, 350 ml",
  "image": ["https://shop.example/products/trail-mug.jpg"],
  "description": "Double-wall steel camping mug.",
  "sku": "TM-350",
  "brand": { "@type": "Brand", "name": "North Trail" },
  "offers": {
    "@type": "Offer",
    "url": "https://shop.example/products/trail-mug",
    "priceCurrency": "USD",
    "price": "24.00",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition"
  }
}

For an eligible Google merchant listing, the product’s name and an Offer with a price are important required data. Use a decimal point and ISO 4217 currency code. Google’s documentation explains merchant listing properties and the Product feature choices. Valid markup only makes a page eligible; Google decides whether and how a rich result appears.

A ProductGroup with variants

When options such as size or color are genuinely distinct purchasable variants, Google documents Product variant markup using ProductGroup and hasVariant. Give each variant its real attributes and Offer. The excerpt below is illustrative; production markup should include the required identifying properties and complete page URLs for your setup:

{
  "@context": "https://schema.org",
  "@type": "ProductGroup",
  "name": "Trail shirt",
  "productGroupID": "TS-BASE",
  "variesBy": ["https://schema.org/size"],
  "hasVariant": [
    {
      "@type": "Product",
      "name": "Trail shirt, size M",
      "sku": "TS-M",
      "size": "M",
      "offers": {
        "@type": "Offer",
        "url": "https://shop.example/products/trail-shirt?variant=medium",
        "priceCurrency": "USD",
        "price": "38.00",
        "availability": "https://schema.org/InStock"
      }
    },
    {
      "@type": "Product",
      "name": "Trail shirt, size L",
      "sku": "TS-L",
      "size": "L",
      "offers": {
        "@type": "Offer",
        "url": "https://shop.example/products/trail-shirt?variant=large",
        "priceCurrency": "USD",
        "price": "38.00",
        "availability": "https://schema.org/OutOfStock"
      }
    }
  ]
}

See Google’s Product variant structured data guide for variant URL and property requirements. Do not use AggregateOffer as a shortcut for a group of variants; Google explicitly distinguishes aggregate offers from variants.

Shipping and return details

Shipping information belongs on the relevant Offer as shippingDetails; a product-level return exception belongs in hasMerchantReturnPolicy. Example values below describe one fictional US product and must be replaced with your actual policy:

"offers": {
  "@type": "Offer",
  "url": "https://shop.example/products/trail-mug",
  "priceCurrency": "USD",
  "price": "24.00",
  "availability": "https://schema.org/InStock",
  "shippingDetails": {
    "@type": "OfferShippingDetails",
    "shippingRate": {
      "@type": "MonetaryAmount",
      "value": "5.00",
      "currency": "USD"
    },
    "shippingDestination": {
      "@type": "DefinedRegion",
      "addressCountry": "US"
    }
  },
  "hasMerchantReturnPolicy": {
    "@type": "MerchantReturnPolicy",
    "applicableCountry": "US",
    "returnPolicyCategory":
      "https://schema.org/MerchantReturnFiniteReturnWindow",
    "merchantReturnDays": 30,
    "returnFees": "https://schema.org/FreeReturn",
    "returnMethod": "https://schema.org/ReturnByMail"
  }
}

Google recommends a standard store return policy at the Organization level when it applies broadly; use product-level policy only for a real exception or when no standard policy exists. Review the current shipping and return requirements before publishing. Do not mark up a free return if customers pay return postage, or copy a one-size policy across countries where it differs.

Product schema without a price

Do not insert a guessed, zero, “from” or temporary price to silence a warning. If the product truly has no offer price on the page, omit offers rather than claiming one. A product snippet may still be eligible with qualifying review or aggregate-rating data, but a merchant listing that describes a purchasable product requires price information. If there is no genuine review data either, there may be no Product rich result eligibility to claim. Google’s product snippet requirements allow a review, aggregate rating, or offer for the snippet feature; its merchant listing feature has its own required Offer details.

For subscription, quote-based or variable-price products, model the real pricing arrangement supported by Google’s current documentation and visible to users. If the product is genuinely free, zero is different from an unknown price, but Google says merchant listing experiences require a price greater than zero. Do not expect a free item with a zero-price Offer to qualify for that feature.

Validate the page

  1. Confirm the JSON parses and appears in the fetched page HTML.
  2. Run the URL through Google’s Rich Results Test and inspect both errors and warnings.
  3. Compare the marked-up name, image, selected variant, price, currency, inventory, delivery and returns with the visible page and checkout.
  4. Check Merchant Center separately where you use a feed; page markup and feed data are distinct inputs.
  5. After edits, inspect the live URL again and watch Search Console for recrawl and structured data reports.

Google says structured data creates eligibility, not a guarantee of appearance. For Shopify theme behavior and the variant implementation context, read Product JSON-LD for Shopify and the ProductGroup variants guide.

Find out if this is happening to you

Shipwork reads public product HTML and reports Product JSON-LD fields and nested variant markup it can observe. Free, no account, no signup. Paste your store address.

Check my product markup

Questions

Can Product schema have no price?
A Product without an Offer price is not eligible for a merchant listing that needs price data. Some product snippets can qualify through review or aggregate-rating data instead, if that information is genuine and meets Google’s rules.
Should shippingDetails and returns be added to every product?
Only when the values are accurate. Google recommends Organization-level markup for a standard return policy and product-level markup for exceptions; shipping can also be configured in Merchant Center.
Does valid JSON-LD guarantee a rich result?
No. It makes the page eligible when all requirements are met; Google decides whether to show a result.
Can AggregateOffer describe size variants?
Google says not to use AggregateOffer to describe a set of variants. Use ProductGroup and variant markup instead.

Keep reading