Variants Field
Learn how to add and configure the variants field type for audience-based content personalization.
- Adding a Variants Field
- Field Capabilities
- Variant Properties
- Layout Variants
- How Matching Works
- Jaccard Similarity Example
- Tie Breaking
- Recursive Resolution
- Troubleshooting
- Variant not showing?
- Wrong variant selected?
Adding a Variants Field
When defining a collection or singleton field, choose type variants and configure the inner fields that make up each variant's data:
- Field type:
variants - Option:
fieldsâ add any fields (e.g.,heading,image,cta)
Your stored value will look like:
{
"personi:variants": [
{
"id": "v-abc123",
"active": true,
"label": "Default",
"data": { "heading": "Welcome" },
"meta": null,
"audience": []
},
{
"id": "v-def456",
"active": true,
"label": "Members",
"data": { "heading": "Welcome back" },
"meta": null,
"audience": ["member"]
}
]
}
Field Capabilities
The variants field provides:
- Add, remove, and reorder variants
- Toggle active state and set an optional label
- Audience tags editor
- Embedded fields renderer to define the variant data
- Optional meta object for additional notes or configuration
Variant Properties
| Property | Type | Description |
|---|---|---|
id |
string | Unique identifier (auto-generated) |
active |
boolean | Whether this variant is considered for matching |
label |
string | Display name in admin UI |
data |
object | The actual content fields |
meta |
object | Optional metadata (e.g., scheduling) |
audience |
array | Audience tags for matching |
Layout Variants
In Layout pages, add the component "Layout Variants". It contains a layout field of type variants so you can define audience-specific layouts. At API time, Personi unwraps the selected layout automatically.
This allows you to create entirely different page layouts for different audiences - for example, a simplified mobile layout vs. a feature-rich desktop layout.
How Matching Works
When a request includes the personi parameter, Personi resolves variants using this algorithm:
- Filters out inactive variants (
active: false) - Filters out variants outside their schedule window
- Computes Jaccard similarity:
|intersection| / |union| - Picks the variant with the highest similarity score
- Falls back to the first active variant if no audience matches
Jaccard Similarity Example
Request audience: ["member", "premium"]
| Variant | Audience | Calculation | Score |
|---|---|---|---|
| A | ["member"] |
1 / 2 | 0.5 |
| B | ["member", "premium"] |
2 / 2 | 1.0 |
| C | ["guest"] |
0 / 3 | 0 |
Result: Variant B wins with the highest score (1.0)
Tie Breaking
If multiple variants have the same similarity score, the first one in the list wins. This makes the order of variants significant - place your preferred fallback variants earlier in the list.
Recursive Resolution
The resolution runs recursively across arrays, so nested structures containing variants are also handled automatically.
Troubleshooting
Variant not showing?
- Check if the variant is
active: true - Verify audience tags match exactly (case-sensitive)
- Check schedule constraints if using
meta.schedule - Ensure
personiparameter is included in the request
Wrong variant selected?
- Remember: highest Jaccard similarity wins
- Empty audience
[]only matches when no better option exists - Multiple variants with same score â first one wins