Skip to content

Website Analytics User Guide

Overview

alt text

Website Analytics is a lightweight, self-hosted website traffic analytics system. Its core advantages:

  • Self-hosted: All data is stored on your own server and never passes through third-party platforms — full control over data security.

  • High performance: Built on a Go-based collector with a DuckDB columnar storage engine, a single instance can sustain millions of page views (PV) per day.

  • Low footprint: No MySQL/PostgreSQL dependency. The embedded database works out of the box.

  • Accurate and reliable: Distinguishes new vs. returning visitors reliably; behaviour is identical with and without cookies (including incognito), and it is GDPR-compliant.

Comparison

CriterionWebsite AnalyticsWebsite statistics-v2Google GA
Collection methodFront-end JS (cookie-less)Server log parsingFront-end JS
Deployment modelSelf-hosted (private)Self-hosted (private)SaaS / cloud
DatabaseDuckDB embedded (columnar)SQLite embeddedCloud
Web Vitals metrics❌ No front-end performance
Session replay❌ (No native support; requires Clarity/Hotjar or similar)
Conversion funnel
Heatmap❌ (No native support; requires Clarity/Hotjar or similar)
Spider / crawler stats❌ Crawlers not collected✅ Strong at distinguishing real vs. fake spiders❌ Crawlers not collected
UTM / campaign tracking✅ Google Ads
Privacy compliance✅ Anonymous identity hashing, GDPR-friendlyLog-based IP retentionData uploaded to Google
Multi-site management
PricingIncluded in PRO or standalone pluginIncluded in PRO or standalone pluginFree tier; advanced features paid
Use casePrivate deployment, site operationsPrivate deployment, DevOpsSite operations

Feature Matrix

FeatureDescription
OverviewCore metrics such as PV, UV, IP, bounce rate, average visit duration and active-user trends
IP / RegionVisual geographic distribution of visitor IPs at country / province level
SessionsVisit-granular paged session list; multiple visits by the same visitor appear as separate rows, each with detail and behaviour trail
User TrackingRanking of page-view paths and analysis of page-transition event flows
Realtime VisitorReal-time list of online visitors with live navigation trails
Source AnalysisReferrer domains and channel breakdown: direct, search engines, social platforms, external links, paid campaigns and UTM-parameter channels
Visit AnalysisRanking of site entry pages and exit pages
Visitor AnalysisVisitor distribution across six dimensions: geography, browser, OS, device, screen size and language
Page PerformanceCore Web Vitals (LCP, INP, CLS, FCP, TTFB) with averages, scores, trends and dimension breakdowns
HeatmapVisual click-coordinate heat distribution per page, with per-page independent configuration and data queries
Funnel AnalysisCustom conversion step sequences with per-step visitor counts and drop-off rates to locate bottleneck steps and optimise the conversion path
Ad TrackingUTM five-parameter tracking (source, medium, campaign, content, term) plus Click-ID tracking for major ad platforms
Big ScreenFull-screen visualisation of core metrics and IP geo-distribution with a dedicated URL, per-user access control and screen-casting support

Quick Start

Requirements

ItemRequirement
ServerLinux on x86_64 / Arm architecture
Memory1 GB minimum; 2 GB or more recommended
Disk~200 MB base footprint; a site with ~10 K PV/day adds ~100 MB/month (replay disabled)
Web serverNginx (automatic / manual), Apache (manual only), or multiple web servers

Installing the Plugin

Log in to aaPanel, go to App Store, search for Website Analytics, and install the plugin with one click. After installation, open the plugin's settings page to start using it.

Enabling Site Statistics

In the plugin's Sites list, add the sites you want to track and enable statistics in either automatic or manual mode. If a site is behind a CDN, configure the corresponding provider settings so the real visitor IP can be resolved.

SettingDescription
CDN Client IPSupports Cloudflare, Alibaba Cloud and Tencent Cloud; adapts to the matching CDN environment for accurate IP statistics. Can be skipped if the panel-level CDN setting is already enabled
Store IPsDisabled by default (IPs are not persisted; used only for geo-resolution and identity recognition). Once enabled, only newly collected data for that site will store IPs
Session ReplayWhen enabled, the site records user sessions according to the configured sample rate. Note that replay consumes significant storage, so enable it based on your needs

