Reason keys
How a slot gets its sentence, which keys exist and what you can override.
Every slot in a slate carries a reason. Nothing is recommended without a sentence the user could read. This page lists the keys the engine uses today and how to change their text. The idea behind it is in Reasons.
In the slate#
Each item has two fields:
reason_key: the key, chosen from the generator that contributed most to the item's score, when what it would say is true; otherwiserecommended.reason: the sentence, one string per locale.
{
"item_id": "doc_1842",
"position": 0,
"reason_key": "similar_to_read",
"reason": {
"nl": "Omdat je dit net las",
"en": "Because you just read this"
},
"generator": "item_to_item"
}Show reason in the user's locale. If that locale is missing, pick a default of your own (for example nl). Hide the reason line when you show your own list.
The keys#
The winning generator decides the key. The sentences below are the defaults the engine ships.
reason_key | Left by | Default nl | Default en |
|---|---|---|---|
similar_to_read | item_to_item, with context.anchor_item_id | Omdat je dit net las | Because you just read this |
similar | item_to_item, without an anchor | Lijkt op wat je leest | Similar to what you read |
matches_goals | content_affinity on a goal the user declared | Past bij je doelen | Matches your goals |
people_like_you | persona_bayes, user_bayes, user_to_user (only when the person's nearest users engaged with the item) | Populair bij leden zoals jij | Popular with members like you |
trending | trending, on this surface's own 7-day log (all locales together) | Deze week veel gelezen | Widely read this week |
editors_pick | curated; also the control arm and fallback when the surface's list is curated | Gekozen door de redactie | Chosen by the editors |
new | surface_specific for an item under 30 days old; also the control arm and fallback when the list is newest | Nieuw | New |
popular | trending before the surface has its own log (the tenant-wide prior); the control arm and fallback when the list is popular | Populair | Popular |
pairs_with | item_to_item with an anchor of another kind that pairs: a recipe with a product, a workout with a product, a community with a document | Past bij dit recept · Past bij deze workout · Gelezen in deze community | Pairs with this recipe · Pairs with this workout · Read in this community |
more_about_tag | content_affinity won on behaviour rather than a declared goal; item_to_item with any other cross-kind anchor | Meer over dit onderwerp | More about this topic |
recommended | nothing true to say: the winner's own signal was not positive, a cold-start persona, an old item under surface_specific | Aanbevolen | Recommended |
matches_goals is only given for a goal the user declared; an affinity learned from behaviour gets more_about_tag. A collection counts as a recipe collection when its name contains recipe, recept, maaltijd or meal, and as a workout collection when it contains workout, training, oefening or exercise.
time_fit, format_fit and the region boost never name a reason, so they have no key. recommended is a valid key for templates like any other: override its text if "Aanbevolen" does not fit your design, but keep it free of claims. The rule behind it: Reasons.
Overriding the text#
Overrides live in the flow config under reasons, keyed by reason key or by generator kind, then by locale. A reason-key entry wins over a generator-kind entry, which wins over the default. Editing the texts creates a new flow version, like any other change.
{
"reasons": {
"similar_to_read": { "nl": "Lees ook", "en": "Read next" },
"matches_goals": { "nl": "Past bij wat je leest", "en": "Fits what you read" },
"trending": { "nl": "Veel gelezen deze week", "en": "Read a lot this week" }
}
}An override replaces the whole entry for that key: give every locale you serve. A key without an override keeps the defaults above.
Placeholders#
| Placeholder | Filled with |
|---|---|
{anchor_title} | the anchor item's title in the request locale |
{tag} | the taxonomy label of the winning tag in that locale; phases and health claims are never named |
{segment} | the persona's label, from a taxonomy tag of kind segment |
When a placeholder cannot be filled for a locale (no anchor, no label in that locale), that locale gets the default text instead. The rendered reason never contains a placeholder. Serve also checks overrides when you create a flow version: an unknown key, locale or placeholder answers 400 invalid_reason_template.
Special cases#
- Control arm. The control arm gets the surface's editorial list (
newest,curatedorpopular). It carries a reason too (new,editors_pickorpopular), so "a reason for every slot" holds in both arms. - Your own fallback. When your backend shows its own list after a timeout, that list is not from Patterna. Mark those slots as yours, show no Patterna reason, and report no interactions for them.
- Drafted texts. The
reasonsjob drafts a missing nl or en sentence and saves a new, inactive flow version whose note starts withREVIEW NEEDED; it never overwrites a text. It drafts per generator kind, and serve reads generator-kind templates, so the drafts work as they are.