Self-hosted

A tracker that just tracks.

Unlimited domains, users and clicks for one flat price. Runs on your own VPS, installs with one command.

14 days, no card, over Telegram — @roitrack · Cancel any month · 1.6 ms typical redirect

Roitrack campaigns table showing 22 campaigns with clicks, conversions, cost, revenue, profit and ROI, winners in green and losers in red

Campaigns. Winners green, losers red, break-even grey.

What it does

You need to know one thing: which campaigns make money.

Everything a media buyer checks. Nothing they don't.

Two questions, two reports

“How much did I make today?” and “did last month's traffic ever pay off?” are different questions. Most trackers only answer the first. Drag the divider: same campaign, same weeks, revenue credited to the click date on the left and to the payout date on the right.

Weekly report with revenue counted on the date each payout arrived
The same weekly report with revenue credited back to the week the click happened

Same week, same spend. Click-date view reads +107.8% ROI; conversion-date view reads +3.9%. Three of these five weeks flip verdict depending on which question you ask.

The verdict, per campaign

Clicks, conversions, cost, revenue, profit and ROI — per campaign, offer, lander, country. Group up to three levels deep, build your own columns with formulas, save the filters you use daily, export to XLSX when someone asks for a spreadsheet.

iGaming campaigns with registration and first-deposit funnel columns

iGaming funnel: regs, reg cost, FDs, FD cost, reg-to-deposit rate.

Your columns, your maths

Approval rate, CPL, whatever your vertical actually runs on — write the formula once and it becomes a column. Set which columns show on each page and in what order, so a nutra report and an iGaming report each show only what matters there.

Nutra campaigns with custom approval rate and cost-per-lead columns

Nutra: leads, approved, and two custom formula columns.

Facebook, read from every account you have

One ads_read token covers the whole portfolio — every ad account, every business manager, personal, agency or rented. There is no ad account ID to paste and no list to keep in sync: spend is read per campaign, so accounts can appear and disappear underneath it without you reconnecting anything.

Yesterday's cost lands in your own database every day, which is what makes the numbers outlive the account. Lose a BM and you still have the spend, clicks, conversions and profit for every campaign that ever ran on it. Accounts billing in different currencies are each read in their own and converted to USD at a rate pinned to that day, so a report you open next year reads the same as it did the morning after.

The Conversions API runs the other way. When your network fires a postback for a deposit or an approved lead, that becomes an event on your pixel — so Facebook optimises toward the payouts you were actually paid for, instead of toward a click on your lander hours earlier.

Six Facebook ad accounts across three business managers, read through one ads_read token into a single row of totals in US dollars. Six ad accounts sit under three business managers. BM 1 holds a personal account billed in rupees, INR 79,200, worth 900 dollars, and a BM-owned account billed in dollars, USD 5,410. BM 2 holds an agency account, USD 1,275, and a rented account billed in reais, BRL 8,262, worth 1,530 dollars. BM 3 holds a personal account, INR 52,800, worth 600 dollars, and a rented account, BRL 4,590, worth 850 dollars. All six feed a single ads_read token, whichever business manager they sit under. That token reads 6 of 6 accounts, needs no ad account IDs, and pulls spend daily. Rates are pinned per day at 88.0000 rupees and 5.4000 reais to the dollar. The six converted amounts sum to one row of totals: cost 10,565 dollars, revenue 13,946 dollars, profit 3,381 dollars, ROI plus 32.0 percent. BM 1 personalINR 79,200$900 bm-ownedUSD 5,410$5,410 BM 2 agencyUSD 1,275$1,275 rentedBRL 8,262$1,530 BM 3 personalINR 52,800$600 rentedBRL 4,590$850 one ads_read token accounts read6 of 6 ad account IDsnone spend pulleddaily INR → USD88.0000 BRL → USD5.4000 cost$10,565 revenue$13,946 profit$3,381 ROI+32.0% Six Facebook ad accounts across three business managers, read through one ads_read token into a single row of totals in US dollars. Six ad accounts sit under three business managers. BM 1 holds a personal account billed in rupees, INR 79,200, worth 900 dollars, and a BM-owned account billed in dollars, USD 5,410. BM 2 holds an agency account, USD 1,275, and a rented account billed in reais, BRL 8,262, worth 1,530 dollars. BM 3 holds a personal account, INR 52,800, worth 600 dollars, and a rented account, BRL 4,590, worth 850 dollars. All six feed a single ads_read token, whichever business manager they sit under. That token reads 6 of 6 accounts, needs no ad account IDs, and pulls spend daily. Rates are pinned per day at 88.0000 rupees and 5.4000 reais to the dollar. The six converted amounts sum to one row of totals: cost 10,565 dollars, revenue 13,946 dollars, profit 3,381 dollars, ROI plus 32.0 percent. BM 1 personalINR 79,200$900 bm-ownedUSD 5,410$5,410 BM 2 agencyUSD 1,275$1,275 rentedBRL 8,262$1,530 BM 3 personalINR 52,800$600 rentedBRL 4,590$850 one ads_read token INR → USD88.0000 BRL → USD5.4000 cost$10,565 revenue$13,946 profit$3,381 ROI+32.0% accounts read6 of 6 ad account IDsnone spend pulleddaily
Six accounts, three business managers, three billing currencies, one token. The six converted amounts sum to the cost shown, at the rates they were converted at.

