All posts
Ray Iyer
Ray Iyer
Co-founder, Anglera

The technical SEO checklist for SAP Commerce Cloud product pages

A practical checklist for SAP Commerce Cloud product pages: rendering, structured data, titles, canonicals, images, links, performance, and crawlability.

The technical SEO checklist for SAP Commerce Cloud product pages

Enriched product data only helps buyers and AI agents if it actually reaches the rendered page in a form they can parse. This checklist walks through the technical layer on top of that data — rendering strategy, structured data, metadata, canonicals, images, internal links, performance, and crawl controls — for SAP Commerce Cloud's Composable Storefront (Spartacus) and, where it still applies, the legacy Accelerator storefront.

Rendering: make sure there's HTML to read

Composable Storefront ships as an Angular single-page application, which means content is assembled client-side by default. Googlebot can generally execute JavaScript, but many AI crawlers (and some verticals of Googlebot) fetch pages without a full render, and SPA hydration timing can still cause partial or empty snapshots. SAP's own guidance is to run Server-Side Rendering (SSR) for storefront routes that are indexed or bot-crawled, and to reserve client-side rendering (CSR) for authenticated, session-specific views. SAP recommends adding SSR via Spartacus's own schematics (ng add @spartacus/schematics --ssr) rather than hand-wiring Express/Angular Universal, then tuning SsrOptimizationOptionsconcurrency (max simultaneous renders before falling back to CSR, default 20), timeout (per-render wait before falling back to CSR, default 3000ms), maxRenderTime (hard cap before a stuck render's slot releases, default 300000ms/5 min), and cache/cacheSize (default 3000 cached entries) — so PDP renders don't queue behind slow ones under load. If you're still on the JSP-based Accelerator storefront, this isn't a concern since pages are server-rendered by default; the tradeoff there is templating flexibility, not crawlability.

Structured data that matches what's on the page

Spartacus includes a StructuredDataModule (under the SeoModule) that emits JSON-LD via a ProductSchemaBuilder, using a JSONLD_PRODUCT_BUILDER injection token so you can extend or override individual fields without forking the whole schema. Google's guidance for Product structured data is unchanged in substance: name is required, plus at least one of offers, review, or aggregateRating; adding a complete Offer (price, priceCurrency, availability, url) plus aggregateRating is what actually earns rich results and merchant-listing eligibility, not the bare minimum. A representative block:

{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "Example Widget 3000",
  "sku": "WID-3000-BLK",
  "gtin13": "0012345678905",
  "brand": { "@type": "Brand", "name": "Example Co" },
  "image": ["https://cdn.example.com/wid-3000-black-1.jpg"],
  "description": "Industrial-grade widget rated for continuous duty...",
  "offers": {
    "@type": "Offer",
    "price": "249.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock",
    "url": "https://www.example.com/widgets/wid-3000-black"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.6",
    "reviewCount": "38"
  }
}

Google explicitly warns that dynamically-generated markup — JSON-LD injected only after client-side hydration — makes Shopping/Merchant crawls "less frequent and less reliable" for fast-changing fields like price and availability, which is another reason SSR matters here, not just for visible text.

Titles and meta descriptions

Spartacus resolves page metadata through PageMetaResolvers: a title resolver combines product name, category, and brand into the <title>; a description resolver drives the meta description; a PageRobotsResolver sets the robots meta tag. The defaults are workable but generic — for distributor/manufacturer catalogs with thousands of near-duplicate SKUs, override the product title resolver to include the differentiator that matters (size, capacity, finish) rather than relying on the raw product name, and keep meta descriptions under ~155 characters and unique per SKU rather than templated boilerplate that just swaps the product name.

Canonical URLs, especially for variants

Canonical URL generation was introduced in Spartacus 3.2 as an opt-in feature and only became part of the default configuration starting in version 4.0; storefronts upgraded from an older custom SEO setup can still have it silently overridden off, so verify it's actually on:

provideConfig({
  pageMeta: {
    canonicalUrl: {
      forceHttps: true,
      forceWww: false,
      removeQueryParams: true,
      forceTrailingSlash: true,
    },
  },
})

For variant products (color/size groups), the canonical resolver is meant to point variant URLs at the base product — confirm this is actually happening in your catalog model. Spartacus's resolver has a documented gap with multi-level variants (the OCC API only exposes the direct baseProduct, not a super-base higher up), so a common failure mode is every variant self-canonicalizing, fragmenting authority and confusing AI agents that dedupe by canonical URL. On the legacy Accelerator, equivalent SEO directives are configured per catalog/page and control both the canonical tag and sitemap inclusion.

Images and alt text

MediaModel in SAP Commerce has a native altText attribute; the gap is almost never the field, it's population discipline — alt text left blank or auto-filled with the SKU code helps neither accessibility nor image search nor an AI agent trying to confirm what's in the shot. Also confirm image URLs served through your CDN/media conversion layer (Cloudinary, Scene7, or the platform's own media conversion) are stable and not query-string-only, since a canonicalized product URL paired with churning image URLs still reads as "changed" to some crawlers.

Internal linking and crawl paths

PDPs that are only reachable through faceted-search URLs with query parameters are effectively orphaned for crawlers that don't execute filter interactions. Make sure every sellable PDP has at least one static, canonical path from a category/PLP page and, where relevant, from breadcrumb and cross-sell components — Spartacus renders breadcrumbs from the CMS content slot, but they're only as good as the category hierarchy backing them, so a flat or overly deep catalog tree undermines this even when the component itself is correct.

Performance

SSR optimization settings double as a performance lever: an undersized cacheSize or too-low concurrency causes PDPs to fall back to CSR under load precisely when crawlers hit them in bulk. Pair that with standard storefront hygiene — image compression through your CDN, lazy-loading below-the-fold PDP modules, and trimming render-blocking third-party scripts — since Core Web Vitals still factor into ranking and slow renders increase the odds of an SSR timeout fallback.

Crawlability: robots and sitemaps

Composable Storefront's default PageRobotsResolver behavior is FOLLOW/NOINDEX until a resolver explicitly sets INDEX, which is a safe default for non-purchasable pages but needs to be deliberately overridden for real, sellable PDPs — audit this rather than assuming it's correct. Sitemap generation runs on the commerce backend, not the storefront: the SiteMapMediaCronJob triggers the SiteMapMediaJob performable class, which runs its configured list of SiteMapGenerator beans — including ProductPageSiteMapGenerator — to build sitemap XML per site, independent of whether you're on Accelerator or Composable Storefront. Confirm the cronjob is scheduled (not just configured) and that discontinued/unpurchasable SKUs are excluded rather than lingering in the sitemap.

How to validate

  • View-source vs. rendered DOM: run curl -A "Googlebot" https://yoursite.com/p/SKU123 and diff it against what you see in browser dev tools' Elements panel — if title, meta description, or JSON-LD are missing from the curl output but present in the DOM, SSR isn't serving that route.
  • Structured data: paste the live URL into Google's Rich Results Test and check for both errors and missing-recommended-field warnings, not just pass/fail.
  • Canonicals: spot-check a variant URL and confirm the <link rel="canonical"> in the raw HTML points at the base product, not itself.
  • Sitemap: fetch /sitemap.xml (or the site-specific sitemap index) and confirm recently added SKUs appear within your expected refresh window.

Verified as of July 2026 against SAP Help Portal and Spartacus documentation for Composable Storefront; SSR optimization defaults, resolver behavior, and structured-data requirements are version- and configuration-dependent, so confirm against your specific SAP Commerce Cloud release notes before treating any default as fixed.

None of this matters if the underlying product data is thin — a perfectly rendered page with three bullet points and no attributes still gives buyers and AI agents little to work with. Anglera plugs into SAP Commerce Cloud (or whatever PIM feeds it) to keep specs, use-cases, and identifiers enriched continuously, so the rendering and structured-data work above has something substantive to carry onto the page.

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