01
Visits
Pages, sources, UTM campaigns, countries and devices. Unique visitors per day without cookies, with bots filtered out.
pageviews · sources · utm_* · countries
Cookieless · server-side · revenue
Send pageviews and sales from your backend with a library for Laravel, Node or Django. See which source brings buyers, not just clicks, while your visitors’ IPs never leave your server.
Free during the beta · Laravel · Express · Next.js · Django · FastAPI
Visitors
12,480
Purchases
214
Revenue
€6,930
Revenue by first source
each sale credited to the source that brought the buyer
Events
CheckoutController.php
// when the payment clears
Rom::track('purchase', revenue: [
'amount' => 29, 'currency' => 'EUR',
]);
In production at
A film-on-demand platform
Revenue per traffic source, from the first rental.
A football analytics SaaS
Behind Cloudflare’s cache, with its servers on the same screen.
credited.dev
A developer portfolio, counted without a single cookie.
Run of mine
In mining, run of mine is the ore as it comes out of the mine, unsorted. That is how your data lands in runomine: visits, money and the health of your servers, together. No three tools to glue, no exports to cross.
01
Pages, sources, UTM campaigns, countries and devices. Unique visitors per day without cookies, with bots filtered out.
pageviews · sources · utm_* · countries
02
Signups, checkouts and purchases with their amount. Every euro credited to the source that brought that buyer.
signup → checkout_started → purchase
03
Queues, errors, CPU and database connections next to the traffic. When sales drop, you see whether it was your marketing or your server.
queue.pending · jobs.failed · web_cpu
Install
Install the library for your stack, put your token in the environment and call track() where the money happens. Pageviews count themselves through the middleware.
200$ composer require runomine/runomine-php
# .env: pageviews start counting through the middleware
RUNOMINE_TOKEN=rm_live_…
// Business events, from anywhere in your app
Rom::track('purchase', ['plan' => 'pro'],
['amount' => 29, 'currency' => 'EUR']);
$ npm i @runomine/node
import runomine from '@runomine/node'
app.use(runomine.express()) // pageviews, reads RUNOMINE_TOKEN
runomine.track('purchase', { plan: 'pro' },
{ revenue: { amount: 29, currency: 'EUR' }, request: req })
$ npm i @runomine/node
// middleware.ts: pageviews
import { withRunomine } from '@runomine/node/next'
export default withRunomine()
// a server action or route handler
track('purchase', { plan: 'pro' },
{ revenue: { amount: 29, currency: 'EUR' }, request })
$ pip install runomine
# settings.py: pageviews, reads RUNOMINE_TOKEN
MIDDLEWARE += ['runomine.django.RunomineMiddleware']
# Business events, from any view or task
from runomine.django import track
track(request, 'purchase', revenue={'amount': 29, 'currency': 'EUR'})
$ pip install runomine
from runomine.asgi import RunomineMiddleware, track
app.add_middleware(RunomineMiddleware) # pageviews
track(request, 'purchase', revenue={'amount': 29, 'currency': 'EUR'})
<!-- Static sites, CDN-cached pages, SPAs: no cookies, no localStorage -->
<script defer src="https://runomine.com/r.js" data-site="site_xxxxxxxxxxxx"></script>
<!-- Events from the browser -->
<script>rom('signup', { plan: 'pro' })</script>
Another language? Any backend can POST to /api/v1/events with a token.
How it works
Script-based tools receive the IP with every visit, and their server-side APIs ask you to forward it. runomine doesn’t even receive it: the library computes a hash on your server and sends only that.
1 / 3 · browser
Your server gets the request as always: IP, user agent, URL and referrer. Nothing new in the browser: no cookies, no script.
GET /pricing
ip 203.0.113.9 ua Safari/18
→ stays here
2 / 3 · your server
With your token and the UTC date. The salt changes every day, so a person counts once per day and site, and can’t be followed across days or sites.
salt = HMAC(token, "runomine:"+day)
visitor = SHA256(salt|ip|ua|host)[:16]
→ 5f9e1bebe31e8bf5
3 / 3 · runomine
It classifies the source, drops bots and stores the event. The user agent gives the device and browser, then it’s discarded.
{
"type": "pageview",
"url": "https://…/pricing",
"visitor": "5f9e1bebe31e8bf5",
// no "ip": it stays on your server
}
If Cloudflare serves the page, your backend never sees it. That’s what the beacon is for: under 1.5 KB, no cookies, no localStorage, and it honours Do Not Track and GPC. It yields the same hash, so nobody counts twice.
PHP, Node, Python and runomine implement one algorithm and are tested against one shared test vector. You can read every line of the library you install.
Revenue attribution
Send purchase with its amount and runomine credits it to the first source that brought that buyer. Pass your user id and the purchase joins the visits made before they logged in.
A film-on-demand platform knew Instagram was its best channel: it brought more visitors than anything else. Once it counted money, direct traffic turned out to convert best.
| Source | Visits | Revenue |
|---|---|---|
| 46% 21% | ||
| 24% 26% | ||
| direct | 18% 41% | |
| newsletter | 12% 12% | |
Illustrative, shaped like the real case. Not the customer’s figures.
Funnels and operations
Build the steps from the names you already send (signup, checkout_started, purchase) and see where people drop off.
Demo data
Queues, failed jobs, CPU and Postgres connections on the same timeline as the traffic. Mark a deploy or a newsletter send and see what changed.
Compare
They’re all good tools. This is what changes when you count from the backend, and when you count money.
| Feature |
|
Google Analytics 4 | Plausible | Fathom |
|---|---|---|---|---|
| Cookies on the visitor’s device | None | Yes (_ga) | None | None |
| Sending from your backend | Libraries for Laravel, Node and Python | Measurement Protocol, alongside the tag | Events API, you forward the visitor IP | — |
| Visitor IP reaches the provider | No, with the libraries | Yes | Yes | Yes |
| Revenue per traffic source | First source per buyer | Ecommerce and attribution models | Revenue goals (Business plan) | Event values |
| Funnels | ✓ | Funnel explorations | Business plan | Not advertised |
| Server metrics next to traffic | ✓ | — | — | — |
| Open source | — | — | Yes (AGPL) | — |
| Price | Free during the beta | Free (GA360 is paid) | From $9/month | From $15/month |
Checked in October 2026 against each product’s public pages and docs. If something has changed, we’ll correct it.
Privacy and GDPR
runomine is built to measure without tracking. But no cookies doesn’t mean the GDPR stops applying, and we’d rather show you exactly where the line is.
Nothing on the device
No cookies, no localStorage, no fingerprinting. Neither the libraries nor the beacon store anything in the browser.
The IP stays with you
The libraries hash on your server and send only the hash. With the beacon, runomine computes it from the request and discards the IP.
A hash that expires daily
The salt changes every UTC day: one person counts once per day and site, and can’t be followed across days or sites.
Do Not Track and GPC
The beacon drops hits sent with DNT: 1 or Sec-GPC: 1. Bots are filtered centrally.
What still applies
The GDPR. The IP and user agent are personal data while your server processes them, and a hash is pseudonymisation, not anonymisation. runomine acts as your processor and signs a data processing agreement with you (DPA, art. 28 GDPR).
The banner. Measuring visits and funnels is designed to fit the audience-measurement exemption described by Spain’s AEPD and France’s CNIL: your own purpose, aggregate statistics, no cross-site tracking. Joining purchases to a known user to attribute revenue goes beyond that list, so assess its legal basis (often consent) with your DPO. We’d rather tell you that than promise “no banner, ever”.
Pricing
All of runomine while we polish it with the first customers. When prices come, they’ll be published here, with notice before anything is charged.
0 €during the beta
FAQ
purchase event with revenue (amount and currency). runomine credits it to the first source that brought that buyer. If you pass your own user id, purchases made after logging in are linked to the visits from before.Visits, sales and servers in one place. Installed in less time than it took to read this page.