A campaign it can't see is named, not zeroed

When the token can't read a campaign, the report names it. It does not record zero spend. Zero spend is a number you would act on — it reads as a free campaign, and scaling one of those is expensive.

A currency it can't price writes nothing

No rate for that day and that account, and nothing is written. A total that quietly drops one account looks exactly like a complete one, and a gap you can see is worth more than a number you can't check.

The conversion loop in five steps: a Facebook click goes out, and the real payout comes back to the pixel that aimed it. A closed loop in five steps. A Facebook ad carries the pixel id in ?pixel= on its URL. The click hits your tracker, which stores fbclid to match on, and the visitor goes to a lander, where an optional fbp snippet can run, or straight to the offer. The conversion happens on the network, hours to weeks later. roitrack maps it to a Facebook event, per campaign, taking the campaign conversion or any of event1 to event10, with write-only tokens. The pixel receives a real payout rather than a button click, and the return leg carries that back to the ad, which aims better next time. Facebook ad?pixel= on the ad URL Click hits the tracker fbclid stored to match lander or direct to offer fbp optional on lander Conversion happenson the network hours to weeks later Mapped to a Facebook event per campaign: conversion or event1–event10 Pixel gets a real payouttokens are write-only the next ad aims better The conversion loop in five steps: a Facebook click goes out, and the real payout comes back to the pixel that aimed it. A closed loop in five steps. A Facebook ad carries the pixel id in ?pixel= on its URL. The click hits your tracker, which stores fbclid to match on, and the visitor goes to a lander, where an optional fbp snippet can run, or straight to the offer. The conversion happens on the network, hours to weeks later. roitrack maps it to a Facebook event, per campaign, taking the campaign conversion or any of event1 to event10, with write-only tokens. The pixel receives a real payout rather than a button click, and the return leg carries that back to the ad, which aims better next time. Facebook ad?pixel= on the ad URL Click hits the tracker fbclid stored to match lander or direct to offer fbp optional on lander Conversion happenson the network hours to weeks later Mapped to a Facebook event per campaign: conversion or event1–event10 Pixel gets a real payouttokens are write-only the next ad aims better The pixel is trained on the payout, not on the click.
The pixel is trained on the payout, not on the click.

Flows without the flowchart

Direct to offer, or through a bridge lander. Split traffic across offers and landers by weight, random or sticky per visitor, with country and OS targeting per flow. That's the whole rotation feature — no diagram editor to learn.

One campaign splitting traffic: a single flow, weighted sixty forty across a bridge lander and an offer, with a fallback. A campaign sends traffic into one flow. The campaign uses sticky rotation, so a returning visitor gets the path they had the first time. The flow is targeted to Germany and France and to Android. It splits three ways: sixty per cent to a bridge lander, which then sends the visitor on to Offer A; forty per cent direct to Offer A with no lander; and a fallback to Offer B. One split, no nesting. Campaignrotation: sticky per visitor Flowcountry DE, FR · OS Android Bridge lander60 then Offer A Offer A40 direct, no lander Offer B fallback One campaign splitting traffic: a single flow, weighted sixty forty across a bridge lander and an offer, with a fallback. A campaign sends traffic into one flow. The campaign uses sticky rotation, so a returning visitor gets the path they had the first time. The flow is targeted to Germany and France and to Android. It splits three ways: sixty per cent to a bridge lander, which then sends the visitor on to Offer A; forty per cent direct to Offer A with no lander; and a fallback to Offer B. One split, no nesting. Campaignrotation: sticky per visitor Flowcountry DE, FR · OS Android Bridge lander60 then Offer A Offer A40 direct, no lander Offer B fallback
One campaign, one flow, three destinations. The weights are shares of the traffic; sticky rotation keeps a returning visitor on the path they were given first time.

