Files
portal/docs/storylines.md
T
Bendik Aagaard LynghaugandClaude Fable 5.1 f395ace556
docs / deploy (push) Successful in 3s
Test / test (push) Successful in 1m1s
Storylines: the same site told several ways, one per visitor, counted
Any text a person reads may be a list, one entry per storyline, every
list the same length. A visitor is given one storyline for the whole
site and reads it on every page and in every mail about their case.
Records and events carry the storyline; GET /report gives counts per
bucket, storyline and state, and nothing else.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
2026-09-30 15:11:27 +02:00

2.4 KiB

Storylines

The same site, told two ways, and counted.

Anywhere content says something to a person, it may say it in several ways by giving a list instead of one string:

name: Vil du hjelpe til i nabolaget?
description:
  - Dugnad, 17. mai og komiteene trenger flere hender. Si hva du kan.
  - Naboene gjør det meste selv. Her melder du deg til det du har lyst på.
alternatives:
  - name: [Bli med, Meld deg]
    consequence: [[Send], [Meld meg]]

Each index is a storyline. A visitor is given one at their first request, kept in a cookie (portal_storyline) for a year, and reads that storyline on every page, in every button and in every mail the site sends them about their case. A single string is every storyline.

The rules

  • Same length everywhere. Every list of texts in the content has the site's arity, so a storyline never has a hole in it. The lint refuses a list of another length and names it.
  • What varies is what a person reads: name, description, label, placeholder, title, a mail's subject and body, a list's empty line, consequence and encouragements (those two as lists of lists).
  • What the machine reads never varies: a field's name (the stored key), a select's options (the stored values), states, groups, paths, buckets.
  • One storyline per site, not per page. That is what makes it a storyline rather than a scatter of variants: a warm front door leads to a warm form and a warm mail.
  • A signed-in person keeps the storyline they had as a visitor.
  • A site that tells one storyline sets no cookie.

What is counted

Every record and every answer event carries the storyline it came from (storyline on Answer and on portal.answers.submitted). The mail a case gets tells the same storyline, so a person who read the warm front door is not thanked in the plain voice.

GET /report gives the counts, per bucket, per storyline, per state:

{ "storylines": 2,
  "buckets": { "hjelpebehov": { "0": { "open": 3, "ordnet": 9 },
                                "1": { "open": 5, "ordnet": 14 } } } }

Storylines are assigned evenly, so those numbers are the comparison: which words brought more people to send, and how their cases went. No record, field, address or time leaves the site. The trainer reads this (portal-trainer report) next to what its personas scored offline, and the plan's tones are where the storylines are written.