Adding Product JSON-LD on Optimizely Configured Commerce — and keeping it in sync
How distributors add schema.org Product JSON-LD in Optimizely Configured Commerce and keep it synced with the live PDP, with a validated example.

Configured Commerce ships a native toggle that generates Product structured data for you, which covers the basics but not every field AI shopping agents and Google now look for. This guide covers what the built-in feature outputs, which fields distributors typically need to add themselves (GTIN, aggregateRating), and how to keep the JSON-LD from drifting away from what a buyer actually sees on the page.
What the native toggle gives you
Configured Commerce (Spire) has a built-in Product Structured Data setting. In the Admin Console, go to Administration → Settings → Site Configurations, find the SEO section, and toggle on Product Structured Data (off by default). When enabled, Configured Commerce generates schema.org Product JSON-LD from the same Product Details data that renders the page and injects it into the Spire PDP's page head. The same section has toggles for Breadcrumb, Sitelinks Search Box, and Organization structured data too.
On Classic CMS, the equivalent switch lives in Content Administration: open the Product Detail Page in the page tree, click Edit Page, and select Enable Structured Page Data.
Per Optimizely's Schema.org tags documentation and the related SEO user interfaces article, the native feature populates: product name, product ID, URL, description, SKU, manufacturer number, brand, image, category, and Offer data (availability, price, currency). That's a solid baseline, but GTIN/UPC/EAN and aggregateRating/review aren't part of the documented default output — exactly the fields that matter most for Google Shopping eligibility and AI shopping-agent matching. Plan to extend the default markup rather than assume it's complete.
The fields that matter, and where they come from
| JSON-LD property | Native Configured Commerce source | Notes |
|---|---|---|
name | Product short/long description | Already covered by the toggle |
sku | Product SKU / ERP number | Already covered |
mpn | Manufacturer Item / manufacturer number | Covered ("manufacturer number" per Optimizely docs) |
brand | Product brand / manufacturer field | Covered |
gtin, gtin8/12/13/14 | UPC/EAN custom property or attribute | Not in the documented default output — add as a custom property |
offers.price, offers.priceCurrency, offers.availability | Real-time pricing and inventory (RTPI) | Covered, but accuracy depends on RTPI being enabled — a stale cached price defeats the point |
aggregateRating, review | Product reviews (native reviews or a third-party integration, e.g., Bazaarvoice/Yotpo/PowerReviews) | Not in the documented default output — needs custom mapping from whatever feeds the visible star rating |
If GTIN isn't already a first-class product field in your catalog, add it as a custom property on the Product entity (Admin Console → Administration → System → Application Dictionary → Properties tab → Add Property Configuration) so it's available to both the PDP template and the JSON-LD generator. A category-level Attribute Type (Admin Console → Catalog → Attribute Types) works too if GTIN already fits your faceting model, but a custom property is the more direct fit for a per-SKU identifier.
Adding the fields the native feature doesn't cover
In Spire, structured data is rendered server-side on the Product Details page, which is why it stays reasonably in sync when you use the native toggle — it reads from the same Product Details data the visible page renders. To add GTIN or aggregateRating, extend that same rendering path rather than build a parallel one:
- Extend the Product Details head/meta rendering (the same component that already emits the native JSON-LD) to append
gtinandaggregateRatingusing properties already on the product model — the custom property you added, plus whatever your review provider exposes asratingValue/reviewCount. - If GTIN or rating data comes from the PIM/ERP, extend the
GetProductHandlerchain (or add a custom handler to it) so those fields land on the product model before it reaches the PDP — a single source of truth instead of a second lookup living only in a template. - Avoid a separate CMS "Structured Page Data" content block for this. That field (Content Administration → Advanced tab in Spire, or More Options in Classic) is meant for static schema on content pages like Organization or FAQ markup — hand-entered, and it won't track SKU-specific data as the catalog changes.
Example JSON-LD
This is the shape to aim for on a distributor PDP — adjust to your catalog fields, and only include aggregateRating if you have genuine review counts behind it:
{
"@context": "https://schema.org/",
"@type": "Product",
"name": "3/4 in. NPT Brass Ball Valve, 600 WOG",
"sku": "BV-0750-NPT",
"mpn": "BV0750N-BR",
"gtin12": "049793623145",
"brand": {
"@type": "Brand",
"name": "Apex Flow Controls"
},
"description": "Full-port brass ball valve rated to 600 WOG, threaded NPT connections, PTFE seats.",
"image": [
"https://www.example-distributor.com/images/products/bv-0750-npt-1.jpg"
],
"category": "Valves & Fittings > Ball Valves",
"offers": {
"@type": "Offer",
"url": "https://www.example-distributor.com/p/BV-0750-NPT",
"priceCurrency": "USD",
"price": "18.42",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "36"
}
}
Wrap this in a standard JSON-LD script tag when rendering into the page head:
<script type="application/ld+json">
{ ... the object above ... }
</script>
Keeping it in sync with the visible page
The failure mode to design against is a JSON-LD block that quietly diverges from the DOM — a price or inventory change that reaches the visible PDP but not the schema. Three practical rules:
- One data source, two renderers. The JSON-LD generator and the visible price/availability/rating widgets should read from the same product model response, not independent queries or cached snapshots taken at different times.
- Turn on real-time pricing and inventory (RTPI) if you enable Product Structured Data — Optimizely ties accurate
Offerdata to RTPI being active; without it, the schema can advertise a stale price even with the toggle "on." - Treat GTIN, brand, and manufacturer number as catalog-governed fields, not template constants. If they live in a spreadsheet import or an ERP field not wired to the product model the PDP/JSON-LD reads from, they'll go stale independently of the rest of the page. Route metadata (title, meta description, meta keywords) the same way — via Admin Console → Catalog → Products → Edit → Content tab, Product Import, or ERP integration — rather than hand-editing it separately from JSON-LD.
How to validate
- View-source vs. rendered DOM. Because Spire server-renders the head,
curlshould return the same JSON-LD script block as "View Page Source" in the browser. If it only shows up in DevTools' rendered DOM, it's being injected client-side after the crawler-relevant response and won't be reliably read by all consumers.curl -s https://www.example-distributor.com/p/BV-0750-NPT | grep -A 30 'application/ld+json' - Google's Rich Results Test: paste the live URL, confirm the
Producttype is detected with no errors, and check that price/availability match what's rendered on the page. - Schema Markup Validator for a stricter, non-Google-specific check of the vocabulary itself.
- Spot-check after a price or inventory change — update a SKU's price in the admin, then re-curl the PDP to confirm
offers.pricemoved with it, not just the visible page.
Verified as of July 2026 against Optimizely's Configured Commerce support and developer documentation; menu paths and default field lists are current for Spire and Classic CMS as published, but confirm against your version and plan since structured data behavior can vary by release.
None of this works without clean data behind it, though — a JSON-LD block is only as good as the GTIN, brand, and spec values feeding it. Anglera plugs into your PIM or Configured Commerce catalog directly, continuously enriching those underlying attributes so the fields above (GTIN, mpn, category, spec-driven descriptions) stay populated and current, rather than blank or stale when your schema tries to read them.
