{"id":307215,"date":"2026-05-07T17:57:24","date_gmt":"2026-05-07T17:57:24","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/harvv-analytics\/"},"modified":"2026-05-13T16:55:13","modified_gmt":"2026-05-13T16:55:13","slug":"harvv-analytics","status":"publish","type":"plugin","link":"https:\/\/cn.wordpress.org\/plugins\/harvv-analytics\/","author":20576231,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.0.8","stable_tag":"1.0.8","tested":"6.9.4","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"Harvv Analytics","header_author":"Harvv","header_description":"Zero-PII behavioral analytics pixel with WooCommerce order sync. No cookies, no consent banner required.","assets_banners_color":"","last_updated":"2026-05-13 16:55:13","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/harvv.com\/wordpress","header_author_uri":"https:\/\/harvv.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":110,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"ecommercepros505","date":"2026-05-07 17:46:07"},"1.0.1":{"tag":"1.0.1","author":"ecommercepros505","date":"2026-05-13 14:58:58"},"1.0.2":{"tag":"1.0.2","author":"ecommercepros505","date":"2026-05-13 15:51:42"},"1.0.3":{"tag":"1.0.3","author":"ecommercepros505","date":"2026-05-13 16:10:40"},"1.0.4":{"tag":"1.0.4","author":"ecommercepros505","date":"2026-05-13 16:19:39"},"1.0.5":{"tag":"1.0.5","author":"ecommercepros505","date":"2026-05-13 16:29:33"},"1.0.6":{"tag":"1.0.6","author":"ecommercepros505","date":"2026-05-13 16:41:06"},"1.0.7":{"tag":"1.0.7","author":"ecommercepros505","date":"2026-05-13 16:50:21"},"1.0.8":{"tag":"1.0.8","author":"ecommercepros505","date":"2026-05-13 16:55:13"}},"upgrade_notice":{"1.0.8":"<p>Pixel now subscribes to GTM\/GA4 dataLayer events for precise conversion capture, publishes Harvv signals back to dataLayer for downstream routing, and dedupes between DOM and dataLayer-sourced events in real time. Customers running GTM get the most accurate Harvv data with no setup.<\/p>","1.0.7":"<p>Adds GA4 coexistence: pixel now detects GA4 presence, honors Consent Mode v2 (downgrades to anonymous when analytics_storage is denied), and tags commerce events with GA4-equivalent names. No double-counting. No setup needed.<\/p>","1.0.6":"<p>Adds three new conversion-focused signals (cart-add clicks, coupon attempts, exit intent on cart\/checkout) and per-click scroll depth. Pixel-side update; no setup needed. Auto-update is on by default so sites running 1.0.3+ already have the new signals flowing.<\/p>","1.0.5":"<p>Adds an in-WP admin notice when the plugin detects an optimization tool that needs manual exclusion-list config (Perfmatters, W3 Total Cache, Hummingbird). Dismissible per-user.<\/p>","1.0.4":"<p>Important fix: the plugin&#039;s pixel `` tag now ships with the right exclusion attributes for every major optimization plugin (WP Rocket, LiteSpeed, Autoptimize, WP Fastest Cache, NitroPack, Cloudflare Rocket Loader). Before 1.0.4 the pixel could be lazy-loaded, which meant Core Web Vitals data was missing on every session.<\/p>","1.0.3":"<p>Architecture cleanup: plugin now loads the canonical Harvv pixel from harvv.com instead of a bundled copy. Always-current pixel, smaller exposure surface for your site key, no breaking changes to existing installs.<\/p>","1.0.2":"<p>Adds plugin-attribution: the dashboard can now tell you which plugin is causing a UX issue, not just where it happens. Site metadata only \u2014 no personal data. Opt out under Settings \u2192 Harvv Analytics \u2192 Preferences if you&#039;d rather not share.<\/p>","1.0.1":"<p>Single-site auto-register was silently broken before this release \u2014 please upgrade. Also restores Woo order sync (API base was hitting NXDOMAIN).<\/p>","1.0.0":"<p>First release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3525855,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3525855,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8"],"block_files":[],"assets_screenshots":[],"screenshots":[],"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[232,193119,986,396,286],"plugin_category":[36,45,54],"plugin_contributors":[262211],"plugin_business_model":[],"class_list":["post-307215","plugin","type-plugin","status-publish","hentry","plugin_tags-analytics","plugin_tags-behavioral-analytics","plugin_tags-conversion-tracking","plugin_tags-privacy","plugin_tags-woocommerce","plugin_category-analytics","plugin_category-ecommerce","plugin_category-security-and-spam-protection","plugin_contributors-ecommercepros505","plugin_committers-ecommercepros505"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/harvv-analytics\/assets\/icon-128x128.png?rev=3525855","icon_2x":"https:\/\/ps.w.org\/harvv-analytics\/assets\/icon-256x256.png?rev=3525855","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p><strong>Zero PII. No cookies. No consent banner required.<\/strong><\/p>\n\n<p>Harvv Analytics ships a lightweight (under 10 KB gzipped) behavioral tracker that captures how visitors interact with your pages \u2014 dead clicks, rage clicks, scroll depth, hover intent, JavaScript errors, engagement time \u2014 and syncs WooCommerce orders to your Harvv dashboard. It never reads cookies, never transmits names, emails, phone numbers, or addresses, and never stores personal data in your WordPress database.<\/p>\n\n<p>Because the plugin transmits no personal data, it does not require a cookie-consent banner under GDPR, CCPA, or PECR. Your visitors see no pop-ups; your checkout flows are not slowed; your compliance posture is simpler.<\/p>\n\n<p><strong>What this plugin does<\/strong><\/p>\n\n<ul>\n<li>Enqueues a vanilla-JS tracker (no jQuery, no external scripts) on your frontend.<\/li>\n<li>Captures behavioral signals: scroll depth, click targets, dead\/rage clicks, hover intent, page errors, engagement time.<\/li>\n<li>Syncs WooCommerce orders on <code>woocommerce_payment_complete<\/code> (never blocks checkout).<\/li>\n<li>Passes customer identity as a non-reversible hash derived from the site's own salts \u2014 the raw email never leaves WordPress.<\/li>\n<li>Works with WooCommerce HPOS (Custom Order Tables) out of the box.<\/li>\n<li>Multisite-aware: one network API key, per-subsite Site IDs, per-subsite admin overrides.<\/li>\n<\/ul>\n\n<p><strong>What this plugin does NOT do<\/strong><\/p>\n\n<ul>\n<li>Does not set or read cookies.<\/li>\n<li>Does not transmit email addresses, names, phone numbers, postal addresses, or IP addresses.<\/li>\n<li>Does not load any JavaScript from external URLs \u2014 the tracker ships bundled with the plugin.<\/li>\n<li>Does not create custom database tables on your WordPress site.<\/li>\n<li>Does not record session replays or keystrokes.<\/li>\n<\/ul>\n\n<p><strong>Why you might want this<\/strong><\/p>\n\n<p>If you run a WooCommerce store and want to see the dead clicks, rage clicks, and broken checkout paths your visitors hit \u2014 without making them click through a GDPR banner \u2014 Harvv is designed for you. The behavioral signals are sent to your Harvv dashboard where they become a prioritized list of UX fixes with plain-English explanations.<\/p>\n\n<h3>External Services<\/h3>\n\n<p>This plugin relies on the Harvv analytics service (operated by Olivas Venture Capital LLC d\/b\/a Harvv) to store and analyze behavioral events. Data is transmitted to the following endpoint:<\/p>\n\n<ul>\n<li><strong>Endpoint:<\/strong> <code>https:\/\/harvv.com\/v1\/track<\/code> (overridable via the <code>HARVV_API_BASE<\/code> constant in <code>wp-config.php<\/code> for staging or self-hosted receivers)<\/li>\n<li><strong>When:<\/strong> Events are sent continuously while a visitor is on your site (batched every 5 seconds or on tab close, via <code>navigator.sendBeacon<\/code> when available). WooCommerce order events are sent once, on <code>woocommerce_payment_complete<\/code>.<\/li>\n<li><strong>What is sent (behavioral events):<\/strong> Session ID (random, in-memory, regenerated per browser tab \u2014 never a stable cookie), visitor ID (sessionStorage-scoped, cleared when the tab closes), event type, page path (no query string with sensitive params), referrer, viewport dimensions, CSS selectors of clicked\/hovered elements (tag + id + first class name only, no text content), JavaScript error messages, engagement timestamps.<\/li>\n<li><strong>What is sent (WooCommerce events):<\/strong> Order ID, order status, order total, line-item product IDs and quantities, coupon codes, payment method name, shipping method name, non-reversible customer hash (derived via <code>wp_hash()<\/code> using your WordPress salts).<\/li>\n<li><strong>What is NOT sent:<\/strong> Names, email addresses, phone numbers, postal addresses, IP addresses, raw user IDs, cookies, session replays, keystroke data, form values.<\/li>\n<li><strong>Registration endpoint:<\/strong> <code>https:\/\/harvv.com\/v1\/sites\/register<\/code> \u2014 called once per site (or subsite on Multisite) to obtain a Site ID. Transmits only the site URL, site name, WordPress version, PHP version, and plugin version.<\/li>\n<li><strong>Pixel script (canonical, 1.0.3+):<\/strong> <code>https:\/\/harvv.com\/px\/&lt;your_site_key&gt;\/pixel.js<\/code> \u2014 enqueued on the frontend via <code>wp_enqueue_script<\/code>. This is the same canonical pixel served to every Harvv-installed site regardless of install channel (WP plugin, Laravel package, direct script-tag, Shopify integration). Loaded once per page, ~15.6 KB gzipped. The pixel itself transmits only the behavioral signals described above. Sites that need an offline-capable \/ self-hosted pixel can override the URL via <code>define( 'HARVV_PIXEL_URL', '...' );<\/code> in <code>wp-config.php<\/code>, or via the <code>harvv_pixel_url<\/code> filter.<\/li>\n<li><strong>Connect flow:<\/strong> <code>https:\/\/harvv.com\/connect\/wordpress<\/code> \u2014 opened in a new browser tab when an admin clicks \"Connect to Harvv\" in the plugin settings. Harvv's hosted signup page handles authentication; it then POSTs the API key back to your site's own REST endpoint (<code>\/wp-json\/harvv\/v1\/connect<\/code>) with a nonce you generated locally.<\/li>\n<li><strong>Stack-inventory endpoint:<\/strong> <code>https:\/\/harvv.com\/v1\/inventory<\/code> \u2014 called once at site registration and refreshed weekly by WP-Cron. Sends a <strong>site-context snapshot<\/strong>: installed plugin slugs + versions, the active theme slug + version, WordPress version, PHP version, MySQL\/MariaDB version, server software string (e.g. \"nginx\/1.24.0\"), site language code, timezone, permalink-structure boolean, WP_DEBUG boolean, memory limit, max execution time, object cache backend, WP-Cron disabled boolean, multisite blog count, total user count (number only \u2014 no usernames, no emails, no per-role breakdown), aggregate post and page counts, custom post type slugs + publish counts, and (when WooCommerce is active) WooCommerce version, store currency, base country, and product count. <strong>No visitor data, no usernames, no email addresses, no post content, no comments, no IP addresses, no PII of any kind.<\/strong> Powers plugin-attribution and platform-specific UX diagnosis on the Harvv dashboard. Admins can preview the exact payload at <strong>Settings \u2192 Harvv Analytics \u2192 Preview the exact diagnostic snapshot we would send<\/strong>. Disabled by clearing the <strong>Settings \u2192 Harvv Analytics \u2192 Preferences \u2192 Share stack info<\/strong> checkbox, by adding <code>define( 'HARVV_SHARE_INVENTORY', false );<\/code> to <code>wp-config.php<\/code>, or by returning <code>false<\/code> from the <code>harvv_share_inventory<\/code> filter.<\/li>\n<li><strong>Harvv terms of service:<\/strong> <a href=\"https:\/\/harvv.com\/terms\">https:\/\/harvv.com\/terms<\/a><\/li>\n<li><strong>Harvv privacy policy:<\/strong> <a href=\"https:\/\/harvv.com\/privacy\">https:\/\/harvv.com\/privacy<\/a><\/li>\n<\/ul>\n\n<p>By activating this plugin and supplying an API key, you consent to the transmission of the data described above to Harvv. You can disconnect at any time from the plugin's settings page; uninstalling removes all plugin options from your database.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin through the WordPress Plugins screen, or upload the plugin folder to <code>\/wp-content\/plugins\/harvv-analytics\/<\/code>.<\/li>\n<li>Navigate to <strong>Settings \u2192 Harvv Analytics<\/strong>.<\/li>\n<li>Click <strong>Connect to Harvv<\/strong> \u2014 this opens harvv.com in a new tab for signup. Once you complete signup, the tab will notify this plugin and your API key will be saved automatically.<\/li>\n<li>Alternatively, expand <strong>I already have an API key<\/strong> and paste your key manually.<\/li>\n<li>On WooCommerce sites, no further action is needed \u2014 order events start flowing on the next completed payment.<\/li>\n<\/ol>\n\n<p>For multisite networks: go to <strong>Network Admin \u2192 Settings \u2192 Harvv Analytics<\/strong> and set one network-wide API key. Each subsite will auto-register with Harvv on its next pageload and receive its own Site ID.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20require%20a%20cookie%20consent%20banner%3F\"><h3>Does this require a cookie consent banner?<\/h3><\/dt>\n<dd><p>No. The plugin sets no cookies and transmits no personal data. Under GDPR, CCPA, and PECR, cookie-consent banners are required only when a site sets non-essential cookies or transmits personal data to third parties. Harvv transmits only behavioral signals (dead clicks, scroll depth, etc.) and a non-reversible customer hash \u2014 these are not personal data under any major privacy regime.<\/p>\n\n<p>If your legal counsel interprets the regulations more conservatively than we do, you can still add Harvv to your privacy policy's third-party services section. The plugin provides suggested language at <strong>Settings \u2192 Privacy \u2192 Policy Guide<\/strong>.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20work%20without%20woocommerce%3F\"><h3>Does this plugin work without WooCommerce?<\/h3><\/dt>\n<dd><p>Yes. The WooCommerce integration loads conditionally \u2014 on a non-Woo WordPress site, the plugin runs as a pure behavioral pixel.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20slow%20down%20my%20checkout%3F\"><h3>Does this plugin slow down my checkout?<\/h3><\/dt>\n<dd><p>No. All outbound HTTP calls use <code>wp_remote_post()<\/code> with <code>'blocking' =&gt; false<\/code>, and the browser tracker uses <code>navigator.sendBeacon()<\/code> or <code>fetch<\/code> with <code>keepalive: true<\/code>. Nothing in the plugin waits on a response from Harvv.<\/p><\/dd>\n<dt id=\"is%20this%20plugin%20hpos%20%28custom%20order%20tables%29%20compatible%3F\"><h3>Is this plugin HPOS (Custom Order Tables) compatible?<\/h3><\/dt>\n<dd><p>Yes. The plugin declares compatibility with <code>custom_order_tables<\/code> and uses only the WC_Order CRUD API \u2014 never direct <code>$wpdb<\/code> access against order tables.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20my%20site%20loses%20internet%20connectivity%3F\"><h3>What happens if my site loses internet connectivity?<\/h3><\/dt>\n<dd><p>The browser tracker queues events locally and attempts to flush on each interval; unsent events are discarded silently when the browser tab closes. WooCommerce order events are fire-and-forget \u2014 if your site cannot reach <code>harvv.com<\/code> at the moment of <code>payment_complete<\/code>, the event is lost. We do not queue order events for retry on-site because doing so would require creating a custom database table, which this plugin intentionally does not do.<\/p>\n\n<p>As of 1.0.1 the plugin records the timestamp of the most recent successful Woo sync and surfaces it on the settings page so an admin can spot a silently broken integration before reconciling Stripe and Woo manually.<\/p><\/dd>\n<dt id=\"how%20do%20i%20uninstall%3F\"><h3>How do I uninstall?<\/h3><\/dt>\n<dd><p>Delete the plugin from the Plugins screen. All plugin options (<code>harvv_api_key<\/code>, <code>harvv_site_id<\/code>, and related) are removed via <code>uninstall.php<\/code>. The plugin never creates custom database tables on your site, so nothing is left behind.<\/p><\/dd>\n<dt id=\"i%20use%20caching%20plugins%20%E2%80%94%20does%20this%20conflict%3F\"><h3>I use caching plugins \u2014 does this conflict?<\/h3><\/dt>\n<dd><p>No. The tracker is enqueued in the footer and is cache-friendly (same output for every visitor). The Connect-flow REST endpoint is under <code>\/wp-json\/harvv\/v1\/*<\/code> and is gated by a one-shot nonce, so caching that endpoint is harmless.<\/p><\/dd>\n<dt id=\"is%20the%20site%20key%20in%20my%20page%20source%20a%20secret%3F\"><h3>Is the Site key in my page source a secret?<\/h3><\/dt>\n<dd><p>No \u2014 the Site key is a public, per-site identifier. Think of it like a Stripe <strong>publishable<\/strong> key: it ships embedded in your page source so the browser tracker can authenticate its POSTs to Harvv. It can be used only to send events for the site it was issued for; it cannot be used to read your account data or events from any other site. If you ever need to rotate it, do so from the Harvv dashboard.<\/p><\/dd>\n<dt id=\"how%20do%20i%20keep%20harvv%20exempt%20from%20my%20optimization%20plugin%3F\"><h3>How do I keep Harvv exempt from my optimization plugin?<\/h3><\/dt>\n<dd><p>As of 1.0.4 the plugin auto-injects the exclusion attribute for every major optimization tool, so most setups are immune out of the box. The exceptions are three tools that match by URL pattern rather than HTML attribute:<\/p>\n\n<ul>\n<li><strong>Perfmatters<\/strong> \u2014 Settings \u2192 Perfmatters \u2192 Assets \u2192 Script Manager \u2192 \"Delay JavaScript\" \u2192 Exclusions: add <code>harvv.com\/px\/<\/code>.<\/li>\n<li><strong>W3 Total Cache<\/strong> \u2014 Performance \u2192 Minify \u2192 JS \u2192 Never minify the following JS files: add <code>https:\/\/harvv.com\/px\/*<\/code>.<\/li>\n<li><strong>Hummingbird<\/strong> \u2014 Hummingbird \u2192 Asset Optimization \u2192 Files to exclude: add <code>harvv.com\/px\/<\/code>.<\/li>\n<\/ul>\n\n<p>If you're not running any of those three, you do not need to do anything \u2014 the plugin's auto-injected attributes handle WP Rocket, LiteSpeed Cache, Autoptimize, WP Fastest Cache, NitroPack, and Cloudflare Rocket Loader automatically.<\/p><\/dd>\n<dt id=\"how%20can%20i%20prevent%20the%20tracker%20from%20loading%20on%20specific%20pages%3F\"><h3>How can I prevent the tracker from loading on specific pages?<\/h3><\/dt>\n<dd><p>Add a filter on <code>harvv_should_load_tracker<\/code> in your theme's <code>functions.php<\/code> or a small site-specific plugin:<\/p>\n\n<pre><code>add_filter( 'harvv_should_load_tracker', function( $load ) {\n    if ( is_admin() || is_cart() || is_checkout() ) {\n        return false;\n    }\n    return $load;\n} );\n<\/code><\/pre>\n\n<p>The filter fires before <code>wp_enqueue_script<\/code> runs, so a <code>false<\/code> return prevents the script tag from ever appearing in HTML.<\/p><\/dd>\n<dt id=\"how%20do%20i%20point%20the%20plugin%20at%20a%20staging%20or%20self-hosted%20receiver%3F\"><h3>How do I point the plugin at a staging or self-hosted receiver?<\/h3><\/dt>\n<dd><p>Define <code>HARVV_API_BASE<\/code> in <code>wp-config.php<\/code> before WordPress loads plugins:<\/p>\n\n<pre><code>define( 'HARVV_API_BASE', 'https:\/\/staging.example.com' );\n<\/code><\/pre>\n\n<p>The plugin sends every outbound API call (registration, Woo order sync) to that base URL. The Connect flow always uses <code>https:\/\/harvv.com<\/code> because Harvv's hosted signup page is the only place that can mint a fresh API key.<\/p><\/dd>\n<dt id=\"how%20do%20i%20tell%20if%20woocommerce%20order%20sync%20is%20working%3F\"><h3>How do I tell if WooCommerce order sync is working?<\/h3><\/dt>\n<dd><p>Settings \u2192 Harvv Analytics shows the time since the most recent successful sync underneath the \"Connected \u2713\" badge on WooCommerce sites. If a sync fails (DNS error, sslverify mismatch, etc.) the error message is shown in red and the timestamp is preserved from the last successful send. The plugin never blocks checkout \u2014 these signals are surfaced asynchronously so you can spot a failing integration before it becomes a reconciliation problem.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20send%20a%20list%20of%20my%20other%20plugins%3F%20why%3F\"><h3>Does the plugin send a list of my other plugins? Why?<\/h3><\/dt>\n<dd><p>Yes \u2014 by default, the plugin sends Harvv a snapshot of which other plugins, theme, WordPress version, and PHP version are installed on the site. <strong>This is site metadata, not visitor data.<\/strong> No personal information, no user content, no option values.<\/p>\n\n<p><strong>Why we do this:<\/strong> Harvv's value comes from telling you <em>exactly<\/em> what's wrong with your site's UX. The browser tracker can see \"users are bouncing on \/pricing because of a 600ms layout shift\" \u2014 but without knowing which plugins are running, the diagnosis stops at \"something is shifting layout.\" With the stack snapshot, we can attribute the shift to the specific plugin causing it (e.g. \"Yoast 22.8 injects a meta tag late\") and tell you exactly what to fix. Faster diagnosis = faster fix = better speed and UX for your visitors. That's what this plugin is for.<\/p>\n\n<p><strong>What's sent (1.0.2 \u2014 site context):<\/strong><\/p>\n\n<ul>\n<li>Installed plugins: slug only (e.g. <code>yoast-seo<\/code>, not the human display name), version, active boolean.<\/li>\n<li>Active theme: slug, display name, version, parent theme slug.<\/li>\n<li>Environment: WordPress version, PHP version, MySQL\/MariaDB version, server software string, site language code (<code>en_US<\/code>, <code>fr_FR<\/code>, \u2026), timezone (<code>America\/Chicago<\/code>), permalink-structure boolean (\"pretty\" vs \"plain\"), WP_DEBUG boolean, memory limit, max execution time, object cache backend (external \/ none), WP-Cron disabled boolean, multisite boolean + blog count.<\/li>\n<li>Aggregate counts (no individual content): total registered users (number only), published + draft post and page counts, every custom post type's slug + publish count.<\/li>\n<li>WooCommerce (only when active): version, store currency code, store base country, total published product count.<\/li>\n<\/ul>\n\n<p><strong>What is NOT sent<\/strong> (and we want to be explicit): no usernames, no email addresses, no IP addresses, no visitor data, no post titles or content, no comment data, no plugin option values, no user passwords, no per-user breakdowns (we only send the total count), no \"last login\" timestamps. Click <strong>Settings \u2192 Harvv Analytics \u2192 Preview the exact diagnostic snapshot we would send<\/strong> to see the literal JSON payload before your next sync fires.<\/p>\n\n<p><strong>Three independent opt-outs<\/strong>, any of which disables the feature fully \u2014 no opt-out beacon is sent, the feature simply does nothing:<\/p>\n\n<ol>\n<li><strong>UI toggle (recommended for most admins):<\/strong> uncheck <strong>Settings \u2192 Harvv Analytics \u2192 Preferences \u2192 Share stack info<\/strong>.<\/li>\n<li><strong>Site-config constant (recommended for staging-first \/ WP-CLI workflows):<\/strong> add <code>define( 'HARVV_SHARE_INVENTORY', false );<\/code> to <code>wp-config.php<\/code>. This wins over the UI toggle.<\/li>\n<li><strong>Programmatic filter (for advanced cases):<\/strong> <code>add_filter( 'harvv_share_inventory', '__return_false' );<\/code> in a small mu-plugin.<\/li>\n<\/ol>\n\n<p>The plugin will continue to work normally with the feature disabled; you just give up the plugin-attribution column in the Harvv dashboard.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20auto-update%3F\"><h3>Does this plugin auto-update?<\/h3><\/dt>\n<dd><p>Yes \u2014 Harvv Analytics defaults to auto-update from WordPress 5.5+ so new behavioral signals and bug fixes reach your site without you having to remember to click Update. Behavioral pixels are most valuable when they're current; an out-of-date pixel silently misses entire classes of issues, so the default leans toward \"stay current.\"<\/p>\n\n<p>If you'd prefer to manage updates manually (e.g. on a staging-first workflow), add this line to your <code>wp-config.php<\/code>:<\/p>\n\n<pre><code>define( 'HARVV_AUTO_UPDATE', false );\n<\/code><\/pre>\n\n<p>The plugin will then defer to WordPress's normal per-plugin auto-update toggle (which defaults to OFF until you click \"Enable auto-updates\" on the Plugins screen).<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.8<\/h4>\n\n<ul>\n<li><strong>New:<\/strong> dataLayer source. The pixel now subscribes to <code>window.dataLayer<\/code> and ingests GA4 recommended events (<code>add_to_cart<\/code>, <code>begin_checkout<\/code>, <code>view_cart<\/code>, <code>purchase<\/code>, <code>view_item<\/code>, <code>generate_lead<\/code>, <code>sign_up<\/code>, <code>search<\/code>) as Harvv <code>cm<\/code> events with <code>src:'dl'<\/code>. When a customer's GTM container fires a GA4 conversion event, Harvv captures the same logical event via the dataLayer instead of re-detecting from the DOM. More precise, less noise.<\/li>\n<li><strong>New:<\/strong> dataLayer sink. Harvv's detected commerce signals are also pushed to <code>window.dataLayer<\/code> under <code>event: 'harvv_signal'<\/code> (namespaced \u2014 never reuses GA4 event names, so no double-counting in customer's GA4 reports). Customers can set up GTM triggers on <code>harvv_signal<\/code> to route Harvv signals to Meta Pixel, Klaviyo, or any other tool managed through GTM.<\/li>\n<li><strong>New:<\/strong> in-pixel dedupe. DOM-detected events are held for 100ms; if a matching dataLayer event arrives in that window (GTM fired on the same click), the DOM emission is suppressed and the dataLayer version wins. Result: one event per real conversion, regardless of how many signal paths the customer's site has.<\/li>\n<li><strong>New:<\/strong> broader optimization-tool attribution. The <code>pf.deferred<\/code> event's <code>via<\/code> field now also detects LiteSpeed Cache and Cloudflare Rocket Loader in addition to WP Rocket, Perfmatters, and NitroPack. Dashboard banner and email alert can name the specific tool deferring the pixel.<\/li>\n<li><strong>Internal:<\/strong> GA4 event-name mapping centralized in <code>GA4_NAMES<\/code> (Harvv\u2192GA4) and <code>GA4_TO_KIND<\/code> (GA4\u2192Harvv). Adding a new mapping is a one-line change in either object.<\/li>\n<\/ul>\n\n<h4>1.0.7<\/h4>\n\n<ul>\n<li><strong>New:<\/strong> GA4 coexistence layer. The canonical pixel now detects whether Google Analytics 4 is installed on the page (via <code>gtag<\/code>, <code>google_tag_manager<\/code>, or <code>dataLayer<\/code>) and stamps every session with a <code>ga4<\/code> flag. Commerce events (<code>cm\/ca<\/code>, <code>cm\/co<\/code>) carry a <code>ga4<\/code> alias mapping to the GA4 recommended event names (<code>add_to_cart<\/code>, <code>begin_checkout<\/code>) so the Harvv dashboard can label both. Harvv and GA4 stay separate-namespaced \u2014 no dataLayer writes by default \u2014 which means <strong>zero double-counting<\/strong> in the customer's GA4 reports.<\/li>\n<li><strong>New:<\/strong> GA4 Consent Mode v2 awareness. When <code>analytics_storage<\/code> is denied in the site's consent config, the pixel downgrades to anonymous mode automatically (in-memory visitor ID, no cookie or localStorage writes) \u2014 mirroring GA4's own \"cookieless ping\" behavior so the privacy posture stays consistent across both tools.<\/li>\n<li><strong>Docs:<\/strong> new runbook at <code>docs\/runbooks\/ga4-coexistence.md<\/code> documents the cross-system contract, expected number-deltas vs GA4, and the canonical answer for \"why don't my Harvv numbers match GA4?\" support questions.<\/li>\n<\/ul>\n\n<h4>1.0.6<\/h4>\n\n<ul>\n<li><strong>New conversion signals (canonical pixel):<\/strong> the pixel now fires on three high-value commerce moments, automatically detected from any page (no configuration needed):\n\n<ul>\n<li><strong>Cart-add clicks<\/strong> (<code>cm<\/code>, kind <code>ca<\/code>) \u2014 every time a visitor clicks an \"Add to cart\" \/ <code>add_to_cart_button<\/code> \/ <code>single_add_to_cart_button<\/code> \/ <code>[data-add-to-cart]<\/code> element. Element id + scroll depth at click attached.<\/li>\n<li><strong>Coupon attempts<\/strong> (<code>cm<\/code>, kind <code>co<\/code>) \u2014 when a visitor focuses any input named coupon \/ discount \/ promo. Strong leading indicator for conversion intent.<\/li>\n<li><strong>Exit intent on commerce URLs<\/strong> (<code>cm<\/code>, kind <code>ei<\/code>) \u2014 mouse leaves the viewport from the top edge on <code>\/cart<\/code>, <code>\/checkout<\/code>, <code>\/basket<\/code>, or <code>\/payment<\/code>. One emit per pageload. Predicts cart abandonment.<\/li>\n<\/ul><\/li>\n<li><strong>Scroll-depth at click<\/strong> \u2014 every interaction (<code>ix<\/code>) event now carries <code>sp<\/code> = scroll % of the page when the click happened. Lets the dashboard answer \"are customers clicking my CTA from above the fold or after scrolling past it?\".<\/li>\n<li><strong>Lazy-load attribution (Layer 5):<\/strong> when the pixel detects it was deferred, the <code>pf.deferred<\/code> event now includes the detected optimization tool (<code>wp_rocket<\/code>, <code>perfmatters<\/code>, <code>nitropack<\/code>). The dashboard banner and the email alert can now name the specific plugin causing the delay.<\/li>\n<li><strong>Plugin-side:<\/strong> no PHP code change in this version; new signals are in the canonical pixel that the plugin enqueues. Sites running plugin 1.0.3+ already get the new signals automatically \u2014 the 1.0.6 bump captures the changelog so admins know what's new on their dashboard.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li><strong>New:<\/strong> when the plugin detects Perfmatters, W3 Total Cache, or Hummingbird active on the site (the three optimization plugins that have no HTML-attribute opt-out), an admin notice now appears with the exact URL pattern to paste into that plugin's exclusion list. Dismissible per-user. We deliberately do NOT show the notice for WP Rocket, LiteSpeed, Autoptimize, WP Fastest Cache, NitroPack, or Cloudflare Rocket Loader because the 1.0.4 attribute carpet already handles those.<\/li>\n<li><strong>New:<\/strong> dismiss endpoint <code>\/wp-json\/harvv\/v1\/dismiss-lazyload-notice<\/code> (admin-gated; per-user user_meta).<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li><strong>Performance:<\/strong> the plugin's pixel <code>&lt;script&gt;<\/code> tag now ships with the full carpet of vendor-specific exclusion attributes so it is exempt from delay-JS \/ lazy-load passes in WP Rocket, LiteSpeed Cache, Autoptimize, WP Fastest Cache, NitroPack, and Cloudflare Rocket Loader. Before 1.0.4 these tools could catch our pixel and delay it until first user interaction, which meant we missed the initial-paint Core Web Vitals (LCP \/ INP \/ CLS) on every session. After 1.0.4 the pixel boots immediately regardless of which optimization tool is installed.<\/li>\n<li><strong>Documentation:<\/strong> three tools (Perfmatters, W3 Total Cache, Hummingbird) have no HTML-attribute opt-out \u2014 exclusion is URL-pattern only via their respective settings pages. The new FAQ entry \"How do I keep Harvv exempt from my optimization plugin?\" lists the exact URL pattern to paste into each.<\/li>\n<li><strong>Internal:<\/strong> new <code>Harvv_Enqueue::inject_exclusion_attrs()<\/code> method, hooked on <code>script_loader_tag<\/code>. Attribute set researched 2026-05-13 against each vendor's primary documentation. Conflict-free (each tool only inspects its own attribute).<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li><strong>Architecture:<\/strong> the plugin now loads the canonical Harvv pixel directly from <code>https:\/\/harvv.com\/px\/&lt;site_key&gt;\/pixel.js<\/code> instead of a bundled copy of <code>tracker.min.js<\/code>. New behavioral signals shipped to the canonical pixel propagate to your site within minutes \u2014 no plugin update required. Same source of truth our Laravel package and direct-install path already use.<\/li>\n<li><strong>Privacy + security:<\/strong> the per-site key is no longer rendered into page source via <code>wp_localize_script<\/code>. The canonical pixel identifies the site via its URL path and the server-injected preamble. Tighter exposure surface for the (public-but-still-best-not-broadcasted) key.<\/li>\n<li><strong>Compat:<\/strong> offline-capable installs can pin to a self-hosted mirror via <code>define( 'HARVV_PIXEL_URL', '...' );<\/code> in <code>wp-config.php<\/code>. The <code>harvv_pixel_url<\/code> filter is also available for runtime overrides.<\/li>\n<li><strong>Internal:<\/strong> new double-install guard (<code>window.__harvvLoaded__<\/code>) so a site running both the WP plugin AND the canonical script tag won't double-fire events. First one to boot wins; second one bails cleanly. The reconciliation event is also recorded server-side via <code>sites.install_sources<\/code> so the dashboard can show \"both paths installed since X\".<\/li>\n<li><strong>Compat:<\/strong> the bundled <code>tracker.min.js<\/code> stays in the plugin directory for backward compat (CDN cache TTLs), but the enqueue no longer references it. Slated for removal in a future release.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li><strong>New:<\/strong> site-context snapshot \u2014 sends a list of installed plugin slugs + versions, active theme, WordPress\/PHP\/MySQL versions, server software, locale, timezone, memory limit, post and page counts, custom post type slugs + counts, total user count, object cache backend, WooCommerce details when active, and other site-level configuration to Harvv. The dashboard uses this to attribute UX issues to the plugin or platform configuration causing them. Site metadata only \u2014 no personal data, no user content, no usernames, no emails, no per-user data.<\/li>\n<li><strong>New:<\/strong> \"Preview the exact diagnostic snapshot we would send\" reveal on the settings page. Renders the literal JSON payload before it's sent, so admins can audit before opting in. (Reviewer-friendly transparency pattern.)<\/li>\n<li><strong>New:<\/strong> weekly WP-Cron event refreshes the snapshot so the dashboard stays current as the site changes.<\/li>\n<li><strong>New:<\/strong> opt-out UI on the settings page under <strong>Preferences \u2192 Share stack info<\/strong>. Defaults to on; uncheck to disable. Code-level opt-outs also available: <code>define( 'HARVV_SHARE_INVENTORY', false );<\/code> in <code>wp-config.php<\/code> or <code>add_filter( 'harvv_share_inventory', '__return_false' );<\/code>.<\/li>\n<li><strong>Privacy:<\/strong> suggested-policy text in Settings \u2192 Privacy now mentions the snapshot and how to disable it. Readme <code>External Services<\/code> section enumerates every field that ships.<\/li>\n<li><strong>Internal:<\/strong> new option keys <code>harvv_share_inventory<\/code>, <code>harvv_last_inventory_sync_ts<\/code>, <code>harvv_last_inventory_error<\/code> (cleaned up on uninstall). New WP-Cron hook <code>harvv_inventory_refresh<\/code> (cleared on uninstall). New REST endpoint <code>\/wp-json\/harvv\/v1\/diagnostic-preview<\/code> (admin-gated; returns the next payload that would be sent).<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li><strong>New:<\/strong> plugin now defaults to auto-update so new behavioral signals + bug fixes ship without manual intervention. Opt out by defining <code>HARVV_AUTO_UPDATE<\/code> as <code>false<\/code> in <code>wp-config.php<\/code>.<\/li>\n<li><strong>Fix:<\/strong> auto-register now runs on single-site installs (was multisite-only \u2014 single-site admins who only pasted a Site Key would never get a Site ID assigned, and the tracker would silently never load).<\/li>\n<li><strong>Fix:<\/strong> API base URL switched from <code>api.harvv.com<\/code> (DNS NXDOMAIN) to <code>harvv.com<\/code>. The Connect flow, registration endpoint, and Woo <code>\/v1\/track<\/code> ingest now resolve to the production receiver. Existing installs with <code>HARVV_API_BASE<\/code> overridden in <code>wp-config.php<\/code> keep their override.<\/li>\n<li><strong>UX:<\/strong> \"API key\" renamed to \"Site key\" throughout the UI to reflect public-key semantics (like a Stripe publishable key). Help text explains why it's safe to expose in page source.<\/li>\n<li><strong>Observability:<\/strong> Settings page now shows the time since the most recent successful WooCommerce sync, and the most-recent sync error (if any), on Woo-enabled sites. Helps spot a silently broken integration without cracking open the WP debug log.<\/li>\n<li><strong>Observability:<\/strong> Settings page now surfaces a red error message under the Site ID field when auto-register fails, with a hint that re-saving retries immediately.<\/li>\n<li><strong>Docs:<\/strong> Readme now documents the <code>harvv_should_load_tracker<\/code> filter and the <code>HARVV_API_BASE<\/code> override constant, both of which existed in code but weren't surfaced anywhere user-facing.<\/li>\n<li><strong>Internal:<\/strong> <code>Harvv_Multisite::maybe_auto_register_subsite()<\/code> removed \u2014 the logic moved to <code>Harvv_Core::maybe_auto_register()<\/code>. Network-admin UI and per-subsite override behavior unchanged.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<li>Behavioral tracker (dead clicks, rage clicks, scroll depth, hover intent, JS errors, engagement).<\/li>\n<li>WooCommerce <code>payment_complete<\/code> order sync.<\/li>\n<li>HPOS (Custom Order Tables) compatibility declared.<\/li>\n<li>Connect-to-Harvv flow with one-shot nonce + HMAC-signed callback.<\/li>\n<li>Manual API-key entry as alternative path.<\/li>\n<li>Multisite support with per-subsite override.<\/li>\n<li>WordPress Privacy API integration (suggested policy text + empty exporter).<\/li>\n<\/ul>","raw_excerpt":"Zero-PII behavioral analytics pixel with WooCommerce order sync. No cookies, no consent banner required.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/307215","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=307215"}],"author":[{"embeddable":true,"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/ecommercepros505"}],"wp:attachment":[{"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=307215"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=307215"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=307215"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=307215"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=307215"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/cn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=307215"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}