=== Post Views Counter – Lumo View Pulse ===
Contributors: mehdijabin, mansourjabin
Tags: post-views, views-counter, analytics, statistics, woocommerce
Requires at least: 6.3
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.15.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Cache-safe post views counter for posts, pages and products. Badges, popular lists, reports and email digests.

== Description ==

A page cache serves ready-made HTML, so PHP never runs and a classic view counter records nothing. Full analytics suites solve that by loading a third-party script on every page, which is a lot of weight when all you wanted was one number next to a post or a product.

Lumo View Pulse takes the middle road. A tiny beacon fires after the page has loaded, a short-lived token proves the request belongs to that exact item, the request passes your bot, role, IP and session filters, and one row is written in your own database. Nothing leaves your server.

The number is then available everywhere you already work: a sortable Views column in wp-admin, a badge on the post or product itself, and `orderby` support so any loop can be sorted by what people actually open.

= Counting that survives a page cache =

* **Beacon mode (default).** Counts after load with `sendBeacon()`, so cached pages are counted too.
* **REST fetch mode.** Same REST endpoint, using `fetch()` instead of `sendBeacon()`.
* **Server mode.** Classic PHP counting for sites with no page cache. If a known cache plugin is active while Server mode is on, Setup warns you instead of silently under-counting.
* Optional engagement gates: wait *n* seconds, or require a scroll percentage, before a view counts.
* Optional write buffering when a persistent object cache is in use, flushed on a schedule, so busy sites batch their writes.

= Count one thing, show another =

Every public post type gets two independent switches: **Count** records the view, **Badge** prints it on the front end. Count products without showing anything, or show a number on posts you barely track. Quick presets for **Store**, **Blog** and **All public** get you live in one click.

Beyond single items, you can optionally count term archives, author archives, the homepage, other archives, date archives, search results, 404s and account screens.

= The badge on the item itself =

* Before the content, after it, or manual only (shortcodes, blocks and widgets).
* All time, today, last 7 days or last 30 days.
* Eye icon, text label, locale number formatting — each one a switch.
* **Refresh on cached pages** pulls the live total after load, so stale HTML never shows a stale number.
* A legacy `post-views` CSS class can be emitted for themes that were styled for an older counter.

= Popular lists in the builder you already use =

Views are a sort key, not just decoration. Any `WP_Query` (and the REST post collection) can order by `'orderby' => 'lumovipu_views'`:

