=== RoyalComply === Contributors: royalpluginsteam Tags: gdpr, cookie consent, ccpa, cookie banner, cookie notice, consent mode, cookie policy, consent management, privacy, cookie law, consent banner, privacy compliance Requires at least: 5.9 Tested up to: 6.9 Stable tag: 1.0.2 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html GDPR and CCPA cookie consent banner with Google Consent Mode v2. Blocks analytics and marketing scripts until the visitor gives consent. == Description == RoyalComply is a cookie consent and privacy compliance plugin for WordPress. It blocks analytics and marketing scripts until consent is given, supports Google Consent Mode v2, and adapts banner behavior based on the visitor's jurisdiction (GDPR, CCPA, and 19 US state privacy laws). The plugin runs entirely on your server. It does not connect to any external services. **Features:** * **Script blocking** — Uses the WordPress `script_loader_tag` filter to change the `type` attribute of analytics and marketing scripts to `text/plain` until consent is given, preventing execution. * **Google Consent Mode v2** — Outputs the `gtag('consent', 'default', {...})` call with a denied state before Google Tag Manager loads, and sends `consent update` events when the visitor makes a choice. * **Regional banner behavior** — Detects the visitor's region from CDN request headers (Cloudflare `CF-IPCountry` etc.) with a browser-timezone fallback. Banner behavior switches between opt-in (GDPR), opt-out (CCPA), and other jurisdictions as configured. * **Cookie scanner** — Scans your site's rendered HTML for known third-party script patterns (Google Analytics, Facebook Pixel, Hotjar, etc.) and matches them against a built-in database of 50+ cookie names. The scanner reads HTML your site already produces. No outbound HTTP requests are made. * **Consent logging** — Stores each consent choice with a SHA-256 hashed visitor identifier, timestamp, and category selections. Exportable to CSV. No IP addresses or personally identifiable information are stored. * **Banner customization** — 6 position options, bar or box layout, full color control. Combined CSS and JavaScript on the frontend is under 8KB. * **Geo detection** — Reads the `CF-IPCountry` and similar headers already present in the incoming request. Falls back to the browser's timezone via JavaScript. No IP lookup service is called. **Cookie Categories:** * **Necessary** — Always allowed. WordPress sessions, WooCommerce cart, PHP sessions. * **Analytics** — Google Analytics, Hotjar, Clarity, Matomo, Plausible. * **Marketing** — Facebook Pixel, Google Ads, LinkedIn, TikTok, Pinterest. * **Preferences** — Language selection (Polylang, WPML, qTranslate). **Compliance Coverage:** * GDPR (EU/EEA) — Opt-in consent required * CCPA (California) — Opt-out with "Do Not Sell" link * VCDPA (Virginia), CPA (Colorado), CTDPA (Connecticut), UCPA (Utah), TIPA (Tennessee), ICDPA (Indiana), MTCDPA (Montana), TDPSA (Texas), OCPA (Oregon), DPDPA (Delaware), FDBR (Florida), NJDPA (New Jersey), NHDPA (New Hampshire), KCDPA (Kentucky), NEBDPA (Nebraska), ICDPA (Iowa), MCDPA (Maryland), MNDPA (Minnesota) == Installation == 1. Upload the `royalcomply` folder to `/wp-content/plugins/`. 2. Activate the plugin through the Plugins menu. 3. Go to RoyalComply > Dashboard to configure. 4. Run the cookie scanner to detect existing cookies. 5. Customize your banner appearance under Banner Design. == Frequently Asked Questions == = How does script blocking work? = RoyalComply uses WordPress's `script_loader_tag` filter to change script types from `text/javascript` to `text/plain` until consent is given. This prevents scripts from executing. The approach does not require output buffering or DOM manipulation. = Does it work with Google Tag Manager? = Yes. When Google Consent Mode v2 is enabled, RoyalComply outputs the required `gtag('consent', 'default', {...})` call before GTM loads, then updates consent state when the user makes a choice. = Is this plugin GDPR compliant? = RoyalComply is designed to help site owners meet GDPR's consent requirements. It blocks analytics and marketing scripts until the visitor gives explicit opt-in consent, stores a record of each consent choice with a SHA-256 hashed identifier, and provides a "Reject All" button with the same prominence as "Accept All". Whether a given site is fully GDPR compliant also depends on the rest of its privacy practices (privacy policy, data processing agreements, etc.), which are outside the scope of this plugin. = Does this work for CCPA? = Yes. When the visitor's region is detected as California (or any configured opt-out jurisdiction), RoyalComply switches the banner to opt-out mode and displays a "Do Not Sell or Share My Personal Information" link that records the visitor's opt-out choice. = Does it make external API calls? = No. Geo detection uses CDN headers (Cloudflare, etc.) that are already present in the request, plus browser timezone as a fallback. No third-party services are contacted. = Is the consent log GDPR-compliant? = Yes. Visitor identifiers are SHA-256 hashed with a site-specific salt. No IP addresses or personally identifiable information is stored. = Can I use this with WooCommerce? = Yes. WooCommerce session and cart cookies are automatically categorized as "necessary" and are never blocked. == Screenshots == 1. Dashboard with compliance overview and consent statistics. 2. Cookie management with category badges and scanner. 3. Banner design with live preview and color customization. 4. Consent log with export and filtering. 5. Settings page with region detection and script blocking options. == External services == RoyalComply does not connect to any third-party services. The plugin runs entirely on your own WordPress install and does not send data to any external server, API, or CDN. The built-in **cookie scanner** makes a single loopback HTTP request to your own site's homepage (`home_url( '/' )`) using the WordPress `wp_remote_get()` function, with a 10-second timeout. This request goes to the same WordPress install; no third-party service is contacted. The scanner then reads the returned `Set-Cookie` response headers and the HTML response body, and searches the body for known third-party script hostnames (for example `google-analytics.com`, `connect.facebook.net`, `js.stripe.com`, `widget.intercom.io`, `cdnjs.cloudflare.com`). These hostnames are stored as pattern strings inside the plugin and are compared against the response body using PHP's `stripos()` function. The plugin does not make any network requests to the services the pattern strings refer to; it only reads HTML that your own site already generates. The scanner runs only when the site administrator clicks the "Scan Site" button in the RoyalComply admin screen. It is not run on a schedule and is not triggered by visitors. **Geo detection** reads HTTP headers that are already present in the incoming page request (for example Cloudflare's `CF-IPCountry` header) and, as a JavaScript fallback, reads the visitor's timezone from the browser using `Intl.DateTimeFormat().resolvedOptions().timeZone`. No IP geolocation API is contacted. **Google Consent Mode v2** outputs a `gtag('consent', 'default', {...})` JavaScript call in the page. This call runs in the visitor's browser and is consumed by Google Tag Manager or gtag.js if those are already installed on the site. RoyalComply itself does not load Google's scripts; the integration only configures the consent state that the site's existing Google scripts read. == Changelog == = 1.0.2 = * Compliance: Renamed text domain from `royal-comply` to `royalcomply` so it matches the plugin slug, as required by WordPress.org internationalization guidelines. * Readme: Rewrote the plugin description in a neutral, factual tone, removing promotional and comparative phrasing. * Readme: Added an "External services" section that documents how the cookie scanner and geo-detection work, and clarifies that the plugin makes no outbound HTTP requests. * Code: Added file-level documentation to the scanner and script-blocker classes explaining that the hostname strings inside them are local pattern-matching dictionaries, not URLs that the plugin contacts. = 1.0.1 = * Security: Removed unnecessary sslverify bypass on cookie scanner * Compatibility: Tested up to WordPress 6.9.3 = 1.0.0 = * Initial release * Cookie consent banner with 6 position options * Script blocking via the script_loader_tag filter * Google Consent Mode v2 support * Built-in database of 50+ known cookies * Cookie scanner for site analysis * GDPR-compliant consent logging with CSV export * Geo detection via CDN request headers and browser timezone (no third-party IP lookup) * CCPA "Do Not Sell" support * Customizable banner colors, text, and layout * Privacy and cookie policy text generator == Upgrade Notice == = 1.0.0 = Initial release. Install and configure your cookie consent banner.