Goals defined from what you already send
A goal is an event name or a page path. No separate instrumentation and no tag manager: if the tracker already reports it, it can be a goal, and the conversion rate is computed against the visitors actually in scope for the range and filters applied.


Three attribution models, side by side
First-touch credits the referrer that originally found the person, last-touch the one that closed them, linear splits it across the chain. They are shown together deliberately: on real data they produce genuinely different answers, and a tool that reports only one is making a strategic decision on your behalf.


Revenue over time and by channel
Revenue reported through the tracker's revenue() call, trended over the range and broken down by the acquisition channel credited under the model you selected.


And a webhook when one converts
Goal conversions fire outbound webhooks, signed with an HMAC over the timestamp and body so the receiver can verify them. An endpoint that keeps failing is disabled automatically after twenty attempts, and a separate job re-enables endpoints that were only down transiently.
How it works, precisely
- Goal types
- Event name match or page path match
- Attribution
- First-touch, last-touch, linear
- Revenue input
- falorb.revenue(amount, currency) from the tracker or the Node SDK
- Webhook signing
- HMAC over `timestamp.body`, auto-disable after 20 failures
Goals & revenue: the usual questions
Can revenue come from Stripe instead of the browser?
Not yet. The integrations layer, Stripe inbound first, is designed and documented but not built. Today revenue arrives through the tracker's revenue() call or the server-side Node SDK, which is the more reliable of the two.
Next, most people read
Run it yourself this afternoon
Clone the repository, bring up the stack with Docker Compose, paste one script tag. The data never leaves your machines.

