The engineer's guide to content operations [E-commerce edition] (ssr)
Written by John Siciliano
Missing Image!
Why can some teams launch global campaigns in minutes (đź‘‹ Tecovas) while yours is still waiting on a homepage swap?
Hint: It’s not their CMS. It’s their architecture.
The best teams don’t scale by adding headcount or hacking together workflows.
They build systems around their team and operations.
Not a custom CMS, but a stack built on structured content, developer primitives, and programmable workflows.
Fully customizable. Minimal maintenance. Built to scale.
Why now? Delay has real costs.
Commerce teams are creating more content for more surfaces with smaller teams and higher expectations. But most systems were built for publishing, not operations.
AI can't work without structured, queryable content. New surfaces mean more duplication without reuse. Each workaround adds technical debt, and replatforming becomes inevitable.
Sanity gives you the infrastructure to move faster and adapt to whatever comes next. Structured content, programmable workflows, and automation-ready architecture built for scale.
This guide shows the architecture, code snippets, and workflows behind high-velocity, scaling e-commerce teams.
The brands you'll see:
- Tecovas – Western boots and apparel, known for craftsmanship and rapid product drops.
- SKIMS – Kim Kardashian’s shapewear and loungewear brand with a massive global presence.
- Lady Gaga – The artist’s official storefront, featuring exclusive merch and creative campaigns.
- Sanetti – A premium cycling brand built by Sanity to demo complex e-commerce workflows (without NDAs or blurred screenshots).
But first, what’s everyone dealing with right now?
The current state of e‑commerce content ops
E-commerce teams are under pressure to move faster with less.
Customers expect personalized, localized, story-driven experiences across every channel. But most content systems still assume you're shipping static pages, not orchestrating real-time campaigns. AI, automation, and structured content are now table stakes.
Here’s what we’re seeing:
- AI is used to translate entire collections.
- Sales, product drops, and regional promotions still require manual updates across multiple markets, often under tight deadlines.
- Headless CMSes made front ends more flexible, but editorial workflows are still siloed, slow, and hard to scale.
- PDPs are evolving from spec sheets into brand storytelling surfaces with embedded video, longform copy, and dynamic modules tailored by market.
- Teams are expected to support more channels, languages, and surfaces without scaling headcount or adding dev dependencies.
The most forward-looking teams are rethinking how content gets planned, modeled, and delivered, not just how it gets displayed.
Why e‑commerce teams hit a wall
The commerce platform doesn’t matter as much as it used to. They can all sell a product online, whether it’s Shopify, Magento, SFCC, BigCommerce, or Commerce Tools. The real challenge is everything that happens around the product: localized campaigns, seasonal storytelling, personalized promotions, and managing all of it across markets without scaling your team.
Here’s where content operations start to break down:
- Multi-market content is a mess. Launching in five regions means managing five versions of the same content. Every region duplicates efforts.
- Campaigns live in spreadsheets and Slack threads. There’s no single source of truth, so updating a banner means chasing down URLs, translations, and image variants across tools.
- Personalization is talked about more than it’s implemented. Targeting VIP customers or tailoring content by UTM parameters is theoretically possible, but operationally out of reach for most teams.
- Content teams rely too heavily on devs. Even minor updates, like tweaking PDP copy or scheduling a homepage swap, often require an engineer’s time.
- Tech is holding them back. Even with headless stacks and composable platforms, most teams still rely on rigid models, duplicated content, and manual processes that don’t scale.
The shift doesn’t happen because someone wants a shinier CMS. It happens when the cost of doing things the old way gets too high. What starts as fixing one pain point becomes an opportunity to rethink how content moves through your organization—not just how it’s stored or displayed but also how it’s modeled, governed, reused, and orchestrated. I.e., how companies can leverage a Content Operating System.
What is a "Content Operating System"?
You’re already running a content system (even if you didn’t mean to).
It’s the spreadsheets, Slack threads, and last-minute dev requests that hold everything together. Launching a sale means chasing down banners, image variants, and approvals and duplicating those efforts across markets.
A Content Operating System replaces that with actual infrastructure: structured content, developer tooling, and workflows that match how your team operates, not just how content looks but also how it moves.
This guide shows our customers’ architectures in five stages of content operations:
- Plan and govern – Model complex product data, evolve without rewrites, and enforce smart rules that guide editors without blocking them.
- Create and manage – Build editing tools that fit your teams’ exact workflows, from full-featured CMSes to single-purpose custom apps.
- Distribute and automate – Efficiently launch campaigns across languages, regions, and surfaces.
- Analyze and optimize – Link content variants to conversion data, run experiments, and personalize without ballooning scope.
- Extend and integrate – Connect to your stack (PIM, ERP, DAM, storefront) with real-time sync and zero infrastructure headaches.
The Content Operating System is built to be shaped. It includes editors, workflows, and data models. Every part is customizable to match how your team works.
This guide shows how engineers at brands like Tecovas, SKIMS, and Lady Gaga moved from managing content to orchestrating it. It’s not about switching CMSes. It’s about building systems that scale with your business.
1. Planning and governing: Architecting your "foundation"
In this section, we'll explore:
- Why "foundation" is in quotes
- The technical features that enable a fluid data model
- How Tecovas models products, colorways, and variants
- How to enable editors to create multi-market campaigns at scale
- Putting precise governance policies in place
The perfect foundation trap
Starting from a blank slate feels like the best opportunity to get it right this time. No more duplicated efforts per market. Let's finally fix our wonky colorways and structure of variants.
Of course, you want to learn from and fix the shortcomings of your current system. However, even if you design the perfect model today, it will slowly calcify as your business evolves (e.g., new product types, seasonal campaigns, unexpected market requirements, etc.).
Most companies are forced into an impossible choice:
- Invest months in an exhaustive content model that tries to anticipate every future need.
- Or build something quick and simple that you'll painfully outgrow within months.
What if your foundation wasn't fixed in concrete but could adapt organically as your needs change? Let's learn how your competition keeps shipping while your developers are stuck maintaining increasingly complex workarounds, and editors spend too much time on manual processes.
Make it work → Make it right → Make it fast
With Sanity, you can follow the classic dev mantra: make it work, make it right, make it fast. Start by shipping something that works. See how it performs. Then refactor and optimize once you understand what’s needed.
These are the technical features unique to Sanity's infrastructure that make this possible:
- Schemaless data store: Without rigid structures, you have the flexibility to add, remove, or modify fields without breaking existing content. If your existing content requires modifications, you can use the Migration API.
- Migration API: Structure changes happen. Not a problem. Use the CLI to create and run migrations (shout out
-dry-run
flag). - Marking fields as deprecated: Even small things like marking a field as deprecated when it's at the end of its lifecycle support the evolving data models.
- AI assistance: Because the foundation is in code, you can unleash your favorite agentic coding tool.
This is why “foundation” is in quotes. Sanity doesn’t treat your architecture as a rigid, fixed system. As you learn what works and what doesn't, you can adapt your content system. Thanks, developer tooling.
While the definition of "perfect" will change, let's explore how Tecovas models the trickiest parts of e-commerce.
How Tecovas solved the products, colorways, and variants architecture
E-commerce data is highly relational. So, this begs the question: How do we model our data to enable maximum reuse and flexibility for those edge cases?
Tecovas needed a product model that separated core product information from color-specific details while abstracting away variant complexity. This would enable them to define global product information once and optionally add specific information to colorways, such as care guides.
Before we look at Tecovas, let's look at a simple schema type to ease us into a more complex one:
import { defineType, defineField, defineArrayMember } from 'sanity'
// Simple schema for e-commerce
export const productType = defineType({
name: 'product',
title: 'Product',
type: 'document',
fields: [
// Basic product information
defineField({
name: 'name',
title: 'Product Name',
type: 'string',
validation: Rule => Rule.required()
}),
defineField({
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'name'
},
validation: Rule => Rule.required()
}),
// Product details
defineField({
name: 'price',
title: 'Price',
type: 'number',
validation: Rule => Rule.required().positive()
}),
defineField({
name: 'images',
title: 'Product Images',
type: 'array',
of: [{ type: 'image' }]
})
]
})
Tecovas’ product data model separates base products from colorways. Shared content like name, description, and sizing lives on the product. Colorways are their own documents referenced from products, so editors can override things like imagery or marketing copy when needed.
+-------------------+
| Product |
|-------------------|
| Name |
| Description |
| Sizing |
| [Colorways] ------+----+
+-------------------+ |
|
v
+-------------------+
| Colorway |
|-------------------|
| Color |
| Images (override) |
| Marketing copy |
+-------------------+
For example, Tecvoas uses a separate “care guide” document type, which defines instructions on the PDP based on the colorway the user selects.
+--------------------+
| Care Guide |
|--------------------|
| Instructions |
| Applies to: |
| [Colorways] -------+
+--------------------+

