virling Docs
v0.1.0 virling.com GitHub
virling Docs

Quickstart

Run Virling on your own server, add the tracking script to your site and connect a payment provider. From then on, every new payment shows the visit that brought it.

Self-host6 stepsv0.1.0

Note

Hosted plan coming soon. app.virling.com is not open yet, so this guide covers self-hosting. Steps 4 to 6 will be the same on the hosted plan.

Warning

Payments need the next release. v0.1.0, the current release, has tracking, sign-in and onboarding. Payment sync, attribution, the dashboard, VIRLING_BASE_URL and VIRLING_SECRET_KEY ship in the next release. Until it is out, build from source from main to use them.

You need a Linux or macOS server with Docker or one of the release binaries, and a domain pointing at it. Virling listens on port 8080 and keeps everything in one data folder: SQLite for settings, DuckDB for events.

Start the server

Pick one way to run it. Each starts the server with the app turned on, which serves sign-in, the dashboard and payment sync.

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
curl -LO https://github.com/virling/virling/releases/download/v0.1.0/virling-v0.1.0-x86_64-unknown-linux-gnu.tar.gz
tar xzf virling-v0.1.0-x86_64-unknown-linux-gnu.tar.gz
cd virling-v0.1.0-x86_64-unknown-linux-gnu
VIRLING_BASE_URL=https://stats.example.com ./virling serve --app
Also built for Linux arm64 and macOS on Apple silicon.
[Unit]
Description=Virling
After=network-online.target
Wants=network-online.target

[Service]
User=virling
Environment=VIRLING_DATA=/var/lib/virling
Environment=VIRLING_BASE_URL=https://stats.example.com
ExecStart=/usr/local/bin/virling serve --app
Restart=on-failure

[Install]
WantedBy=multi-user.target
EXAMPLEThe repo does not ship a unit file yet. Save this as /etc/systemd/system/virling.service, then run sudo systemctl enable --now virling.

Check that it is up: curl http://localhost:8080/health prints ok.

Warning

Keep the secret key. Payment keys are encrypted with secret.key in the data folder, or with VIRLING_SECRET_KEY if you set it. Lose it and you have to reconnect every provider.

Add your site

Create the site and its owner from the command line. The owner account is created if it does not exist. You can also add sites after signing in.

$ virling add-site yourdomain.com \
    --owner you@example.com --timezone Europe/Berlin
Added yourdomain.com. Script tag:
<script defer src="https://YOUR-VIRLING-HOST/v.js" data-site="yourdomain.com"></script>

With Docker, run it inside the container: docker exec virling virling add-site yourdomain.com --owner you@example.com. The timezone decides where your report days start and defaults to UTC.

Sign in

Open https://stats.example.com/login and enter the owner email. Without an SMTP server, the sign-in link is printed to the server log instead of being emailed. With Docker, read it with docker logs virling.

Note

Send real emails. Set VIRLING_SMTP_URL, for example smtps://user:pass@smtp.example.com:465, and VIRLING_MAIL_FROM for the sender. See Sign-in email.

Add the script

Paste this before </head> on every page. It loads with defer and never blocks rendering.

<script defer src="https://stats.example.com/v.js"
  data-site="yourdomain.com"></script>

Attributes the script reads:

AttributeWhat it does
data-site RequiredThe domain you added in step 2. Pages on its subdomains count toward it.
data-api OptionalSend events to this URL instead of /api/event on the script host.
data-cookieless OptionalNever set the virling_vid cookie. Visitors are counted with a daily hash, and payments show as Unattributed.
data-respect-gpc OptionalSend nothing when the browser has Global Privacy Control turned on.
data-dev OptionalAlso track on localhost. Off by default, so local testing stays out of your reports.

Track a goal from your code with virling("goal", "signup"). Route changes in single-page apps are tracked on their own. See Framework guides for Next.js, Astro, WordPress, Framer and Webflow.

Connect payments

In the app, open your site’s setup, then Connect payments, and paste a read-only key. Virling imports the last 90 days, converts amounts to USD and checks for new payments every minute.

Pass the visitor ID into checkout so each payment is credited to the visit that brought it. On your server, read the virling_vid cookie. In the browser, window.virling?.vid?.() returns the same ID.

// Stripe Checkout (Node): pass the visitor ID on the session
const session = await stripe.checkout.sessions.create({
  client_reference_id: req.cookies.virling_vid,
  line_items: [{ price: "price_...", quantity: 1 }],
  mode: "subscription",
  success_url: "https://yourdomain.com/thanks",
});

Note

Payment links need nothing. Stripe Payment Links, Polar checkout links and Dodo payment links are tagged by the script when a visitor clicks them. Payments without a visitor ID still count, as Unattributed.

See Link checkout to visits for Dodo Payments, Polar and LemonSqueezy.

Next steps

Was this page helpful?No Edit this page on GitHub