One file. No cookies. Full picture.
Self-hosted web analytics in a single PHP file and SQLite.
Upload it to any PHP host and see your traffic in minutes, without a cookie banner.
On any host with PHP 8.3 or newer, download the latest release, then:
unzip puls-*.zip && cd puls-*/
php puls user:add admin # create your login
php -S localhost:8080 -t public # try it, or point your web server at public/Add one line to every site you want to track:
<script src="https://stats.example.com/?js" data-site="example.com" defer></script>That's it. Docker, Nginx, Laravel Forge and shared hosting without SSH are covered in Install and run.
- One file, no infrastructure. A PHP file, a dashboard page and SQLite. No Node, no Docker, no database server, no build step. It runs on ordinary PHP web hosting.
- Private by design. No cookies and no stored IP addresses. A visitor is a hash with a random salt that is deleted after the day, so it can never be computed again, not even by whoever runs the server. Puls is designed to work without a consent banner.
- Your data, on your server. One SQLite file you can copy, back up or delete. MIT licensed, no limits, no account.
- Light on your pages. The tracking script is under 2 KB gzipped and sends with
sendBeacon, so it never holds up the page.
Bots are counted apart from your visitors: AI crawlers such as GPTBot, ClaudeBot and PerplexityBot, search engines, SEO tools, social previews and uptime monitors, with the pages they read. Behind Nginx, Puls also logs 404s and redirects as pages to fix, with the pages that link to them. Both sections stay folded until you open them, and their headers say what is inside ("1,128 visits from 8 bots", "2 not found, 3 redirects"), so you can tell when one is worth a look.
puls.track('signup', { plan: 'pro' }) is all it takes. Each event gets a trend, a rate per 100 visitors, a breakdown by any key in its data, a two-step funnel and a CSV export. Save a breakdown and it becomes a card on the dashboard, with its total, its change and a sparkline.
A goal is a page or an event. Its tile shows the visitors who converted, their share of all visitors, the change against the previous period and, if you set one, a target such as 10 per week.
- Traffic: channels (paid, campaign, organic, social, referral, direct), UTM campaigns with a link builder, Google Ads detection, entry and exit pages, bounce rate and session length
- Over time: compare with the previous period, custom date ranges, chart notes for campaigns and mentions, release markers from your app version, a live visitor count
- Teams and clients: one dashboard for many sites, sites in groups, users limited to their own sites, read-only share links, a JSON and CSV API
- Tracking without code: phone and email clicks, downloads, form submissions, outbound links
- Keeping personal data out: drop query strings or turn ids and tokens in URLs into
:idand:tokenbefore anything leaves the browser - Everyday use: dark mode, a ⌘K command palette for sites and pages, installable as an app, white-label branding, an interactive CLI
| What you run | Database | Cookies | Hosted version | License | |
|---|---|---|---|---|---|
| Puls | One PHP file on any PHP 8.3 host, or Docker | SQLite, built in | None | No | MIT |
| GoatCounter | One Go binary | SQLite or PostgreSQL | None | Free, donation-supported | EUPL (modified) |
| Umami | Node.js app, or Docker | PostgreSQL | None | Free tier and paid plans | MIT |
| Plausible CE | Docker Compose, 2 GB RAM recommended | PostgreSQL and ClickHouse | None | Paid | AGPL-3.0 |
| Matomo | PHP app | MySQL or MariaDB | Yes by default, can be turned off | Paid | GPL-3.0 |
| Google Analytics | Nothing, Google hosts it | Google's servers | Yes | Free | Proprietary |
From each project's own documentation, October 2026. Corrections are welcome as issues or pull requests.
When to pick something else. Puls is made for small and medium sites that you run yourself.
- You would rather not run anything: Plausible and Umami have hosted plans, and GoatCounter has a free hosted service.
- Millions of pageviews a month on one site: a database built for analytics, like Plausible's ClickHouse, stays fast at that size. Puls's dashboard slows down there: a 30-day view of a site with 2 million pageviews a year takes about 3 s on a laptop (
scripts/benchmark.php), and making it faster is on the roadmap. - E-commerce reports, heatmaps or session recordings: Matomo does that, Puls doesn't.
- No cookies, ever
- No IP addresses stored: the visitor id is a hash of IP and user agent with a random salt that is deleted after the day
- No fingerprinting: no canvas, font or WebGL tricks
- Collected: page path, referrer domain, browser, device type, UTM parameters, language and country (from the
Accept-Languageheader) - Kept: pageviews until you delete them, custom events for 400 days (
EVENTS_RETENTION_DAYS), bot visits for 90 days and broken links for 30 days after the last hit
You decide what your sites send. Keeping personal data out of URLs shows how to drop search terms, ids and personal links before they reach Puls.
- Install and run: release download, shared hosting, Nginx, Apache, Laravel Forge, Docker, upgrading
- Tracking and integrations: script attributes, custom events, frameworks (Next.js, Astro, Laravel, Statamic, React), auto events, server-side bot tracking, reverse proxies
- Configuration and CLI:
.envsettings, users and access, share links, excluding your own visits, white-label, every CLI command - Read API: JSON and CSV with a share token, also for your AI assistant
- Changelog and roadmap
MIT. Made by Webready in Sweden. The dashboard uses the Figtree typeface, under the SIL Open Font License (public/fonts/OFL.txt).




