Repository navigation
0.5.0 — revenue and Umami import in the core
Revenue
Send an amount and a currency with any event:
vitrus("purchase", { revenue: 49.90, currency: "USD" })- Normalised at ingest.
revenuemust be a number ≥ 0 (a numeric string such as"49.90"is accepted),currencya three-letter ISO 4217 code in any case. - A bad amount never loses the event. An amount that is not a number, negative, over one billion or missing its currency is removed, and the reason is kept in
_revenue_rejectedso it can be counted and shown rather than silently reported as less. computeRevenuereturns, for one currency at a time: revenue, orders, average order value, revenue per visitor (over all human visitors), conversion rate (sessions with a payment ÷ all sessions), a breakdown by channel, source, campaign, event, page, country or device, a series, the previous period and the rejected amounts by reason — each as a query with its SQL and parameters.- No currency conversion. Amounts in different currencies are never added together: an exchange rate is a number from somewhere else, and a total built on one could not be checked against the data.
- Attribution. Channel, source and campaign are where the visit began — the session's first event — because a checkout page almost never has an outside referrer. Page, event, country and device are the payment's own.
- Revenue from verified AI-agent sessions is reported on its own line, not in the totals.
Import from Umami
importUmamiCsv(store, csv, options) reads an Umami export — one row per page view or event, the same grain Vitrus stores — into events.
- Idempotent. Each event keeps its Umami id; importing the same file twice adds nothing, and the summary reports what was actually written.
- No double counting. Rows at or after the first event Vitrus itself collected are skipped and counted.
- Same rules. Channels and sources are re-classified with Vitrus's referrer table. Umami's session becomes a visitor and its visit a session.
- Removable. Every row carries its batch id;
removeImportdeletes exactly one batch. - Plausible is deliberately not supported: its export contains daily totals, not visits, and turning totals into visits would mean inventing them.
Scope
Both are in the core library. The hosted dashboard at app.vitrus.dev has a Revenue page and an upload for imports; the self-hosted server does not expose routes for them yet — call the functions directly for now.