OPTIMIZE · THE AFFINITY ENGINE · HOW IT WORKS

How the affinity engine works.

The formulas, the defaults and the rules, as the product holds them in October 2026. It is arithmetic, so it can be written down in full.

On this pageThe words on screen
  1. The words on screen
  2. How it works
  3. What is kept
  4. How a score rises
  5. How it fades, and how strong it is
  6. The defaults
  7. A worked example
  8. The points law
  9. Where interests come from
  10. What teaches it
  11. Joining and leaving
  12. One audience's settings
  13. Recommendations
  14. Offers
  15. What our engineers set
  16. The core
  17. What keeps it honest
  18. Common questions

The words on screen

On screenIn the arithmetic
"How long interest lasts"τ, the memory
"How much activity counts as strong interest"K, the bar for strong interest
"A visitor joins an audience at"The join threshold
"and leaves when it falls below"The leave threshold
"What each visitor action counts for"w, the points each action adds
"The interests the engine scores on"The interests, each read from a tag or field on your content
"Safety limits"The floor below which a value is forgotten, and the most values kept per interest
"Affinity on" or "Affinity off"Whether the three serving conditions hold, and which one does not
"tune this audience"One audience's own memory, bar and join point

How it works

What is kept

  • For each visitor and each interest value, two numbers: a score, and the moment it was last touched.
  • They live in that visitor's own Durable Object on Cloudflare, named for the site, its environment and the visitor, so no two sites ever mix.

How a score rises

An action adds its points w to every interest value it touches, after fading what was there:

R becomes R × e^(-Δt/τ) + w

where Δt is the time since the value was last touched. An action with no points adds nothing.

How it fades, and how strong it is

  • Fading is computed whenever a score is read: the score now = the stored score × e^(-Δt/τ).
  • Strength = R / (R + K), always between 0 and 1. K sets how much activity counts as strong interest: at R = K, strength is exactly 0.5.
  • Half-life = τ × ln 2. With a memory of 7 days, an interest halves in about 4.9 days.

The defaults

A site starts from these on its first approved save.

SettingDefault
"How long interest lasts"7 days (a half-life of about 4.9 days)
"How much activity counts as strong interest"1.8
"A visitor joins an audience at"0.6
"and leaves when it falls below"0.45
"What each visitor action counts for""Added to the bag" 3 · "Bought" 5
Content behaviours, offered until you apply them"Was shown a piece of content" 0.25 · "Lingered on a piece of content" 2 · "Clicked a piece of content" 1 · "Watched a video to the end" 2
"Safety limits"A value below 0.0001 is forgotten; at most 24 values per interest
"The interests the engine scores on"Channel; add your own

A worked example

Our own arithmetic on the defaults, not a product output.

  1. Three points arrive at once,

    from one add to cart. Strength is 3 / (3 + 1.8) = 0.625, above 0.6, so the visitor joins the audience.

  2. About 17.7 hours later,

    with no further activity, the score has faded below 2.7, where strength drops under 0.6. From then on, pages stop treating the visitor as a member: each page checks membership against the audience's own join point.

  3. About five days later,

    the score is below 1.47, where strength drops under 0.45, the leave point.

The points law

  • What an action is worth changes only through the engine's own tuning, behind its own approval card. No capture setting and no catalog entry can write it.
  • An event's definition in the catalog can note an intended weight, as a record only.

Where interests come from

  1. By hand, on the Engine tab: "Add an interest", with a name, the field to read it from, and its own memory if you want one, saved through an approved tune.
  2. The arrival channel, with a memory of 30 days, added when affinity is switched on.
  3. Your taxonomies, through the catalog. A tag becomes a value on its taxonomy's interest, and a tag on at least two items earns a draft audience, which serves only once its interest is configured and the audience is activated.

What teaches it

An event reaches the engine only through three gates, in this order.

  1. The engine is connected,

    and the site's settings are saved. Otherwise affinity is off, and costs nothing.

  2. Personalization is allowed for this visitor.

    Global Privacy Control outranks everything, then the visitor's recorded grant, then their consent cookie, then the regime's default.

  3. The event carries what your content is about,

    under the interests you set. A plain page view carries nothing for it, and never reaches it.

In practice, adding to cart and buying teach it with the platform's points; a click on a recommended card teaches it once "Clicked a piece of content" has points, because every card carries its item's tags; and so does any other event you give points to that carries the field an interest reads.

Joining and leaving

  • The engine joins a visitor to an audience at a strength of 0.6 or more, and keeps them while it stays at 0.45 or more. The gap keeps the engine's record of a visitor near the line from flickering in and out.
  • Each join and each leave writes an explanation: the score, both thresholds, the trigger and the settings version.
  • On every page, membership is recomputed against that audience's own join point.

One audience's settings

  • "tune this audience" overrides the join point, the memory and the bar for strong interest for that audience, as each page is served.

Recommendations

  • The score of an item is the visitor's strength summed over the item's tags.
  • The order: pins first, then score, then your fallback order, then catalog order. 1 to 12 cards, 4 by default. "Narrow by" means any of the values within one interest, and all of the interests together.
  • When there is nothing to rank on, because the visitor has not consented, sends Global Privacy Control, is in the holdout, or the site has no settings, or the engine cannot be reached, the section uses its fallback: "The most recently updated items", "Your pins, then catalog order", or "Hide the section entirely".
  • The slot rules apply when switched on: the stage of the buying journey, freshness, how often the visitor has seen a piece, variety, and merchandising weights.
  • Feedback. Every card carries its decision and its position. A card that was really at least half in view counts as an impression, and when learning is allowed, a click sends the item's tags back to the engine.
  • No AI model is called while a page is ranked.

Offers

  • When an event lifts a visitor over an audience's join point, every approved live offer for that audience is sent down that visitor's live channel, under the same consent gate, and each one is logged as an exposure. A page applies only the offers meant for its own live slots.

What our engineers set

  • The engine's connection: its address and token, the live channel's secrets, and its deployment on Cloudflare.
  • Affinity serves once three things are in place: saved settings, active content bound to a learned audience, and that connection. The Engine tab's "Affinity on" or "Affinity off" names the one that is missing.

The core

  • The engine's core is a small module of pure arithmetic, with no dependencies and no trained model, held unchanged by an enforced check.

What keeps it honest

Deterministic.

The same history always gives the same scores.

Explained.

Every join and leave carries its cause.

Consent-gated.

No consent, no learning; Global Privacy Control, never.

Governed points.

One door for weights, behind its own approval.

Separate by site.

Each visitor's store is named for one site.

Failing quietly.

If the engine cannot be reached, pages lose personalization and nothing else.

Common questions

Why can strength never reach 1?

Because it is R / (R + K): it climbs toward 1 as activity grows, and K decides how much activity counts as strong.

Why two thresholds?

So that the engine's record of a visitor hovering near the line does not flicker in and out of an audience with every action. Pages themselves check each audience's join point as they are served.

Why does a page view not count?

The engine scores only actions you give points to that carry what your content is about, and a plain page view carries nothing for it to score.

What happens when I change the memory?

The site's own pages pick it up on the next page load, and the change can be undone.

What is the arrival-channel interest for?

It lets audiences form around how people arrive, not only around your content, with a memory of 30 days.

Is a visitor's score shared across my sites?

No. Each site keeps its own.

What happens to scores when a visitor is erased?

They are deleted with the rest of the visitor's record, their live state is reset, and their live channel is closed.