alt text

Note: After enabling statistics, purge the CDN cache or add the following paths to the CDN cache whitelist so the tracking scripts are always delivered:

nginx
/bt-stats.js
/bt-stats.gif
/bt-replay.js
/bt-replay-config
/bt-stats-replay

Deploying the Tracking Script

Automatic deployment is preferred. Switch to manual deployment in the following cases: the web server is Apache, the site already sits behind a reverse proxy, or automatic injection fails.

Automatic deployment: the plugin rewrites the site's Nginx configuration and injects the tracking script itself. No site-code changes are needed — collection and reporting begin as soon as statistics are enabled.

Manual deployment

For Apache, reverse-proxy, or failed-automatic-deployment scenarios. After statistics are enabled manually, the plugin first writes the collector-endpoint forwarding config, then complete the three steps below:

① Get the script: the plugin generates a snippet containing the site's unique website_id. In normal use, simply copy the snippet provided by the plugin — no replacement is required.

② Choose a placement (pick one): both methods use the same snippet; configure either of them.

  • Method A — Nginx: add a sub_filter rule inside the site's server block to insert the snippet before </head>:
nginx
sub_filter '</head>' '<script defer src="/bt-stats.js?site={website_id}&version1"></script><script defer src="/bt-replay.js?site={website_id}"></script></head>';
  • Method B — Page code (recommended): paste the snippet before the </head> tag on every page of the site. For multi-page sites, put it in a shared template (e.g. header.htm) so a single edit applies site-wide:
html
<script defer src="/bt-stats.js?site={website_id}&version1"></script>
<script defer src="/bt-replay.js?site={website_id}"></script>

alt text

③ Verify: return to the plugin and click Verify. The plugin fetches the site homepage and checks whether the bt-stats.js snippet is live; you can also confirm it yourself via the deployment self-check below. Once verification passes, statistics for the site go live.

Notes & compatibility

Embedding in a standalone JS file: to load the tracker from your own JavaScript bundle, drop the outer <script> wrapper and inject the scripts dynamically instead. If the site uses a CDN, purge the CDN cache after the change.

Reverse proxy: automatic deployment aborts when a reverse proxy is detected on the site. Add the following directive inside the relevant proxy_pass block and retry, or use the manual method above:

nginx
proxy_set_header Accept-Encoding "";

Core endpoints (for troubleshooting)

EndpointPurpose
/bt-stats.jsServes the site tracking script
/bt-stats.gifReceives and reports visitor statistics

Deployment self-check (optional; applies to automatic and manual alike)

  1. Open any page of the target site.

  2. Open the browser developer tools and switch to the Network tab.

  3. Look for a bt-stats.gif request: a 200 status with a 1×1 transparent GIF response means the collector is working.

  4. Wait a few seconds, then return to the plugin's overview page and confirm that statistics are being generated.

Metrics Reference

Core Traffic Metrics

MetricFormulaDescription
PVTotal page-view eventsTotal number of page views
UVUnique visitors (deduplicated by anonymous identity)Approximated as "same IP + same browser + same month ≈ same visitor"; the identity rotates monthly, so visitors cannot be correlated across months
IPUnique IPs: counted via COUNT(DISTINCT ip) after the site enables “Store IPs”; shows 0 by defaultIPs are not collected by default. Enable “Store IPs” in Sites → site settings if you need true unique-IP data (applies only to newly collected data)
Bounce rateSingle-page visits / total visitsA visit is delimited by a 30-minute inactivity window; the share of visits that left after a single page
Avg. durationTotal dwell time / total visitsAverage dwell time per visit, capped at 30 minutes to filter out anomalous data

Percentile Benchmarks

