2026-09-30 15:11:27 +02:00
|
|
|
# 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:
|
|
|
|
|
|
|
|
|
|
```yaml
|
2026-09-30 15:31:59 +02:00
|
|
|
name: Want to help out in the neighbourhood?
|
2026-09-30 15:11:27 +02:00
|
|
|
description:
|
2026-09-30 15:31:59 +02:00
|
|
|
- The work day, the spring fair and the committees need more hands. Say what you can do.
|
|
|
|
|
- The neighbours do most things themselves. Sign up here for whatever you fancy.
|
2026-09-30 15:11:27 +02:00
|
|
|
alternatives:
|
2026-09-30 15:31:59 +02:00
|
|
|
- name: [Join in, Sign me up]
|
|
|
|
|
consequence: [[Send], [Count me in]]
|
2026-09-30 15:11:27 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{ "storylines": 2,
|
2026-09-30 15:31:59 +02:00
|
|
|
"buckets": { "requests": { "0": { "open": 3, "solved": 9 },
|
|
|
|
|
"1": { "open": 5, "solved": 14 } } } }
|
2026-09-30 15:11:27 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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
|
2026-09-30 15:31:59 +02:00
|
|
|
(`portal report`) next to what its personas scored offline, and
|
2026-09-30 15:11:27 +02:00
|
|
|
the plan's `tones` are where the storylines are written.
|