Let your own site show different content to different visitors, using rules a marketer sets in Xenia.
This page is for developers connecting a custom site or app. It covers how your site asks Xenia which content to show a given visitor.
The division of work is the point of it: your developers own the page, and the marketer owns which version wins. Nobody has to deploy to change the answer.
In a journey's Content Cloud node, they pick the default content, give it a content key, add the rules and the alternative content each rule selects, then choose Apply rules.
On render, your site sends that content key plus what it knows about the visitor, for example their segment or country.
Xenia returns either "show the default" or "swap this part for that version", and your site renders accordingly.
The content key is the contract between the two sides. Agree it once, and the marketer can change the rules behind it whenever they like.
Create a token in the app under API Tokens. It is tied to one workspace and one environment, so a token made for staging cannot touch live content.
The token is displayed only when you create it, and Xenia keeps no copy it can show you again. Store it as a server-side secret. If your browser code needs one, have your server issue a short-lived token per session instead of shipping a long-lived one to the client.
The same page lists your existing tokens with who created them and when they expire, and lets you revoke any of them. A revoked token stops working within about a minute.
Send the content key and the visitor context:
{
"contentKey": "homepage-hero",
"data": { "segment": "vip", "country": "US" },
"locale": "en"
}data is whatever the rules need to make a decision, and it is the same set of
facts the marketer sees when writing those rules.
When a rule matches, you get back what to swap:
{
"personalized": true,
"baseEntryId": "115680",
"swaps": [
{
"identifier": "hero_banner_list",
"replacementEntryId": "166060",
"mode": "section"
}
]
}When nothing matches, you get the default:
{ "personalized": false, "baseEntryId": "115680", "swaps": [] }Each swap names the part of the page to replace and what to replace it with. mode
is section to replace the whole block, or items to keep the block and swap only
what is inside it.
Fetch the default and the replacements from your own CMS and swap them by identifier. Identifiers are matched at any depth, so a block nested inside another block can be swapped, as long as your CMS query actually expanded that level.
This works with any CMS, because Xenia only tells you what to swap and never touches your content.
Put a short timeout on the request and render the default content on any failure. Requests are rate limited, so a burst of traffic can be turned away, and your page must stay fast and correct when that happens.
Other things worth handling: an unrecognized content key means nobody has set that content up yet, and a rejected token means it has expired or been revoked, so it needs replacing in the app.