=== Lexiscript Consent & Privacy === Contributors: jmwatee Tags: consent, gdpr, cookies, privacy, ccpa Requires at least: 6.0 Tested up to: 7.1 Requires PHP: 7.4 Stable tag: 1.0.1 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Blocks non-essential trackers until your visitor consents, applying the consent model of their own region. Free for one website. == Description == Most consent banners describe what a site does. This one changes it. The Lexiscript widget intercepts the browser APIs that scripts use to insert themselves, so a tracker is caught at the moment it tries to load rather than disclosed after it has already run. Non-essential scripts do not execute until the visitor has agreed — and what counts as agreement depends on where that visitor is. **Region-aware by default.** A visitor in Germany, one in California and one in Kenya get different behaviour from the same installation. The widget applies one of three consent models according to the visitor's location: * Opt-in, where nothing runs until consent is given: EU, UK, Kenya, Nigeria, Brazil * Opt-out, presented as "Do Not Sell or Share": California * Notice-only: South Africa, Canada These groupings reflect how Lexiscript reads the published rules for each region. They are a product configuration, not a legal determination about your site — see "Not legal advice" below. **What the widget does on your site** * Blocks non-essential scripts before they run, rather than describing them afterwards * Shows a preference centre with per-category choices, not all-or-nothing * Gives "Reject all" the same prominence as "Accept" * Pre-ticks nothing under an opt-in model * Honours the Global Privacy Control signal automatically * Treats a stored decision as expired after the configured lifetime * Invalidates previous consent when the tracker set changes, because the visitor never agreed to the new ones * Never blocks the page itself — the scripts are blocked, not your content * Fails closed: if the configuration cannot be reached, it serves deny-all rather than letting everything through * One small vanilla JavaScript file, no framework, no dependencies **Why this plugin exists** The widget is one script, and the only thing that is easy to get wrong is where it goes — it must run before every other script on the page or it has nothing left to intercept. This plugin registers it with WordPress's script loader and prints it at the top of the document head, ahead of the tags that themes and other plugins add, and keeps it there through theme changes. = Plans and pricing = A Lexiscript account is free, and so is scanning your site and reading the findings. **The free plan also runs the consent widget on one website**, which is all most sites need. If your Lexiscript account holds more than one website, the free widget serves the first one you added. The others will not return a configuration, and no banner will appear on them, until you move to a paid plan. Nothing stops working after a trial period. Current pricing is on https://jaytechkenya.com/lexiscript. = External service = This plugin requires a Lexiscript account and loads a script from Lexiscript, a service operated by Jaydee Innovation Hub (Nairobi, Kenya). The plugin does not function without it. * The plugin registers and prints one script, served from `https://widget.jaytechkenya.com`, with your site key as a query parameter. This is Lexiscript's own service endpoint, not a general-purpose third-party CDN, and the script is the service. * That script runs in your visitors' browsers. It requests your site's consent configuration from Lexiscript, and the visitor's IP address is used at the edge to resolve their country — and US state where relevant — in order to decide which consent model applies. The IP address is used for that lookup and is not retained as part of a visitor profile. * The visitor's own consent choices are stored in their browser. They are not sent to Lexiscript. * This plugin itself makes no requests to Lexiscript from your server, and reads or transmits nothing from your WordPress database. * Service terms: https://jaytechkenya.com/terms * Privacy policy: https://jaytechkenya.com/privacy * About the service: https://jaytechkenya.com/lexiscript = Not legal advice = Lexiscript reports what your website does and which published rules are relevant to it. It does not determine whether your site is lawful, it does not make your site compliant with any law, and nothing it produces is legal advice. Whether your use of this plugin meets your obligations is a question for your own adviser. == Installation == 1. Create an account at https://jaytechkenya.com/lexiscript and add your website. 2. Open your website in the Lexiscript dashboard and copy the id from the install snippet. 3. Install and activate this plugin. 4. Go to **Settings → Lexiscript** and paste the id into the Site key field. 5. Load your site in a private window. The banner should appear, and your analytics should not fire until you accept. If the banner does not appear, and this is the second or third website on your Lexiscript account, that is the plan boundary: the free plan covers one site. If you previously pasted the Lexiscript tag into your theme by hand, remove it — two copies of the widget is not better than one. == Frequently Asked Questions == = Do I need a paid plan? = Not for one website. Creating an account, adding a site, scanning it and running the consent widget on it are all free. A paid plan covers additional websites and adds automatic monthly re-scans. = Why does this script load before everything else? = Because it has to. The widget works by intercepting the browser APIs that scripts use to insert themselves, which only affects scripts that load after it. The plugin registers the widget with `wp_register_script()` and then prints that one handle at `wp_head` priority 0, rather than letting it print with the rest of the queue at priority 9 — several tag-manager plugins deliberately hook earlier than 9, and anything that loads first wins. = It is not blocking my Google Tag Manager container = Check that no other plugin or your theme is printing a tag above this one. This plugin prints at `wp_head` priority 0, which is earlier than anything using the default priority, but code hooked at priority 0 before it, or hard-coded directly into `header.php` above `wp_head()`, will still win. Move it below `wp_head()` and it will be caught. = Will this slow my site down? = The widget is a single small JavaScript file. It is loaded synchronously and deliberately so: a deferred or asynchronous script cannot intercept tags that have already started loading, which would defeat the point. = Does it work with caching plugins? = Yes. The tag is static markup, so it caches like the rest of the page. The consent decision itself is made in the visitor's browser, not on your server, so a cached page serves the correct behaviour to every visitor regardless of where they are. = Does it work on multisite? = Yes. Each site in the network has its own site key, set on that site's own settings screen. = Can I point it at a different host? = Yes, for self-hosted or staging deployments, by defining a constant in `wp-config.php`: `define( 'LEXISCRIPT_WIDGET_HOST', 'https://widget.example.com' );` It is deliberately not a setting. The value decides the origin of a script that runs on every page of your site, so it belongs with your deployment constants rather than in a form. = What happens if I deactivate it? = The tag stops being printed and trackers run as they did before. Your settings are kept in case you reactivate; deleting the plugin removes them. == Screenshots == 1. The settings screen — one field to paste your site key. 2. The consent banner as a visitor in an opt-in region sees it. 3. The preference centre, with per-category choices. == Changelog == = 1.0.1 = * Corrected the plan information. The consent widget runs on one website on the free plan; the previous release wrongly stated that it required a paid plan. = 1.0.0 = * First release. == Upgrade Notice == = 1.0.1 = Corrects the plan information in the readme. No functional changes. = 1.0.0 = First release.