All posts
Ray Iyer
Ray Iyer
Co-founder, Anglera

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.

Adding Product JSON-LD on Optimizely Configured Commerce — and keeping it in sync

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 propertyNative Configured Commerce sourceNotes
nameProduct short/long descriptionAlready covered by the toggle
skuProduct SKU / ERP numberAlready covered
mpnManufacturer Item / manufacturer numberCovered ("manufacturer number" per Optimizely docs)
brandProduct brand / manufacturer fieldCovered
gtin, gtin8/12/13/14UPC/EAN custom property or attributeNot in the documented default output — add as a custom property
offers.price, offers.priceCurrency, offers.availabilityReal-time pricing and inventory (RTPI)Covered, but accuracy depends on RTPI being enabled — a stale cached price defeats the point
aggregateRating, reviewProduct 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 gtin and aggregateRating using properties already on the product model — the custom property you added, plus whatever your review provider exposes as ratingValue/reviewCount.
  • If GTIN or rating data comes from the PIM/ERP, extend the GetProductHandler chain (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:

  1. 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.
  2. Turn on real-time pricing and inventory (RTPI) if you enable Product Structured Data — Optimizely ties accurate Offer data to RTPI being active; without it, the schema can advertise a stale price even with the toggle "on."
  3. 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, curl should 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 Product type 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.price moved 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.

Ray Iyer

About the author

Ray IyerCo-founder, Anglera

Ray is a co-founder of Anglera, building the product-data infrastructure for agentic commerce — turning messy catalogs into structured, AI-readable data that buyers and answer engines can find. Previously product at Uber; Stanford CS.

See it on your own SKUs.

A 30-minute walkthrough on your categories and your supplier data.

Book a demo