MetricDefinitionFocusUse case
P50MedianMiddle of the dataBaseline for typical traffic and performance
P7575th percentileUpper bound of 75% of dataDiagnosing poor experience for the majority
P9595th percentileUpper bound of 95% of dataHunting long-tail anomalies and slow requests

Web Vitals Score Thresholds

MetricDefinitionGoodNeeds improvementPoorBad
LCP (Largest Contentful Paint)When the largest content element finishes loading≤ 1.5 s≤ 2.5 s≤ 4 s> 4 s
INP (Interaction to Next Paint)Interaction response latency≤ 100 ms≤ 200 ms≤ 500 ms> 500 ms
CLS (Cumulative Layout Shift)Layout shift during load≤ 0.05≤ 0.1≤ 0.25> 0.25
FCP (First Contentful Paint)Time to first content render≤ 1 s≤ 1.8 s≤ 3 s> 3 s
TTFB (Time to First Byte)Time until the first byte from the server≤ 400 ms≤ 800 ms≤ 1.8 s> 1.8 s

Feature Reference

Heatmap

The heatmap visualises where visitors click on a page, making it easy to spot high-traffic zones and the content users focus on. Use it to evaluate page layout, the exposure of buttons and ad placements, and to refine interaction design for better conversion.

alt text

How to use: on the Heatmap page, add the URL of the page to monitor and save it to generate a click-heat distribution. Data can be filtered by device type (desktop / tablet / mobile) to compare heat across viewports for multi-device optimisation.

Compatibility notes:

  • Heatmap preview relies on iframe-embedding the target page. If the site sends X-Frame-Options: SAMEORIGIN or a CSP frame-ancestors restriction, remove it or allow the panel domain/IP, or the preview will not load.
  • If one-click injection into the site config fails, add the CSP allowance manually to the site's Nginx/Apache config, substituting the real panel domain or IP for frame-ancestors.

alt text

Conversion Funnel

The funnel lets you define custom conversion steps and reports the visitor count and drop-off rate at each step, showing the full path from entry to goal completion so you can pinpoint where users leave and optimise those pages or flows.

Example: a three-step conversion — homepage (index.html) → download page (download.html) → installation success page (/successinstall.html). The funnel displays entrants, drop-offs and the step conversion rate per node, so the weakest step is obvious and can be prioritised.

alt text

Session Replay

Session replay reconstructs a visitor's real browsing session — mouse movement, clicks, scrolling and page navigation — as a video, giving a direct view of the user's path. Without extra instrumentation you can diagnose sluggish pages, unresponsive buttons and broken flows, understand why users drop off, and improve interaction design.

Enabling replay: after statistics are enabled for a site, turn on the replay switch in Sites → site settings, optionally adjusting the sample rate and path filters, to begin capturing replay data.

Replay settings:

SettingDescription
Replay switchEnable / disable replay capture for the site
Sample rateA decimal in (0,1] controlling the share of visitors recorded, e.g. 0.1 records 10%, 0.5 records 50%. Lower it according to traffic volume and storage before enabling
Path filterPage paths to exclude from recording (substring match; pages that match are not recorded), e.g. /login, /admin/. Filtering login and payment pages is recommended

Replay request flow:

RequestDescription
/bt-replay.jsServes the replay recorder script; after load it requests the config and decides whether to record
/bt-replay-configReturns replay config: sample=1 starts recording, sample=0 means not started or not sampled; recordingId is the recording-instance ID
/bt-stats-replayUploads replay data blocks. HTTP 204 is a valid upload; a 200 indicates the upload was blocked and the data is rejected as invalid

Example replay-config response:

json
{
    "sample": 0,
    "blockUrls": null,
    "recordingId": "80c8e723-888b-4c56-b5e2-34fed4460430",
    "maxDuration": 30,
    "maskLevel": "moderate",
    "sessionId": "1f9f8d4c-..."
}
FieldDescription
sample1 start recording / 0 not sampled
blockUrlsPage paths to exclude (substring match; matching pages do not start recording)
recordingIdRecording-instance ID for this page load
maxDurationPer-recording timeout in minutes; recording stops automatically when reached (default 30)
maskLevelMasking level: moderate / strict
sessionIdAnonymous session identifier (server-issued without cookies; shared with the stats channel)

