Lightweight WordPress analytics

What Vireo Analytics adds to each pageview, measured on the free plugin: the bytes your visitors download, the requests their browser makes, and the work your database does. The method is at the end, so you can repeat it.

Scripts, gzipped
3,459 bytes for both, downloaded once
Beacons per pageview
1 when the page shows, up to 2 more when the reader leaves
Database writes per beacon
0. Views are written once a minute, in a batch.

What visitors download

Vireo adds two scripts to the end of each page. Both ship minified, and your server compresses them like any other file.

Bytestracker.jsvitals.jsBoth
As shipped, minified6,2292,0358,264
Gzipped2,4561,0033,459

tracker.js counts the view and time on page. vitals.js measures Core Web Vitals.

With compression on, a first-time visitor downloads about 3.5 KB. In our test, Chrome reused its copy on the next page and downloaded nothing. How long a browser keeps the files depends on your server’s cache headers, and their address only changes when the file does.

Vireo also keeps WP Rocket from minifying them. That plugin can keep serving an old minified copy after Vireo updates, so the tracker would miss whatever the update added.

Requests per pageview

WhenRequest
First page a visitor seestracker.js and vitals.js, from your own site
The page is showingOne pageview beacon
The reader leaves or switches awayOne beacon with the seconds the page was in front of them, and one with its Core Web Vitals

A page that’s read once and left costs three small beacons, plus the two files on the first page. A reader who switches to another tab and comes back sends one more time beacon each time they leave again. The vitals beacon goes once per page, and only if something was measured. Your server answers each beacon with an empty 204 response.

The beacons go to endpoint.php, a small file in the plugin folder that loads WordPress without your other plugins or your theme.

Database work when a beacon arrives

The endpoint checks the visitor isn’t a bot and hasn’t opted out, works out the day’s visitor hash, and appends one line to a buffer file in your uploads folder. It writes nothing to the database. Here are the queries we logged for each kind of beacon:

BeaconQueriesWrites
Pageview60
Time on page50
Core Web Vitals30

Each count includes the query every WordPress request makes to load its settings. The rest read Vireo’s own options, such as its settings and the day’s secret for telling visitors apart.

Database work once a minute

WordPress’s scheduler runs Vireo’s job, which reads the buffer, adds the views up in memory and writes the results in one transaction. The daily totals took 7 writes, one each for site totals, pages, referrers, countries, devices, hours and bounce rate. That was the same for a batch of one view and a batch of 50.

Each view also needs a few single-row queries on small indexed tables: whether this visitor was already counted today, how many views they’ve made today for the repeat-view cap, and the country cache. One view on its own took 12. The batch of 50 took 281, about 5.6 per view, because a visitor’s later views reuse what the batch already looked up.

How we measured

  • Plugin: Vireo Analytics 0.21.0 for script sizes, the files on WordPress.org. Requests and queries were measured on 0.13.0, as the only active plugin.
  • Server: WordPress 7.1.3 with its default theme, PHP 8.3 on Apache and MariaDB 11.8, in Docker, with no persistent object cache.
  • Sizes: the byte counts of tracker.js and vitals.js as shipped, then each one through gzip -9, and both together.
  • Requests: Chrome, driven by Playwright, opened a post, then a page, then closed the tab. We logged every request to Vireo’s files and endpoint, and checked the buffer file for the beacons sent on leaving, because the browser doesn’t report those to the test tool.
  • Queries: MariaDB’s general query log, with a marker query just before and after each request. We sent one beacon of each kind, then ran the once-a-minute job through WP-CLI with an empty buffer, with one view, and with 50 views from 10 visitors across 5 pages, and counted the queries on Vireo’s tables.

These are test numbers from one setup. A site with an object cache such as Redis, more referrers or more pages will see different counts, and you can repeat each step on your own staging site.

Questions

Can I turn off the Core Web Vitals script?
Yes. Add add_filter( 'vireo_collect_web_vitals', '__return_false' ); to your theme’s functions.php or a small plugin. vitals.js is then never requested and its beacon is never sent, which leaves one file and up to two beacons per page.
Does it work with caching and optimisation plugins?
Yes. Cached pages are counted, because the browser sends the view. Vireo keeps its scripts out of JavaScript delay in WP Rocket, Perfmatters, LiteSpeed Cache and FlyingPress, so the view is sent without waiting for someone to scroll or click.
What if my host blocks Vireo’s endpoint?
Some hosts refuse to run PHP files inside wp-content. Vireo tests its endpoint, falls back to WordPress’s standard admin-ajax route if the test fails, and tests again every hour. That route loads your plugins and theme on each beacon, so it costs your server more than the endpoint does.

Add analytics without the weight

Vireo Analytics is free on WordPress.org. Every number on this page is the free plugin.

Get Vireo free on WordPress.org

More on how Vireo works