If the user selects the "Scotch" colorway, they'll see instructions for “Polish and shine,” but if they choose “Sand/Bone,” the care instructions will now read "DO NOT condition or polish." This happens automatically because Tecovas treats content as data.
Here's what the colorway field looks like:
defineField({
name: 'selectedColorways',
title: 'Selected Colorways',
type: 'array',
of: [
defineArrayMember({
type: 'reference',
to: [{ type: 'colorway' }],
options: {
filter: ({ document, parentPath }) => {
const parentsParent = findParentsParent({ parentPath, document })
return {
filter: `_type=="colorway" && _id in *[_type=="product" && _id==$productId].colorways[]._ref`,
params: {
productId: parentsParent.product._ref,
},
}
},
},
}),
],
})
This model gives them reusable content at the product level, override capability at the colorway level, and a cleaner editorial experience without variant clutter. When product requirements change, they evolve their model without starting from scratch.
This architectural approach reduced Tecovas’ product launch time from two weeks to around 20 minutes and empowered their editorial team to make content changes without developer intervention.
Enabling editors to create campaigns (with a fraction of the effort)
Most teams end up with creative marketing ideas bottlenecked by development capacity, leading to delayed campaigns and frustrated teams.
As you define your data models, consider how to empower editors to create campaigns without developers. And to do it well, empower them to use bespoke designs without stepping outside the design system. You’re not just avoiding repetitive engineering work; you’re enabling speed, scale, and brand consistency.
Content is data. That's a fundamental belief of Sanity. Site-wide banners, heroes, product carousels, feature grids, and CTAs are no different. These become reusable layout components that editors can compose safely and flexibly, all within the constraints of your design system.
Let's explore how to enable editors to create award-winning shopping experiences and launch multi-market campaigns without duplicating efforts per market or filling up the engineering backlog.
How Lady Gaga's editorial team owns 9/10 website updates (and wins awards)
This isn't just about spinning up cookie-cutter product detail pages. Lady Gaga's creative vision demands much more, like dynamic visuals and interactive shopping experiences.
In fact, their editorial team now owns 9/10 website updates, including creating four homepages and a site that won them three industry awards.
Editors can run with it because the engineers built a library of blocks, such as heroes, mood pickers, and album displays. Each maps to a front end React component that uses TypeScript to ensure the presentation matches the schema.
With live preview, there are no surprises. The team sees exactly how updates will look before publishing, something especially critical during high-stakes moments like Grammy-night launches.
Lady Gaga's team turned homepage launches into editorial plays by treating landing page content as data.
How Sanetti scales seasonal campaigns with structured content
Zoom out to something like Black Friday, and the problem shifts from creativity to scale. Every market, page, and product needs updating. Without structured content, teams hardcode links, duplicate blocks, and scramble to clean up when the sale ends. Efforts are multiplied by locales, regions, and surface areas.
Sanetti solves this by modeling campaigns as structured, referenceable content.

