Ten weeks and eleven releases after launch, our privacy-first Laravel analytics package has passed 100 installs on Packagist. Here is what that number means, what 1.2.2 changed, and what never will.
Cairn, our open-source, privacy-first analytics package for Laravel, has passed 100 installs on Packagist. As of this week the count stands at 130, with 55 of those in the last month. That is a small number by most measures, and we are pleased with it anyway. Cairn is ten weeks old, has never been advertised, and solves a problem most people do not yet know a Laravel package can solve.
Ten weeks, eleven releases
We introduced Cairn at 0.1.0 on 3 August. The pre-release line ran through 0.4.0 in under a week, and 1.0.0 followed on 9 August as a promise about the public API rather than a code change. Since then:
- 1.1.0 (31 August) made the dashboard filters narrow the whole page, or say why they cannot.
- 1.2.0 (7 September) surfaced data Cairn was already collecting: languages, screen sizes, Core Web Vitals, landing and exit pages, and top content.
- 1.2.1 (8 September) fixed the beacon on Laravel 13 and added an origin check to the collect endpoint.
- 1.2.2 (16 September) made the dashboard's cost stop growing with the traffic it describes.
The first three are covered in detail in Cairn 1.0 to 1.2.1. 1.2.2 has not had a post of its own, so here is the short version.
1.2.2: the same numbers, far fewer queries
The report builder asked storage once per chart point, and counted unique visitors once per row per day. A thirty-day chart was thirty queries. The same range at hourly detail was seven hundred and twenty. A ranked table with visitors over a month ran over a thousand. 1.2.2 reads each range once and splits it into buckets in PHP, and counts unique visitors for a whole report in a single request.
Measured on MySQL 8 against thirty days of forty routes:
- Overview chart, 30 days: 90 queries in 30.9ms, down to 2 queries in 8.6ms.
- Chart at hourly detail: 720 queries in 260.6ms, down to 1 query in 65.9ms.
- Ranked table with visitors: 1,201 queries in 359.5ms, down to 2 queries in 142.8ms.
The query counts matter more than the milliseconds. Those figures were taken against a database on the same machine. Against a managed database a millisecond or two away, two thousand round trips were seconds of waiting before any work started. A new index on cairn_aggregates, with the equality columns first and the bucket range last, took one dashboard's aggregate reads from 0.68s to 0.04s on a 748,000-row table.
The same release fixed a real bug. Every point on a visitor chart also counted the following day, because a bucket's window was inclusive at both ends. Daily charts showed roughly double the true line, and disagreed with the headline total above them. Totals were never affected. If your visitor chart looked generous before September, that is why.
composer require divoto/cairn:^1.2
php artisan migrate
What has not changed
No IP address is stored anywhere. Nothing is written to a visitor's device in the default configuration. The visitor hash rotates its salt every 24 hours and the old salt is destroyed. The architecture tests that assert each of those have run green on every one of the eleven tags. No install count changes that, and a contribution that weakens any of them will be declined however well written it is.
If you are one of the 130
Thank you. We do not know who most of you are, which is rather the point of the package. If you have hit something that does not behave as the docs describe, or a panel you wish existed, the issue tracker is open. And if Cairn is useful to you, a star on GitHub is the cheapest way to help the next person find it.
- GitHub: github.com/divoto/cairn
- Packagist: packagist.org/packages/divoto/cairn
- Changelog: github.com/divoto/cairn/blob/main/CHANGELOG.md
- Technical write-up: Cairn in our portfolio
Paige Newsom
Author at IfHighLow