How to Integrate Dynamic Yield with Your Headless CMS
Connect Dynamic Yield to structured content so you can run personalized experiences, A/B tests, and recommendations without copying campaign copy by hand.
What is Dynamic Yield?
Dynamic Yield is a personalization and experimentation platform used by ecommerce, travel, finance, and media teams to tailor digital experiences by audience, behavior, context, and product affinity. It supports web and app personalization, A/B testing, product recommendations, triggered messages, and audience targeting. Dynamic Yield is often used by teams that need campaign decisions to happen in milliseconds while keeping product, editorial, and promotional content consistent across channels.
Why integrate Dynamic Yield with a headless CMS?
Personalization breaks down when campaign logic and content live in different places. A merchandiser updates a promo headline in one tool, a developer hard-codes a fallback in another, and Dynamic Yield serves a campaign that still references last week's offer. The result is familiar: duplicated copy, stale images, inconsistent product language, and tests that take too long to launch.
Connecting Dynamic Yield to a headless CMS category tool lets you keep experiment decisions in Dynamic Yield while keeping structured content in one source. For example, a Dynamic Yield campaign can decide that a returning shopper should see a "winter running" hero, while your content back end provides the headline, image, CTA, locale, and linked product collection. When content is structured as typed JSON in Sanity's Content Lake, Dynamic Yield doesn't need to scrape HTML or parse page blobs. It gets predictable fields.
The alternative is usually manual export work. Someone builds a CSV feed, uploads it on a schedule, checks whether image URLs are still valid, and repeats the process for each locale. With Sanity, webhooks can fire when a promotion, product story, or landing page is published, GROQ can select only the fields Dynamic Yield needs, and Functions can run the sync logic without a separate worker service. There is still mapping work to do, especially around IDs, locales, and campaign naming, but once those rules are set, the handoffs get much clearer.
Architecture overview
A typical Sanity and Dynamic Yield integration has two paths: a content sync path and a decisioning path. On the sync path, an editor publishes content in Sanity Studio, such as a promotion, campaign slot, article teaser, product collection, or localized hero. A Sanity webhook triggers on that publish event, often filtered by document type with GROQ. The webhook calls a Sanity Function or your own API route. That server-side code uses @sanity/client and a GROQ query to fetch the full document, including referenced products, image URLs, audience tags, locale, start date, end date, and canonical URL. The Function then transforms the result into the feed or item shape your Dynamic Yield account expects and calls the Dynamic Yield feed ingestion endpoint or account-specific Data Feed API with your Dynamic Yield API key. On the decisioning path, your site or app loads the Dynamic Yield Web SDK, mobile SDK, or calls the Dynamic Yield Experience API from the server. Dynamic Yield evaluates the visitor, session, context, and campaign rules, then returns a variation or recommendation set. That response can include Sanity document IDs, feed item IDs, or campaign payload fields. Your frontend renders the selected experience using content from Sanity, and sends impressions, clicks, add-to-cart events, or purchases back to Dynamic Yield through its event collection APIs. The main trade-off is ownership. Dynamic Yield should own targeting, testing, recommendations, and decision logic. Sanity should own the structured content fields, editorial workflow, localization, and publishing lifecycle. Trying to make one system do both usually creates extra work.
Common use cases
Personalized hero campaigns
Let Dynamic Yield choose the audience or variation, then render Sanity-authored headlines, images, CTAs, and links for each hero slot.
A/B tests for editorial content
Test landing page copy, promo banners, article teasers, and calls to action while keeping each variant modeled and approved in Sanity Studio.
Merchandised product recommendations
Combine Dynamic Yield recommendation strategies with Sanity product stories, collection descriptions, badges, and seasonal campaign metadata.
Localized personalized experiences
Sync locale-specific content fields from Sanity so Dynamic Yield campaigns can serve the right offer, language, and regional image.
Step-by-step integration
- 1
Set up Dynamic Yield
Create or select your Dynamic Yield site, note the section ID, and create the API credentials needed for server-side API calls. If you're syncing catalog or content items, configure a custom feed or data feed in Dynamic Yield and confirm the upload or ingestion endpoint for your account. For frontend decisioning, install the Dynamic Yield Web SDK on your site, or plan to call the Experience API from your server.
- 2
Model personalization-ready content in Sanity Studio
Create schemas for the content Dynamic Yield will reference, such as promotion, campaignSlot, productStory, or landingPageHero. Include stable IDs, title, image, CTA label, CTA URL, locale, audience tags, start and end dates, priority, and references to products or categories. Keep IDs stable because Dynamic Yield campaigns and feeds depend on them.
- 3
Write the GROQ query for the feed shape
Use GROQ to fetch exactly the fields Dynamic Yield needs. For example, select the published campaign slot, dereference the image asset URL, include the linked collection slug, and filter out expired content. This keeps the payload small and avoids sending draft-only fields.
- 4
Create the sync mechanism
Add a Sanity webhook that triggers on publish, update, and delete events for the relevant document types. Point it to a Sanity Function, Next.js route, or middleware endpoint. The handler should verify the request, fetch the full document from the Content Lake, transform it into the Dynamic Yield feed item format, and call the Dynamic Yield API endpoint.
- 5
Connect Dynamic Yield on the frontend
Use the Dynamic Yield Web SDK, mobile SDK, or Experience API to request a campaign decision for the current page and user context. Return either a variation payload or a Sanity document ID, then render the selected Sanity content in your frontend. Send impressions, clicks, and conversion events back to Dynamic Yield so reports reflect what users actually saw.
- 6
Test with one campaign before scaling
Start with one slot, such as a homepage hero or product detail page recommendation block. Test publish, update, unpublish, locale fallback, deleted images, expired offers, Dynamic Yield preview mode, and analytics events before adding more campaign types.
Code example
A short webhook handler that receives a Sanity publish event, fetches the published document with GROQ, and sends the mapped item to a Dynamic Yield feed ingestion endpoint. Dynamic Yield feed upload URLs can be account-specific, so keep yours in an environment variable.
import {createClient} from '@sanity/client'
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID!,
dataset: process.env.SANITY_DATASET!,
apiVersion: '2025-01-01',
token: process.env.SANITY_READ_TOKEN!,
useCdn: false
})
export async function POST(req: Request) {
const {documentId} = await req.json()
const item = await sanity.fetch(`
*[_id == $id][0]{
_id,
title,
locale,
"slug": slug.current,
"image": image.asset->url,
ctaLabel,
ctaUrl,
audienceTags,
startsAt,
endsAt
}
`, {id: documentId})
if (!item) return Response.json({ok: true, skipped: true})
const dyItem = {
id: item._id,
name: item.title,
url: `https://www.example.com/${item.locale}/${item.slug}`,
image_url: item.image,
metadata: {
ctaLabel: item.ctaLabel,
ctaUrl: item.ctaUrl,
locale: item.locale,
tags: item.audienceTags,
startsAt: item.startsAt,
endsAt: item.endsAt
}
}
const res = await fetch(`${process.env.DY_FEED_API_URL}/items/${encodeURIComponent(dyItem.id)}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'DY-API-Key': process.env.DY_API_KEY!
},
body: JSON.stringify(dyItem)
})
if (!res.ok) {
throw new Error(`Dynamic Yield feed sync failed: ${res.status}`)
}
return Response.json({ok: true, id: dyItem.id})
}How Sanity + Dynamic Yield works
Build your Dynamic Yield integration on Sanity
Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect Dynamic Yield campaigns to the content your teams publish every day.
Start building free โCMS approaches to Dynamic Yield
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Personalization content structure | Campaign content often lives inside page templates or HTML blocks, which makes field-level mapping to Dynamic Yield harder. | Schemas define campaign slots, variants, audiences, locales, and references as typed fields that can map cleanly to Dynamic Yield. |
| Real-time sync on publish | Teams often rely on scheduled exports, manual feed uploads, or developer-run scripts. | Webhooks and Functions can react to publish, update, and delete events, then call Dynamic Yield from server-side code. |
| Field-level feed control | Feeds may include whole pages or rendered markup, which adds cleanup work before Dynamic Yield can use the data. | GROQ can project the exact feed shape Dynamic Yield needs, including references, asset URLs, filters, sorting, and slices. |
| Experiment variant workflow | Variants are often duplicated as pages or hard-coded into the frontend, which increases the chance of mismatched copy. | Sanity Studio can model variants as structured documents, while Content Releases and scheduled publishing help coordinate launch timing. |
| Multi-channel reuse | Personalized content is usually tied to one website presentation layer. | One structured back end can feed Dynamic Yield, web, mobile, email, commerce surfaces, and AI agents. |
| Implementation trade-off | Fast for simple page edits, but personalization feeds can become brittle as tests and locales grow. | Schema-as-code takes upfront planning, but it gives developers version control and gives teams predictable data for Dynamic Yield. |
Keep building
Explore related integrations to complete your content stack.
Sanity + LaunchDarkly
Use feature flags to control rollout of Sanity-powered experiences while Dynamic Yield handles audience decisions and tests.
Sanity + Optimizely
Connect structured Sanity content to experimentation workflows for teams comparing testing strategies across channels.
Sanity + Uniform
Compose personalized digital experiences with Sanity content and connect them to targeting, testing, and delivery logic.