All posts
Ray Iyer
Ray Iyer
Co-founder, Anglera

Making your commercetools catalog agent-readable (AEO)

How to make a commercetools PDP agent-readable: structured attributes, Product JSON-LD, and server-rendered answers AI systems can parse.

Making your commercetools catalog agent-readable (AEO)

Once your catalog data is actually rich — real attributes, not marketing copy — the job shifts from "what do we know about this product" to "what does the page expose, and in what form." commercetools gives you a flexible attribute model and multiple front-end paths — its own Frontend product, or a custom storefront on the Composable Commerce APIs — but none of that guarantees a shopping agent or crawler can read what you built. This guide covers modeling attributes so they're extractable, emitting Product structured data from them, rendering it server-side, and answering buyer questions directly instead of leaving them to a spec table.

Model attributes so there's something to extract

commercetools organizes product data through Product Types, which define the Attributes available to a product (name, label, and an attribute type: text, number, boolean, date, enum, localized enum, money, set, or the beta nested type for tabular/structured sub-attributes). The type you pick determines whether an agent gets a clean, structured value or has to parse prose:

  • Use enum or localized enum for closed sets (size, connector type, certification) rather than free text — it forces consistent values across the catalog.
  • Use set when an attribute can hold more than one value (compatible device list, included accessories).
  • Use the nested attribute type for genuinely structured sub-data (a specification block with its own name/value pairs), capped at five levels of nesting.
  • Reserve free-text attributes for actual prose (a fit note, a care instruction), not for data an agent would otherwise have to regex out of a sentence.

commercetools also lets you define Product-level Attributes (shared across every variant) separately from Variant-level Attributes (size, color, SKU-specific facts), instead of relying on a sameForAll constraint — this shipped as a public beta in June 2025 and reached general availability in December 2025. Pull shared specs (brand, material, certifications) from the product level once, and only re-render the attribute block when the customer switches variants — that keeps the PDP's structured data consistent instead of duplicating, or contradicting, the same fact per variant.

commercetools does not have a built-in GTIN, EAN, or MPN field — only sku is native to the Product Variant. If you need those identifiers for structured data or Google Merchant Center, model them as custom attributes on the relevant Product Type. See the attribute types reference and Product Types and Attributes docs for the full type catalog and constraints.

Resolve enum keys to labels before you render

Plain and localized enum attributes are defined on the Product Type as key/label pairs (e.g., key poly_cotton, label "Poly-Cotton Blend"). Depending on the API and projection you query, the value may come back as just the key or as the full {key, label} object — check what your storefront's query actually returns before building the template. Either way, render the human-readable label to the page, not the internal key. An agent reading poly_cotton off the DOM has to guess at meaning; one reading "Poly-Cotton Blend" doesn't.

Emit Product JSON-LD from the same attribute set

Structured attributes are only half the job until they're expressed as markup a search or shopping agent actually parses. Map your commercetools fields into schema.org/Product JSON-LD and inline it in the page:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Aria Trail Running Shoe",
  "description": "Lightweight trail runner with a Vibram outsole and waterproof upper.",
  "sku": "ARIA-TR-BLK-42",
  "gtin13": "0194493847213",
  "mpn": "ARIA-TR-42",
  "brand": {
    "@type": "Brand",
    "name": "Anglera Outdoor"
  },
  "offers": {
    "@type": "Offer",
    "url": "https://example.com/p/aria-trail-running-shoe",
    "priceCurrency": "USD",
    "price": "129.00",
    "availability": "https://schema.org/InStock"
  }
}

Per Google's merchant listing structured data guidelines, name, image, and offers (with price and priceCurrency) are required; sku, gtin/gtin8/gtin12/gtin13/gtin14, mpn, brand, aggregateRating, and review are recommended — but most manufactured goods still need brand plus a GTIN or MPN to be fully eligible. None of those live natively on a Product Variant except SKU, which is why modeling them as custom attributes pays off.

Server-render it — don't leave it to client JS

commercetools' own Frontend product is built on Next.js and supports SSR, SSG, and client-side rendering as deployment choices, per its architecture documentation; the same principle applies to any custom storefront built on the Composable Commerce APIs. The JSON-LD block, the visible attribute table, and any answer text need to be present in the HTML the server returns on first request — not injected after a client-side fetch resolves. Google is blunt about this: JavaScript-generated markup "may reduce crawl frequency" for time-sensitive fields like price and availability. Most AI shopping agents and answer engines are less patient than Googlebot about executing JS, so treat SSR as the baseline, not an optimization.

Answer the buyer's question in sentences, not just a table

A spec table tells an agent that a shoe has a 4mm heel-to-toe drop; it doesn't answer "is this good for wide feet?" or "does this work in the rain?" Use your structured attributes to generate a short, server-rendered paragraph that answers the two or three questions buyers actually ask for that category — sourced from the same enum/attribute values, so the prose and the table can't drift apart. You don't need FAQPage schema for this to work for an AI agent — Google restricted FAQ rich results in 2023 and dropped the feature from Search entirely in May 2026, so there's no SERP payoff left to chase there anyway. Plain, visible, server-rendered text an agent can read off the DOM is what matters, schema wrapper or not.

What an AI agent can and cannot extract

Can extract:

  • Visible text and attribute values present in the server-rendered HTML (view-source, not just the rendered DOM)
  • JSON-LD present in that same initial HTML response
  • Enum values once resolved to their human label
  • A directly stated answer sentence ("machine washable, cold water, tumble dry low")

Cannot extract:

  • Content that only appears after client-side hydration or a follow-up fetch, if the agent doesn't execute JS or gives up before hydration completes
  • Meaning trapped in an internal enum key, SKU suffix, or product-type code with no label rendered anywhere
  • Facts that only exist inside an image, PDF spec sheet, or size-chart graphic with no text equivalent
  • Attributes that exist in commercetools but were never wired into the storefront's GraphQL/HTTP API query, or are scoped to a channel/store the current page doesn't request

How to validate

  • View-source vs. rendered DOM: load the PDP, then compare curl output against the inspected DOM. A large gap means your JSON-LD or attribute content is client-injected.
    curl -s -A "Mozilla/5.0 (compatible; Googlebot/2.1)" https://example.com/p/aria-trail-running-shoe | grep -A5 "application/ld+json"
    
  • Structured data check: run the page through Google's Rich Results Test and Schema Markup Validator to confirm the JSON-LD parses and required properties are present.
  • Attribute audit: for a sample SKU, diff what's in commercetools (the commercetools Merchant Center back office, or a raw API response) against what actually renders on the live page — anything missing there is invisible to an agent no matter how well-modeled it is upstream.

Verified as of July 2026 against current commercetools API and Frontend documentation and Google's structured data guidelines; attribute-response shapes and JS-crawling behavior can shift between plan/version and search engine, so re-check before relying on specifics in production.

None of this works without the enrichment underneath it — the specs, use-cases, and identifiers that make an attribute table worth rendering. That's the side Anglera handles: it plugs into commercetools (or whatever PIM or commerce platform you're already running) and keeps product attributes complete and current, so the JSON-LD, attribute tables, and answer paragraphs described here always have real, structured data behind 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