All Posts
EngineeringMay 31, 2026

Sanity on Shopify Hydrogen: Headless CMS Integration Guide (2026)

Shopify's native content management was never the strength of the platform. Custom metafields and Online Store 2.0 sections solve the simple cases. Once you have marketing teams who want to ship landing pages weekly, brand campaigns that span multiple regions, or editorial content that lives alongside the catalog, the native tooling runs out. Hydrogen makes the gap obvious because content rendering moves into your application code and your CMS choice becomes a first class architectural decision.

Shopify's native content management was never the strength of the platform. Custom metafields and Online Store 2.0 sections solve the simple cases. Once you have marketing teams who want to ship landing pages weekly, brand campaigns that span multiple regions, or editorial content that lives alongside the catalog, the native tooling runs out. Hydrogen makes the gap obvious because content rendering moves into your application code and your CMS choice becomes a first class architectural decision.

Sanity is the headless CMS we reach for most often on enterprise Hydrogen storefronts. The reasons are practical: real time collaboration that brand teams actually use, a content model expressive enough for editorial use cases without being baroque, and a query language (GROQ) that maps cleanly onto the access patterns Hydrogen needs. This is the architecture, the data flow, and the operational details that matter.

What Sanity and Shopify Each Own

The first decision in any Sanity plus Shopify integration is the source of truth question. Get this wrong and you spend the project arguing about sync direction.

The right split:

  • Shopify owns: products, variants, inventory, pricing, customer accounts, orders, checkout, payment, fulfillment. Anything transactional or commercial.
  • Sanity owns: page structure, marketing content, brand assets, editorial copy, navigation, promotional banners, landing pages, blog content, product descriptions when richer than Shopify's HTML allows.
  • Shared (referenced from Sanity, sourced from Shopify): product cards on marketing pages, collection imagery, hero product callouts, anywhere editorial content references commerce data.

The shared zone is where most projects go wrong. The temptation is to duplicate product data into Sanity so the CMS feels self contained. Don't. Shopify is the source of truth for product data, period. Sanity references products by ID, fetches the live data at render time, and only stores supplementary content (custom imagery, editorial copy, campaign tags).

The Content Model

A working content model for a mid sized brand on Hydrogen plus Sanity looks roughly like this:

// schemas/page.ts
export default {
  name: 'page',
  type: 'document',
  fields: [
    { name: 'title', type: 'string' },
    { name: 'slug', type: 'slug', options: { source: 'title' } },
    {
      name: 'sections',
      type: 'array',
      of: [
        { type: 'heroSection' },
        { type: 'productGridSection' },
        { type: 'editorialSection' },
        { type: 'collectionFeatureSection' },
      ],
    },
    { name: 'seo', type: 'seoMetadata' },
  ],
}

// schemas/productReference.ts
export default {
  name: 'productReference',
  type: 'object',
  fields: [
    {
      name: 'shopifyProductId',
      type: 'string',
      validation: (Rule) => Rule.required(),
    },
    { name: 'customTitle', type: 'string' }, // optional override
    { name: 'customImage', type: 'image' },  // optional override
    { name: 'campaignTag', type: 'string' }, // editorial only
  ],
}

Two patterns matter here.

First, the section based page builder. Marketing teams want flexibility without engineering involvement on every campaign. A sections array of typed section objects lets editors compose pages from approved building blocks. Each section type maps to a Hydrogen component. New section types are an engineering deliverable; new page assemblies are not.

Second, the product reference object. Sanity stores only the Shopify product ID and any editorial overrides. The product data itself (price, availability, default image, variant options) is fetched live from Shopify at render time. This means inventory changes in Shopify reflect immediately on Sanity rendered pages without any sync pipeline.

The Fetch Pattern in Hydrogen

The Hydrogen loader pattern composes a Sanity query and a Shopify Storefront API query in parallel, then joins them at render time. The shape:

// app/routes/pages.$slug.tsx
import { json } from '@shopify/remix-oxygen';
import { sanityClient } from '~/lib/sanity.server';

export async function loader({ params, context }) {
  const sanityQuery = `
    *[_type == "page" && slug.current == $slug][0] {
      title,
      sections[] {
        _type,
        ...,
        _type == "productGridSection" => {
          products[] {
            shopifyProductId,
            customTitle,
            campaignTag
          }
        }
      }
    }
  `;

  const page = await sanityClient.fetch(sanityQuery, { slug: params.slug });

  if (!page) throw new Response('Not Found', { status: 404 });

  // Collect product IDs from all sections
  const productIds = collectProductIds(page.sections);

  const { products } = await context.storefront.query(PRODUCTS_BY_ID_QUERY, {
    variables: { ids: productIds },
  });

  return json({ page, productMap: keyBy(products, 'id') });
}

Two requests, both cached at the edge, joined in the loader. The Sanity request is cached aggressively because content changes are editorial events; the Shopify request is cached for shorter windows because inventory and price change.

Hydrogen 2025's cache primitives make this clean. CacheLong for Sanity content (revalidate on webhook), CacheCustom with a 60 second SWR window for Shopify product data, and CacheNone for cart or session state. Get the cache strategy right and your origin load drops to near zero.

Preview is the Operational Gotcha

The single biggest project failure mode for Sanity plus Hydrogen is preview. Marketing teams expect to see draft content rendered in the actual storefront before publishing. Out of the box, neither Sanity nor Hydrogen handles this elegantly.

The pattern that works:

  1. Sanity emits a signed preview URL that hits your Hydrogen storefront with a ?preview=token parameter.
  2. A middleware on the storefront verifies the token (Sanity provides a JWT verification utility), sets a preview cookie, and forwards the request.
  3. The Sanity client in preview mode uses the drafts. perspective and useCdn: false to read unpublished documents.
  4. Sanity's Presentation tool can render the live storefront in an iframe with click to edit overlays mapped to the section types.