A single campaign document contains:
- Hero copy
- Supplemental terms and conditions
- Exit modal copy
- Side cart copy
- Inline editorial callouts
- PDP copy
- Scheduling, including start and end dates
This single document contains the promotional data, including translations and the ability to define market-specific promotions.
Sanetti’s team queues up promotions ahead of time, previews them on the live site, and launches confidently. They don’t worry about 404s, duplication, or cleanup. Structured content isn’t just a dev convenience; it’s the only sustainable way to operate at e-commerce scale.
With great editorial power comes... very few issues?
Actually, yes.
Beyond providing blocks to build pages that stay within the design system, there are governance policies that ensure editors create compliant content that looks great on the front end.
You can create context-aware validations, conditional fields, and custom inputs that guide editors toward correct content without blocking their workflow. Since these rules are defined in code, they can incorporate your specific business logic, access real-time data, and evolve alongside your content model.
Unlike UI-based systems, Sanity gives you several powerful tools to create precise editing experiences:
- Custom validation rules with full access to document context:
defineField({
name: 'salePrice',
type: 'number',
validation: Rule => Rule.custom((value, context) => {
// Only validate if this is a sale item
if (!context.parent.onSale) return true
// Ensure sale price is lower than regular price
if (!value || value >= context.parent.regularPrice) {
return 'Sale price must be lower than regular price'
}
// Ensure minimum margin requirements
const margin = 1 - (value / context.parent.cost)
if (margin < 0.15) {
return 'Sale price does not meet minimum margin requirements'
}
return true
}),
})
- Conditional fields that appear only when relevant:
defineField({
name: 'shippingRestrictions',
type: 'object',
// Only show for physical products
hidden: ({ parent }) => parent?.productType !== 'physical',
fields: [
defineField({
name: 'restrictedCountries',
type: 'array',
of: [{ type: 'string' }]
}),
defineField({
name: 'restrictionReason',
type: 'string',
// Only require if there are restrictions
validation: Rule => Rule.custom((value, context) => {
if (context.parent?.restrictedCountries?.length > 0 && !value) {
return 'Please provide a reason for shipping restrictions'
}
return true
})
})
]
})
For example, Tecovas configured a custom validation rule that prevents editors from creating CTAs that will wrap on the front end, ensuring the CTA is easily scannable and converts the best.
Rule.custom((value, context) => {
const ctaContext = context as CTAContext
if (ctaContext.parent.uiStyle !== 'button' || !value || value.length <= 40) {
return true
}
return 'Text after 40 characters will cause word wrapping'
})
By implementing these precise guardrails, teams dramatically reduce the number of issues that reach production.
Because Content Lake is schemaless, all of this shape-defining is for the editing tools.
"Tools" plural?
Yes. The way you manage content should be as flexible as you model it.
Let's explore how companies configure the default editing interface, Sanity Studio, build custom editing experiences with App SDK, and define custom editorial workflows to move products from merchandising to live (in 20 minutes).
2. Content creation and management: Interfaces built for how you work
In this section, we'll explore:
- How the editing interface is generated from your content model
- Why teams like Sanetti and Tecovas run multiple studios with role-specific access
- When to extend the studio vs. build a custom app with App SDK
- How SKIMS launches coordinated content drops across products, blogs, and banners
- When code can make editing easier (not harder)
Most platforms treat the CMS UI as the starting point. Sanity flips that. You define your content model, and the interface is generated from that. Add a new field to your schema? The input shows up in the UI.

