First-party measurement and consent
The analytics tags you add (Google Analytics, Plausible, PostHog and the rest) are yours, and your consent manager governs them by category. This page is about the other kind: the counters Forumulate itself keeps so that your console can show views, unread searches, form drop-off and A/B results. They are first-party, they never leave our service, and they are now gated by the same consent as your own tags.
What we measure, and what each records
Every one of these is sent from the reader page to our API. None sets a cookie of its own, none is shared with a third party, and none identifies a person: where a count is "per reader", the reader is a keyed hash of the address and browser that only the server can compute, never the address itself.
Measurement | Sent to | What is stored | Browser storage |
|---|---|---|---|
Docs page view |
| One view per reader per page per day, with the referring site | none |
Forum topic view |
| One view per reader per topic per day |
|
Blog post, release, roadmap item view |
| One reader per post per day; the post's view count | none |
Call-to-action click |
| One click per reader per release per day, with the link | none |
Event page view and registration |
| A per-day counter by |
|
Form progress |
| A form "pass": viewed, started, last question touched, how many answered; the answers only if you keep partial answers |
|
Docs search |
| The query and how many results it found (the "searches with no results" report) | none |
FAQ search |
| The settled query and how many questions it matched | none |
A/B exposure and goal |
| Which arm a reader saw; which goal they reached, credited to that arm | cookie |
Course landing variant |
| Views and conversions per variant |
|
Course affiliate click |
| One click per referral code |
|
Member read time |
| Seconds a signed-in member had the topic open | none |
Changelog widget open and click |
| One open or click per reader per day | none |
A few things readers do are not measurement and are not gated: rating a page ("Was this helpful?"), leaving a comment or an NPS score, asking a question, voting, following. Those are things the reader chose to send you.
Server renders never count. A blog post, a roadmap item and a docs search used to be counted inside the API read that rendered them; the reader now marks those reads (X-Forumulate-Measure: client, or ?measure=client on the search) and counts them through the gate instead. A caller that does not mark its read (the SDK, an agent) is counted as before.
How consent gates them
There is one gate on the reader, and every row in the table above goes through it, including the browser storage in the last column.
A consent manager is active on the space (our hosted banner, or any provider you configured under Cookies & consent): a measurement runs only once the reader has granted
analytics. Before they decide it waits on the page. A grant sends it; a refusal drops it, and so does leaving the page. Nothing is sent, and nothing is written to the browser, before a decision.No consent manager (the space is unconfigured, or set to
none): what happens is thefirstPartyAnalyticssetting below. A reader who refused analytics in Cookie settings is still not counted.
The decision is read from Google Consent Mode v2 (analytics_storage), which every supported provider sends, so the gate does not depend on any one vendor. A provider that sends no Consent Mode signal is treated as "not yet decided", and nothing is counted.
The changelog widget runs on your own product, not on our reader. There it follows the host page's Consent Mode when the page has one (a default of denied counts as a no until the reader answers), and the setting below when it has none.
The setting: firstPartyAnalytics
always, with-consent or off. Set it on the organization (PUT /orgs/{orgId}/consent) and override it on a space (PUT /orgs/{orgId}/spaces/{spaceId}/consent, with mode: inherit or mode: override). A space's value wins, then the organization's, then the default.
Value | No consent manager | Consent manager active |
|---|---|---|
| Counted, unless the reader refused in Cookie settings | Counted only after a grant |
| Counted only after a grant in Cookie settings | Counted only after a grant |
| Never counted | Never counted |
The default is always because of what these counters are: aggregates kept on our side, deduplicated by a hash only the server can compute, never a cookie and never a lasting identifier on the reader's device. That is the kind of audience measurement European regulators exempt from prior consent, and it is what every space did before this setting existed. If your counsel reads it differently, set with-consent or off. An active consent manager gates measurement whatever this says, so the setting only decides the case where no one is asked.
The public resolve, GET /public/orgs/{orgId}/spaces/{spaceId}/consent, always answers with the resolved value, so you can check what a space will do:
{ "provider": "hosted", "scriptSources": [], "firstPartyAnalytics": "always" }Related
Cookies & consent: registering your CMP.
Analytics: the tags you add yourself.
In the API
Every operation below is also reachable from the other surfaces without a dedicated command. forumulate api <Operation> calls it from the CLI, the JavaScript SDK has a typed method for each one (the last column names it; the Python and Go clients are generated from the same spec), and an agent reaches the organization-scoped ones through the MCP call_api tool. Where a CLI command or MCP tool exists too, the last column names it. Operation names link to the API reference.
Consent Public
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Get the consent in a space (public reader) |
| |
| Create a receipt in a space |
|