Coseller Protocol — a referral economy layered on top of Market.
Authorized players (:coseller role) share trackable URLs to game assets
(a Market capability, or an external website/app). A buyer's clicks become
touches. When the GM settles a paid checkout, a GM-configured portion of
each order's existing Market commission becomes a coseller pool, which is
distributed across the buyer's chain-of-influence via a pluggable attribution
algorithm (see game.protocols.coseller-attribution).
Coseller is a pure distribution layer: it never changes the buyer's price or
the seller's net. It reads Market orders/checkouts from the shared game-state
and writes only its own :coseller namespace. Settlement is a manual,
idempotent GM command — no auto-fire on payment.
Coseller Protocol — a referral economy layered on top of Market. Authorized players (`:coseller` role) share trackable URLs to game assets (a Market capability, or an external website/app). A buyer's clicks become `touches`. When the GM settles a paid checkout, a GM-configured *portion* of each order's existing Market commission becomes a `coseller pool`, which is distributed across the buyer's chain-of-influence via a pluggable attribution algorithm (see `game.protocols.coseller-attribution`). Coseller is a pure distribution layer: it never changes the buyer's price or the seller's net. It reads Market orders/checkouts from the shared game-state and writes only its own `:coseller` namespace. Settlement is a manual, idempotent GM command — no auto-fire on payment.
(handle-claim-visitor payload)Binds an anonymous visitor's referral history to the member they became.
Before a reader has an identity, their ?ref= visits are recorded as real
touches under a GM-minted visitor:<uuid>. This re-keys every one of those
touches onto the caller's player-name and resolves their signup :referred-by
by first-touch over the merged history — correcting an already-stamped referrer
when a claimed touch predates it, because those touches become visible under
the member's name only now (see recompute-referrer).
A visitor id can be claimed exactly once: re-claiming by the same member is a no-op, and a different member is refused. The claim is also recorded when there are no touches to move, which locks the id.
Self-touches are re-keyed and kept, not dropped — earliest-touch and
buyer-touches already exclude them, so attribution stays correct while the
engagement record survives.
Limitation: the visitor id lives in one browser, so a reader who arrives on one device and joins on another cannot claim the first device's touches.
Binds an anonymous visitor's referral history to the member they became. Before a reader has an identity, their `?ref=` visits are recorded as real touches under a GM-minted `visitor:<uuid>`. This re-keys every one of those touches onto the caller's player-name and resolves their signup `:referred-by` by first-touch over the merged history — correcting an already-stamped referrer when a claimed touch predates it, because those touches become visible under the member's name only now (see `recompute-referrer`). A visitor id can be claimed exactly once: re-claiming by the same member is a no-op, and a different member is refused. The claim is also recorded when there are no touches to move, which locks the id. Self-touches are re-keyed and kept, not dropped — `earliest-touch` and `buyer-touches` already exclude them, so attribution stays correct while the engagement record survives. Limitation: the visitor id lives in one browser, so a reader who arrives on one device and joins on another cannot claim the first device's touches.
(handle-ledger-settlement-failed payload)MoM callback after the ledger/batch effect fails. The settlement remains visible as failed and does not update payout totals.
MoM callback after the ledger/batch effect fails. The settlement remains visible as failed and does not update payout totals.
(handle-ledger-settlement-succeeded payload)MoM callback after the ledger/batch effect succeeds. This is the only place coseller settlement becomes economic truth.
MoM callback after the ledger/batch effect succeeds. This is the only place coseller settlement becomes economic truth.
(handle-player-join payload)Records a brand-new member's signup (fired by MoM's gm/player-join) and, when
their ?ref= first-touch already exists, attributes the referring coseller.
Keyed by player-name, so it reconciles with handle-record-touch by name
regardless of arrival order. Idempotent: never overwrites an existing
:joined-at or :referred-by. Returns coseller :updated-state for MoM to
merge (invoked from the GM's player-join handler).
Records a brand-new member's signup (fired by MoM's `gm/player-join`) and, when their `?ref=` first-touch already exists, attributes the referring coseller. Keyed by player-name, so it reconciles with `handle-record-touch` by name regardless of arrival order. Idempotent: never overwrites an existing `:joined-at` or `:referred-by`. Returns coseller `:updated-state` for MoM to merge (invoked from the GM's player-join handler).
(handle-preview-chain payload)Preview a buyer's chain-of-influence and weights under the current policy — without settling anything. Attribution is buyer-level (any of the buyer's touches in the window count, regardless of which asset was linked).
Preview a buyer's chain-of-influence and weights under the current policy — without settling anything. Attribution is buyer-level (any of the buyer's touches in the window count, regardless of which asset was linked).
(handle-query-payouts payload)Return coseller payout ledgers, optionally for a single :coseller. Each ledger
carries a grand :totals plus a :totals-by-kind breakdown of own-sale
(:direct) vs recruit-override (:override) income, and per-entry :kind
tags (override entries also list their :sources recruits).
Return coseller payout ledgers, optionally for a single :coseller. Each ledger carries a grand `:totals` plus a `:totals-by-kind` breakdown of own-sale (`:direct`) vs recruit-override (`:override`) income, and per-entry `:kind` tags (override entries also list their `:sources` recruits).
(handle-query-policy payload)Return the resolved attribution policy.
Return the resolved attribution policy.
(handle-query-referrals payload)List member-referral edges derived from :signups — every new member a coseller brought in, whether or not they became a coseller themselves. Each row is {:referrer :referee :joined-at :referred-at :via :became-coseller}. Optionally filtered by :referrer (that coseller's downline — who they recruited) or :referee (that member's upline — who recruited them). Only referred signups (those with a resolved :referred-by) are returned.
List member-referral edges derived from :signups — every new member a coseller
brought in, whether or not they became a coseller themselves. Each row is
{:referrer :referee :joined-at :referred-at :via :became-coseller}. Optionally
filtered by :referrer (that coseller's downline — who they recruited) or
:referee (that member's upline — who recruited them). Only referred signups
(those with a resolved :referred-by) are returned.(handle-query-settlements payload)List settlements, optionally filtered by :buyer, :checkout-id, :order-id, or :coseller (settlements in which that coseller earned a split).
List settlements, optionally filtered by :buyer, :checkout-id, :order-id, or :coseller (settlements in which that coseller earned a split).
(handle-query-touches payload)List touches, optionally filtered by :coseller, :buyer, :capability-id.
List touches, optionally filtered by :coseller, :buyer, :capability-id.
(handle-record-touch payload)A buyer's visit through a coseller's referral code (the :token, which resolves
to a coseller via their stable :ref-token). Records each engagement click for
analytics while attribution still treats the buyer as one member in that
coseller's chain-of-influence. Optional :capability-id/:path record which
page drove the visit (analytics only — no settlement code reads them).
A deduped repeat visit no longer discards its path: it accumulates into a
bounded :paths set on the existing touch, so which posts a reader arrived
through is answerable for anonymous readers — who are exactly who coseller
links are aimed at. :path itself stays the first one seen.
Self-touches are recorded but excluded from settlement. The actor is the
buyer.
The buyer may be a GM-minted visitor:<uuid> standing in for a reader who has
no identity yet; handle-claim-visitor re-keys those onto a real player-name
when they join. Anonymous repeat visits through the same coseller collapse onto
one touch (bumping :count/:last-ts) rather than appending, since unlike a
member's clicks they are unbounded by any seat.
A buyer's visit through a coseller's referral code (the `:token`, which resolves to a coseller via their stable :ref-token). Records each engagement click for analytics while attribution still treats the buyer as one member in that coseller's chain-of-influence. Optional :capability-id/:path record which page drove the visit (analytics only — no settlement code reads them). A deduped repeat visit no longer discards its path: it accumulates into a bounded :paths set on the existing touch, so which posts a reader arrived through is answerable for anonymous readers — who are exactly who coseller links are aimed at. :path itself stays the first one seen. Self-touches are recorded but excluded from settlement. The actor is the buyer. The buyer may be a GM-minted `visitor:<uuid>` standing in for a reader who has no identity yet; `handle-claim-visitor` re-keys those onto a real player-name when they join. Anonymous repeat visits through the same coseller collapse onto one touch (bumping `:count`/`:last-ts`) rather than appending, since unlike a member's clicks they are unbounded by any seat.
(handle-register payload)Player opts in as a coseller and is assigned a stable referral code
(:ref-token) — the affiliate handle they append to any page URL as
?ref=<code>. The code is generated once and preserved across re-registration.
Optional :payout-ref records where this coseller wants to be paid.
Player opts in as a coseller and is assigned a stable referral code (`:ref-token`) — the affiliate handle they append to any page URL as `?ref=<code>`. The code is generated once and preserved across re-registration. Optional `:payout-ref` records where this coseller wants to be paid.
(handle-set-policy payload)Game Master configures attribution: which algorithm splits the pool, how much
of each order's commission becomes the coseller pool (:pool-share-bps), the
attribution :window-days, and :payout-hold-days (how long a paid order
must wait — absent buyer confirmation — before it's eligible for
settlement). Unspecified fields keep their current value.
Game Master configures attribution: which algorithm splits the pool, how much of each order's commission becomes the coseller pool (`:pool-share-bps`), the attribution `:window-days`, and `:payout-hold-days` (how long a paid order must wait — absent buyer confirmation — before it's eligible for settlement). Unspecified fields keep their current value.
(handle-settle-checkout payload)Game Master settles every not-yet-settled, release-eligible order in a PAID
Market checkout. Ordinary orders use buyer confirmation or the general hold;
seller-direct orders wait from fulfillment for their configured hold and
return window. Orders not yet
eligible are reported under :held, not settled. The command records
:pending-ledger settlements and returns ledger effects for MoM to execute;
only the MoM success callback finalizes :settled state and payout totals.
Idempotent: orders already settled or pending are skipped, so re-running is
safe.
Game Master settles every not-yet-settled, release-eligible order in a PAID Market checkout. Ordinary orders use buyer confirmation or the general hold; seller-direct orders wait from fulfillment for their configured hold and return window. Orders not yet eligible are reported under `:held`, not settled. The command records :pending-ledger settlements and returns ledger effects for MoM to execute; only the MoM success callback finalizes :settled state and payout totals. Idempotent: orders already settled or pending are skipped, so re-running is safe.
(new-visitor-id)Mint an anonymous visitor id. Deliberately not new-id, whose <prefix>-<uuid>
shape would yield visitor:-<uuid>.
Mint an anonymous visitor id. Deliberately not `new-id`, whose `<prefix>-<uuid>` shape would yield `visitor:-<uuid>`.
(validate-payload event-key payload)(visitor-id? s)True when s is a GM-minted anonymous visitor id rather than a player-name.
True when `s` is a GM-minted anonymous visitor id rather than a player-name.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |