{"id":339990,"date":"2026-07-19T18:23:48","date_gmt":"2026-07-19T18:23:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/gpc-guard-for-woocommerce\/"},"modified":"2026-07-19T18:23:20","modified_gmt":"2026-07-19T18:23:20","slug":"harbor-privacy-guard-for-woocommerce","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/harbor-privacy-guard-for-woocommerce\/","author":23530116,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.5.1","stable_tag":"1.5.1","tested":"7.0.2","requires":"5.8","requires_php":"7.4","requires_plugins":null,"header_name":"Harbor Privacy Guard for WooCommerce","header_author":"Harbor Plugins","header_description":"Server-side GPC browser signal detection, Google Consent Mode v2 integration, and WooCommerce checkout tracking enforcement with audit logging.","assets_banners_color":"127dae","last_updated":"2026-07-19 18:23:20","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/harborplugins.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":42,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.5.1":{"tag":"1.5.1","author":"harborplugins","date":"2026-07-19 18:23:20"}},"upgrade_notice":{"1.5.0":"<p>Consent cookies and the audit table are renamed (wgc_ to gpcg_ prefix). If you added the old cookie names to a cache exclusion list, update them to gpcg_consent and gpcg_gpc_js.<\/p>","1.4.0":"<p>The plugin is now GPC Guard for WooCommerce. Licensing activates out of the box via the bundled Freemius SDK, uninstall cleanup is multisite-complete, and Cloudflare visitor headers are only trusted from verified Cloudflare edge IPs.<\/p>","1.3.0":"<p>Adds configurable audit-log retention with daily pruning (default 2 years) to bound table growth, inline-script stripping in Pro Full Coverage Mode, CDN-aware rate limiting, and a fix for a duplicated thank-you notice on block checkout.<\/p>","1.2.0":"<p>Opt-outs are now logged for non-purchasers (banner + GPC), IP hashing uses a dedicated salt that survives auth-key rotation, and consent-dependent pages are auto-excluded from full-page caches. TikTok, Bing, and multi-state jurisdiction blocking are now Pro features.<\/p>","1.1.0":"<p>Database schema update: run the upgrade to add visitor_state column and order_id index to the audit log table. The plugin handles this automatically on activation.<\/p>","1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3613817,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3613817,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3613817,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3613817,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.5.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3613817,"resolution":"1","location":"assets","locale":"","width":1280,"height":540},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3613817,"resolution":"2","location":"assets","locale":"","width":1280,"height":620},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3613817,"resolution":"3","location":"assets","locale":"","width":1440,"height":714},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3613817,"resolution":"4","location":"assets","locale":"","width":1440,"height":478},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3613817,"resolution":"5","location":"assets","locale":"","width":1440,"height":478}},"screenshots":{"1":"Consent banner (bottom position)","2":"WooCommerce thank-you page opt-out confirmation notice","3":"Plugin settings page - GPC detection and script blocking","4":"Plugin settings page - consent banner customization","5":"Monthly compliance summary on the settings page"}},"plugin_section":[],"plugin_tags":[166295,20011,272358,396,286],"plugin_category":[45,54],"plugin_contributors":[271094],"plugin_business_model":[],"class_list":["post-339990","plugin","type-plugin","status-publish","hentry","plugin_tags-ccpa","plugin_tags-consent","plugin_tags-gpc","plugin_tags-privacy","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_category-security-and-spam-protection","plugin_contributors-harborplugins","plugin_committers-harborplugins"],"banners":{"banner":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/banner-772x250.png?rev=3613817","banner_2x":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/banner-1544x500.png?rev=3613817","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/icon-128x128.png?rev=3613817","icon_2x":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/icon-256x256.png?rev=3613817","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/screenshot-1.png?rev=3613817","caption":"Consent banner (bottom position)"},{"src":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/screenshot-2.png?rev=3613817","caption":"WooCommerce thank-you page opt-out confirmation notice"},{"src":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/screenshot-3.png?rev=3613817","caption":"Plugin settings page - GPC detection and script blocking"},{"src":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/screenshot-4.png?rev=3613817","caption":"Plugin settings page - consent banner customization"},{"src":"https:\/\/ps.w.org\/harbor-privacy-guard-for-woocommerce\/assets\/screenshot-5.png?rev=3613817","caption":"Monthly compliance summary on the settings page"}],"raw_content":"<!--section=description-->\n<p>Harbor Privacy Guard for WooCommerce enforces visitor privacy choices on the server. Instead of setting a client-side consent flag for tracking scripts to read, it detects the visitor's consent state in PHP and dequeues known tracking script handles before WordPress renders the page, so scripts that were declined never load.<\/p>\n\n<p><strong>GPC Browser Signal Detection<\/strong><\/p>\n\n<p>GPC (Global Privacy Control) is a browser-level opt-out signal that is legally binding in 12 US states. When a user enables it \u2014 through their browser settings or a privacy extension \u2014 their browser sends <code>Sec-GPC: 1<\/code> on every HTTP request. This plugin detects that header server-side, requiring no user interaction with a banner. A small JavaScript snippet also reads <code>navigator.globalPrivacyControl<\/code> and sets a first-party cookie (<code>gpcg_gpc_js<\/code>) so GPC is honored even when the header is absent (some proxies strip it).<\/p>\n\n<p><strong>Google Consent Mode v2<\/strong><\/p>\n\n<p>The plugin emits <code>gtag('consent','default',{...})<\/code> before GTM loads, at <code>wp_head<\/code> priority 1 \u2014 the integration point Google's Consent Mode v2 documentation requires. Google's GA4 behavioral modeling needs this consent signal to be present even for visitors who deny tracking; the plugin supplies it so modeling continues to work for users who have denied or not yet responded.<\/p>\n\n<p><strong>California CPRA Opt-Out Audit Trail<\/strong><\/p>\n\n<p>California's CPRA regulations (effective January 2026) require stores to log opt-out signals with a timestamped record. This plugin stores consent decisions in a dedicated database table (<code>{prefix}gpcg_opt_out_log<\/code>) rather than <code>wp_options<\/code>. Opt-outs are recorded where they happen \u2014 when a visitor declines (or accepts) the banner, when an automatic GPC signal is detected (deduplicated to once per visitor per day), and at WooCommerce checkout \u2014 so the trail covers non-purchasers, not only completed orders. Each row records the hashed IP address (SHA-256 with a dedicated, stored plugin salt kept separate from WordPress auth keys so it survives key rotation \u2014 the raw IP is never written to disk), the consent state (granted \/ denied \/ gpc), the signal source (banner \/ gpc_header \/ gpc_js \/ default), the WooCommerce order ID, the page URL, and a UTC timestamp. A confirmation notice is displayed on the WooCommerce thank-you page to satisfy the California requirement that users receive visible confirmation of their opt-out.<\/p>\n\n<p><strong>Minimal Performance Impact<\/strong><\/p>\n\n<p>On the fast path \u2014 consent granted, no GPC signal \u2014 there is no output buffering and no HTML rewriting; the expensive work never runs. To keep per-visitor consent state correct, responses that depend on a consent cookie or GPC signal are automatically excluded from full-page caches (and the consent cookies are registered with WP Rocket and LiteSpeed Cache); first-visit pages remain cacheable. Output buffering for script stripping is a Pro feature and is never activated for consented users.<\/p>\n\n<p><strong>Free vs Pro<\/strong><\/p>\n\n\n\n\n  Feature\n  Free\n  Pro\n\n\n\n\n  GPC header detection (Sec-GPC)\n  \u2713\n  \u2713\n\n\n  GPC JavaScript detection\n  \u2713\n  \u2713\n\n\n  Block WooCommerce Google Analytics integration\n  \u2713\n  \u2713\n\n\n  Block Facebook \/ Meta Pixel\n  \u2713\n  \u2713\n\n\n  Block TikTok Pixel\n  \u2014\n  \u2713\n\n\n  Block Bing \/ Microsoft UET\n  \u2014\n  \u2713\n\n\n  Google Consent Mode v2 dataLayer defaults\n  \u2713\n  \u2713\n\n\n  Consent banner (accept \/ decline)\n  \u2713\n  \u2713\n\n\n  Opt-out confirmation on WooCommerce thank-you page\n  \u2713\n  \u2713\n\n\n  Audit log of banner, GPC, and checkout consent events (hashed IP, order ID, state, source)\n  \u2713\n  \u2713\n\n\n  Output-buffer script stripping (catches inline + third-party injected scripts)\n  \u2014\n  \u2713\n\n\n  Custom domain blocklist\n  \u2014\n  \u2713\n\n\n  CSV compliance export\n  \u2014\n  \u2713\n\n\n  Multi-state consent UI (California vs Virginia vs Colorado)\n  \u2014\n  \u2713\n\n\n\n\n<p><strong>How It Works<\/strong><\/p>\n\n<ol>\n<li>On every request, PHP checks the <code>Sec-GPC<\/code> header and the <code>gpcg_gpc_js<\/code> cookie (set by a tiny JS snippet that reads <code>navigator.globalPrivacyControl<\/code>).<\/li>\n<li>If GPC or no consent: known tracking script handles are dequeued; <code>gtag('consent','default',{ad_storage:'denied',...})<\/code> fires before GTM at <code>wp_head<\/code> priority 1.<\/li>\n<li>Consent decisions are logged to a dedicated audit table (SHA-256 hashed IP, UTC timestamp) when the visitor uses the banner, when GPC is detected (once per visitor per day), and at WooCommerce checkout completion.<\/li>\n<\/ol>\n\n<h3>Privacy<\/h3>\n\n<p>This plugin stores consent decisions in the database table <code>{prefix}gpcg_opt_out_log<\/code>. Visitor IP addresses are hashed with SHA-256 and a site-specific salt before storage \u2014 raw IPs are never written to disk. The hashed IP, consent state (granted\/denied\/gpc), signal source (banner\/gpc_header\/gpc_js\/default), WooCommerce order ID (when applicable), and page URL are retained until the plugin is uninstalled or the site administrator exports and purges the table. This plugin transmits nothing to external servers; the bundled Freemius SDK is opt-in only, used solely for Pro license activation if you choose to enter a license key.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>In your WordPress admin, go to <strong>Plugins &gt; Add New<\/strong>.<\/li>\n<li>Search for \"Harbor Privacy Guard for WooCommerce\" or click <strong>Upload Plugin<\/strong> and select the downloaded <code>.zip<\/code> file.<\/li>\n<li>Click <strong>Install Now<\/strong>, then <strong>Activate<\/strong>.<\/li>\n<li>Navigate to <strong>WooCommerce &gt; GPC Compliance<\/strong> to review the default configuration. Script blocking is enabled for Google Analytics and Facebook \/ Meta Pixel out of the box.<\/li>\n<li>Optionally customize the consent banner message and positioning, then save. The plugin is active immediately \u2014 no additional setup is required.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20replace%20my%20existing%20cookie%20banner%3F\"><h3>Does this replace my existing cookie banner?<\/h3><\/dt>\n<dd><p>It can, but it also works alongside one. If you already run another consent-management plugin, consider disabling its visitor-facing banner so your store does not show two banners; its other features (cookie scanning, privacy-policy pages) can remain active alongside this plugin.<\/p><\/dd>\n<dt id=\"what%20is%20the%20global%20privacy%20control%20%28gpc%29%3F\"><h3>What is the Global Privacy Control (GPC)?<\/h3><\/dt>\n<dd><p>GPC is a browser-level opt-out signal (like Do Not Track, but legally binding in 12 US states). When a user enables it in their browser or privacy extension, their browser sends <code>Sec-GPC: 1<\/code> on every HTTP request. This plugin detects that header server-side and blocks tracking without requiring the user to interact with a banner.<\/p><\/dd>\n<dt id=\"will%20this%20break%20my%20woocommerce%20store%3F\"><h3>Will this break my WooCommerce store?<\/h3><\/dt>\n<dd><p>No. The plugin only dequeues scripts that are enqueued through WordPress's script system. It does not modify orders, prices, or checkout logic. If you use a tracking script that is injected outside of <code>wp_enqueue_scripts<\/code> (for example, hardcoded into a theme), the free tier will not block it \u2014 that case is handled by the Pro output-buffer feature.<\/p><\/dd>\n<dt id=\"does%20this%20work%20with%20google%20tag%20manager%3F\"><h3>Does this work with Google Tag Manager?<\/h3><\/dt>\n<dd><p>Yes, for Consent Mode v2 purposes. The plugin emits <code>gtag('consent','default',...)<\/code> before GTM loads so GTM respects the consent state and suppresses or permits its tags accordingly. Note: the free tier does not prevent the GTM container script itself from loading \u2014 it only controls what GTM does once loaded. If you need to block the GTM script entirely when consent is denied, enable the Pro output-buffer mode.<\/p><\/dd>\n<dt id=\"how%20do%20i%20view%20the%20audit%20log%3F\"><h3>How do I view the audit log?<\/h3><\/dt>\n<dd><p>The consent log is stored in the <code>{prefix}gpcg_opt_out_log<\/code> database table. A monthly summary is shown at the bottom of the <strong>WooCommerce &gt; GPC Compliance<\/strong> settings page. Pro users can download a full date-ranged CSV from that same page.<\/p><\/dd>\n<dt id=\"is%20the%20audit%20log%20gdpr-compliant%3F\"><h3>Is the audit log GDPR-compliant?<\/h3><\/dt>\n<dd><p>IPs are hashed with SHA-256 and a site-specific salt before storage. The raw IP is never stored. Hashed IPs cannot be reversed to identify individuals, which means the log does not constitute personal data under most interpretations of GDPR. You should still mention the log in your privacy policy and confirm with your legal counsel whether your specific jurisdiction requires additional disclosures.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20a%20user%20has%20already%20set%20gpc%20and%20visits%20a%20new%20page%3F\"><h3>What happens when a user has already set GPC and visits a new page?<\/h3><\/dt>\n<dd><p>The server detects <code>Sec-GPC: 1<\/code> on every request independently. No cookie or session is required for GPC to be honored \u2014 the header is checked fresh on each page load. The JavaScript fallback cookie (<code>gpcg_gpc_js<\/code>) is also checked on each request but is only a fallback for environments where the HTTP header is stripped.<\/p><\/dd>\n<dt id=\"does%20this%20work%20with%20page%20builders%20%28elementor%2C%20divi%2C%20bricks%29%3F\"><h3>Does this work with page builders (Elementor, Divi, Bricks)?<\/h3><\/dt>\n<dd><p>Yes for script blocking. The plugin dequeues scripts by WordPress handle name, which works regardless of which page builder renders the page. The Consent Mode v2 defaults are emitted via <code>wp_head<\/code> at priority 1, which fires before any page builder output. If your page builder injects tracking scripts by hardcoding them into a template (outside of <code>wp_enqueue_scripts<\/code>), those scripts will not be blocked by the free tier \u2014 use the Pro output-buffer mode in that case.<\/p><\/dd>\n<dt id=\"what%20data%20does%20uninstalling%20the%20plugin%20delete%3F\"><h3>What data does uninstalling the plugin delete?<\/h3><\/dt>\n<dd><p>Deleting the plugin via <strong>Plugins &gt; Delete<\/strong> removes all plugin options and all plugin transients from <code>wp_options<\/code> on every site of the network. The consent audit log table (<code>{prefix}gpcg_opt_out_log<\/code>) is also dropped. This is irreversible \u2014 export a CSV before uninstalling if you need to retain the log for compliance purposes.<\/p><\/dd>\n<dt id=\"will%20blocking%20tracking%20hurt%20my%20conversion%20rate%3F\"><h3>Will blocking tracking hurt my conversion rate?<\/h3><\/dt>\n<dd><p>The plugin only blocks tracking for visitors who have actively opted out (declined the banner or enabled GPC) or who have not yet interacted with the banner. Visitors who accept cookies are unaffected. For opted-out visitors, GA4's consent mode modeling can still estimate conversions from anonymized signals \u2014 which requires the <code>gtag('consent','default',...)<\/code> call this plugin provides.<\/p><\/dd>\n<dt id=\"how%20does%20multi-state%20consent%20work%3F\"><h3>How does multi-state consent work?<\/h3><\/dt>\n<dd><p>Version 1.1 introduces automatic jurisdiction detection using CDN headers (Cloudflare, CloudFront, Vercel). When <strong>Jurisdiction-aware mode<\/strong> is enabled in the advanced settings, visitors from opt-out US states (Virginia, Texas, Utah, and others) are allowed tracking by default unless they actively decline \u2014 matching the legal standard for those states. Visitors from strict opt-in states (California, Colorado, Connecticut, Oregon) and the EU\/EEA always require an explicit consent grant. Conservative mode (the default) requires opt-in everywhere regardless of jurisdiction.<\/p><\/dd>\n<dt id=\"does%20this%20work%20with%20page%20caching%20%28wp%20rocket%2C%20litespeed%2C%20cloudflare%29%3F\"><h3>Does this work with page caching (WP Rocket, LiteSpeed, Cloudflare)?<\/h3><\/dt>\n<dd><p>Yes. Because script blocking is a per-visitor decision, the plugin automatically marks any response that depends on a consent cookie or GPC signal as non-cacheable (via the <code>DONOTCACHEPAGE<\/code> constant and no-cache headers), registers the <code>gpcg_consent<\/code> \/ <code>gpcg_gpc_js<\/code> cookies with WP Rocket and LiteSpeed Cache, and bypasses Cache Enabler for those requests. In the default Conservative mode this is fully safe: the only cacheable page (a first visit with no cookie and no GPC) renders with tracking already stripped, so a cached copy can never leak tracking to anyone.<\/p>\n\n<p>Two configuration notes for maximum safety:<\/p>\n\n<ol>\n<li>Static-file caches that serve a stored page <em>before<\/em> WordPress loads (Cache Enabler, WP Super Cache, W3 Total Cache) decide whether to serve from cache based on their own excluded-cookies list. Add <code>gpcg_consent<\/code> and <code>gpcg_gpc_js<\/code> to that list so a visitor who already made a choice is always served a fresh page. WP Rocket and LiteSpeed are handled automatically.<\/li>\n<li>CDN-level full-page caches (Cloudflare APO, Fastly, Varnish) sit in front of WordPress and do not see <code>DONOTCACHEPAGE<\/code>; configure them to vary on the <code>gpcg_consent<\/code> \/ <code>gpcg_gpc_js<\/code> cookies and the <code>Sec-GPC<\/code> request header.<\/li>\n<\/ol>\n\n<p>When Jurisdiction-aware mode (Pro) is enabled, the plugin disables full-page caching entirely, because the rendered consent state depends on the visitor's geo \u2014 which page caches do not vary on.<\/p><\/dd>\n<dt id=\"do%20i%20need%20a%20freemius%20account%20for%20the%20free%20version%3F\"><h3>Do I need a Freemius account for the free version?<\/h3><\/dt>\n<dd><p>No. The free tier works entirely without a Freemius account. Freemius is only used for the Pro license key activation and upgrade flow.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20send%20any%20data%20to%20external%20services%3F\"><h3>Does this plugin send any data to external services?<\/h3><\/dt>\n<dd><p>The plugin itself sends nothing off-site: consent decisions and the audit log stay in your WordPress database. The bundled Freemius SDK powers optional Pro licensing and is strictly opt-in: on first activation it shows a consent screen, and no data is transmitted unless you explicitly opt in. If you choose Skip, the plugin remains fully functional and nothing is ever sent. Details: freemius.com\/privacy (Freemius privacy policy).<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.5.1<\/h4>\n\n<ul>\n<li>Renamed to Harbor Privacy Guard for WooCommerce per WordPress.org plugin-review naming guidance<\/li>\n<li>Documented the opt-in Freemius licensing service in the readme<\/li>\n<li>Removed an external URL from a code comment flagged by automated review<\/li>\n<\/ul>\n\n<h4>1.5.0<\/h4>\n\n<ul>\n<li>Pro functionality now ships as a separate premium-only module; the WordPress.org build contains only free features with no locked functionality<\/li>\n<li>All code prefixes renamed from wgc_ to gpcg_ for uniqueness: the consent cookies are now <code>gpcg_consent<\/code> and <code>gpcg_gpc_js<\/code>, the audit table is <code>{prefix}gpcg_opt_out_log<\/code>, and cache-exclusion lists should be updated accordingly<\/li>\n<li>Removed the Plugin URI header and tightened plugin metadata for the WordPress.org directory<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Renamed to GPC Guard for WooCommerce (final WordPress.org identity); text domain is now harbor-privacy-guard-for-woocommerce<\/li>\n<li>Freemius SDK is now bundled as a Composer dependency under vendor\/ and licensing activates out of the box; Pro features unlock with a license key on the same codebase<\/li>\n<li>Uninstall cleanup moved to the Freemius after_uninstall hook (uninstall.php removed) and now clears the pruning cron on every site of a multisite network<\/li>\n<li>Consent banner and settings dialog now restore each background element's prior inert state on close instead of force-clearing it, protecting other plugins' modals and drawers<\/li>\n<li>Cloudflare visitor headers (CF-Connecting-IP, True-Client-IP, CF-IPCountry) are only trusted when the request verifiably came through a Cloudflare edge IP; other CDNs can register ranges via the gpcg_trusted_cdn_ip_ranges filter<\/li>\n<li>The banner's Global Privacy Control auto-suppression now honors the GPC JavaScript detection setting<\/li>\n<li>Audit rows with no explicit visitor signal now record signal_source \"default\" instead of claiming a banner interaction<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Audit-log retention: a configurable retention window (default 730 days, 0 = keep forever) with automatic daily pruning bounds table growth and supports GDPR storage-limitation<\/li>\n<li>Output-buffer script stripping (Pro) now also removes inline tracking script blocks that reference a blocked domain, not just external src scripts<\/li>\n<li>Rate limiting and audit IP hashing now resolve the real client IP behind CDNs (Cloudflare\/Akamai headers by default; X-Forwarded-For behind the gpcg_trust_forwarded_ip filter), so proxied visitors get distinct buckets and hashes<\/li>\n<li>Schema self-repair on upgrade verifies the visitor_state column and order_id index exist and adds them if a prior dbDelta silently skipped them<\/li>\n<li>Freemius licensing now initializes early and independently of WooCommerce, and the SDK only loads when credentials are configured (leaner free tier)<\/li>\n<li>Fix: the thank-you opt-out notice no longer renders twice on WooCommerce block-based order-confirmation pages<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Audit trail now records banner accept\/decline decisions and automatic GPC opt-outs (deduplicated once per visitor per day), not only checkout events \u2014 so the log covers non-purchasers<\/li>\n<li>IP hashing now uses a dedicated, stored plugin salt instead of the WordPress auth salt, so hashes remain stable and joinable when auth keys are rotated<\/li>\n<li>Page-cache safety: consent-dependent responses are automatically marked non-cacheable (DONOTCACHEPAGE + no-cache headers) and the consent cookies are registered with WP Rocket and LiteSpeed Cache; prevents cached pages leaking tracking scripts to opted-out visitors<\/li>\n<li>TikTok Pixel blocking, Bing\/Microsoft UET blocking, and Multi-state jurisdiction UI moved to the Pro tier<\/li>\n<li>Plugin renamed to \"GPC &amp; Consent Mode Compliance for WooCommerce\" for WordPress.org trademark-policy compliance (slug and settings unchanged)<\/li>\n<li>Security: CSV compliance export now neutralizes spreadsheet formula\/DDE injection in exported cells<\/li>\n<li>Hardening: Sec-GPC header and GPC cookie reads now pass through wp_unslash\/sanitize; added index.php directory-listing guards<\/li>\n<li>Fix: readme \"Tested up to\" and package version aligned to a single source of truth<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Multi-state jurisdiction detection via CDN headers (Cloudflare, CloudFront, Vercel)<\/li>\n<li>Jurisdiction-aware consent mode: opt-out US states (VA, TX, UT, etc.) allow tracking by default; strict states (CA, CO, CT, OR) and EU always require opt-in<\/li>\n<li>Visitor state (US-CA format) recorded in audit log for per-state compliance reporting<\/li>\n<li>Settings menu renamed to \"Privacy &amp; Consent\" for clarity<\/li>\n<li>Jurisdiction settings section added to admin settings page<\/li>\n<li>Fix: dedup transient no longer set when audit log insert fails (prevents silent data loss)<\/li>\n<li>Fix: banner fetch error now throws on non-2xx responses (prevents infinite re-show loop)<\/li>\n<li>Fix: Store API checkout logs empty page URL (correct \u2014 AJAX context has no thank-you URL)<\/li>\n<li>Fix: multisite uninstall now cleans up all subsites<\/li>\n<li>Fix: CSS <code>:focus<\/code> rules updated to <code>:focus-visible<\/code> (keyboard-only focus indicators)<\/li>\n<li>Fix: dark mode reject button contrast improved for WCAG AA compliance<\/li>\n<li>Fix: reduced-motion media query added for banner transitions<\/li>\n<li>Fix: <code>aria-hidden<\/code> added to thank-you notice checkmark icon<\/li>\n<li>Fix: monthly compliance summary cached with 5-minute TTL (was uncached, causing unbounded DB scans)<\/li>\n<li>Fix: soft nonce check on REST consent-update endpoint (logged-in users protected from CSRF)<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>GPC header and JavaScript detection<\/li>\n<li>Google Consent Mode v2 dataLayer integration<\/li>\n<li>WooCommerce script blocking (Google Analytics, Facebook Pixel, TikTok, Bing)<\/li>\n<li>Block-checkout (Store API) audit logging for HPOS compatibility<\/li>\n<li>Consent banner (accept \/ decline) with WCAG 2.1 focus trap<\/li>\n<li>Opt-out confirmation on WooCommerce thank-you page<\/li>\n<li>Audit log table with SHA-256 hashed IPs and order IDs<\/li>\n<li>Monthly consent summary on admin settings page<\/li>\n<li>CSV compliance export (Pro)<\/li>\n<\/ul>","raw_excerpt":"WooCommerce-specific server-side enforcement of GPC browser signals, Google Consent Mode v2, and California opt-out audit logging.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/339990","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=339990"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/harborplugins"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=339990"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=339990"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=339990"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=339990"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=339990"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=339990"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}