Skip to content

Data model

OpenPartner is event-sourced. Three layers are immutable raw inputs; the rest are derived views or ledgers.

Raw tables (immutable)

Click

Every click on a partner link.

FieldTypeNotes
clickIdULIDPrimary key.
partnerIdULIDWhich partner gets credit.
campaignstring?Optional grouping.
landingUrltextWhere the user landed.
referertext?HTTP referrer.
ipHashtextSalted hash. We don’t store raw IPs.
uatextUser agent.
createdAttimestamptzClick time.

Event

Conversion events from the SDK or server-side.

FieldTypeNotes
eventIdULIDPrimary key.
userIdstringCustomer’s user identifier.
typestringEvent name.
amount / currencyint / stringMoney in minor units.
metadatajsonbFree-form.
occurredAttimestamptzEvent time.

Derived (re-runnable from raw)

Identity

Bridge between a userId and the clickId they came from. Written when op.identify() is called and there’s an active click cookie.

Attribution

Result of running the attribution model over raw data. References the event and the click(s) credited. Re-derivable.

Ledger (immutable, audit-grade)

Commission

Computed from Attribution + program rules. Never updated in place — corrections are written as new rows referencing the original.

Payout

Stripe Connect transfer record. Never updated — refunds and reversals are new rows.

Why this matters

You can’t lose attribution history because the raw data is intact. You can re-run with a different model. You can audit any commission back to its source click. And exports are lossless because the raw layers are everything you need to re-derive.