=== Vireo Analytics – Cookieless Google Analytics Alternative with Search Console ===
Contributors: RebelCode, jeangalea
Tags: google-analytics-alternative, privacy-friendly, marketing-analytics, cookieless-analytics, headless-wordpress
Requires at least: 6.9
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 0.10.3
License: GPLv3 or later
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Self-hosted WordPress analytics that imports your Google Analytics history, shows the searches behind each post, and filters out bots. No cookies.

== Description ==

Vireo Analytics is self-hosted analytics for WordPress. It brings your history with you when you leave Google Analytics, shows the Google searches behind each post, and tells you what AI assistants take from your site against the readers they send back. Visitor data stays in your own database, with no cookies and no consent banner.

= Bring your history with you =

Switching analytics tools usually means your charts start again on the day you switch. Vireo imports your daily traffic, pages, referrers, countries and devices from Google Analytics 4, so the years you already have stay in front of you.

It also imports from Koko Analytics, Jetpack Stats, Statify, WP Statistics, Burst Statistics, Independent Analytics, SlimStat and Plausible (from Plausible's CSV export), bringing whatever each one kept: referrers per post, browsers and devices, missing pages, outbound clicks, downloads and custom events where the source recorded them. Imports run in batches you can watch, stop the day before Vireo's own data begins so no day is counted twice, and ask before importing a range you've already brought in. The [switching guides](https://vireowp.com/import/) show what comes across from each one.

= The searches behind each post =

Google stopped passing search terms to websites years ago, so most analytics plugins see a visit from Google and nothing more. Connect Search Console once and every post's stats screen lists the searches it appeared for, with clicks, impressions and average position. The Overview shows the landing page beside each search.

= What AI takes, and what it sends back =

ChatGPT, Claude, Gemini, Perplexity and Copilot are reported as their own traffic source. Next to the readers they send, Vireo counts the pages their crawlers fetched, so you can see the ratio for your own site. It works on the history you've already collected.

= Numbers you can check =

Over 800 known crawlers, AI trainers, SEO tools, uptime monitors and headless browsers are kept out of your numbers. Vireo reports how many it excluded and why, so a figure lower than your server logs makes sense. Automated browsers that claim to be Chrome are caught by the flags automation tools set on themselves, and prefetched pages nobody looked at aren't counted. The [bot directory](https://vireowp.com/bots/) lists every one Vireo knows.

= Headless WordPress: Astro, Next.js and others =

If your posts live in WordPress but visitors read them on an Astro, Next.js or other front end, Vireo can count that front end too. Enter its address in Settings, paste one script tag into the front end, and each pageview is matched to the WordPress post it shows, so per-post stats and Search Console searches keep working. It's free for one front end.

= Your other sites, in the same dashboard =

Run a static site, a docs site or a landing page next to your WordPress site? Add it under Settings and paste one tag into it. Its visits are counted on their own, without cookies, and a site selector on the Overview switches between your sites. One connected site is free.

= Everything else =

* An Overview that opens with what changed since the previous period, and the pages and sources behind it.
* A Popular posts block, shortcode and widget built on your real, bot-filtered view counts, plus a view counter for single posts.
* A Year in review for any year with data, including the history you imported from another tool, and weekly highlights on the Overview and in the weekly email.
* Top pages, referrers grouped by how people arrived, countries and devices, with filters for each.
* Core Web Vitals from your real visitors, graded at the 75th percentile the way Google grades them.
* Notes pinned to a date, so a spike still has its explanation weeks later.
* A weekly email digest, CSV export of any view, and a views column on the Posts screen.
* Custom events for clicks and form submissions, and 404 tracking to find broken links.
* Read-only dashboard access for editors or clients, without making them administrators.
* Multisite support, with one view across the network.
* Headless WordPress support: count visits to the Astro, Next.js or other front end that shows your WordPress content.
* Connected sites: count visits to your other sites, WordPress or not, from the same dashboard.
* A warning in Site Health if recording stops, so a broken setup doesn't look like a quiet week.
* Reports for WP RSS Aggregator and Spotlight sites: clicks through to aggregated articles per feed source, and what visitors do with Instagram feeds.
* Translated into German, Spanish, French, Italian, Japanese, Dutch, Portuguese (Portugal and Brazil) and Russian.

= Vireo Pro: see which pages and visitors make you money =

The free plugin is complete on its own. Vireo Pro is for sites that sell something or report to clients:

* Revenue from WooCommerce, Easy Digital Downloads, FluentCart and Freemius, traced to the page and source that brought each buyer.
* Goals and funnels, with each step's conversion on screen.
* Shareable read-only dashboards for clients, with an expiry date and a password.
* More connected sites, a live view, entry and exit pages, and a weekly email that explains what changed.

Pro starts at $60 for the first year on one site, with a 30-day money-back guarantee. [See Vireo Pro and pricing](https://vireowp.com/pricing/).

= Privacy =

Vireo sets no cookies and stores nothing on visitors' devices. Visitors are counted with a salted hash that changes every day, so nobody can be followed from one day to the next. Do Not Track and Global Privacy Control are honoured without a setting. Visitor data is never sent to RebelCode or anyone else; the only outside services are the ones you choose to connect, listed under External services below.

== Installation ==

1. Upload the plugin files to `/wp-content/plugins/vireo-analytics/`, or install via Plugins → Add New and search for "Vireo Analytics".
2. Activate the plugin through the Plugins menu.
3. Visit **Vireo Analytics → Overview** to see your dashboard. First pageviews will appear within a minute.

To bring your history across from Google Analytics or another plugin, go to **Vireo Analytics → Settings → Import data**. If another supported analytics plugin is installed, the Overview offers to import from it.

== Frequently Asked Questions ==

= Is there a paid version? =

Yes, Vireo Pro. Everything described above stays free. Pro adds revenue and conversion reports for stores, goals and funnels, client dashboards and more connected sites. If you stop paying, the free plugin keeps working with all your data. [Pricing is on vireowp.com](https://vireowp.com/pricing/).

= Is this GDPR-compliant? =

Yes. Vireo Analytics doesn't set cookies, doesn't use localStorage for tracking, and hashes visitor identifiers with a salt that rotates every 24 hours. No consent banner is required for basic analytics. Country-level geolocation is derived from the IP on the server; the raw IP is never written to the analytics tables, and the short-lived buffer file holding it is deleted as soon as the aggregator processes it, usually within a minute. You should still mention the plugin in your privacy policy.

= What exactly does the "Visitors" number mean? =

Within a single day it's a true unique count: one person is counted once no matter how many pages they read. Over a longer range it's the sum of the daily counts, so someone who visited on three days in the month counts three times.

That isn't laziness, it's the privacy model. A visitor is identified by a hash of their IP and browser, salted with a secret that is thrown away and regenerated every night. Tomorrow the same person produces a completely different hash, so there is nothing that can link them back to today. That's what makes cookie-free, consent-free tracking legitimate rather than a technicality. The cost is that "unique people this month" is a question the data genuinely cannot answer, and we'd rather say so than print a number that looks precise and isn't.

Pageviews are exact over any range.

= Does it honour Do Not Track and Global Privacy Control? =

Yes, and it's on by default. If a visitor's browser sends `DNT: 1` or `Sec-GPC: 1`, the tracker refuses to fire for them, and the collection endpoint refuses the pageview even if something sends one anyway. Those visits are not recorded anywhere. This costs you some traffic in the dashboard, which is the point: an opt-out you can switch off isn't an opt-out. If you have a specific reason to override it, the `vireo_honor_opt_out` filter can return false.

= Why are my numbers lower than another plugin's? =

Most analytics plugins count some automated traffic as visitors: uptime monitors (StatusCake, UptimeRobot, Pingdom), SEO crawlers (Ahrefs, Semrush, MJ12), AI crawlers (GPTBot, ClaudeBot, PerplexityBot) and testing tools. Vireo filters those out and shows you what it removed, by category, so you can check the difference yourself. If you'd rather count some of them, the `vireo_bot_ua_pattern` filter changes the pattern.

= Can I migrate from Jetpack Stats? =

Yes. Settings, then Import data, pulls your daily pageviews, top posts and referrers from the WordPress.com Stats API for whatever date range you choose. You paste in your WordPress.com API key and the site address the stats are recorded under; Jetpack doesn't need to be active or connected. Jetpack Stats has no visitor counts, so imported days show pageviews only.

= Can I migrate from Google Analytics? =

Yes. Settings, then Import data, brings your history across: daily pageviews and visitors, your pages, your referrers and which pages they sent readers to, countries, devices, outbound clicks, downloads, form submissions and your own custom events. It reads the Analytics Data API directly, so you need a Google service account key and your numeric property ID rather than the G- measurement ID. Sessions, conversions and the events GA4 collects on its own (page views, scrolls, session starts) do not come across.

= Can I migrate from Plausible Analytics? =

Yes. Export your site from Plausible (Site settings, then Imports & Exports), then upload the zip under Settings, then Import data. Daily pageviews and visitors, pages, referrers, countries, device types, goals and custom events come across, with outbound clicks, file downloads and 404s landing in the same reports as Vireo's own. No API key is needed, and the uploaded file is deleted as soon as it has been read. Browsers, operating systems, entry and exit pages and custom properties are not imported.

= Does Vireo share anything with MainWP? =

Only if the site is connected to a MainWP dashboard through MainWP Child. Then the dashboard can read the site's visitor and pageview totals, top pages and top referrers, over MainWP's own signed connection. Nothing about individual visitors is shared, and the dashboard already has administrator access to the site. To switch it off, add `add_filter( 'vireo_mainwp_enabled', '__return_false' );` to the site.

= Can I show my most popular posts? =

Yes. Add the Popular posts block anywhere blocks work, including block theme templates, or use the `[vireo_popular_posts]` shortcode or the Popular posts (Vireo) widget on classic themes. Choose how many posts, the period (last 7, 30 or 90 days, or all time), which post types, and whether to show featured images and view counts. It uses the same bot-filtered counts as your dashboard, lists only published posts that aren't password-protected, adds no tracking, and is cached so it stays fast. To show a single post's views, use the Post views block or `[vireo_views]`.

= Does it work with caching plugins? =

Yes. Tracking runs on every page load via a lightweight POST beacon, including cached pages. When you first activate the plugin, you may need to wait for your cache to regenerate before every page starts tracking. Once that happens, tracking is universal.

= My theme or landing page doesn't count visits. Why? =

The tracker loads in the footer through `wp_footer()`. Some themes, page builders and landing-page templates leave that call out, so the tracker never loads. Add `<?php do_action( 'vireo_print_tracking_script' ); ?>` just before `</body>` in that template. It's safe on pages that also call `wp_footer()`: the tracker only prints once.

= My site is headless. Can it count visits to my Astro or Next.js front end? =

Yes. Under Settings, then Tracking, enter the front end's address under "Headless front end". Pages on that site can then send pageviews to this WordPress site; anything from another address is refused. Paste the script tag shown under the setting into every page of the front end. It counts Astro view transitions on its own, and with `data-spa="history"` it counts page changes on other single-page front ends. Each pageview is matched to the WordPress post at the same path, so a front end that keeps the permalink structure needs nothing else, and Top pages, the per-post view counts and Search Console per post all work as they do for a theme. One front end per site.

Two things stay out of reach. Crawlers are counted when they fetch a page from WordPress, so the crawler and AI-bot numbers do not include requests made to the front end. And Core Web Vitals are not collected from the front end yet.

= How does it compare to Google Analytics? =

Google Analytics shows you more (segmentation, audiences, attribution modelling) but requires a cookie banner, sends your visitors' data to Google, and has become increasingly complex. Vireo Analytics answers "how many people visited what, from where, on what device", which is what most WordPress site owners actually look at. For site owners who don't need enterprise-grade attribution modelling, the tradeoff is usually worth it.

= Does it track logged-in admins? =

By default, no. There's a setting at **Vireo Analytics → Settings** to enable admin tracking if you want to see your own visits (useful for testing).

= How long is data kept? =

Raw visitor hashes and referrer rows are aggregated into daily rollups after 24 hours. Daily rollups are kept indefinitely unless you set a retention limit in **Settings → Retention**. The default retention is 730 days (two years).

= Will it slow down my site? =

The tracking beacon is fired asynchronously after the page is interactive, using the browser's `navigator.sendBeacon()` API where available. The pageview is recorded by a standalone endpoint that boots WordPress without loading plugins or your theme. Hosts that block direct PHP inside wp-content fall back to admin-ajax automatically. On a well-hosted site you will not notice a difference.

== External services ==

This plugin includes an optional importer for historical Jetpack Stats data. When (and only when) a site owner runs that importer from **Vireo Analytics → Settings → Import data**, the plugin calls the WordPress.com Stats API at `https://stats.wordpress.com/csv.php` to retrieve the site's existing pageview, referrer, and top-post history.

What is sent:

* The WordPress.com API key the site owner pastes into the import screen.
* The site address whose stats are being imported.
* A requested date range and table name (e.g. `views`, `referrers`, `topposts`).

What is not sent: no visitor data, no user data, no site content, no credentials beyond the API key the site owner entered.

When it is sent: only while the import is actively running, in response to a site owner clicking "Run Import". No background or recurring calls are made.

The Stats API is provided by Automattic Inc. (WordPress.com).

* Terms of Service: https://wordpress.com/tos/
* Privacy Policy: https://automattic.com/privacy/

The importer is entirely optional.

= Google Analytics (optional, importer) =

When a site owner runs the Google Analytics importer, the plugin signs a request with the service-account key they pasted and calls `https://oauth2.googleapis.com/token` for an access token, then `https://analyticsdata.googleapis.com` to read that property's history.

What is sent: the service account's own credentials and a date range. No visitor data, no site content, nothing about anyone reading the site.

When it is sent: only while an import is running, in response to a site owner starting one. The key can be removed from the same screen afterwards.

= Google Search Console (optional) =

When a site owner connects Search Console, the plugin authenticates the same way and calls `https://searchconsole.googleapis.com` to read the searches that led people to the site.

What is sent: the service account's own credentials, the property address the owner entered, and a date range.

When it is sent: once a day on a schedule, and whenever the owner presses the refresh control. A refresh fetches the last week straight away and then the rest of the requested history in the background, a fortnight at a time over a few minutes, so that one press can produce several calls in a row. This is the one recurring outbound call the plugin makes, and it only happens on sites that have connected Search Console. Disconnecting stops it and removes the schedule.

Both Google APIs are provided by Google LLC.

* Terms of Service: https://policies.google.com/terms
* Privacy Policy: https://policies.google.com/privacy

= DB-IP (optional, geolocation) =

Country-level geolocation needs a local database, and Pro's city-level detail needs a second one. When a site owner presses the download button, the plugin fetches the current monthly file from `https://download.db-ip.com`.

What is sent: nothing but the request for the file. No site data, no visitor data, no identifiers. Lookups afterwards happen entirely on your own server against the downloaded file; no address is ever sent anywhere.

When it is sent: only when the owner presses the button.

DB-IP Lite data is provided by DB-IP under CC BY 4.0.

* Website: https://db-ip.com/
* Privacy Policy: https://db-ip.com/legal/privacy

A site that imports nothing, connects nothing and downloads no geolocation database contacts none of these services.

It does make one recurring request to itself: once an hour the plugin posts to its own tracking endpoint to check the fast path is still reachable, because a host rule or a CDN change can break it silently. That request never leaves your server and carries no data about anyone.

None of these paths send visitor data anywhere. Every one of them pulls data in.

== Screenshots ==

1. The overview: what changed since the period before, this week's highlights, the headline numbers, what the bot filter kept out, and daily traffic.
2. One post's stats, with the Search Console searches that brought people to it.
3. AI assistants: how many pages their crawlers took, against how many readers they sent back.
4. Top pages, referrers grouped by how people arrived, and where in the world they were.
5. Importing history from Google Analytics 4, Plausible, Koko Analytics, Jetpack Stats and other plugins.
6. Settings, including which roles can read the dashboard without being administrators.
7. Year in review, including the history you imported from another tool.
8. A Popular posts block built on your own, bot-filtered view counts.

== Changelog ==

= 0.10.3 =
* Fixed: notices from Vireo Analytics Pro were hidden on Vireo's own screens along with other plugins' notices, so Pro's Freemius revenue set-up card never appeared on the Settings page.
* Changed: the cache that remembers which country an address belongs to, and the fallback used to tell visitors apart, now key on a hash that cannot be reproduced without the site's own secret, instead of a plain MD5 of the address. The old cache rows are cleared on update and rebuild as visits arrive.

= 0.10.2 =
* Fixed: add-ons that wait for new data, such as the Pro spike alert, are now told when Vireo finishes writing it. They never were, so spike alerts never ran.

= 0.10.1 =
* Fixed: on sites using WP Rocket's JavaScript minification, the tracker could stay on an old copy after updates, so WP RSS Aggregator and Spotlight clicks were never counted.
* Fixed: clicks on the padding of Spotlight's "View on Instagram" button weren't counted.

= 0.10.0 =
* Added: connected sites. Count visits to the other sites you run from this dashboard, whether or not they use WordPress: a static site, a docs site, a landing page. Each one keeps its own numbers, and a site selector on the Overview switches between them. Add a site under Settings, Tracking and paste its tag; visits are accepted only from that site's address. Free includes one connected site. Pages on a connected site are listed by address, and per-post reports, Search Console, the weekly email, the REST API and imports stay with this WordPress site.

= 0.9.1 =
* Added: headless WordPress. Enter the address of the Astro, Next.js or other front end that shows your posts under Settings, Tracking, and its pages send pageviews here and are matched to the posts they show. The front end adds one script tag, which also counts Astro view transitions and other client-side page changes. Pageviews sent from any other site are refused.
* Added: a Popular posts block, shortcode and classic widget that list your most viewed posts over the last 7, 30 or 90 days or all time, with optional featured images and view counts. Counts are Vireo's own bot-filtered numbers, and private, draft and password-protected posts are never listed.
* Added: a Post views block and [vireo_views] shortcode that show how many times a post has been viewed.
* Added: comment counts next to views in the posts list, Top pages and each post's stats, with comments per 1,000 views once a page has enough traffic.
* Added: Year in review. A screen for any calendar year with data: pageviews and visitors, the change on last year when there's a full record to compare, busiest month and day, pageviews by month, top pages, posts published that year, how people arrived, top countries, Google searches and AI crawlers. Months brought in from another tool are marked as imported and credited to it. Copy a plain-text summary or print it.
* Added: weekly highlights. The Overview and the weekly email list up to three things worth knowing about the last seven days, such as your best week so far, a post passing 1,000 views or a site sending visitors for the first time. A quiet week shows none.
* Added: imports bring across more of what each plugin kept, where it recorded it. Referrers per post, devices and missing pages from WP Statistics, Burst Statistics, Independent Analytics and SlimStat. Outbound clicks and downloads from WP Statistics, Independent Analytics, SlimStat and Plausible. Custom events from WP Statistics, Independent Analytics and Plausible. Missing pages and device types from Plausible. Filtered bots from WP Statistics and SlimStat. The Google Analytics import adds referrers per page, outbound clicks, downloads and your own events.
* Changed: the weekly email opens with "Your week on" your site's name.
* Changed: Jetpack Stats imports record pageviews only. Jetpack has no visitor counts, and copying views into visitors invented a number.
* Changed: the Koko Analytics importer no longer offers countries and devices, which it could never read.
* Fixed: importing from Independent Analytics filed every post under "/singular" and every missing page under "/404". Pages now land at their real addresses.
* Fixed: importing from SlimStat counted downloads, crawlers and feed readers as pageviews.
* Fixed: dates in chart titles, the dashboard widget and the email showed the day before on sites west of UTC.
* Security: a pageview could name a draft, private or scheduled post and put its title on the dashboard. Only posts a visitor could see are accepted now, and titles of non-public posts already recorded show as their address instead.
* Fixed: imported page paths, referrers and event names are cleaned the same way as the ones Vireo records itself.
* Fixed: missing-page tracking stored addresses with accented or other non-Latin characters cut short, so /café/ was recorded as /caf/.
* Fixed: a change too small to show as a whole percent appeared as a red 0% on the Overview and the dashboard widget.
* Fixed: the import history line shows every date in your site's date format.

= 0.9.0 =
* Added: import your history from Plausible Analytics. Upload the export zip from Plausible's site settings, and Vireo brings across your daily visitors and pageviews, pages, referrers, countries and device types.
* Added: groundwork for MainWP. A MainWP dashboard can now read a site's visitors, pageviews, top pages and referrers over MainWP's own signed connection, for an upcoming Vireo Analytics for MainWP add-on. Site owners can switch it off with the `vireo_mainwp_enabled` filter.
* Added: the weekly email opens with a one-line summary of what changed since the week before.
* Added: themes and landing pages that skip wp_footer() can load the tracker with do_action( 'vireo_print_tracking_script' ).
* Added: Support and Rate links on the Plugins screen, a support-forum link in Settings, and a one-time review request on the Overview after two weeks of use, which you can dismiss for good.
* Fixed: importing from another analytics plugin added its numbers on top of the days Vireo had already counted. Imports now stop the day before Vireo's own data begins, and the import screen says where. You can still include those days, with a warning that they'll be counted twice.
* Fixed: the Search and Social source filters showed no referrers, and any source filter left "What changed" without its sources because of a database error.
* Fixed: referrers now land in the same group on the dashboard card and in the source filters. Hacker News, Product Hunt, Slack, Discord and Mastodon instances count as Social, and AI assistants have their own group.
* Fixed: visits from the Google app on Android show as "Google app" under Search, and other common Android apps (Gmail, LinkedIn, Reddit, Slack, Telegram) show by name.
* Fixed: bots that name themselves (Amazon, Claude and DeepSeek search bots, xAI, Kimi, Mistral, Mojeek and more) are counted in their own category instead of "Other bots", about 40 bots that were counted as visitors are now filtered, and Internet Explorer 11 visitors on Windows 7 are no longer mistaken for search engines. Categories are assigned as stats are saved, so earlier history keeps its old ones.
* Fixed: counts of one read correctly across the plugin ("1 day", "1 view", "1 request").
* Changed: days with a note get a pin on the traffic chart, so a spike carries its explanation without hovering.
* Changed: the countries card shows the map with the top ten under it, and the map shades every country with visitors, not only the top ten.
* Changed: the front page is called "Home" in "What changed" and the weekly email, matching Top pages, and referrers shown by name (ChatGPT, Gemini) show their site address underneath.
* Fixed: the import screen and first-run banner no longer offer a plugin whose tables are empty.
* Fixed: the AI crawler ratio shows a whole number from 10 up, and several small layout issues in Top referrers, the bot note and the roles setting.
* Fixed: the group totals in Top referrers (Search, AI assistants, Social, Referral) count every site in the range, not only the ten listed, so they match the source filters and the Search & AI tab.
* Security: a Plausible upload is capped by its unpacked size, loading the import screen can no longer cancel a running import, each import run keeps its own progress so two tabs can't interfere, and long page paths or hosts in non-Latin scripts no longer make an import fail.

= 0.8.9 =
* Changed: Settings is split into tabs (General, Tracking, Email digest, Search Console & API, Import & export), and the dashboard into Overview, Search & AI, Page speed, and Issues & campaigns. The tab is kept in the URL, so reloads and shared links open on it.
* Changed: the import screen starts with the analytics plugins found on this site, each with its own button. Other sources sit below as secondary options.
* Fixed: after an import finished, the screen still offered "Start Import" next to a warning about running it twice, which read as if the first run had failed. It now says the import is done, with the date range and pageviews brought in, and running the same source again needs a confirmation. Jetpack gets the same overlap check as Google Analytics.
* Fixed: the import screen's record count was wrong (it showed 180 for 90 days).

= 0.8.8 =
* Fixed: on a busy day with thousands of distinct pages or referrers, the database could reject the single statement that saved them, and after five tries that stretch of traffic was set aside instead of counted. Rows are now saved in batches of 500, still inside one transaction.
* Fixed: a database error early in a save could go unnoticed if a later query in the same step succeeded, so the buffer was deleted with some of its rows missing. Every failed query now stops the save and keeps the buffer for another try.

= 0.8.7 =
* Fixed: sites on WP Engine recorded no visitors. WP Engine's network sends a `Cf-Verified-Bot: false` header with every request, and Vireo treated any value in that header as a verified bot. It now counts as a bot only when the value is `true`.

= 0.8.6 =
* Changed: Vireo Analytics is now developed and supported by RebelCode, the team behind WP RSS Aggregator and Spotlight.

= 0.8.5 =
* Added: a card for sites running WP RSS Aggregator. It counts the readers who click an aggregated item through to the original article, per feed source, and, for items imported as posts, the views each source's posts get on your site.
* Added: a card for sites running Spotlight. It counts how often visitors open an Instagram post from a feed, follow a link from the post, press Follow or Load more, and on which page.
* Both start counting when Vireo detects the plugin, and can be switched off with the `vireo_track_wpra` and `vireo_track_spotlight` filters.

= 0.8.4 =
* Fixed: a post ID that matches no post could list one page twice. The tracker sends the post ID from the visitor's browser, so a client can send any number; one that resolves to no post is now ignored and the view counts under the page's address.

= 0.8.3 =
* Fixed: one visitor could add unlimited pageviews in a day. A crawler that runs scripts viewed the same archive pages almost ninety times each and put several hundred pageviews into one day's report. Each visitor now counts for at most 5 views of a page and 50 views in total per day; anything past that is reported under filtered traffic as repeated views. Both limits can be changed with the `vireo_visitor_path_cap` and `vireo_visitor_daily_cap` filters.
* Fixed: the front page could appear twice in the page lists and in What changed, once by its title and once as "/", because some views were recorded with its post ID and some without. Pages are now grouped by address.
* Fixed: comparisons for a range that ends today weighed part of a day against a whole one, so every page looked like it was losing traffic in the morning. The previous period is now scaled to the share of today that has passed.

= 0.8.2 =
* Fixed: two long searches that began with the same 190 characters were stored as one, and the second overwrote the first's clicks and impressions. Searches are now told apart by their full text. Updating refetches the last 90 days of Search Console data once so the split applies to recent history.
* Changed: the Search Console button now reads "Fetch the last 90 days". It fetches the last week straight away and the rest in the background, which "now" no longer described.
* Changed: Japanese translations follow the Japanese WordPress style guide for spacing around English words, numbers, colons and brackets.

= 0.8.1 =
* Fixed: the "Connect Search Console" link on a post's stats screen opened Settings at the top of the page instead of at the Search Console section.

= 0.8.0 =
* Added: each post's screen now shows the searches it appeared for in Google, with the clicks and average position for each. Google has passed almost no organic search terms to websites since 2013, so no analytics plugin can read them from the visit itself. Search Console still has them, and this joins them to the post they reached.
* Added: the site-wide search list on the Overview names the page Google showed for each search.
* Fixed: Search Console history was being cut off. A pull stopped at 25,000 rows for the whole date range, and a 90-day pull on one modest site hit that exactly, so roughly nine rows in ten were dropped without any message. The top searches survived, because Google sorts by clicks, but the long tail and anything totalled from it did not. Pulls now read everything Google returns.
* Changed: refreshing Search Console fetches the last week immediately and the rest of the history in the background, a fortnight at a time. Reading the full history in one request took over a minute once nothing was being dropped, which is longer than an admin page is allowed to run on many hosts.
* Fixed: Search Console data was never removed by the data retention setting, so it was kept indefinitely whatever retention you chose.

Older versions are in [changelog.txt](https://plugins.trac.wordpress.org/browser/vireo-analytics/trunk/changelog.txt), which also ships with the plugin.

== Upgrade Notice ==

= 0.8.7 =
Fixes sites on WP Engine recording no visitors. Update if your site is hosted there.

= 0.2.2 =
Performance fix from the plugin review: the tracker's rate limiter no longer writes to the options table on sites without a persistent object cache.

= 0.2.1 =
Privacy and hardening fixes from the plugin review: no third-party requests, no generated PHP files, nonce-checked admin filters.

= 0.2.0 =
Initial public release.
