Skip to content
Conduit

mcp server

virling

Open-source revenue attribution: see which traffic channel brings paying customers. Stripe, Dodo Payments and Polar. One Rust binary.

virling/virlingcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 21, 2026

Virling joins every visit to the payment that followed. It answers the questions a founder asks every week:

  • Which channel brought the most revenue this month?
  • Did that launch, tweet or Reddit post make money, or just traffic?
  • What is a visitor from each source worth?
  • What path did my last paying customers take before they paid?

It runs as one Rust binary with embedded storage. No Postgres, no ClickHouse, no Redis.

Status: early development. Releases are on the releases page and run on your own server today. Expect breaking changes until a stable release. A hosted plan is on a waitlist at virling.com.

What works today

  • Tracking script (/v.js, about 1.3 KB gzipped, source in assets/v.src.js): pageviews, UTM tags, referrers, single-page-app route changes, custom goals, and a first-party visitor ID. Stripe Payment Links, Polar checkout links and Dodo payment links get the visitor ID added automatically.
  • Cookieless mode: a daily-rotating salted hash instead of a cookie, for sites that want no consent banner, at the cost of payment attribution.
  • Event ingest into embedded DuckDB, with bot filtering, per-site rate limits and channel rules (Paid, Email, AI, Organic search, Communities, Social, Referral, Direct). Visitor IPs are never stored.
  • Payment sync from Stripe, Dodo Payments, Polar and LemonSqueezy with a read-only key (LemonSqueezy keys cannot be limited): a 90-day backfill, then a poll every minute. Virling never creates, changes or refunds anything. LemonSqueezy payments count toward revenue, but linking them to visits waits on webhook support.
  • Attribution: last non-direct or first touch, with a 30, 60, 90 or 365 day lookback. Renewals keep the channel of the customer's first payment. Payments without a visitor ID count as Unattributed.
  • Revenue dashboard: revenue, revenue per visitor and conversion by channel, referrer, campaign, page and country, payment journeys, a Visitors page, retention by first channel, tracked short links, and AI assistant visits next to AI crawler hits.
  • Reports and sharing: weekly email reports with agency branding, and an optional public dashboard.
  • Read API, MCP server and CLI: read-only access with API keys, so virling query and AI assistants can answer revenue questions. An agent skill is in skills/virling.
  • WordPress plugin in integrations/wordpress.
  • Magic-link sign-in and onboarding (behind --app).

Not available yet: attribution for LemonSqueezy payments, the hosted plan, team members, imports from other tools, other attribution models and Windows builds.

Run it

With Docker:

docker run -d --name virling -p 8080:8080 -v virling-data:/data \
  -e VIRLING_BASE_URL=https://stats.example.com \
  ghcr.io/virling/virling:latest serve --app
docker exec virling virling add-site yourdomain.com --owner you@example.com

The full guide, with release binaries, a reverse proxy and payment setup, is at docs.virling.com. To run from source, you need Rust 1.99 or newer:

cargo run --release -- add-site yourdomain.com --owner you@example.com
cargo run --release -- serve --app

Then add the script to your site:

<script defer src="https://YOUR-VIRLING-HOST/v.js" data-site="yourdomain.com"></script>

Track a goal from your code:

virling("goal", "signup");

Pass the visitor ID into checkout so payments can be matched back to visits:

virling.vid();

Configuration

VariableDefaultWhat it does
VIRLING_DATA./virling-dataFolder for the SQLite and DuckDB files
VIRLING_ADDR0.0.0.0:8080Address to listen on
VIRLING_BASE_URLhttp://localhost:8080Public URL, used in emails and snippets
VIRLING_APPoffServe sign-in and the app
VIRLING_SMTP_URLunsetSMTP for emails, e.g. smtps://user:pass@smtp.example.com:465. Unset: emails are logged
VIRLING_MAIL_FROMVirling <login@virling.com>Sender for sign-in emails
VIRLING_TRUST_PROXYoffRead the client IP from X-Forwarded-For
VIRLING_EVENTS_PER_SECOND200Ingest limit per site

Development

cargo test

worker/ holds the Cloudflare Worker that serves virling.com during the waitlist phase. It reuses the landing pages in assets/ and builds with wrangler deploy.

License

AGPL-3.0. Self-host it freely. If you run a modified version as a service, share your changes.

Built by Stacklance Infotech LLP.

↑↓ navigate openesc close