Trust levels
Not all events deserve the same trust. A public write key ships in your page source; anything a browser claims, the browser’s owner can forge. Kilden makes the trust level of every event explicit instead of pretending it doesn’t exist.
The three levels
Section titled “The three levels”| Level | How it’s established | verified |
|---|---|---|
| Client | Public write key, no proof of identity | Anonymous events: false by convention — there’s no identity to verify, and nothing treats them as suspect. Identified events without a valid token: false, meaning unproven |
| Verified client | Public write key + a valid identity verification JWT signed by your backend (sub = the event’s distinct_id) |
true |
| Server | Secret write key, from your backend only | true — the secret key is the authentication |
Verification is always computed, on every identified event, regardless of the project’s enforcement mode — so monitor mode measures exactly what enforce would block.
Which features care
Section titled “Which features care”- Analytics: everything counts. Unverified events are kept (
verified: false), never dropped or rewritten — they’re data, just not trusted. - Campaign triggers: identified persons must be verified to start a journey. Anonymous events pass. Exit events always pass (exiting is the safe direction).
- Identity mutations (
$identify,$set,$set_once): governed by the project’s mode — inenforce, unverified mutations from identified users can’t create or change persons. - Messaging reads (upcoming in-app messenger): verification required always, in every mode — reading someone’s message thread is not a “monitor” kind of risk.
Two classes of write keys
Section titled “Two classes of write keys”- Public key — safe to embed in browsers and mobile apps. Identifies the project, authenticates nothing. Can be scoped with allowed origins.
- Secret key — backend only, never embedded in a client. Events sent with it are server facts. The decide API outright rejects secret keys (
403) so they’re never tempted into frontend code.
Rule of thumb: data that must be true goes server-side. Revenue, subscription state, anything that triggers money or messaging — send it from your backend with the secret key. Use the browser for behavior, the backend for facts, and identity verification to make browser identity trustworthy.