Numbers that don't lie

Duplicate clicks deduped so postbacks attribute to the right click. Browser prefetches filtered before they inflate anything. Traffic-loss compensation built into the cost maths.

Domains that handle themselves

Add a domain and SSL issues itself — Let's Encrypt, or full Cloudflare mode with the DNS record created over the API. Bulk-add a list at once. Live certificate status, so an expiry never surprises you.

Your data stays on your box

Your campaign data sitting on somebody else's server is a problem you can simply not have. Roitrack runs on your VPS instead. Your campaigns, your sources, your numbers — nobody else's business, including ours. We can't see your stats even if we wanted to.

Speed

Slow redirects burn paid clicks.

Hot redirects never touch a database: in-memory campaign lookup, asynchronous writes, 302 out. These numbers are measured on a 2 vCPU / 4 GB VPS — the minimum spec Roitrack runs on — not estimated.

Redirect, typical (p50)1.6 ms
Redirect, worst 1% (p99)under 10 ms
Max sustained throughput1,000+ clicks/sec
That's a daily ceiling of~86,000,000 clicks

Latency measured warm at normal load; throughput measured at saturation from a separate machine.

Setup

Fresh server to first tracked click, in about fifteen minutes.

  1. Point a domain at your VPS.
  2. Grab your install link from your Roitrack account — license and domain are already baked in.
  3. Paste the one command into a clean Ubuntu server.
  4. Add a source and an offer, launch a campaign. Done.

First time through, budget 30–45 minutes — DNS propagation and wiring your network's postback take most of it, and the interface walks you through both. Every domain or campaign after that takes under two minutes. Updates ship through the interface: one click, no SSH.

Switching

Already running a tracker? Campaigns move in a couple of minutes each.

Campaigns take a couple of minutes each to recreate. Any source or network works through URL templates and macros — if it can fire an S2S postback, it works here. Nothing needs an integration built for it.

Run both for a week if you want the overlap — one campaign pointed at each, same traffic. Coming from Keitaro? Here is how the two compare.

Pricing

One plan. Everything included.

$69/month

Typical self-hosted trackers ask $130+ a month once you pass one user and ten domains. This is the whole price, at any size. Pricing it against a metered cloud tracker? Here is how Roitrack compares to Voluum and to RedTrack.

  • Every feature on this page
  • Unlimited campaigns, offers and landers
  • Unlimited domains and users
  • Unlimited clicks and conversions
  • Monthly billing — no annual contract, cancel any month
  • Cancel and your data stays put — it was never on our servers
  • Cloudflare integration
  • Support by email or Telegram
Start tracking

Your maximum risk is one month. One license per server. Requires your own VPS from any provider (roughly $10–15/month); Ubuntu 24, 2 vCPU / 4 GB minimum — don't go lower.

Who builds this

Media buyers who got tired of the bill.

We've been buying traffic for six years. We built Roitrack because self-hosted trackers wanted $130+ a month the moment we needed more than one user and ten domains — for software running on a server we were already paying for.

So the limits nobody else removes are the ones that are gone here: unlimited domains, unlimited users, unlimited clicks, one price — the whole case for a self-hosted affiliate tracker, in one plan. Everything on this page is what we use to run our own campaigns.

Questions

The things people ask first.

Do you have a trial?

Yes — 14 days, the full version, no card. It's issued by hand rather than a signup button, so you're set up by the people who built it. Message @roitrack on Telegram or email support@roitrack.app — usually set up within the hour.

Can you see my campaign data?

No. Roitrack is fully self-hosted — everything lives on your server. The license check is the only thing that talks to us, and it carries no campaign data.

What do I need to run it?

A fresh Ubuntu 24 VPS from any provider, 2 vCPU / 4 GB minimum — don't go below that. Point a domain at it, grab your install link, paste one command. If you can do that, you can run Roitrack.

What happens if I cancel?

Your data stays where it has always been: on your server. The license stops validating after a short grace period, so the app stops working until you resubscribe. Nothing is deleted and nothing leaves your box.

Does it handle CPA, CPL and RevShare?

Yes. Payouts arrive by postback with your own status mapping, and conversions that land weeks after the click still attribute to the click that earned them — which is exactly what the two reports above are for.

Does it cloak?

Yes. You can send invalid traffic to a 404, a blank page or a safe page you set, so it stays out of your numbers.

What if I need help?

Email support@roitrack.app or message @roitrack on Telegram.

A tracker that just tracks.

See what's printing. Kill what's burning. $69 a month, on your own server.

Start tracking