How to Wire LLM-Driven Personalisation Into Your CMS
Most personalisation projects die the same way. An engineer wires an LLM to a content API, ships a "for you" module, and within a month editors have no idea why a customer in Berlin saw a discontinued product pitched in the wrong tone.
Most personalisation projects die the same way. An engineer wires an LLM to a content API, ships a "for you" module, and within a month editors have no idea why a customer in Berlin saw a discontinued product pitched in the wrong tone. The model was reading stale content, there was no review step, and nobody can reconstruct what prompt produced what copy. Personalisation became a black box bolted onto the side of the CMS, and the legal team wants it turned off.
Sanity, the AI-native content platform, treats this differently. Sanity is the AI Content Operating System, an intelligent backend where personalisation logic lives inside the same governed content model your editors already trust, not in a detached script that drifts out of sync. That distinction is the whole article. When the LLM reads structured content, writes back through schema-aware APIs, and every variant passes through the same review and audit surfaces as hand-authored copy, personalisation stops being a liability and becomes a workflow.
This guide walks through wiring LLM-driven personalisation into your CMS the right way: modelling variant content, grounding the model in fresh data, keeping a human in the loop, and measuring whether any of it actually works.
Why bolted-on personalisation breaks in production
The failure mode is predictable. A team stands up personalisation as a layer that sits outside the content system: a serverless function calls an LLM, the LLM invents copy from a prompt, and the result is injected into the page at request time. Nothing about that variant is a first-class content object. It is not stored, not versioned, not reviewable, and not connected to the source material it was supposed to reflect. When a product gets discontinued or a claim gets corrected in the CMS, the personalised variant keeps repeating the old version because it was generated from a snapshot that has since gone stale.
The stakes are not cosmetic. In regulated industries a hallucinated price, an outdated compliance disclosure, or an off-brand tone shown to a specific segment is a real exposure, and because the variant exists only at the edge, nobody can answer the two questions that matter after the fact: what did this user actually see, and what produced it. Legacy CMSes make this worse because they stop at publishing. They hand you an API and assume the intelligence happens somewhere else, so personalisation logic accumulates in glue code that no editor can see and no auditor can trace.
The reframe is to make every personalised variant a governed content object living in the same system as the canonical content. This maps to the Model your business pillar: if a variant is not something you can model, review, and query, it should not be shown to a customer. Get the data model right first, and the LLM becomes a contributor to your content operation rather than a rogue process running past it.
Model the variant, not just the prompt
Personalisation that survives contact with production starts in the schema. Instead of treating a personalised block as an ephemeral string the LLM returns, you model it as structured content: a base document, a set of variant fields keyed by audience or segment, and the metadata describing which rule or model produced each one. In Sanity that content lives in the Content Lake and is authored and reviewed in Sanity Studio, so a variant is queryable, versioned, and governed exactly like any other document.
Portable Text is central here. Because it represents rich text as structured blocks, marks, and annotations rather than a wall of HTML, an LLM can generate or rewrite a variant while preserving the structure the frontend depends on: a call-to-action stays a call-to-action, a legal annotation stays attached to the clause it qualifies, and links survive intact across generation. That structure also survives chunking and retrieval, which matters the moment the same content feeds an LLM downstream. Compare that to personalisation systems that store variants as opaque strings, where the model is free to drop a required disclaimer or mangle a link and nobody notices until a customer does.
Schema-aware generation is the mechanism that makes this practical at scale. Agent Actions let an LLM generate, transform, or translate content against your actual schema, so a variant comes back shaped to fit the fields it belongs in rather than as free text you have to parse and hope. Model the variant as a real object and everything downstream, review, audit, rollback, and measurement, becomes ordinary CMS work instead of a bespoke pipeline.

