Skip to content
Academy
Marketing Academy · Field Work●SEO
CoreBuild the Asset· 45 minutes

Ship It Right: Building a Valid Product Schema Block From Scratch

FirstCry (Brainbees Solutions)

Objective: Given one real product's facts, build a complete, valid JSON-LD Product schema block from zero, matched exactly to what the live page visibly shows, and get it to pass Google's Rich Results Test with zero errors.

FirstCry is launching Rich Results on its baby-gear PDPs for the first time. You're handed one real product, a baby stroller priced at ₹8,999, in stock, with a 4.4-star average from 87 verified reviews already visible on the page, and asked to build and sign off the first JSON-LD block from scratch.

Four passes: pick the right schema type and top-level fields, fill the offers object correctly, cross-check every value against what the page actually shows, then validate the finished block.

What does a complete, valid Product JSON-LD block look like when built from a real page's exact visible facts, and how do you confirm it passes Google's own validator?

Structured Data/JSON-LD Authoring/Schema Validation

Before you start

What you'll need

  • —Basic familiarity with JSON syntax
  • —Access to a text editor and the target product page
Offer object
the nested schema.org block declaring price, priceCurrency, and availability, all three required for Google to render a price badge.
Availability
a schema.org URL value (e.g. https://schema.org/InStock) telling Google the current stock state of the product.

Free path (everything below is enough to finish)

FreeValidate the finished block via URL Inspection's live Rich Results test before it ships

Free, and the same validation engine Google's indexing pipeline itself uses to determine rich-result eligibility.

Paid upgrades (optional, faster/deeper)

Building and validating one Product schema block needs zero paid tools; a text editor and GSC's free validator are the whole free path.

SEMrush(optional)
FreemiumRun a bulk schema audit once Product schema rolls out across the full FirstCry catalog, not just this one PDP

The free path (manual JSON-LD build plus GSC validation) is complete for building and shipping this one block; SEMrush is worth it once auditing schema across thousands of live product pages.

The process

4 steps

Step 01 of 04

The Schema Types That Actually Move the Needle

The lesson's table lists Product schema as unlocking prices, ratings, and availability, and names it the best fit for ecommerce and SaaS pages.

Given a baby-stroller PDP with a real name, brand, price, stock status, and an on-page rating, which @type and top-level properties does the lesson's table point you toward?

Notion— A plain text editor, drafting the raw JSON-LD before pasting it into the CMS's head snippet field.

Procedure

  1. Confirm the page is a single, purchasable product, not a category or article, and set @type to Product
  2. Add the baseline identity fields: name, image, description, brand
  3. Stub out placeholders for offers and aggregateRating, to be filled in the next steps
Sample output
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "FirstCry Comfort Ride 3-Wheel Baby Stroller",
  "image": "https://www.firstcry.com/img/comfort-ride-stroller.jpg",
  "description": "Lightweight 3-wheel stroller with reclining seat and all-terrain wheels.",
  "brand": {
    "@type": "Brand",
    "name": "FirstCry Original"
  },
  "offers": { },
  "aggregateRating": { }
}

Healthy

@type is Product, and every baseline identity field (name, image, description, brand) is filled with the real page values, not placeholder text.

Unhealthy

Leaving @type as a generic "Thing" or copying an @type from a different product family, which prevents any of the intended rich-result types from being considered at all.

What this means

Getting @type right is the single highest-leverage decision in the whole block. Every property added after this point is wasted if the type doesn't match what the lesson's table says triggers Product rich results.

So what do I do about it?

SymptomActionEffort
The draft schema was copy-pasted from a different product templateRebuild the identity fields from this exact product's real page content before adding offers or ratings30 min
YouYou can do this yourself, no engineering access required.

Step 02 of 04

How It Works

The lesson's minimal JSON-LD example shows the offers object needs price and priceCurrency at minimum, with availability as the field that tells Google whether the item can currently be purchased.

The stroller is in stock at ₹8,999. What exact values go in offers.price, offers.priceCurrency, and offers.availability?

Notion— Same text editor, filling in the offers object stub from Step 1.

Procedure

  1. Set price to the exact numeric value shown on the page, 8999, with no currency symbol inside the field
  2. Set priceCurrency to the ISO code, INR
  3. Set availability to the schema.org URL for the current stock state, https://schema.org/InStock
Sample output
"offers": {
  "@type": "Offer",
  "price": "8999",
  "priceCurrency": "INR",
  "availability": "https://schema.org/InStock"
}

Healthy

price, priceCurrency, and availability are all present and match the live page exactly, using the full schema.org URL form for availability.

Unhealthy

Leaving priceCurrency out because "the price is obviously in rupees," which Google's parser does not infer on its own.

What this means

All three offer fields are required for Google to render a price badge at all, not just recommended; a partial offers block is treated the same as a missing one for rich-result eligibility.

So what do I do about it?

SymptomActionEffort
The offers block is missing priceCurrencyAdd the ISO currency code explicitly before submitting for validation5 min
YouYou can do this yourself, no engineering access required.

Step 03 of 04

Common Mistakes

The lesson warns against marking up content that isn't visible on the page and against mismatching schema type to content; both are guideline violations that can trigger a manual removal of rich-result eligibility.

The page shows 87 reviews and a 4.4 average directly on screen. Does the draft's aggregateRating block honestly match what's visible, and is anything else on the page still unrepresented in the schema?

Notion— Same text editor, cross-checking the draft against the live rendered page side by side.