Privacy protection: replay enables input masking by default (moderate) — input fields, passwords, emails, phone numbers and other form content are masked and never enter the recorded data. A site may be set to strict, in which case visible page text is also masked for stronger visitor privacy.

Compatibility notes:

  • Sites with statistics enabled automatically: enabling replay injects the required config automatically — no manual action needed.
  • Sites enabled manually: update the </head> config on every page to include the replay script so replay can work.

Live Dashboard

The live dashboard is an immersive full-screen view aggregating core traffic metrics and IP geo-distribution. It supports a dedicated URL and per-user access control, making it suitable for operations reviews or NOC displays on large screens.

alt text

How to use: under the plugin's Dashboard settings, enable the dashboard, configure the access port, safe path or domain, then add dashboard users and their site authorisations. Open the generated URL on a large-screen device for full-screen display.

alt text

Global Settings

Beyond per-site configuration, the plugin provides global collection controls and data maintenance, all managed from the plugin's settings page.

Global Exclusion Rules

Rules below are global; matching traffic is not collected. They are commonly used to keep admin, testing and crawler traffic from polluting your statistics:

SettingDescriptionFormat
Excluded IPsVisitors whose IP (or IP range) match are not reported (defaults include 127.0.0.1)192.168.1.1 or 192.168.1.1-192.168.1.10, one per line
Excluded domainsRequests whose Host matches are not reportedtest.example.com
Excluded URLsPage requests matching the path are not reported; wildcards supported/favicon.ico, /admin/*

Real Visitor IP (CDN / Proxy)

The collector reads the real visitor IP from the X-Real-IP header by default. Behind a CDN or reverse proxy, if unique-IP or geo statistics look wrong, enable a custom header in the global settings and enter the header that actually carries the real client IP (e.g. Cloudflare's CF-Connecting-IP, or the equivalent source-return header used by Alibaba Cloud / Tencent Cloud CDN). Sites already covered by the panel-level CDN setting need no per-site override.

Data Retention & Cleanup

OperationDescription
Retention periodStatistics are purged automatically by retention days (default 365, minimum 7); cleanup includes DuckDB log compaction / WAL recycling. Adjustable in settings
Manual cleanupPurge data older than N days, or clear everything at once, to free disk space quickly
Site dataAfter a site is deleted in the panel, its residual statistics and config can be removed from the plugin in one step

FAQ

1. Why are statistics lower than the actual traffic?

  • The tracking script does not cover every page, so some pages report no data.

  • Ad blockers or browser extensions block the tracking script.

  • The backend filters out invalid/illegitimate reports automatically.

  • A misconfigured CDN IP resolution distorts unique-IP and visitor statistics.

2. Browser compatibility

Fully compatible with mainstream modern browsers (Chrome, Firefox, Safari, Edge, etc.). Web Vitals metrics are only collected in browsers that support the PerformanceObserver API.

3. Data storage lifetime

The plugin stores data in DuckDB with columnar compression — a site at ~10 K PV/day adds only ~100 MB per month. Data is purged automatically according to the retention period (adjustable in plugin settings; cleanup includes log compaction / WAL recycling). Increase the retention period if you need long-term storage.

4. Multi-site support

Multiple sites are supported at once. Each site's data is fully independent; deploy the tracking script per site to collect per-site statistics.

5. User privacy handling

  • Cookie-less by design: no cookies are written or read, so behaviour is consistent when cookies are disabled or in incognito windows.

  • Visitors are identified by a server-side deterministic anonymous hash (no personally identifiable information is collected). The identity rotates monthly, so data cannot be correlated to an individual across months.

  • IPs are not persisted by default: they are used only for geo-resolution and identity hashing. If retention is required, the site owner enables the “Store IPs” toggle per site.

  • Privacy signals such as browser GPC, DNT and data-do-not-track are respected — collection stops for visitors that signal opt-out.

  • All statistics stay on your own server and are never uploaded to any third party.