Let’s briefly learn about Sanity’s architecture, then look at how Sanetti splits their editing experience across multiple studios and how SKIMS uses structured releases to coordinate high-stakes launches down to the minute.
A quick primer on the Sanity architecture
When defining the shape of your content, you govern how the editing tools write data to the content database, Content Lake.
You can interact with Content Lake in many ways, from developer-centric mediums such as automation scripts to editor-centric interfaces such as Sanity Studio or custom apps made with App SDK.
Let's take a step back and look at the entire Sanity Operating System to explain the different interconnected layers:
- Content Lake (content database)
- Compute and AI (business logic)
- APIs and SDKs (developer tools)
The Sanity Dashboard for running your content operations apps, such as:
- Studio (customizable CMS)
- Media Library (asset management)
- Canvas (AI-powered content creation)
- Your custom-built apps (using the App SDK)
When you modify your schema, Sanity Studio automatically generates the UI. Sanity Studio is an open-source React app that is fully customizable. However, drastic customizations are more time-consuming and challenging than spinning up a custom app using App SDK, the primitives that could essentially build Sanity Studio.
Studios don't just differ from company to company, they can differ within a single company.
Why Sanetti uses multiple studios
Your content operations are only as efficient as the tools to manage them.
Sanetti serves multiple markets and has different teams that manage the content across the surfaces. For example, they have a marketing team that updates global website content and a team that manages just the merchandising for the U.S. market.
Studios are customizable windows into Content Lake, so why serve these different audiences the same window? Doing so would create a lot of visual noise and might open the doors for the wrong content to be edited (Hola World).
Sanetti uses multiple studios and assigns permissions based on each person’s needs. This way, editors can log in and get to where they need to much faster and remove things that aren't for that team altogether.
...
// Sanetti's Studios
export function workspaces({dataset}: {dataset: string}): WorkspaceOptions[] {
return [
defaultWorkspace({dataset, languages: supportedLanguages}),
marketingSiteIntWorkspace({dataset, languages: supportedLanguages}),
marketingSiteUsaWorkspace({dataset, languages: [getLanguage('en-US')]}),
adminUsaWorkspace({dataset, languages: [getLanguage('en-US')]}),
];
}
This is a typical pattern when you want to:
- Give different user roles access to different content types
- Separate concerns (marketing vs admin content)
- Provide region-specific editing experiences
- Limit complexity by showing only relevant document types per workspace
Regardless of the studio, what happens when "Publish" is clicked? Whatever you want! Execute serverless code, run AI automations, or start an editorial workflow. Let's now look at how SKIMS moves products from merchandising to live with Content Releases (we'll look at AI & automation in a later section).
How SKIMS batch launches content at the exact time they plan
A new product drop is coming soon. It requires a new product collection, a blog post, and promotional content like banners and CTAs. And it all needs to drop at exactly 8:00 am EST.
What do you do?
Answer: Create a new release in Sanity Studio (via the UI or programmatically), make all the changes in the latest drop, and set the release to go live at 8:00 EST.