Ground the model in fresh, structured content
An LLM generating personalisation is only as trustworthy as the content it reads. Feed it a scraped snapshot of your marketing site and it will confidently personalise around information that changed last week. This is the single most common source of embarrassing output: the model is not lying so much as reading from a stale copy nobody remembered to refresh. The fix is to ground generation in the live, structured content of the CMS itself and to keep the grounding current automatically.
Sanity approaches freshness at the data layer. The Embeddings Index API and dataset embeddings put semantic search directly on your content, and because the embeddings are tied to the content, they update as the content updates rather than living in a separate vector store you have to re-sync on a schedule. That removes an entire class of drift bugs where the index and the source disagree. For real-time needs, Content Lake real-time subscriptions let a personalisation workflow react the moment a document changes, so a discontinued product or a corrected claim propagates into what the model can see immediately.
When the personalisation task is genuinely retrieval-heavy, grounding an agent in a body of source material, that is where Sanity Context and Knowledge Bases turn PDFs, sites, and datasets into governed, agent-readable content. The deeper agent-retrieval architecture is its own topic (agent-context.org covers it), but the CMS-side principle holds: the LLM should retrieve from the same governed content your editors maintain, not a parallel copy that quietly rots. Freshness is not a feature you add later; it is a property of tying retrieval to the content model.
Keep a human in the loop with real governance
Fully autonomous personalisation is a tempting demo and a poor production posture. The moment an LLM can write copy that reaches customers without review, you have automated the production of unreviewed public statements at scale, which is exactly the thing your brand, legal, and compliance teams exist to prevent. The goal is not to remove humans; it is to remove the tedious work while keeping the judgment. That means every LLM-generated variant enters the same review workflow as human-authored content.
In Sanity, LLM-touched content moves through the Studio and Content Releases just like any other change: variants can be staged, reviewed, scheduled, and released together, so a marketer can see the full set of personalised messages before any of them go live rather than discovering them in production. AI Assist puts the model inside the editor where the reviewer already works, so an editor can generate a variant, rewrite a block in a different voice, translate headings into several locales, or fact-check a claim against a knowledge base, then approve or reject with full context. Functions provide the automation hooks that connect editors to these workflows: translate-on-publish, moderate-on-publish, or enrich-on-publish run as governed serverless steps rather than untracked glue code.
Governance also means accountability after the fact. Roles and Permissions control who can trigger generation and who can approve it, and Audit logs record what happened. Because Sanity carries SOC 2 Type II, GDPR alignment, regional hosting for data residency, and a published sub-processor list, the personalisation you ship sits inside a compliance posture your security team can actually sign off on.
Measure whether the personalisation is working
Personalisation without measurement is superstition. Teams routinely ship a personalised experience, watch a vanity metric wobble, and declare victory without ever isolating whether the variant caused the change. The discipline that matters is treating each variant as a testable hypothesis: what audience, what message, what expected behaviour, and what would tell you it failed. That is only possible when the variant is a real content object with metadata attached, which is exactly why the modelling step earlier is not optional.
Because variants live in the Content Lake as structured documents, you can query them with GROQ to answer operational questions directly: which segments have variants, which were LLM-generated versus human-authored, which are stale relative to their source, and which have never been reviewed. That queryability turns evaluation from a spreadsheet exercise into content operations. You can also close the loop on quality: use AI Assist or an App SDK app to fact-check generated variants against a knowledge base before they publish, catching the fabricated claim at authoring time rather than in a customer complaint.
The broader point is the fifth differentiator: rigid systems force you to scale people to scale output, while an AI-native content operation scales output without a proportional headcount. But that only holds if you can trust the output, and trust comes from measurement. A personalisation program you can query, evaluate, and correct inside the CMS is one you can safely let grow. One you cannot inspect is one you will eventually be asked to switch off.
A reference wiring, end to end
Putting the pieces together gives a concrete pipeline that avoids every failure mode above. First, model the content: a canonical document plus variant fields keyed by segment, authored in Portable Text so structure and annotations survive. Second, ground the model: expose the relevant content through the Embeddings Index API and dataset embeddings so generation retrieves fresh, semantically relevant source material, with Content Lake real-time subscriptions keeping the working set current.
Third, generate through schema-aware APIs: Agent Actions produce variants shaped to the schema, and Functions trigger enrichment or translation on publish as governed steps rather than ad hoc scripts. Fourth, review: variants land in the Studio, editors use AI Assist to refine and fact-check, and Content Releases stage the full set for a coordinated launch. Fifth, govern and measure: Roles and Permissions gate who can generate and approve, Audit logs record it, and GROQ queries let you evaluate coverage, freshness, and review status on demand.
This is what it means for AI to be wired into the data model, the editor, and the delivery layer rather than added on top with a plugin. Legacy CMSes bolt AI on and leave you to stitch the governance, freshness, and measurement together yourself, which is how personalisation becomes the black box nobody trusts. Sanity provides one shared foundation where personalisation is just governed content that a model happens to help produce. That is the difference between a demo that impresses a stakeholder and a program you can run in production for years.