Visitor analytics
First-party, cookie-free statistics - anonymised at write.
Visitor analytics
lazysite records its own traffic (SM140), so visitor statistics work out
of the box - no web-server log access, no cookies, no JavaScript beacon.
The processor appends one compact JSON line per request to
lazysite/logs/access-YYYYMMDD.jsonl, and the Visitor Stats plugin
(enabled on Plugin Manager) aggregates it for the manager Stats page.
The first-party access log
Every request the processor serves is recorded: page views (cache hits included), clean-URL 404s and scanner probes. Each line carries the time, path, status, truncated user-agent, external referrer, bytes, channel (operator traffic is marked and excluded from visitor statistics) and the request Host for per-domain splitting.
The log is anonymised at write: the visitor field is a daily-salted
keyed hash of the address - the same visitor yields the same key within
a day, so unique visitors are "distinct daily visitors" - and the IP
itself is never stored. Attacker-controlled fields are stripped of
control characters and length-capped against log injection. Daily files
are pruned after retention_days (default 90); writes are single
O_APPEND appends that never block or break serving.
Traffic classes
Because there are no cookies and no JS, every classification is a log-only heuristic over user-agent, path and status - an honest estimate, not authenticated identity. Requests are classed as:
- human - the headline audience; totals, top pages, trend and referrers count only this class
- ai - AI assistants and model fetchers (GPTBot, ClaudeBot, PerplexityBot, ...), plus non-browser clients on the automation endpoints
- bot - crawlers, monitors and headless/automation tooling
- noise - probe paths (
wp-login.php,.env, any.php), secret-fishing, infrastructure fetches (favicon, robots, sitemap, feeds) and 404ed build-manifest probes - logged_in - operator activity on the manager surface
Referrer spam is dropped from the external-referrers report, and
self-referrers count as on-site navigation. Your own automation is kept
out of human by convention: give it a user-agent containing
lazysite-agent/<partner-id>.
Configuration
Settings live in lazysite/stats.conf, edited on the plugin's config
page:
| Key | Default | Meaning |
|---|---|---|
first_party |
true |
Record first-party traffic; off = read the web-server log instead |
retention_days |
90 |
Days of first-party log files kept |
window_days |
30 |
Reporting window for the Stats page |
top_n |
15 |
Rows in the top-pages / top-referrers tables |
ai_user_agents |
- | Extra UA substrings to count as AI |
noise_paths |
- | Extra path prefixes to treat as noise |
The web-server access log survives as the fallback source when no first-party data exists (and its error log as a summarised diagnostics tier); log paths are auto-detected or set by the server owner at install time - never by a site manager.
The analyse_visitors action
analyse_visitors (control API and MCP, gated by the analytics
capability) returns a sanitised analytics export for AI reasoning:
totals, per-class shares, a per-day series, top pages, referrers,
status codes and a capped event stream - never a raw log line, a
filesystem path or a visitor IP. Ingestion is incremental and cached,
so each call parses only new log lines; pass window (days, up to 365)
to widen the view.
Notes
- Browsing analytics complement the audit trail, which records material actions (auth, edits, deletes) - not browsing
- On a site with no auth store, the visitor key is salted from a dedicated random salt, so keys stay non-reversible
- Successful static-asset serves handled directly by the web server are only visible to the fallback/diagnostics tier