Content Releases lets you bundle related content changes together, preview how they’ll appear as a cohesive unit, and push out the updates simultaneously via a defined time or a manual approval.
When they need to end the promotion, they schedule another release setting it back to the default.
If there are unique promotions every day for a week, then they set a release for each day and sit back as the schedule handles getting everything live and reverted on time.
Tables, calendars, maps, and grids with App SDK
Sanity Studio is optimized for editing single documents. It is fully customizable, but if your editorial needs diverge significantly from its core patterns, it can be faster to build a custom editing interface using the App SDK.

App SDK provides the primitives that make up Sanity Studio, primarily React hooks, that enable the same affordances in the studio, such as real-time updates and authentication. App SDK does all the heavy lifting for building a native Sanity app.
Studio is likely where the majority of editing will be done, but what if merchandisers need to edit multiple products at once, such as updating badges across a seasonal collection, adjusting pricing for a flash sale, or tagging low-stock items for de-prioritization in search?

The following is a lightweight React component that fetches a list of product
documents. It supports filtering, pagination, and real-time updates, so any changes made elsewhere (like in the studio or an API) will automatically reflect in the UI without a manual refresh.
import {useDocuments} from '@sanity/sdk-react'
// A simple, reactive product list with real-time updates and pagination
export function ProductList() {
const {count, data, hasMore,loadMore} = useDocuments({
documentType: 'product',
search: searchTerm,
batchSize: 10,
orderings: [{field: '_createdAt', direction: 'desc'}]
})
return (
<div>
<ol>
{data.map((doc) => (
<li key={doc.documentId}>
<MyProductComponent doc={doc} />
</li>
))}
</ol>
{hasMore && <button onClick={loadMore}>Load More</button>}
</div>
)
}
Because the React hooks do the heavy lifting and are deployed to Sanity, they are quick to spin up and require minimal maintenance. That's why Sanetti spins up apps that make editors even a 🤏 more efficient, such as the store hours app.
Sanetti owns four physical locations, and editors need to update store hours for holidays and other scenarios. While the document list approach in the studio is not rocket science, it is not the most efficient way for store managers to update hours.

They built a store hours app that lets editors see and update hours across all their stores in one intuitive view. They don't need training or to think in terms of CMS.