Procedure

  1. Open the live product page next to the JSON-LD draft
  2. Confirm ratingValue and reviewCount in the draft match exactly what's rendered on the page (4.4 and 87)
  3. Scan the page for any other visible fact (SKU, GTIN if shown) not yet represented in the schema
Sample output
"aggregateRating": {
  "@type": "AggregateRating",
  "ratingValue": "4.4",
  "reviewCount": "87"
}

Cross-check against live page: ratingValue and reviewCount match exactly. No SKU
or GTIN is currently displayed on the page, so neither is added to the schema yet.

Healthy

Every value in aggregateRating matches the visible page exactly, and no field is added for information the page doesn't actually show.

Unhealthy

Inflating reviewCount to a rounder number, or adding a GTIN value that isn't displayed anywhere a shopper can see it, both guideline violations even if technically valid JSON.

What this means

The draft passing this cross-check is what separates "technically valid schema" from "schema Google will actually trust," since the guideline violation the lesson warns about is invisible to a syntax validator.

So what do I do about it?

SymptomActionEffort
No one currently cross-checks schema values against the rendered page before publishingAdd a page-vs-schema side-by-side check as a required step before any PDP schema ships5 min
YouYou can do this yourself, no engineering access required.

Step 04 of 04

How It Works

The lesson instructs validating every schema block with Google's Rich Results Test before launch, since it shows exactly what rich-result types Google can detect and flags any errors.

Paste the finished block into Google's Rich Results Test (accessible via GSC's URL Inspection on a live URL). What does a clean pass look like, and what would still block launch?

Google Search Console— URL Inspection > Test Live URL, or the standalone Rich Results Test at the same validation engine.

Procedure

  1. Paste the finished JSON-LD block or the live URL into the Rich Results Test
  2. Confirm the detected type reads "Product" with zero errors
  3. Review any warnings (non-blocking) separately from errors (blocking) and resolve errors before considering the block launch-ready
Sample output
Rich Results Test: PASS
Detected type: Product
Eligible for: Merchant listing, Product snippet
Errors: 0
Warnings: 0

Healthy

Zero errors, the detected type matches the intended one, and the eligible rich-result types include the ones the launch actually needs.

Unhealthy

Shipping a block with an unresolved warning about a recommended-but-missing field like gtin, which won't block eligibility today but limits which AI shopping tools can confidently cite the page.

What this means

A clean validator pass is the prerequisite the lesson describes, not a guarantee: Google still decides whether to actually show the rich result, but a failing validation guarantees it never will.

So what do I do about it?

SymptomActionEffort
The block hasn't been run through validation before the launch dateBlock the CMS deploy on a passing Rich Results Test result, not just a code review5 min
EitherYou or a developer can handle this, depending on your access.

Analyze your findings

What to look for

Type correctness
Is @type Product, matching what the lesson's table says triggers price, rating, and availability rich results?
Field completeness
Are all three offer fields, price, priceCurrency, and availability, present, not just price alone?
Page match
Does every declared value match exactly what's visibly rendered on the page, no rounding, no invented fields?
Clean validation
Does the finished block pass Google's Rich Results Test with zero errors, not just zero syntax errors?

Make the call

The draft's offers object has price and availability filled in but priceCurrency is missing. What's the consequence of shipping it as-is?

Recommendation · Priority: Medium

“The FirstCry stroller PDP's Product schema block is ready to ship: @type is correctly set to Product, all four identity fields are filled from the real page, the offers object includes price (8999), priceCurrency (INR), and availability (InStock), and the aggregateRating values (4.4, 87 reviews) match exactly what's visibly rendered. The block passed Google's Rich Results Test with zero errors and zero warnings, making it a safe template to replicate across the rest of the baby-gear catalog.”

Common mistakes

What trips people up

  • Leaving priceCurrency out because the price seems obviously local — Google's parser doesn't infer currency, an incomplete offers object can be rejected entirely.

  • Copying identity fields from a different product's template — name, image, description, and brand all need to be rebuilt from this exact product's real page content, not reused from a similar listing.

  • Skipping the page-vs-schema cross-check — technically valid JSON can still violate content guidelines if a value like reviewCount doesn't match what's actually displayed.

  • Treating a clean validator pass as a guarantee of the rich result appearing — passing validation is a prerequisite, not a promise, Google still independently decides whether to show the rich result.

Final deliverable

A complete, validated JSON-LD Product schema block for one real PDP, passing Google's Rich Results Test with zero errors, matched exactly to what the page visibly shows.

See a reference example
Sample output
The same 4-step build applied to a ThredUp resale-item PDP (illustrative): @type Product, offers.price "34.00", offers.priceCurrency "USD", offers.availability set to https://schema.org/InStock for a single available unit. The cross-check step caught that the draft's condition field said "New" while the visible listing clearly stated "Gently Used," a values mismatch fixed before submission.

Success criteria

You're done when you can:

  • @type is set to Product with all four baseline identity fields (name, image, description, brand) filled from the real page
  • offers includes price, priceCurrency, and a correctly formatted availability URL matching the live stock state
  • aggregateRating values match the visibly displayed rating and review count exactly, with no invented fields
  • The finished block passes Google's Rich Results Test with zero errors

Key takeaway

Building schema from scratch is less about JSON syntax and more about discipline: choosing the right type, filling every required field completely, and verifying each value against what the page actually shows before ever running the validator. A clean Rich Results Test pass is the finish line, not the starting point.