All posts
Ray Iyer
Ray Iyer
Co-founder, Anglera

Making your SAP Commerce Cloud catalog agent-readable (AEO)

How to make SAP Commerce Cloud PDPs agent-readable: complete attributes, Product JSON-LD, SSR checks, and buyer-question content that AI can parse.

Making your SAP Commerce Cloud catalog agent-readable (AEO)

Distributor and manufacturer catalogs in SAP Commerce Cloud often have the underlying data an AI shopping agent needs — the gap is usually getting it into a form the agent can parse on the page itself. This guide covers the three things that determine whether a SAP Commerce Cloud product detail page (PDP) is machine-readable: complete structured attributes, valid Product JSON-LD, and server-rendered HTML that doesn't require executing JavaScript to see the content.

Two storefronts, two different starting points

SAP Commerce Cloud customers are typically on one of two storefront architectures, and it changes where you start:

  • Accelerator (Spring MVC / JSP) — the legacy storefront. Pages are rendered server-side by default, so crawlers and most AI agents already see the rendered HTML. Your gap is almost always incomplete structured data (no JSON-LD, or partial schema), not renderability. SAP has scheduled Accelerator's UI templates for removal and end of mainstream maintenance in September 2027, so treat fixes here as a stopgap, not a platform to invest in.
  • Composable Storefront (Spartacus, Angular) — the current SAP-recommended front end. It ships as a single-page application, which means the initial HTML payload can be nearly empty unless Server-Side Rendering (SSR) or prerendering is explicitly configured and running. This is the storefront where "is my content actually in the HTML" becomes the first question to answer, not an afterthought.

Spartacus includes first-party JSON-LD support (JsonLdBuilderModule) and a meta-tag/canonical-URL framework, both covered below — but they only help an agent if the page is served pre-rendered.

Step 1: Complete the structured attributes before you templatize

SAP Commerce Cloud models product attributes two ways, and both matter for AEO:

  • Type system attributes — attributes defined on the product's item type (e.g., Product, or a custom subtype), populated via Impex or the Backoffice Product Cockpit.
  • Classification system attributes ("features") — attributes assigned through a classification category and classification system (e.g., an ETIM- or eCl@ss-style hierarchy), which is how most distributors and manufacturers model spec sheets — voltage, thread size, material, certifications, compatible models — since specs vary by category without a schema change per product type.

Both surface through Product Content Management (PCM) tooling and are retrievable via the OCC (Omni Commerce Connect) API's product endpoint using fields=FULL, which returns base fields plus the classifications array of feature/value pairs. If a spec lives only in classification features and your template only reads type-system fields (or vice versa), it silently never reaches the page — the single most common reason a PDP looks complete in Backoffice but reads thin to an agent.

Step 2: Emit Product JSON-LD

Whichever storefront you're on, the target output is the same: a Product JSON-LD block with identifiers, offer, and — critically for B2B/industrial catalogs — the classification attributes an agent can't infer from a name and photo.

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "1/2 in. Brass Ball Valve, 600 WOG",
  "image": "https://www.example.com/images/BV-1200-050.jpg",
  "sku": "BV-1200-050",
  "mpn": "BV-1200-050",
  "gtin13": "0801234567895",
  "brand": {
    "@type": "Brand",
    "name": "Acme Flow Controls"
  },
  "description": "Full-port brass ball valve rated to 600 WOG for potable water, compressed air, and light industrial fluid lines.",
  "additionalProperty": [
    { "@type": "PropertyValue", "name": "Port Type", "value": "Full Port" },
    { "@type": "PropertyValue", "name": "Pressure Rating", "value": "600 WOG" },
    { "@type": "PropertyValue", "name": "End Connection", "value": "NPT Threaded" },
    { "@type": "PropertyValue", "name": "Material", "value": "Brass (CW617N)" }
  ],
  "offers": {
    "@type": "Offer",
    "priceCurrency": "USD",
    "price": "18.42",
    "availability": "https://schema.org/InStock",
    "url": "https://www.example.com/p/BV-1200-050"
  }
}

The additionalProperty array is where your classification-system features belong — map each surfaced feature/value pair from the OCC classifications response directly into a PropertyValue, rather than only relying on name/description, so an agent can match on a specific spec (pressure rating, thread size, certification) instead of guessing from free text. name, image, and offers (with price/priceCurrency) are the fields Google's product structured-data guidelines require; sku, mpn, gtin13, brand, and classification-derived additionalProperty entries are recommended, not required — but they're what an AI shopping agent actually uses to answer a specific buyer question.

