Pageviews & time on page
Track views and send duration on exit or tab change — a privacy-friendly model with visitor identification via localStorage, no cookies.
Open source · MIT · Laravel 13
IndieStats is a lightweight, self-hosted alternative to mainstream analytics: multiple sites per account, a dedicated snippet, no cookies, and no mandatory consent banners.
What you get
Dashboards, advanced filters, exports, and automatic housekeeping — without handing data to third parties or weighing down the site you track.
Track views and send duration on exit or tab change — a privacy-friendly model with visitor identification via localStorage, no cookies.
See clicks to external domains so you know which off-site resources your visitors use.
Up to 20 key–value properties per event. Tie events to goals and watch conversions over time.
UTM parameters, referrers, and search queries with automatic source classification (search engines, social, and more).
Browser, OS, device type, and country (optional GeoIP via a local MaxMind GeoLite2 database).
XLSX exports run in the background via queues — download data for the selected range and filters when it is ready.
Scheduled jobs remove raw data past your configurable retention window (default ~375 days).
Multiple sites per user, each with a public key and allowed domains to prevent snippet abuse.
A 1×1 pixel for visitors without JavaScript — limited tracking with useful baseline coverage.
Install
PHP 8.3+, Composer, and Node 20+. Supported databases: SQLite (default), MySQL, or PostgreSQL. In production, build frontend assets and run queue workers and cron.
The setup script installs dependencies, runs the Vite build, creates .env,
generates the app key, and runs migrations.
How it works
Try it now!
Clone the repo, run composer run setup, or follow the manual steps in the README. For local
development, start the stack with composer run dev.
In the app, add a site with a name and allowed domains. Copy the async script and the
noscript fallback before the closing body tag — the base URL is your
APP_URL.
Multi-site overview, per-site detail with charts, server-side tables (DataTables), and filters for path, source, device, country, and UTM parameters.
Production
Set APP_URL to HTTPS, build assets with npm run build, configure cron for Laravel's
scheduler, a queue for exports, and — behind a proxy — trusted proxies for GeoIP.
To run IndieStats (or any Laravel app) in production with zero-downtime deploys, SSL, and workers, you can use Cipi
Explore cipi.sh ↗