// A partial snippet of code from the Store Hours app.
// It generates a table of stores and days for editing.
...
export function StoreHoursTable() {
const {data} = useDocuments({
documentType: 'locations',
batchSize: 10,
orderings: [{field: 'group_locationOverview.field_locationName', direction: 'desc'}],
})
return (
<Card>
...
<TR>
{Object.keys(columns).map((column) => (
<TH key={column}>{column}</TH>
))}
</TR>
...
{data.map((row) => (
<Row documentHandle={row} key={...} />
))}
</Card>
)
}
3. Distributions and automation: Getting content live, everywhere
In this section, we'll explore:
- How SKIMS and Tecovas prevent overselling with the Live Content API
- How “publish” can trigger serverless functions, not just a status change
- How Sanetti scales global promotions without duplicating effort
- How translations can be programmatic, not manual
Publishing content isn’t the finish line. It’s the starting point for orchestration.
Localized banners, inventory-aware PDPs, scheduled product drops, and personalized experiences all require structured content and automation. You can’t brute-force that with spreadsheets and Slack.
That’s why leading teams don’t just “publish.” They sync. They trigger. They orchestrate.
Let’s look at how Tecovas and SKIMS distribute fresh content to every region and channel without busting cache or creating extra work for developers.
How Tecovas and SKIMS never oversell products and keep inventory numbers up to date (without busting cache)
SKIMS and Tecovas were facing two similar issues:
- SKIMS: Would oversell a limited drop because the product would sell out while users were on the PDP
- Tecovas: Would oversell inventory because their cache would show in stock
How did the engineers at these companies ensure both high-performance apps and selling no more inventory than they had in stock?
They use the Live Content API. With just a few lines of code, their apps receive pushed changes, so as soon as Content Lake shows zero inventory, the front end does as well.
// Implementing the Live Content API
import { client } from "@/sanity/client";
import { defineLive } from "next-sanity";
const { sanityFetch, SanityLive } = defineLive({ client });
export default async function Page() {
const {data: products} = await sanityFetch({ query: PRODUCTS_QUERY });
return (
<section>
{products.map((product) => (
<article key={product._id}>
<a href={`/product/${product.slug}`}>{product.title}</a>
</article>
))}
<SanityLive />
</section>
);
}
The Live Content API sends events when fine-grained changes occur, so the CDN is only partly invalidated. This change is propagated throughout the CDN and to individual end-users. Even under high-traffic scenarios with fast-moving events, such as Black Friday sales or limited edition releases, your application's data will be as fresh as the source from which it is consumed.
Overselling can only be a byproduct of high uptime. So, let’s take a step back and see how companies like SKIMS ensure issue-free Black Friday sales.
Supporting millions of visitors on BFCM
Whether it's Black Friday, Memorial Day, or insert your reason for a big push, uptime is paramount. For eight and nine-figure e-commerce businesses, downtime means millions in lost sales.
Sanity is fully managed and globally available. We handle the cloud-hosted backend with automatic scaling and global edge delivery.
Even in a rare "internet outage" (you know the ones where AWS or GCP have an outage and affect every other service from Netflix to GitHub?), your content will still be delivered using the multi-layered CDN architecture.
How it works:
- Content is cached at the edge
- If a cache is stale, it’s refreshed in the background
- Systems stay responsive even during spikes or outages
With the Live Content API, what’s in Content Lake is what’s on your site, even under pressure.
Beyond the technical safeguards, there's a human layer of support: a team of Sanity engineers and support staff monitoring and ready for any curveballs. Our monthly check-in calls are an excellent opportunity to communicate upcoming drops (among many other things).
When your platform handles the traffic without a hitch, you can focus on delivering the important things.
Lady Gaga's team didn't need to build a single API. Here's how.
E-commerce front ends require extensive business logic to handle things like product availability, pricing rules, promotional banners, and personalized content. With GROQ, Lady Gaga’s team could express all that logic directly in content queries, meaning they didn’t have to write or maintain a custom endpoint.
GROQ has been crucial for us. With Sanity, we can shape the data exactly how we need it, right at the query level, without writing custom API endpoints. That saved us a huge amount of development time and made our content models way more flexible. - Michael Klim, CTO, Commerce-UI
While Sanity supports GROQ and GraphQL, the former is recommended because it enables you to express SQL-like logic in a JSON superset syntax.
// Find all products that are 'onSale' and have 'stock' less than 5
*[_type == "product" && onSale == true && stock < 5] {
_id,
name,
price,
salePrice,
stock,
// Calculate the discount percentage on the fly
"discountPercentage": round((1 - (salePrice / price)) * 100 * 100) / 100, // Round to 2 decimal places
// Conditionally project 'isSuperDeal' based on category and calculated discount
"isSuperDeal": select(
category->name == "Electronics" && ((1 - (salePrice / price)) * 100) > 25 => true,
false
)
}
Images will often be part of your GROQ queries. Let’s explore how companies like SKIMS handle images.
Enabling editors to create properly formatted images for all devices
Defining an image field for editors and rendering what they upload on the front end is risky business, even if you add validations for size and dimensions.
That's why companies like SKIMS, Sanetti, and many Sanity users set focal points, enabling editors to point and click where the central point of the crop should be. They also set preview images using custom aspect ratios to remove the guesswork of how they will render across different surfaces.
For e-commerce brands, this small detail can directly impact conversion. Take this image from SKIMS, for example:

Without focal point, the buyer can't tell what the product is and even if they knew it were pants, the buyer doesn't haven enough info to know if they like them.
Here is the same product in a collection:

Thanks to focal point, the crop ensures the full product remains in view.
This single source of truth enables properly displayed images on all surfaces from product grids and lifestyle galleries to in-store displays and mobile apps.
This is what SKIMS does to optimize images
A page on SKIMS can have over 100 images, such as Best Sellers. Editors upload raw images, including 26 MB GIFs that would result in terabytes of bandwidth for a single image.