On Spartacus: import JsonLdBuilderModule and let ProductSchemaBuilder generate the Product, Offer, Review, and Rating blocks from the same product model the PDP renders from; extend it via the SCHEMA_BUILDER / JSONLD_PRODUCT_BUILDER injection tokens to add classification-derived additionalProperty entries — that mapping isn't automatic. Spartacus doesn't validate the JSON-LD it emits, so validation is your responsibility (see "How to validate" below).

On Accelerator (JSP): there's no built-in JSON-LD builder — add a JSON-LD script block (application/ld+json) in the product detail JSP, populated from the same model attributes the visible template already uses, so structured data and visible copy never drift apart.

Step 3: Confirm it's actually server-rendered

Structured data and rich copy are worthless to most agents if they only appear after client-side JavaScript executes. On Accelerator this is rarely an issue. On Spartacus:

  • SSR must be explicitly enabled and running (the Node Express SSR engine, or a prerendering cache in front of it) — an unconfigured or crashed SSR server serves the empty app shell, invisible to non-JS-executing crawlers.
  • Configure the meta-tag and canonical-URL framework (PageMetaResolver, CanonicalUrlOptions) so PDPs emit a stable title, description, og:image, and canonical link server-side rather than relying on the Angular router to write them client-side.
  • Watch SSR cache TTLs on high-SKU catalogs — a stale cached page can serve outdated stock/price copy even after the underlying data changes.

Answer buyer questions in plain, extractable prose

Complete attributes and valid JSON-LD cover the "what is this" and "what does it cost" questions. AI agents fielding a buyer's actual question ("does this fit a 3/4 in. line," "is this NSF certified," "what's the MOQ") match against visible prose, not just markup. For distributor and manufacturer catalogs specifically:

  • Put spec tables and compatibility/fitment notes in server-rendered HTML table or definition-list markup, not inside a PDF datasheet link or an image of a spec sheet.
  • Write a short FAQ block per PDP (or per category template, driven by classification data) answering the 3-5 questions buyers ask most for that product family — certifications, tolerances, lead time, MOQ.
  • Avoid burying compatible-model or cross-reference lists behind a "view more" control that only populates via an unrendered client-side fetch.

What an agent can extract vs. can't

Agent can reliably extractAgent typically cannot extract
Product name, brand, SKU/MPN/GTIN in JSON-LDSpecs that exist only in a linked PDF or spec-sheet image
additionalProperty values mapped from classification featuresClassification data present in Backoffice/OCC but never rendered by the template
Server-rendered spec tables and FAQ proseClient-rendered PDP content on an unconfigured/failed SSR server
Price and availability in a server-rendered OfferReal-time stock shown only via a client-side widget, no static fallback text

How to validate

  • View-source vs. rendered DOM: on the live PDP, use "View Page Source" (or curl the URL) and search for the product name and application/ld+json. If it's missing from source but visible in the rendered DOM, SSR/prerendering isn't reaching that page.
  • curl check: curl -s https://your-domain.com/p/SKU | grep -A2 'application/ld+json' — confirms the JSON-LD ships in the raw HTML response, not just the client render.
  • Google Rich Results Test: paste the live URL to confirm the Product schema parses without required-field errors, particularly a missing image or an incomplete offers block — the two most common reasons a page fails eligibility.
  • Schema.org validator or a JSON-LD linter on the extracted block, since Spartacus (and most Accelerator custom code) won't validate the JSON-LD it emits for you.

Verified as of July 2026 against SAP's Spartacus/Composable Storefront documentation and SAP Commerce classification system documentation; confirm exact module names and default SSR behavior against your specific SAP Commerce Cloud version, as JSON-LD builder tokens and SSR defaults have changed across Spartacus releases.

None of this replaces the enrichment work upstream — a template can only expose attributes that exist somewhere in SAP Commerce, whether in the type system or the classification system. Anglera plugs into SAP Commerce Cloud to keep those type and classification attributes continuously enriched with accurate specs, identifiers, and use-case detail, so the JSON-LD and spec-table work above has complete data to render rather than gaps to paper over.

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