=== Visitrix – Lightweight Visitor Analytics ===
Contributors: akklex
Donate link: https://genius-bot.ru/plugins/#donat
Tags: analytics, statistics, visitors, traffic, stats
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.4.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Lightweight self-hosted visitor statistics: traffic sources, search engines, devices, browsers, time on site and bounce rate. No external services.

== Description ==

Visitrix gives you a clean, informative traffic summary right in the WordPress admin – without third-party services or heavy scripts, and without cookies by default. Open **Statistics** in the admin menu and see where your visitors come from, what devices they use and how engaged they are.

Plugin homepage with screenshots and setup steps (in Russian): [genius-bot.ru/plugins/visitrix/](https://genius-bot.ru/plugins/visitrix/)

= What you get =

* **Key metrics** – visits, visitors, pageviews, bounce rate, page depth, time on site and share of new visitors, each compared with the previous period.
* **Traffic chart** – by hour for short periods, by day for longer ones. Toggle visits, visitors, pageviews and new visitors.
* **Traffic sources** – direct traffic, search engines, social networks, messengers, AI assistants (ChatGPT, Perplexity, Gemini and others), links from other sites, ads (UTM tags, yclid, gclid) and internal traffic.
* **Search engines** – Google, Yandex, Bing, DuckDuckGo, Mail.ru, Baidu and others.
* **New and returning visitors** – bounce rate, page depth and time on site for each group, plus loyalty (how many times visitors came back).
* **Online now** – visitors active during the last 5 minutes.
* **Devices** – PC, smartphone or tablet, plus browsers and operating systems.
* **Goals without setup** – form submissions (Contact Form 7, WPForms, Elementor and regular forms), clicks on phone numbers, e-mails and messengers, file downloads and outbound links, with conversion by traffic source.
* **Scroll map** – see how far visitors scroll each page, right on top of the page, separately for PC, smartphones and tablets.
* **WordPress content** – most read posts, categories, tags and authors, with read depth.
* **Content** – popular pages, landing pages and UTM campaigns.
* **Periods** – today, yesterday, 3 days, week, month or any custom date range.
* **Dashboard widget** with today's numbers.

= How metrics are calculated =

* A **visit** is a sequence of pageviews with no more than 30 minutes of inactivity. Arriving from a different external source starts a new visit.
* A **bounce** is a visit with a single pageview that lasted less than 15 seconds.
* **Time on site** is measured with lightweight engagement pings while the page is visible.
* A **new visitor** is a visitor whose first visit falls within the selected period; everyone else is returning. Each visitor belongs to exactly one group.
* With the **robot filter** (on by default) a visit is counted after the first real interaction: scroll, tap, click, key press or a second pageview.

= Lightweight =

* The tracker script is about 2 KB gzipped, loaded with `defer` and sent with `navigator.sendBeacon`, so it does not slow pages down.
* Beacons are handled right after plugins load – without the theme, `init` hooks or the REST API – so each hit costs a fraction of a page render.
* About 3 requests per pageview: the pageview, a ping at 15 seconds and one when the visitor leaves (plus one every 3 minutes on long reads).
* Works with page caching plugins – the front-end needs no nonces or PHP sessions.
* Compact database tables with automatic cleanup of old records.
* Optional separate database: keep the statistics out of the WordPress database (see below).
* The dashboard is plain JavaScript with built-in SVG charts – no external libraries, no CDN.

= Visitor identification =

Choose the mode that fits your privacy policy:

* **Without cookies** (default) – a random anonymous ID in localStorage.
* **Accurate** – the ID is also kept in a first-party HttpOnly cookie set by your own server. Returning visitors are recognized in Safari after 7+ days and across www/non-www.
* **Anonymous** – nothing is stored in the browser. Pageviews are grouped into visits with a hash of IP and user agent that changes daily; the IP itself is never stored.

Works with the **WP Consent API**: until a visitor allows statistics in your cookie banner, their visits are counted in the anonymous mode.

= Separate database (optional) =

By default the statistics are stored in the WordPress database. On hosting with a small database quota, or to keep the statistics away from the site content, Visitrix can write them to a separate MySQL or MariaDB database:

* a second database of your hosting;
* a cloud MySQL-compatible database: Yandex Managed Service for MySQL, VK Cloud, Selectel, Timeweb Cloud, Amazon RDS and Aurora, Google Cloud SQL, Azure Database for MySQL, DigitalOcean, PlanetScale, TiDB Cloud and others.

The connection is checked before it is saved, SSL/TLS with your provider's CA certificate is supported, and earlier statistics can be copied to the new database in one click, after which the WordPress tables can be emptied. If the external database becomes unreachable, visits are not recorded (they never fall back into the WordPress database) and a notice is shown on the Visitrix pages.

= Privacy =

* No cookies by default; nothing at all is stored in the anonymous mode.
* IP addresses are not stored.
* All data stays in your own database (the WordPress one or a database you choose) and is never sent to third parties.
* Optional respect for the browser Do Not Track signal.
* Suggested text is added to the WordPress Privacy Policy guide.

= Support the development =

Visitrix is free and has no ads or paid limits. If it saves you time, you can thank the developer with a small donation on [genius-bot.ru](https://genius-bot.ru/plugins/#donat) – it helps release updates, translations and new free plugins.

== Installation ==

1. Install the plugin from the **Plugins → Add New** screen, or upload the `visitrix` folder to `/wp-content/plugins/`.
2. Activate the plugin.
3. Open **Statistics** in the admin menu. Data appears after the first visits.
4. Optional: choose excluded roles and data retention in **Statistics → Settings**.

== Frequently Asked Questions ==

= Are my own visits counted? =

By default, visits from logged-in administrators are not tracked. You can choose excluded roles in the settings. To test tracking, open the site in a private window.

= Does it work with caching plugins? =

Yes. The tracker is a static script that sends data to the REST API, so cached pages are counted correctly.

= Do I need a cookie banner? =

Visitrix does not set cookies and does not store IP addresses, but it does store an anonymous identifier in localStorage. Requirements differ by country – please consult your legal adviser.

= Why are the numbers different from Google Analytics or Yandex Metrica? =

Every tool filters bots and counts sessions slightly differently. Visitrix counts only real browsers that execute JavaScript, and ad blockers usually do not block a first-party script, so numbers are often a bit higher.

= Why can a returning visitor be counted as new? =

The anonymous ID lives in the browser. A private window, cleared site data or another device make the visitor look new – other analytics tools have the same limitation. Safari also clears localStorage after 7 days without visits; switch to the **Accurate** mode in the settings to avoid that.

= How do I exclude my own visits? =

Logged-in administrators are not counted by default. To exclude a device where you are not logged in (for example, your phone), open **Statistics → Settings** on it and click **Do not count this browser**.

= Which goals are tracked? =

Without any setup: form submissions (Contact Form 7 counts only successfully sent forms), clicks on `tel:` and `mailto:` links, links to Telegram, WhatsApp, Viber, VK and MAX, downloads of documents, archives and media files, and clicks on links to other sites. Search forms are not counted as goals. The contents of forms are never recorded.

= Does goal and scroll tracking add requests? =

No. Goals and scroll depth are sent together with the regular engagement pings, so the number of requests per pageview stays the same.

= Who can see the statistics? =

Users with the `manage_options` capability (administrators). Developers can change it with the `visitrix_view_capability` filter.

= Will deleting the plugin delete my statistics? =

Only if you enable "Delete all statistics and settings when the plugin is deleted" in the settings. By default the data is kept.

= How do I store the statistics in a separate database? =

Create a MySQL or MariaDB database and a user with the right to create tables in it (at your hosting or a cloud provider). Then open Statistics → Settings → Data storage, choose "A separate MySQL / MariaDB database", enter the host, port, database name, user and password, click "Check connection" and save. For cloud databases enable SSL/TLS and paste the CA certificate your provider gives you. Finally click "Copy earlier statistics" and, after it finishes, "Delete them from the WordPress database" to free the space.

= Can I keep the database password out of the admin? =

Yes. Add the connection to wp-config.php, and the settings screen becomes read-only:

`define( 'VISITRIX_DB_HOST', 'db.example.com:3306' );`
`define( 'VISITRIX_DB_NAME', 'stats' );`
`define( 'VISITRIX_DB_USER', 'stats_user' );`
`define( 'VISITRIX_DB_PASSWORD', 'secret' );`
`define( 'VISITRIX_DB_PREFIX', 'wp_' ); // optional`
`define( 'VISITRIX_DB_SSL', true ); // optional`
`define( 'VISITRIX_DB_SSL_CA', '/path/to/ca.pem' ); // optional`

A password entered in the admin is stored encrypted with the keys of wp-config.php.

= Does a remote database slow the site down? =

Only the beacon requests talk to it, not the pages your visitors see. Choose a database in the same region as your hosting. If the database stops answering, Visitrix pauses new connection attempts for a minute so beacons stay fast.

= Is ClickHouse supported? =

Not yet: the current storage needs a MySQL-compatible database. ClickHouse support is planned.

= Where can I get support? =

Use the support forum on WordPress.org or write to the developer in Telegram: [t.me/Alex_mlr_dev](https://t.me/Alex_mlr_dev).

== Screenshots ==

1. Traffic summary: key metrics with comparison to the previous period and the traffic chart.
2. Traffic sources, device types, search engines and browsers.
3. New and returning visitors and the detailed sources report.

== Additional Information ==

= Developer =

Visitrix is developed and maintained by [genius-bot.ru](https://genius-bot.ru).

* Plugin page: [genius-bot.ru/plugins/visitrix/](https://genius-bot.ru/plugins/visitrix/)
* Website: [genius-bot.ru](https://genius-bot.ru)
* Telegram: [t.me/Alex_mlr_dev](https://t.me/Alex_mlr_dev) – questions, bug reports and feature requests.

= Requirements =

* WordPress 6.2 or later
* PHP 7.4 or later
* MySQL 5.7+ or MariaDB 10.3+
* WordPress REST API must be reachable (it is enabled by default)

= Languages =

Visitrix is fully translatable. Translations are delivered automatically from [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/visitrix/) – you can help translate it into your language.

= Data stored =

* `{prefix}visitrix_visits` – one row per visit: start time, duration, pageviews, source, landing page, UTM tags, device type, browser and OS.
* `{prefix}visitrix_hits` – one row per pageview: page path and title.
* `{prefix}visitrix_visitors` – one row per known visitor: anonymous ID, first and last visit, number of visits.
* `{prefix}visitrix_goals` – one row per reached goal: type, target (form name, phone number, file, domain) and page.

Records older than the retention period (365 days by default) are removed daily. With a separate database the same tables are created there with the prefix you choose; deleting the plugin never touches the external database.

= Developer hooks =

* `visitrix_should_track` (filter) – return `false` to skip tracking on the current page.
* `visitrix_source_rules` (filter) – add or change search engines, social networks, messengers and AI services.
* `visitrix_view_capability` (filter) – capability required to view reports.
* `visitrix_client_ip` (filter) – client IP used for the anonymous daily hash (for sites behind a proxy).

== Changelog ==

= 1.4.0 =
* New: optional separate database for the statistics – a second MySQL/MariaDB database of your hosting or a cloud one (Yandex Cloud, VK Cloud, Selectel, Timeweb Cloud, Amazon RDS, Google Cloud SQL, Azure, DigitalOcean, PlanetScale, TiDB Cloud and other MySQL-compatible services). By default nothing changes: the statistics stay in the WordPress database.
* New: connection check, SSL/TLS with a CA certificate, settings in wp-config.php constants, encrypted password.
* New: copy earlier statistics to the new database and empty the WordPress tables in one click.
* Reports are refreshed right after the storage or the data changes.

= 1.3.1 =
* New: a “Donate” button on the plugin pages and a Donate link on the Plugins screen.

= 1.3.0 =
* New: goals without setup – forms, phone calls, e-mails, messengers, downloads and outbound links, with conversion by source.
* New: scroll map on top of the page for PC, smartphones and tablets.
* New: read depth for pages and posts.
* New: content report – posts, categories, tags and authors.
* Goals and scroll depth are sent with existing pings: no extra requests.

= 1.2.1 =
* Performance: a lightweight collector replaces the REST API endpoint for tracker beacons.
* Performance: fewer engagement pings; the first interaction is sent together with the next ping.

= 1.2.0 =
* New: accurate new vs returning visitors – every visitor belongs to exactly one group, decided on the server.
* New: "Accurate" identification mode with a first-party cookie (works in Safari and across www/non-www).
* New: "Anonymous" mode without any browser storage.
* New: WP Consent API support.
* New: robot filter – visits are counted after the first real interaction.
* New: "Online now" and the loyalty report.
* New: "Do not count this browser" button in the settings.
* Fix: pages prerendered by the browser but never opened are no longer counted.
* Fix: when localStorage is blocked, the tracker falls back to sessionStorage instead of creating a new visitor on every page.

= 1.1.1 =
* Translations are now loaded from translate.wordpress.org.
* The admin menu item is placed after the core menu items.

= 1.1.0 =
* New: "New and returning visitors" report.
* New: "New visitors" line on the traffic chart.
* New: support link on the Plugins screen.

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.4.0 =
Optional separate MySQL/MariaDB database for the statistics, including cloud databases. Nothing changes until you enable it.

= 1.3.0 =
Goals without setup, scroll map and content reports.

= 1.2.1 =
Lower server load: lightweight beacon handler and fewer pings.

= 1.2.0 =
More accurate new and returning visitors, robot filter, consent support and "Online now".

= 1.1.1 =
Compatibility improvements for the WordPress.org directory.

= 1.1.0 =
Adds the new and returning visitors report.