Unoptimized images reduce conversions and incur increased bandwidth fees.
With a quick fix, SKIMS reduced bandwidth for their highest-traffic images by 92%.
They use the optional built-in image pipeline that modifies images on the fly just about any way imaginable (crop, blur, compress, resize, invert, etc.).
SKIMS uses the following image strategies:
- Format conversion: Images are served with
auto=format
, allowing the most efficient format (like WebP or AVIF) to be used based on the browser. - Focal point cropping: Parameters like
crop=focalpoint
withfp-x
,fp-y
, andfp-z
ensure that the image focuses on the most important subject area. - Responsive sizes via
srcset
: Multiple resolutions (1x to 5x) are provided so the browser can load the most appropriate version for the device’s screen. - Dynamic quality scaling: Image quality is tuned based on the device pixel ratio
- Fixed dimensions: A consistent width (
w=600
) is specified to prevent oversized downloads and enforce layout consistency. - On-the-fly image transformation: All adjustments (format, crop, size, quality) are performed via URL parameters at request time, avoiding the need to export or store multiple versions of each asset manually. For format conversions, the fastest will run first (WebP), and AVIF will be queued up and automatically served when it’s ready and if the requester supports it.
// A sample image component.
import imageUrlBuilder from '@sanity/image-url'
const builder = imageUrlBuilder(client)
function urlFor(image) {
return builder.image(image)
}
export function ResponsiveImage({ image }) {
const base = urlFor(image)
.format('auto')
.fit('crop')
.crop('focalpoint') // respects hotspot/crop data in Sanity
.url()
return (
<img
src={urlFor(image).width(600).format('auto').fit('crop').crop('focalpoint').url()}
srcSet={[
urlFor(image).width(600).format('auto').fit('crop').crop('focalpoint').dpr(1).quality(75).url() + ' 1x',
urlFor(image).width(600).format('auto').fit('crop').crop('focalpoint').dpr(2).quality(50).url() + ' 2x',
urlFor(image).width(600).format('auto').fit('crop').crop('focalpoint').dpr(3).quality(35).url() + ' 3x',
urlFor(image).width(600).format('auto').fit('crop').crop('focalpoint').dpr(4).quality(23).url() + ' 4x',
urlFor(image).width(600).format('auto').fit('crop').crop('focalpoint').dpr(5).quality(20).url() + ' 5x',
].join(', ')}
alt={image.alt || ''}
loading="eager"
decoding="async"
width={600}
className="inline-block w-full h-full object-cover transform bg-white bg-cover bg-center object-center transition-opacity duration-100 ease-in-out"
/>
)
}
Schema and style guide aware AI translations
Multilingual is often the Kryptonite of scale, but with AI prompts as data and the latest AI models that know your schema, translations become a strategic advantage rather than a bottleneck.
There are a few ways to kick off translations in Sanity. If every product or document needs to be available in all languages, you can trigger a serverless function on publish to handle the translation automatically. If translation needs vary by product, the editor can choose the target languages manually (same function, different trigger).
Trigger aside, here is how companies develop their translation logic in Sanity Functions using Agent Actions.
// The translation API. Run it using serverless functions, scripts, or anywhere you execute code.
await client.agent.action.translate({
// Replace with your schema ID
schemaId: "your-schema-id",
// Tell the client the ID of the document to use as the source.
documentId: "<document-id>",
// Set the operation mode
targetDocument: { operation: "create" },
// Tell Translate to set this field to the target language,
// in this case, 'el-GR'.
languageFieldPath: "language",
// Set the 'from' and 'to' language
fromLanguage: {id: "en-US", title: "English"},
toLanguage: {id: "el-GR", title: "Greek"},
protectedPhrases: [
"Sanity",
"Media Library",
"Agent Actions"
],
styleGuide: getStyleGuide(),
});
- Determine the languages to translate to. The editor can select these, or it can happen automatically based on your desired business logic.
- Create a style guide. While optional, creating a style guide for the large language models (LLMs) to reference is good practice. These can be saved as a document so editors can customize them or be hard-coded in the function.
- Execute. They can trigger on publish or editor actions.
4. Analysis and optimization: Structured personalization with measurable outcomes
Sanetti didn’t guess what content worked. They built a system to prove it. With structured content in Sanity and behavioral data in PostHog, they tied content decisions directly to conversion metrics.
Targeted content, structured rules
Sanetti needed a scalable way to personalize content. Their merchandisers wanted to tailor product messaging without duplicating effort or hardcoding logic.
They added a reusable field set for personalization rules to relevant document types where they can create variants.
export const personalizationFields = [
defineField({
name: 'personalizationRules',
title: 'Personalization Rules',
type: 'array',
of: [{ type: 'personalizationRule' }]
})
];

Each rule includes conditions (like user attributes) and a priority, turning content variants into queryable data.

Editors could now create multiple variants of a product component, each with different rules. Sanetti used GROQ to query all potential variants and selected the highest-priority match using server-side logic so the user doesn't see any flashes.
From content to experiment
Sanetti uses a serverless function to track new tests by creating experiments in PostHog on publish. PostHog is a product analytics platform that helps teams capture and analyze user interactions.
The function:
- Extracts the rules and maps them to PostHog filters
- Creates a feature flag (experiment) in PostHog
- Updates the original Sanity document with experiment metadata
await fetch(`https://app.posthog.com/api/projects/${projectId}/feature_flags/`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
key: `personalization-${document._id}`,
name: `Personalization: ${document.title}`,
filters: {
groups: variants.map(variant => ({
properties: transformRulesToPostHogProperties(variant.personalizationRules),
rollout_percentage: 100
}))
},
ensure_experience_continuity: true
})
});
This ensures that every content decision is tracked and measurable. When users interact with personalized content, PostHog captures which variant they saw and whether they converted. This data flows back to Sanity, creating a closed loop between content creation and performance.
Completing the loop
Sanetti modified the studio to display the conversion rates next to the content that generated them.

