Skip to content

Headless Commerce with Graph

⏱ 55 minutes advanced
📜AdvancedcommerceGraphcms

Traditional commerce platforms tightly couple the catalog, cart, and storefront rendering. This constrains frontend teams to the platform’s templating engine and deployment cycle. When the marketing team wants a campaign landing page or the mobile team needs product data, the monolithic storefront becomes a bottleneck.

Graph lets you treat the product catalog as a queryable data source. The Commerce platform remains the system of record for products, pricing, and inventory. Graph indexes the catalog and exposes it through GraphQL. Your frontend — whether React, Next.js, or a mobile app — queries exactly the product data it needs with the performance of a CDN-backed API.

┌────────────────────────────────────────────────┐
│ Commerce: Catalog Management │
│ Products, categories, pricing, inventory │
└───────────────────────┬────────────────────────┘
│ sync on publish
┌────────────────────────────────────────────────┐
│ Optimizely Graph │
│ Product index with full-text search, │
│ faceted filtering, category navigation │
└───────────┬───────────────────────┬────────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Web Store │ │ Mobile App │
│ (Next.js) │ │ (React │
│ │ │ Native) │
└──────────────┘ └──────────────┘

Set up the integration between Commerce and Graph so that product publishes trigger Graph re-indexing. The sync should include:

  • Product names, descriptions, and metadata
  • Category hierarchies and assignments
  • Pricing tiers and availability
  • Product images and media references

Verify the sync by publishing a test product in Commerce and confirming it appears in the Graph explorer within your expected latency window.

Create GraphQL queries for common storefront patterns:

Category listing with pagination:

query CategoryProducts($category: String!, $skip: Int, $limit: Int) {
Product(
where: { category: { eq: $category } }
orderBy: { name: ASC }
skip: $skip
limit: $limit
) {
items { name, slug, price, thumbnailUrl, rating }
total
}
}

Search with filters:

query SearchProducts($term: String!, $minPrice: Float, $maxPrice: Float) {
Product(
where: {
_fulltext: { match: $term }
price: { gte: $minPrice, lte: $maxPrice }
}
) {
items { name, slug, price, thumbnailUrl, category }
facets { category { name, count } }
}
}

Product detail pages need richer data including CMS editorial content:

query ProductDetail($slug: String!) {
Product(where: { slug: { eq: $slug } }) {
items {
name, description, price, sku
images { url, alt }
specifications { key, value }
relatedProducts { name, slug, thumbnailUrl, price }
}
}
}

Graph serves read-only catalog data. Cart management, pricing calculations, and checkout remain with the Commerce platform API. Your frontend calls Graph for browsing and Commerce APIs for transactional operations.

OperationSourceWhy
Product browsingGraphFast, cached, CDN-backed
Search and filteringGraphFull-text search with facets
Add to cartCommerce APIRequires real-time inventory check
CheckoutCommerce APIRequires payment processing

Headless commerce via Graph works best when you need multiple frontends (web + mobile + kiosk) consuming the same catalog, or when your frontend team prefers a modern JavaScript framework over the Commerce platform’s built-in rendering. If you operate a single storefront with simple requirements, the built-in Commerce frontend may be sufficient.