* Gutenberg Query Loop
* Elementor Pro loops, via Query ID `lumovipu_views`
* JetEngine listings
* GenerateBlocks, Beaver Builder, and Kadence Blocks Pro query loops
* [Lumo Pro Toolkit](https://lumowp.com/product/lumo-pro-toolkit-complete-wordpress-site-building-suite/) listing and loop grids
* WooCommerce product lists, with HPOS and cart/checkout blocks compatibility declared
* AMP pages, counted with a 1x1 `amp-pixel`

= Shortcodes, blocks, widget =

Three shortcodes cover almost everything:

* `[lumovipu_views id="" period="" force="0"]` — the count for one item
* `[lumovipu_top count="5" types="post,product" period="30d"]` — a popular list
* `[lumovipu_site period="total"]` — the whole-site total

Five blocks ship with the plugin: **View Count**, **Top Content**, **Author Views**, **Term Views** and **Site Total**. There is also a **Lumo View Pulse Top** widget for classic sidebars and the block-based widget screen.

Accepted period tokens: `total`, `today`, `week`, `month`, `year`, `7d`, `30d`, plus an exact day (`20260919`) or year (`2026`).

= A dashboard that reads like a pulse =

Today, this week, this month and all time. Which items are on top and what share each one takes. A device split, and a referrer split (internal, direct, other). This is deliberately not a full analytics suite: it is the pulse of your content and your store.

Admin extras: a sortable Views column on list screens, an optional month-to-month trend on that column, a date-range export, a Views item in the toolbar on single pages, a WordPress dashboard widget, and an option that lets only administrators edit totals.

= Exports and digest emails =

On the **Reports** tab, export all time, 7 days, 30 days, a month or a year as CSV or XML. Schedule a summary daily, weekly or monthly through `wp_mail()`, with a minimum-views threshold, a top-N size, trend lines and spike signals. Send a test mail first to confirm it arrives before you turn the schedule on.

= Privacy by design =

* No external service, no account, no API key. Data stays in your own tables.
* Raw IP addresses are never stored.
* Default de-duplication is a session cookie, or cookieless browser storage, for a window you choose.
* Optional **Strict unique window** stores a one-way HMAC (site salt) instead of the IP.
* Storage is aggregated by day, week, month, year and total — there is no per-visitor log to leak or to bloat the database.
* Skip known bots and model-training crawlers, skip roles, skip IPs with wildcards or CIDR ranges, skip logged-in users or guests, and honour Do Not Track.
* CSV and XML exports contain neither IP addresses nor visit hashes.
* Daily rows are pruned on a retention schedule you set.

= Moving from another counter =

Your old numbers come with you. Tools can import from **Post Views Counter**, **WP-PostViews**, **Statify**, the Lumo CDN addon, or custom meta keys `post_views_count` / `views`.

Analyse first to see exactly what would change, then import with the strategy you want: **Add to existing**, **Replace**, **Skip existing**, **Keep higher** or **Fill empty only**.

If Post Views Counter is still active, Tools warns that two counters will double count. Compatibility helpers (`pvc_get_post_views()`, `pvc_post_views()`, `pvc_most_viewed_posts()`, `pvc_get_most_viewed_posts()`, `pvc_update_post_views()`, `pvc_view_post()` and the `[post-views]` shortcode) load only once the old plugin is gone — so a theme that calls them keeps working, and nothing collides while both are installed.

Health tools: flush the write buffer on demand, recalculate one item's total from its daily rows, clear a single item, or clear every stored total.

= About Boost, stated plainly =

The Boost tab lets an administrator add to an all-time total so an item sits higher in popular lists and sorted queries. It changes list position. It does not invent traffic, it is not a visitor log, and it should not be presented as visits that happened. The plugin says so in its own interface.

= For developers =

Template tags: `lumovipu_get_views()`, `lumovipu_render_views()`, `lumovipu_get_top()`, `lumovipu_render_top()`, `lumovipu_hit()`, `lumovipu_set_total()`.

REST routes: `POST|GET /wp-json/lumo-view-pulse/v1/hit` (token bound to the object, same-origin checked, rate limited) and `GET /wp-json/lumo-view-pulse/v1/views` (totals for publicly viewable objects only).

Hooks include `lumovipu/count/before`, `lumovipu/count/after`, `lumovipu/ajax/before_hit`, `lumovipu/ajax/response`, `lumovipu/hits/query_args`, `lumovipu/integrations`, `lumovipu/capability`, `lumovipu_default_settings` and `lumovipu_settings_saved`.

Tables: `{prefix}lumovipu_hits`, `{prefix}lumovipu_dims`, `{prefix}lumovipu_uniques`. Uninstall can remove everything, if you switch that on.

= Free, GPL, no upsell wall =

Every feature described above is in this plugin. No licence key, no signup, no "pro" tab that unlocks the useful half. Documentation lives at [LumoWP](https://lumowp.com/lumo-view-pulse/).

== Installation ==

1. In wp-admin go to **Plugins > Add New**, search for "Lumo View Pulse", then install and activate. To install manually, upload the `lumo-view-pulse` folder to `/wp-content/plugins/` and activate it from the Plugins screen.
2. Open **Lumo WP > View Pulse**.
3. On the **Setup** tab, pick a preset (Store, Blog or All public), or switch **Count** and **Badge** on per content type.
4. Leave the engine on **Beacon** if you run any page cache. Choose **Server** only if the site has no page cache.
5. Save. Open a post or product in a private window and watch the number move on the **Pulse** tab.

Optional next steps: exclude your own role or IP on Setup, turn on a weekly digest under **Reports**, and import your old counts from **Tools**.

== Frequently Asked Questions ==

= Does it really work with a page cache? =

Yes, and that is the reason it exists. In Beacon mode the count happens after the page has loaded, with a short-lived token tied to that specific post, term or archive, so a page served straight from cache is still counted. Server mode is the exception: it only sees uncached PHP requests, and Setup warns you if a known cache plugin is active while it is on.

= Does it store IP addresses? =

No. Raw IPs are never written to the plugin tables. Default de-duplication uses a session cookie or browser storage. The optional strict unique window stores a one-way HMAC built with your site salt, not the IP. Reports and exports contain no IP addresses and no visit hashes.

= Does it send anything to an external service? =

No. There is no third-party script, no remote API and no account. Views are written to tables in your own database and stay there.

= Is it GDPR friendly? =

It stores no raw IPs and keeps daily aggregates rather than a per-visitor log. You can exclude roles and IP ranges, honour Do Not Track, choose a cookie or cookieless browser storage for de-duplication, and set a retention window after which daily rows are pruned. As always, the final privacy assessment depends on how you configure your own site.

= Will it slow my site down? =

The front-end payload is small and the count happens after load, so it does not block rendering. Totals are aggregated rows rather than a growing visit log. On busy sites with a persistent object cache you can buffer writes and flush them on a schedule.

= What shortcodes does it register? =

`[lumovipu_views]`, `[lumovipu_top]` and `[lumovipu_site]`. There are also blocks for view count, top content, author views, term views and the site total, plus a most-viewed widget.

= How do I sort a query by views? =

Use `'orderby' => 'lumovipu_views'` in `WP_Query`. In Elementor Pro, set the loop Query ID to `lumovipu_views`. Gutenberg Query Loop, JetEngine, GenerateBlocks, Beaver Builder, Kadence Blocks Pro and [Lumo Pro Toolkit](https://lumowp.com/product/lumo-pro-toolkit-complete-wordpress-site-building-suite/) loops read the same data.

= Can I show views on WooCommerce products? =

Yes. Products are counted out of the box, the badge can appear on product cards, single product pages and archives, and product lists in wp-admin get a sortable Views column. HPOS compatibility is declared.

= I already use another views plugin. Can I keep my numbers? =

Yes. Tools imports from Post Views Counter, WP-PostViews, Statify, the Lumo CDN addon, or the `post_views_count` / `views` custom fields, and you can analyse the data before anything is written. Pick Add to existing, Replace, Skip existing, Keep higher or Fill empty only. Deactivate the old counter first so a view is not counted twice.

= Can I display the count in my theme? =

Yes: `echo lumovipu_get_views( get_the_ID() );` for the raw number, or `lumovipu_render_views( get_the_ID() );` for the styled badge. `lumovipu_get_top()` and `lumovipu_render_top()` return or print a popular list.

= What is the Boost feature for? =

It adds to an all-time total so an item ranks higher in popular lists and sorted queries — useful when you are seeding a new site or correcting an import. It moves list position, it does not create visitors, and it should not be presented as real traffic.

= What happens to my data if I uninstall? =

Nothing is deleted unless you ask for it. Turn on "Delete data on uninstall" in Settings before removing the plugin if you want the tables and options gone.

== Screenshots ==

1. Counting that survives a page cache — Beacon after load, REST, or Server mode.
2. Count and Badge are separate switches per content type, with Store, Blog and All public presets.
3. Pulse dashboard: today, week, month and all time, plus top items, devices and sources.
4. The view badge on the item itself, with placement, period, and refresh on cached pages.
5. Shortcodes, blocks, or manual placement for the same number.
6. Sort any loop by views in Gutenberg, Elementor Pro, JetEngine and other builders.
7. Unique views with bot, role, IP and DNT filters. No raw IP addresses stored.
8. Import from Post Views Counter or custom meta — analyse first, then merge or replace.
9. CSV/XML export and scheduled digest emails through wp_mail(), with a test send.
10. Boost raises list position. It does not invent traffic.

== Changelog ==

= 1.15.1 =
* Added - First public release on WordPress.org

= 1.15.0 =
* Changed - Settings header uses a compact view-and-pulse icon

= 1.14.0 =
* Changed - PHP functions, hooks, options, AJAX actions, shortcodes, and database tables now use a unique lumovipu prefix
* Changed - Builder query sorting uses orderby=lumovipu_views

= 1.13.0 =
* Changed - Remaining admin ticks now use the same switches as the rest of the settings screens

= 1.12.0 =
* Security - Hit tokens are bound to the specific post, term, or archive being counted
* Security - Public view totals are returned only for content visitors can already open
* Changed - Admin menu icon CSS and JS are enqueued instead of printed inline

= 1.11.0 =
* Added - Boost tab and list-screen Add views controls to raise all-time totals for popular-list placement

= 1.10.2 =
* Improved - Pulse top-content table sits flush in its section with quieter rank and view columns

= 1.10.0 =
* Changed - Settings screens now use electric-blue actions and slate section chrome
* Improved - Plugin title, status badge, and sidebar navigation follow the same header layout as other Lumo settings pages

= 1.9.0 =
* Improved - Every settings tab now opens with a title card, a short description, and section headers
* Improved - Setup, Reports, Tools, and Settings use labels on the left and switches on the right
* Improved - Pulse totals, Tools health, and Integrations use the same card layout

= 1.8.0 =
* Added - Quick Setup on the Setup tab for store, blog, or all public types
* Added - Content type cards with separate Count and Badge switches
* Changed - Counting, Display, Emails, and Integrations now live inside Setup, Reports, and Settings
* Fixed - Selected type and role chips no longer show a broken WordPress checkbox

= 1.0.0 =
* Added - Cache-safe view counting for posts, pages, and products
* Added - Pulse dashboard, reports, and digest emails
* Added - Import tools, storefront badges, shortcodes, and builder integrations

== Upgrade Notice ==

= 1.15.1 =
First public release on WordPress.org. Shortcodes, hooks, options and tables use the lumovipu prefix, and builder sorting uses orderby=lumovipu_views.