<BarChart
data={metrics.variants.map(variant => ({
name: variant.name,
value: variant.conversionRate * 100
}))}
unit="%"
label="Conversion Rate"
/>
This lets merchandisers see what worked and adjust content directly. Testing and iteration became part of daily workflows.
Sanetti made personalization part of their content model. With Sanity, optimization became a content function, not an analytics project.
5. Extending and integrations: The minimal maintenance yet fully configurable platform
A recurring theme has been discussed, though it hasn't been explicitly said yet. Sanity provides the primitives. These include React hooks, APIs, CLI tools, plugin APIs, webhooks, and serverless functions that enable you to build exactly what your business needs. But unlike most things that involve code, minimal maintenance is involved. Everything is pushed to Sanity's infrastructure. The primary maintenance task is updating packages. That's it. And with the auto-updating studio, you may not even need to do that.
The primitives are a native way to meet unique business requirements without building custom infrastructure or implementing clunky CMS customizations, often in the flavor of iframes. Whether you're integrating with your PIM, DAM, ERP, or inventory systems, the primitives ensure you're not locked into rigid workflows or limited by what comes out of the box.
How two developers at Tecovas built their stack around content
Sanity’s primitives don’t just support integration. They let you build systems that fit how your team actually works.
Tecovas wired their ERP (NetSuite), e-commerce platform (Shopify), asset library (Dropbox), and storefront (Hydrogen) into one system. A prefilled document appears in the studio when a product is added in NetSuite. Merchandisers edit and publish, which triggers a function that updates Shopify. What used to take days now takes under 20 minutes.
This pattern runs through their stack. Dropbox assets sync directly to the studio. Shopify metafields? Replaced with structured content models. Updating 10,000 SKUs before Black Friday? Done in seconds, using Sanity patch mutations and Shopify’s GraphQL sync.
The Sanity primitives enabled Tecovas to:
- Move business logic from brittle templates into configurable schemas.
- Replace spreadsheets with structured workflows.
- Automate without owning infrastructure.
- Let merchandisers manage every product without dev help.
Fewer handoffs. Less maintenance. Faster launches. The primitives shape your content system to your business, not the other way around.
How Lady Gaga syncs with Shopify
Shopify Connect synchronizes content between a Sanity dataset and your Shopify store. This gives you flexibility to use the right tools for your needs. You can take a headless approach using Shopify's Hydrogen framework and Next.js, sync data into Shopify's platform, and use Liquid or the Storefront API.
Lady Gaga's team adopted a headless approach for their storefront, using Shopify’s Hydrogen framework and integrating it with Sanity via Shopify Connect. This setup allows them to manage product data and content separately, providing flexibility and control over their digital experience.

By leveraging Hydrogen, they built a custom React-based front end that fetches enriched product data from Content Lake. Sanity Connect synchronizes product information from Shopify into Sanity, which is combined with additional content like launch copy, styling notes, and media assets. This enriched content is delivered to the storefront through Sanity’s Live CDN, ensuring real-time updates and optimized performance.
This architecture enables the team to maintain Shopify as the source of truth for product data while using Sanity to manage and deliver rich, structured content, resulting in a dynamic and immersive user experience.
For the Lady Gaga team, this means:
- Products stay in sync with Shopify’s inventory and pricing
- Merch teams get complete control over how products are presented on PLPs, PDPs, and landing pages.
Shopify handles commerce. Sanity handles content. The result is a faster, more flexible stack built for conversion and creativity.
Secure your oxygen mask before assisting others
Not because you're more important, but because you can’t help those who rely on you if you’re out of commission.
The idea holds for your content system, too. Provide engineers with the right building blocks, and the rest can actually function.
That’s why Sanity puts engineers first. We give developers flexible primitives, APIs, and complete control to natively create systems that match the team's workflows and overall content operations.
When developers have what they need, everyone benefits. Just like the teams at Tecovas, SKIMS, Lady Gaga, and Sanetti.
They scale e-commerce with small engineering teams and minimal maintenance, from modeling complex product data to launching personalized campaigns across markets. They’re not hacking around rigid platforms. They’re building structured content systems that match their workflows.
This isn’t about “going headless.” It’s about treating content as data and providing the primitives to customize it because no system will be perfect out of the box.
Structured content. Modular workflows. Real-time orchestration. All under your control.
If you’re still shopping for a CMS, zoom out. What you really need is a Content Operating System. If you’re shopping for an oxygen mask, it is best purchased from a well-modeled PDP.