The Presentation tool is the killer feature here and the reason Sanity wins over Contentful for editorial heavy stores. Editors click on a section in the rendered preview and the corresponding document opens in the Studio. There is no context switch, no copy paste of slugs, no "which document am I editing again" confusion. We covered the CMS comparison in Sanity vs Contentful vs Strapi for headless CMS in 2026.

Webhooks and Cache Invalidation

When content publishes in Sanity, the storefront cache needs to invalidate. The pattern:

  1. Sanity webhook fires on publish with the document type and slug.
  2. Storefront endpoint receives the webhook, verifies signature, and issues cache purges for the affected URLs.
  3. For Cloudflare or Vercel hosted storefronts, this is a tag based purge: pages cached with the tag sanity-page-${slug} get invalidated.

Two failure modes to design around. First, slug changes. If an editor renames a page slug, the old URL still points at cached content. The webhook needs to invalidate both the old and new slugs, which means storing the previous slug as a Sanity field or using the document history to diff. Second, reference cascades. If a heroSection document is updated and it's embedded in five pages, all five need to invalidate. This is where Sanity's references GROQ function earns its keep.

Performance Numbers

On a typical enterprise Hydrogen storefront with this architecture:

MetricNative ShopifyHydrogen + Sanity
TTFB (homepage)240ms80ms (edge cached)
LCP (homepage)1.8s1.1s
Editorial publish to live5-15 min (theme deploy)5-30 seconds
Custom landing page time to ship4 to 12 hours30 to 90 minutes

The performance gains are real but the operational gains are bigger. The thing that matters most for brands at scale is publish velocity. The difference between editorial teams shipping a new campaign page in 30 minutes versus waiting for an engineering theme deploy is the difference between a brand that responds to market events and one that doesn't.

When Sanity Plus Hydrogen Is the Wrong Choice

This is a real architecture commitment. The cases where it's not the right call:

  • Catalog driven brands without significant editorial content. A flowers shop selling 200 SKUs with seasonal photography does not need this stack.
  • Teams without React engineering capacity. Hydrogen is React. Sanity is JavaScript. If your team is Laravel or Rails, this stack is the wrong investment.
  • Brands committed to Shopify Online Store 2.0 sections and the Theme Editor workflow. Migrating off the Theme Editor is a substantial cultural change for merchandising teams. Don't underestimate it.
  • B2B catalogs with complex account specific pricing and entitlement. Hydrogen handles this, but the routing logic complexity climbs fast.

For brands that fit the profile (sizeable catalog, active editorial team, strong React capacity, performance constrained on native Shopify), Sanity plus Hydrogen is the architecture we have shipped most consistently and is what we recommend by default at this point.

When This Applies to Your Stack

If you are running Shopify Plus and your marketing or editorial team is consistently bottlenecked on engineering for content changes, the math on a headless migration starts to work. Sanity plus Hydrogen is the path with the lowest operational risk for brands in the $20M to $500M revenue range. Above $500M you should also evaluate Contentful enterprise and commercetools for B2B workloads.

At Contra Collective we have led migrations from Shopify Liquid themes to Hydrogen plus Sanity for enterprise brands with catalogs from 5,000 to 200,000 SKUs. The architectural patterns above are what we have battle tested. If you are evaluating a headless migration or scoping a Hydrogen build, we can help you scope the content model, the cache strategy, and the editorial workflow before any code gets written.

FAQ

Why not just use Shopify's native metaobjects and metafields for editorial content?

Metaobjects work for structured product enrichment (size guides, ingredient lists, fit notes). They do not work as a page builder for marketing campaigns because the authoring experience is built around individual records, not page composition. Once you need draft preview, scheduled publish, multi region content, or editorial workflows, you have outgrown metaobjects.

Can I use Sanity with Shopify Liquid instead of Hydrogen?

Yes, but you lose most of the architectural advantages. The Liquid template language cannot make HTTP requests at render time, so all Sanity content has to sync into Shopify metafields or live in a sidecar app. The sync pipeline becomes the project. Hydrogen's loader pattern is what makes this architecture clean.

How does Sanity compare to Contentful for Shopify Hydrogen?

Sanity's Presentation tool, real time collaboration, and Portable Text are stronger for editorial workflows. Contentful has better enterprise governance features and more mature localization. We covered the head to head in Sanity vs Contentful vs Strapi for headless CMS.

What is the realistic cost of Sanity at enterprise scale?

Sanity's Growth tier handles most mid sized brands. Enterprise tier pricing depends on document count, API request volume, and seat count, typically landing between $30K and $150K annually for brands in the range we see. That is comparable to Contentful enterprise and meaningfully less than Adobe Experience Manager.

Does Sanity support multi region content for international Hydrogen storefronts?

Yes, through internationalized field arrays and document level locale tagging. The pattern that works at scale is locale specific document trees with shared assets, queried by locale in the Hydrogen loader. Combine with Shopify Markets for commercial localization and the model holds.

[ 02 ] — Keep Reading

More from the lab.

Jun 8, 2026Engineering

CrewAI vs AutoGen: Multi-Agent AI Frameworks for Enterprise Teams in 2026

Multi-agent AI systems crossed a threshold in 2025. They moved from research curiosity to production infrastructure at companies that can afford to find out what breaks. The frameworks that emerged to manage these systems now face the same scrutiny any production dependency faces: stability, debuggability, vendor lock-in, and the cost of the person who maintains it at 2am when something fails.

Ready when you are

Want to discuss this topic?

Start a Conversation