Skip to content

webdesign29/inklura-analytics

Repository files navigation

Inklura Analytics

CI License: GPL-2.0-or-later PHP 7.4+ WordPress 5.8+

Privacy-friendly, cookieless, no-PII page-view analytics for WordPress — self-hosted, multisite-safe, no third-party service.

inklura-analytics records aggregate page views in a small per-blog table and shows them on a clean operator dashboard. There are no cookies, no IP storage, and no personal data — just a normalized request path, a day, and a count. It honors Do Not Track, skips configured user roles, and degrades gracefully (a <noscript> pixel fallback). Everything stays on your own server.

Features

Area What it does
Tracking A tiny inline beacon (navigator.sendBeacon, fetch keepalive fallback) POSTs the current path + referrer host to a REST route. A <noscript> 1×1 pixel falls back to admin-ajax. Cookieless, no IP, no PII.
Privacy Honors the DNT / Sec-GPC header, skips logged-in users in an excluded role (default: administrators), never stores IPs or user identifiers. The endpoint re-applies the gate server-side.
Referrers Stores the referrer HOST only (never the full URL or query — no PII), self-referrals dropped, with a Top referrers table.
Devices A coarse desktop / mobile / tablet class from the User-Agent without fingerprinting (well-known platform tokens only), with a breakdown on the dashboard.
Bot filtering Known crawlers / automation / HTTP libraries (and empty User-Agents) are skipped at the endpoint via a conservative UA heuristic.
Storage Per-blog custom tables created via dbDelta: aggregate hits (one row per day + path + device, INSERT … ON DUPLICATE KEY UPDATE), per-day referrer hosts, and a tiny rolling "live" pings table (timestamps only). Paths are normalized (query stripped, slashes collapsed, capped at 190 chars).
Dashboard A date-range selector (today / 7d / 30d / custom), a live last-30-minutes count, views-today + range-total KPI cards, a per-day bar chart, a device breakdown, and top-pages + top-referrers tables. CSV export of the selected range. Server-rendered and escaped.
Settings Enable/disable tracking, choose excluded roles, set retention days, toggle DNT respect, and excluded paths (prefix / glob patterns skipped at the endpoint).
Retention A daily wp-cron event prunes rows older than the retention window (hits + referrers; live pings always roll off). Manual "prune now" button too.
Multisite Per-blog stats (tables per blog), created on activation and when a new site is created (wp_initialize_site). Network-admin defaults page (incl. excluded paths). Uninstall drops every blog's tables.
Auto-update Self-hosted updates for normal-plugin installs — "update available" + one-click update from a manifest, like a wordpress.org plugin (must-use installs update out of band).

Privacy model

  • No cookies — the beacon stores nothing on the client.
  • No IP storage — the server never persists the visitor IP.
  • No PII — only aggregates are stored: day + path + device + count, per-day referrer hosts (never full URLs), and live timestamps (no path).
  • Referrer = host only — the path/query of the referrer is never stored; self-referrals are dropped.
  • Device = coarse bucket — desktop / mobile / tablet from the User-Agent, no fingerprinting (no version, OS build, screen, canvas or font probing).
  • Bot filtering — known crawlers and empty User-Agents are skipped at the endpoint.
  • Do Not Track — visitors sending DNT: 1 (or Sec-GPC: 1) are not counted (configurable).
  • Role exclusion — logged-in users with an excluded role are skipped (default: administrators).

Install

As a normal plugin

Put the repository in wp-content/plugins/inklura-analytics/ and activate Inklura Analytics. The table is created on activation (on every blog when network-activated).

As a must-use plugin

Drop the package under wp-content/mu-plugins/inklura-analytics/ and load inklura-analytics.php from a small mu-loader. The table is created lazily on first run; the auto-updater is disabled for mu installs.

Configure

Open Analytics → Settings in wp-admin:

  • Tracking — enable / disable recording.
  • Do Not Track — honor the DNT header (on by default).
  • Excluded roles — roles whose views are not counted (administrators by default).
  • Retention (days) — how long aggregated rows are kept (pruned daily).
  • Excluded paths — one pattern per line; matched requests are skipped at the endpoint:
    • a trailing * is a prefix match — /cart* skips /cart and /cart/anything;
    • a bare path also matches its sub-paths — /private skips /private and /private/x;
    • * / ? elsewhere are glob-matched per path segment — /a/*/b skips /a/x/b (not /a/x/y/b).

The dashboard (Analytics → Overview) has a date-range selector (today / 7d / 30d / custom), a live last-30-minutes count, a per-day bar chart, a device breakdown, top pages, top referrers, and an Export CSV button for the selected range.

On multisite, Network Admin → Settings → Inklura Analytics sets defaults (incl. excluded paths) that each site can override.

wp-config kill switch

define( 'INKLURA_ANALYTICS_ENABLE', false ); // disable the whole plugin

Endpoints

POST  /wp-json/inklura-analytics/v1/hit   { p: "/path", r: "referrer.host" }   # beacon
GET   /wp-admin/admin-ajax.php?action=inklura_analytics_hit&p=/path            # noscript pixel

Both validate + normalize input, re-apply the privacy gate (DNT, excluded role, bot filter, excluded paths), derive the coarse device class + referrer host server-side, and write via $wpdb->prepare. The dashboard CSV export is a separate nonce-guarded admin-post action.

Hooks

Hook Type Purpose
inklura/inklura-analytics/should_track filter (bool) Final say on whether to track the current request.
inklura/inklura-analytics/record_path filter (string) Adjust/skip the path right before it is recorded ('' to skip).
inklura/inklura-analytics/update_manifest_url filter (string) Override the update manifest URL.
inklura/inklura-analytics/booted action Fires after all modules boot.

Testing

for t in tests/unit/*.php; do php "$t"; done   # WP-free unit tests

The unit tests are WP-free (the bootstrap stubs the handful of WP functions used, and an in-memory $wpdb fake exercises the record → aggregate path). They cover path normalization, referrer-host extraction, device classification, bot detection, date-range math, excluded-path matching, top-N aggregation, CSV building and the updater. Each file prints all passed.

CI lints on PHP 7.4 / 8.1 / 8.3, runs the unit tests, and builds the installable ZIP.

Build a release ZIP

bin/build-zip.sh /tmp/inklura-analytics.zip    # top-level folder: inklura-analytics/

Sponsors

Inklura Analytics is built and maintained with the support of:

  • webdesign29 — web agency (Brest, France).
  • Inklura — WordPress-compatible CMS & hosting.

Interested in sponsoring? Use the Sponsor button or open an issue.

License

GPL-2.0-or-later — see LICENSE.

About

Inklura Analytics — privacy-friendly, cookieless analytics for WordPress. Multisite + self-updating.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors