{"id":388103,"date":"2026-11-02T14:58:32","date_gmt":"2026-11-02T14:58:32","guid":{"rendered":"https:\/\/es.wordpress.org\/plugins\/cumpleconsent\/"},"modified":"2026-11-02T14:58:18","modified_gmt":"2026-11-02T14:58:18","slug":"cumpleconsent","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/cumpleconsent\/","author":23587298,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.19","stable_tag":"1.0.19","tested":"7.1.4","requires":"6.2","requires_php":"7.4","requires_plugins":null,"header_name":"CumpleConsent","header_author":"MenteGlobal SpA","header_description":"Consentimiento y transparencia alineados a la Ley 21.719 de Chile y a su reglamento (D.S. 662): aviso sin patrones oscuros, bloqueo de rastreadores antes del consentimiento, prueba auditable, pol\u00edtica de privacidad con verificaci\u00f3n del art\u00edculo 14 ter, atenci\u00f3n de derechos del titular con plazos legales y registro de actividades de tratamiento. Sin telemetr\u00eda: todo se procesa en tu propio sitio.","assets_banners_color":"272e3f","last_updated":"2026-11-02 14:58:18","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/menteglobal.com\/cumpleconsent","header_author_uri":"https:\/\/menteglobal.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":43,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.19":{"tag":"1.0.19","author":"menteglobal","date":"2026-11-02 14:58:18","revision":3780080}},"upgrade_notice":{"1.0.19":"<p>The compliance report now gets its styles through the WordPress API, and the public consent endpoint compares the full origin (scheme, host and port).<\/p>","1.0.18":"<p>Plugin Check cleanup: no behaviour changes.<\/p>","1.0.17":"<p>Restricts the public consent endpoint to same-origin requests, prints the notice&#039;s files through WordPress functions, stops the diagnostic from raising a critical finding in balanced mode, and renames the JavaScript configuration object to the plugin prefix.<\/p>","1.0.16":"<p>Renames internal and stored names to the plugin&#039;s prefix (with a migration that keeps your data), validates visitor-controlled input before storing it, sanitizes the response sent by email and closes its output buffer explicitly.<\/p>","1.0.15":"<p>Finds the privacy policy on sites that publish it at a different address, reads policies built with page builders (Elementor), ignores empty placeholder pages, and makes sure the notice appears even on themes or templates that do not print the footer.<\/p>","1.0.14":"<p>Fixes the policy detection and verification: recognises a privacy policy the site published by hand, stops reading the page&#039;s CSS as if it were policy text, and no longer shows a coverage score when there is no policy to verify.<\/p>","1.0.13":"<p>Removes the optional &quot;postal address or alternative contact&quot; field from the rights form: the email is enough to answer, as art. 11 expects.<\/p>","1.0.12":"<p>Splits the rights form into two fields (full name and identity document) and stores the document in its own column; it is required, as art. 11 expects the request to identify who files it.<\/p>","1.0.11":"<p>Fixes the rights channel: emails no longer show &quot;WordPress&quot; as the sender, the internal notice reaches the rights mailbox and its delivery is recorded (a failure is visible in the panel), and the published address for exercising rights is the rights mailbox. Includes a test-email button.<\/p>","1.0.10":"<p>Stops the policy generator from replacing a privacy policy the plugin did not write: it leaves it untouched and puts the generated text in a separate draft. Recommended before installing on a site that already publishes its own policy.<\/p>","1.0.9":"<p>Same behaviour as 1.0.8, with the last Plugin Check warning documented. Plugin Check\nreports zero issues. Recommended before submitting to the directory.<\/p>","1.0.8":"<p>Same behaviour as 1.0.7, prepared for the WordPress directory review: English readme, plugin-prefixed namespaces and hooks, and the Plugin Check wording fixes. Recommended.<\/p>","1.0.7":"<p>Fixes the &quot;Run diagnostics&quot; button not saving its result (the panel kept saying it had never run) and adds a visible outcome for every action. Recommended for all sites.<\/p>","1.0.6":"<p>Presentation changes for the WordPress directory and an explicit statement that the plugin does not connect to external services. No behaviour changes.<\/p>","1.0.5":"<p>Fixes the notice not showing on the first visit when the site combines and delays JavaScript (LiteSpeed and similar): the plugin marks its script and delivers the configuration as data, so no optimiser holds it back. Recommended for sites with caching plugins.<\/p>","1.0.4":"<p>Fixes the notice and its panel inheriting the theme styling (faint text, uppercase labels, themed buttons) and makes the configured accent colour actually apply. Recommended for all sites: the notice now looks the same and stays readable on any theme.<\/p>","1.0.3":"<p>Fixes a partial API write switching off toggles that were not in the request (preferences button, embedded content blocking and server-side honouring of consent). Recommended if you configure the plugin with an application password.<\/p>","1.0.2":"<p>Adds configuration and provisioning over the API (application password) and stops the policy page being duplicated when generated. Recommended: it does not change the visitor-facing notice.<\/p>","1.0.1":"<p>Fixes the preferences panel in the default position (it was drawn off-screen) and makes closing without deciding leave the notice in place. Recommended for all sites.<\/p>","1.0.0":"<p>First public version.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3780125,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3780125,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x250.png":{"filename":"banner-1544x250.png","revision":3780125,"resolution":"1544x250","location":"assets","locale":"","width":1544,"height":250},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3780125,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.19"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3780125,"resolution":"1","location":"assets","locale":"","width":1440,"height":900},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3780125,"resolution":"2","location":"assets","locale":"","width":1440,"height":900}},"screenshots":{"1":"First-layer notice: accept, reject and configure with the same visual weight.","2":"Preferences panel, purpose by purpose, with withdrawal always available.","3":"Art. 14 ter verification: which contents the law requires and which ones are covered.","4":"Consent log with the notice fingerprint and integrity check.","5":"Rights requests inbox with the deadlines of art. 11."}},"plugin_section":[],"plugin_tags":[290325,19289,20011,389,396],"plugin_category":[54],"plugin_contributors":[290326],"plugin_business_model":[],"class_list":["post-388103","plugin","type-plugin","status-publish","hentry","plugin_tags-ley-21719","plugin_tags-chile","plugin_tags-consent","plugin_tags-cookies","plugin_tags-privacy","plugin_category-security-and-spam-protection","plugin_contributors-menteglobal","plugin_committers-menteglobal"],"banners":{"banner":"https:\/\/ps.w.org\/cumpleconsent\/assets\/banner-772x250.png?rev=3780125","banner_2x":false,"banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/cumpleconsent\/assets\/icon-128x128.png?rev=3780125","icon_2x":"https:\/\/ps.w.org\/cumpleconsent\/assets\/icon-256x256.png?rev=3780125","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/cumpleconsent\/assets\/screenshot-1.png?rev=3780125","caption":"First-layer notice: accept, reject and configure with the same visual weight."},{"src":"https:\/\/ps.w.org\/cumpleconsent\/assets\/screenshot-2.png?rev=3780125","caption":"Preferences panel, purpose by purpose, with withdrawal always available."}],"raw_content":"<!--section=description-->\n<p><strong>CumpleConsent<\/strong> is not a translated European plugin. It is built on the wording of Chile's <strong>Law 21.719<\/strong> on personal data protection and its regulation (D.S. 662), it quotes the law in Chilean Spanish, and it does what that law actually asks of a website.<\/p>\n\n<p>The plugin screens and the legal texts are in Spanish on purpose: the law, its deadlines and the wording it requires are Chilean. The code is fully translatable (text domain <code>cumpleconsent<\/code>), so anyone can ship another language.<\/p>\n\n<p><strong>What it does<\/strong><\/p>\n\n<ul>\n<li><strong>Privacy notice without dark patterns.<\/strong> Accept, reject and configure carry the same visual weight; nothing is pre-ticked; rejecting takes one click. You can raise the notice version to ask for consent again when purposes change.<\/li>\n<li><strong>Blocking before consent (art. 14 qu\u00e1ter).<\/strong> Four layers: interoperability with <code>wp_consent_api<\/code>, rewriting of enqueued scripts, rewriting of the output HTML for raw and inline scripts, and <strong>embedded content<\/strong> (videos, maps, social, chats) replaced by a placeholder until accepted. It works with full-page caching: the HTML is served inert and each visitor's browser re-activates according to their own decision.<\/li>\n<li><strong>Google Consent Mode v2<\/strong> with a strict or a balanced strategy (cookieless loading, personalisation on acceptance).<\/li>\n<li><strong>Proof of consent (art. 12).<\/strong> Every decision is logged with date and time, a pseudonym, the purposes accepted and rejected, a <strong>cryptographic fingerprint of the notice that was shown<\/strong>, and an integrity HMAC. No name, no email and no plain IP (only an optional salted hash). Exportable to CSV.<\/li>\n<li><strong>Privacy policy: generator plus an art. 14 ter checker.<\/strong> Generates a draft covering the twelve mandatory contents (a\u2013l) with the site's real data, and checks the published policy against them, showing what is missing.<\/li>\n<li><strong>Data subject rights with a legal clock (art. 11).<\/strong> A public request form that registers the request, computes the <strong>30 calendar days<\/strong> to answer (extendable once by 30 more), the <strong>2 business days<\/strong> for a temporary blocking, stores the full reply as evidence, sends an acknowledgement, and warns when a deadline is near. On refusal it records the ground and the 30-business-day window to complain to the Agency.<\/li>\n<li><strong>International transfers (art. 14 ter h and art. 27).<\/strong> A table of recipients, country and safeguard, publishable with a shortcode, plus a warning when the diagnostics finds an undeclared third party.<\/li>\n<li><strong>Record of processing activities, risk matrix and protocols (art. 3 of regulation D.S. 662, letters a, d, e, f and g).<\/strong> Downloads a printable dossier to attach to a compliance programme: characterisation of the operations (eleven items), a matrix graded against the penalties in the law, and the protocols in force.<\/li>\n<li><strong>Site diagnostics.<\/strong> Which third parties actually load, whether the blocking is working, whether another consent manager is competing, and whether the policy claims something the site does not back up.<\/li>\n<li><strong>Consent in forms.<\/strong> An unticked checkbox with a declared purpose and traceability of the notice, plus integration with Contact Form 7, WPForms and Gravity Forms.<\/li>\n<\/ul>\n\n<p><strong>What it does NOT do (no overpromising)<\/strong><\/p>\n\n<ul>\n<li>It is not a compliance programme and it does not appoint a data protection officer: it provides the website-side documentary elements for letters a), d), e), f) and g) of art. 3 of the regulation.<\/li>\n<li>It does not certify or replace legal advice. The art. 14 ter checker detects contents that are present or absent; it does not judge legal sufficiency.<\/li>\n<li>It does not verify visitor age or manage consent for children and adolescents (art. 16 qu\u00e1ter).<\/li>\n<li>It does not encrypt your database and it is not a security plugin.<\/li>\n<\/ul>\n\n<p><strong>The plugin's own privacy:<\/strong> there is no telemetry, no calls to external servers, and no site data is sent anywhere. Everything is processed inside your own installation.<\/p>\n\n<p>This plugin is a project by <strong>MenteGlobal SpA<\/strong> (https:\/\/menteglobal.com), distributed free of charge under GPL-2.0-or-later. The complete source is in the package you installed: you can read it, audit it and change it.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin does not connect to any external service and does not send data to any server other than the site's own:<\/p>\n\n<ul>\n<li>No telemetry, no calls to the author's servers, no licence checks, no updates served from another domain.<\/li>\n<li>If the site already uses Google Tag Manager, the plugin passes the visitor's decision to the browser (<code>gtag('consent','update')<\/code>) so that tags respect consent. That happens inside the visitor's browser and targets the container the site already had installed: the plugin sends nothing to Google on its own.<\/li>\n<li>The consent log, the policy and the rights requests are stored in the site's own database.<\/li>\n<li>The diagnostics \u2014and the verification of the privacy policy when the site keeps its text outside the post content (page builders such as Elementor)\u2014 make HTTP requests <strong>to the site's own pages<\/strong> (local loopback requests) to read what the site really serves. Those requests never leave the site's server.<\/li>\n<\/ul>\n\n<p>The plugin also ships a <strong>list of domains of well-known third-party services<\/strong> (<code>googletagmanager.com<\/code>, <code>connect.facebook.net<\/code>, <code>maps.googleapis.com<\/code>, and similar). That list exists <strong>to block those scripts before the visitor consents<\/strong>: the plugin never contacts those services and never sends them anything. It is a blocking list, not a connection.<\/p>\n\n<p>Third-party services the plugin interacts with: none.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>cumpleconsent<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or install it from Plugins \u2192 Add New.<\/li>\n<li>Activate it.<\/li>\n<li>Go to <strong>CumpleConsent \u2192 Settings<\/strong> and fill in the controller's identity (legal name, Chilean RUT, legal representative and contact email). Saving it turns the notice on.<\/li>\n<li>Under <strong>Documents<\/strong>, generate the privacy policy and review the art. 14 ter verification.<\/li>\n<li>Declare your providers under Settings \u2192 Transfers and enable the rights form.<\/li>\n<li>Add <code>[cumpleconsent_preferencias]<\/code> to your site footer so people can withdraw consent at any time (art. 12).<\/li>\n<\/ol>\n\n<p>No server configuration and no theme changes are required.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20it%20replace%20a%20european%20cookie%20plugin%3F\"><h3>Does it replace a European cookie plugin?<\/h3><\/dt>\n<dd><p>Yes, for Chilean sites. It is built on Law 21.719 and its regulation: the Agency, the deadlines of art. 11, the twelve contents of art. 14 ter and the safeguards of art. 27. If you also serve visitors from the European Union you can combine it with a GDPR consent manager, but keep a single tool issuing the notice.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20page%20caching%20%28wp%20rocket%2C%20litespeed%2C%20cloudflare%29%3F\"><h3>Does it work with page caching (WP Rocket, LiteSpeed, Cloudflare)?<\/h3><\/dt>\n<dd><p>Yes. Blocking is applied in the served HTML and the decision is resolved in each visitor's browser, so a cached page never exposes trackers to someone who did not consent. Saving settings purges the caches it knows about; if you use another one, purge it when the notice or its version changes.<\/p><\/dd>\n<dt id=\"what%20does%20the%20consent%20log%20store%3F\"><h3>What does the consent log store?<\/h3><\/dt>\n<dd><p>One row per decision: UTC date and time, pseudonym, event (accept all, reject all, customise, withdraw, form), purposes accepted and rejected, notice version, fingerprint of the notice shown, optional IP hash and an integrity HMAC. No name, email or plain IP is stored. It is purged automatically after the retention period you configure, which should match the one declared in your policy.<\/p><\/dd>\n<dt id=\"what%20if%20my%20site%20has%20no%20privacy%20policy%3F\"><h3>What if my site has no privacy policy?<\/h3><\/dt>\n<dd><p>It generates a draft with the twelve contents of art. 14 ter, but review it: the policy is yours and must reflect what you actually do. The checker tells you what is missing.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20a%20visitor%20rejects%3F\"><h3>What happens if a visitor rejects?<\/h3><\/dt>\n<dd><p>Nothing loads beyond what the site needs to work. Embedded content (videos, maps, social) shows a placeholder and only loads if the visitor accepts that purpose, even after rejecting the rest.<\/p><\/dd>\n<dt id=\"how%20do%20i%20ask%20for%20the%20log%20to%20be%20reverted%20or%20deleted%3F\"><h3>How do I ask for the log to be reverted or deleted?<\/h3><\/dt>\n<dd><p>Settings \u2192 Log: you can export everything to CSV or delete the whole log. On uninstall the data is kept by default (it is proof of compliance) unless you explicitly tick \"Delete all plugin data on uninstall\".<\/p><\/dd>\n<dt id=\"can%20it%20be%20used%20on%20multisite%3F\"><h3>Can it be used on multisite?<\/h3><\/dt>\n<dd><p>The plugin works per site. On multisite networks it is activated and configured site by site; there is no shared network setting.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.19<\/h4>\n\n<ul>\n<li><strong>The compliance report no longer contains a hand-written <code>&lt;style&gt;<\/code> tag.<\/strong> Its CSS is declared with <code>wp_add_inline_style()<\/code> on a registered handle and printed by the core with <code>wp_print_styles()<\/code>. The report stays self-contained \u2014it is archived and printed, sometimes offline\u2014 which is why the styles travel inline instead of in an external file.<\/li>\n<li><strong>The public consent endpoint compares the full origin.<\/strong> It now compares scheme, host and port instead of only the host name, so <code>http:\/\/site<\/code>, <code>https:\/\/site<\/code> and <code>https:\/\/site:8443<\/code> are different origins, as the same-origin policy requires.<\/li>\n<\/ul>\n\n<h4>1.0.18<\/h4>\n\n<ul>\n<li>Plugin Check cleanup. Removed an unused helper that read the <code>wp_mail_from<\/code> core filter, and documented why the one-time migration queries build their table names from <code>$wpdb-&gt;prefix<\/code> and literal suffixes. No behaviour changes.<\/li>\n<\/ul>\n\n<h4>1.0.17<\/h4>\n\n<ul>\n<li><strong>The public consent endpoint only accepts same-origin requests.<\/strong> It previously accepted <code>Sec-Fetch-Site: same-site<\/code>, which includes a sibling subdomain and would have let one decide consent on behalf of another's visitor. Now only <code>same-origin<\/code> passes, and without that header the check falls back to the request's origin\/referer host.<\/li>\n<li><strong>The notice's own files are printed with WordPress functions<\/strong> (<code>wp_enqueue_style()<\/code>, <code>wp_enqueue_script()<\/code>, <code>wp_print_styles()<\/code>, <code>wp_print_scripts()<\/code>) instead of hand-written tags, both in the normal path and in the fallback used when a theme prints neither header nor footer.<\/li>\n<li><strong>The diagnostic no longer raises a critical finding in balanced mode.<\/strong> \"Detected third parties are not blocked in the served HTML\" only applies to the strict strategy, which is the one that leaves markers; in balanced mode a site may rely on Google Consent Mode and have no markers by design.<\/li>\n<li><strong>The JavaScript configuration object is now <code>cumpleconsentConfig<\/code><\/strong> instead of the three-letter <code>ccnConfig<\/code>, which could collide with another plugin.<\/li>\n<\/ul>\n\n<h4>1.0.16<\/h4>\n\n<ul>\n<li><strong>Internal names and stored data now use the plugin's own prefix.<\/strong> Constants, options, tables, hooks, cron events, transients and meta keys moved from the short <code>ccn_<\/code> prefix to <code>cumpleconsent_<\/code>, as the directory guidelines require (at least four characters). A one-time migration moves existing options, tables, the log salt, the policy meta key and the scheduled events, so an existing installation keeps its data \u2014 and the previous consent cookie is still read so visitors are not asked again.<\/li>\n<li><strong>Visitor-controlled input is validated before use.<\/strong> The consent cookie and the request body are decoded and then reduced to the expected shape: the anonymous identifier must match its format, purposes are cast to booleans, the notice version is stripped of stray characters, and the context must be one of the known values. Anything else is discarded instead of being stored.<\/li>\n<li><strong>The response text sent by email is sanitized<\/strong>, and the output buffer opened by the script blocker is now explicitly closed on shutdown (only down to its own level, never touching buffers opened by the theme or other plugins).<\/li>\n<li>The readme now clarifies that the bundled list of third-party domains is a <strong>blocking list<\/strong>: the plugin never contacts those services.<\/li>\n<\/ul>\n\n<h4>1.0.15<\/h4>\n\n<ul>\n<li><strong>The policy is found on more sites, and only when it really is a policy.<\/strong> Detection now also looks at the usual alternative addresses (<code>\/privacidad\/<\/code>, <code>\/aviso-de-privacidad\/<\/code>, <code>\/privacy-policy\/<\/code>) and, as a last resort, at published pages with \u00abprivacidad\u00bb in the title (excluding the cookie policy). A page is only adopted if it actually has a policy inside: an empty placeholder page is no longer linked, which used to report 0 of 12 contents.<\/li>\n<li><strong>Policies built with a page builder are now read.<\/strong> Elementor and similar store the content outside <code>post_content<\/code>, so a perfectly good policy scored 0. The text is now read from the builder's own data, and as a last resort from the page as the site renders it.<\/li>\n<li><strong>The notice is delivered even when the theme does not print the footer.<\/strong> Templates such as \"coming soon\" pages or builder canvases skip <code>wp_footer()<\/code>, and the notice never appeared; it is now injected into the served HTML when the normal hooks did not run.<\/li>\n<\/ul>\n\n<h4>1.0.14<\/h4>\n\n<ul>\n<li><strong>A site that already publishes its own privacy policy is no longer reported as having none.<\/strong> The plugin now recognises the policy assigned in its settings, the usual <code>\/politica-de-privacidad\/<\/code> page, or the page WordPress itself marks as the privacy policy, so the admin notice and the policy link work on sites whose policy was written and published by hand.<\/li>\n<li><strong>The art. 14 ter verifier reads the policy, not the page's stylesheet.<\/strong> It discards the contents of embedded <code>&lt;style&gt;<\/code> and <code>&lt;script&gt;<\/code> blocks before checking: pages built as custom HTML (or Elementor fragments) carry their CSS inside the content, and the verifier was scoring a style sheet.<\/li>\n<li><strong>No coverage score is invented when there is no published policy.<\/strong> It used to fall back to scoring the text the plugin generates, showing 100% for a page the site did not have; now it reports that there is nothing to verify.<\/li>\n<\/ul>\n\n<h4>1.0.13<\/h4>\n\n<ul>\n<li><strong>The rights form no longer asks for a postal address or alternative contact.<\/strong> The email the data subject provides is already a means to answer them, which is what art. 11 requires, so the optional field only added friction. Solicitudes received before this version keep their stored value.<\/li>\n<\/ul>\n\n<h4>1.0.12<\/h4>\n\n<ul>\n<li><strong>Name and identity document are now two separate fields in the rights form.<\/strong> They are different pieces of data: the form asks for the full name in one field and the RUT (or other identity document) in another, the document is required to process the request (art. 11: the request must identify who files it), it is stored in its own column, it is covered by the integrity hash of the record, and it appears in the admin view, the CSV export and the internal notice.<\/li>\n<\/ul>\n\n<h4>1.0.11<\/h4>\n\n<ul>\n<li><strong>Emails sent by the plugin now show the site name as the sender<\/strong> instead of \"WordPress\", and carry a Reply-To so the data subject can answer the mailbox that actually handles rights.<\/li>\n<li><strong>The rights channel can no longer fail silently.<\/strong> The internal notice now goes to the rights mailbox (never to an unrelated fallback), its outcome is stored on the request, a failed delivery is flagged in the requests list, and the admin screen says when the channel is not wired to its own mailbox. New <strong>\"send a test email\"<\/strong> button on the requests screen, which reports the server's rejection reason when delivery fails.<\/li>\n<li>The address published for exercising rights is the rights mailbox \u2014 in the form, the generated policy and the processing record \u2014 while the general contact address is listed separately.<\/li>\n<\/ul>\n\n<h4>1.0.10<\/h4>\n\n<ul>\n<li><strong>The privacy policy generator no longer overwrites a policy the plugin didn't write.<\/strong> If the assigned page already has content of its own \u2014 a document the site wrote, reviewed and published \u2014 the generated text now goes to a <strong>separate draft<\/strong> and the admin explains it, instead of replacing the page content. The page is updated in place only when the plugin wrote it (tracked with a post meta and the stored page id).<\/li>\n<li>The admin message tells the three outcomes apart: generated, updated, or kept as a separate draft.<\/li>\n<\/ul>\n\n<h4>1.0.9<\/h4>\n\n<ul>\n<li>Documents the only Plugin Check warning left: the <code>litespeed_purge_all<\/code> hook.\nIts name belongs to LiteSpeed Cache, so it cannot be renamed; the plugin calls it\nwith its exact name and only when LiteSpeed is listening. With that note, Plugin\nCheck reports zero issues for this plugin.<\/li>\n<\/ul>\n\n<h4>1.0.8<\/h4>\n\n<ul>\n<li>Ready for the WordPress directory's Plugin Check: the readme is now in English (as the directory requires), the readme title matches the plugin name, and the <code>Domain Path<\/code> header was removed because no translation file is shipped yet.<\/li>\n<li>Internal namespace and hooks renamed to follow the plugin prefix (<code>CumpleConsent\\...<\/code> classes and <code>cumpleconsent_...<\/code> hook names) so the prefixing checks pass. Nothing changes for visitors, for stored settings or for the database.<\/li>\n<li>Added translator comments to every string with placeholders, ordered the placeholders in two admin messages, unslashed and sanitised one admin input, and documented as false positives the few remaining Plugin Check warnings: the plugin's own escaping helpers (<code>badge()<\/code>), <code>wp_dropdown_pages()<\/code> (it escapes its own output), the table name built from <code>$wpdb-&gt;prefix<\/code>, the public consent endpoint (an anonymous visitor cannot carry a nonce) and the <code>litespeed_purge_all<\/code> hook, which belongs to LiteSpeed Cache.<\/li>\n<\/ul>\n\n<h4>1.0.7<\/h4>\n\n<ul>\n<li><strong>Fixes the site diagnostics appearing not to run.<\/strong> Its result was saved, but the settings sanitizer dropped the internal keys on every save \u2014 the diagnostics itself, the last policy date and the install marks \u2014 so the panel kept saying it had never run. Those keys are now preserved.<\/li>\n<li>The admin now shows the outcome of every action (diagnostics run, log purged, policy generated or published, reply saved, deadline extended). A click used to produce no visible signal even when the action had run.<\/li>\n<li>If the diagnostics cannot read the site's front page, it says so with the technical reason instead of reporting without having looked.<\/li>\n<\/ul>\n\n<h4>1.0.6<\/h4>\n\n<ul>\n<li>Presentation changes for the WordPress directory: the plugin name is now simply \"CumpleConsent\" (the long title moved into the description), \"Tested up to\" is 7.1, the tags are down to five, and the short description fits the 150 characters the directory shows under the name.<\/li>\n<li>States explicitly that the plugin does not connect to any external service (the \"External services\" section), as the review process asks.<\/li>\n<li>No behaviour changes: notice, blocking, policy and rights channel work exactly as in 1.0.5.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li><strong>The notice no longer depends on the site's JavaScript optimisers.<\/strong> Cache plugins (LiteSpeed, Autoptimize, WP Rocket and similar) merge the site's JavaScript into a single bundle loaded after the visitor's first interaction. The notice fell inside that bundle: on a clean visit it never showed, and once merged it could no longer be excluded per file from the cache settings. The notice script is now marked so it is neither combined nor delayed, and the configuration travels as a <strong>data block<\/strong> (<code>type=\"application\/json\"<\/code>), which no optimiser delays because it is not code to execute. Verified in Chrome reading the configuration from that block only.<\/li>\n<li>With this, the notice works on a site with aggressive caching without touching the cache plugin settings.<\/li>\n<li>Eight new tests pinning the behaviour: the script marks, that other plugins' scripts are left alone, and that the data block is valid JSON and cannot close its own tag.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li><strong>The notice and its panel no longer inherit the theme styling.<\/strong> The whole appearance (system typeface, colours, buttons, boxes, floating button) is anchored to the plugin's own containers and shielded, because many themes win the cascade with rules such as <code>.elementor-kit-12 h2<\/code>, <code>.elementor-kit-12 button<\/code> or <code>.elementor-kit-12 label<\/code>. Measured on a real Elementor site: the notice title sat at 1.2:1 contrast (invisible), the four buttons at 2.21:1 with the theme background, the policy link at 1:1, and each purpose label in uppercase and the theme colour. Each one now carries its own styling and a verified contrast (AA 4.5:1 minimum).<\/li>\n<li><strong>The configured accent colour is actually applied.<\/strong> It was saved in the settings and used by nobody: the notice always showed the factory green.<\/li>\n<li>The rights form and embedded content keep their own typeface and buttons, but keep the site's text colour where the author places them, so they do not become unreadable on dark backgrounds.<\/li>\n<li>New tests: anchoring of every selector, shielded identity properties, contrast computed on the real CSS colours, and verification that the configured accent reaches the notice.<\/li>\n<li>New test bench (<code>tests\/navegador\/generar-banco.py<\/code>): downloads the site CSS and measures the notice in Chrome with it, to catch this kind of leak without relying on anyone's eyes.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li><strong>Important fix: a partial write through the REST API no longer switches off the toggles that are not in the request.<\/strong> The admin form submits the full state \u2014 where an unticked checkbox does not travel, so its absence means \"off\" \u2014 but the API may write only what changes. The sanitizer now tells the two cases apart: over the API, what is absent is kept; from the panel, the previous behaviour stands. Without this, configuring the plugin with an application password silently turned off the floating preferences button, the embedded content blocking and the server-side honouring of consent.<\/li>\n<li>Six new tests pinning that panel\/API difference, including that a boolean sent as false over the API is actually applied.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li><strong>Settings can now be read and written over the API<\/strong> (<code>\/wp\/v2\/settings<\/code>), with the same credential any WordPress client uses: an application password. It requires <code>manage_options<\/code>, the same capability the panel already required, and the option stores no credentials. Useful to leave compliance ready on client sites from a script, without asking for panel keys.<\/li>\n<li><strong>Dedicated provisioning and verification routes<\/strong> (<code>cumpleconsent\/v1\/status<\/code>, <code>\/policy<\/code> and <code>\/rights-page<\/code>): site status with the concrete pending items, policy generation, and creation or reuse of the rights channel page, also without entering the admin.<\/li>\n<li><strong>Generating the policy no longer duplicates the page.<\/strong> If none is assigned and the site already has one with the slug <code>politica-de-privacidad<\/code>, that one is updated instead of creating a second (it used to leave a copy with the <code>-2<\/code> suffix).<\/li>\n<li>Cache purging after saving settings now also happens when the change arrives over the API, not only from the admin form.<\/li>\n<li>The option is registered on <code>init<\/code> instead of <code>admin_init<\/code>: REST requests do not go through <code>admin_init<\/code>, so exposing it there would never have appeared in the API.<\/li>\n<li>New tests for the provisioning routes, the required capability, the status and the page reuse.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li><strong>Important fix for the preferences panel.<\/strong> The panel declares <code>position: fixed<\/code>, but only the \"centred\" position had coordinates: with the default position (bottom bar) the panel had none and was drawn off-screen, so pressing \"Configure\" looked as if the notice vanished. The coordinates now sit in the panel base rule and no position can be left unanchored.<\/li>\n<li><strong>Closing without deciding no longer leaves the visitor without a notice.<\/strong> Pressing \"Close\" (or Escape) brings the first-layer notice back while no decision is recorded.<\/li>\n<li><strong>Accepting does not reload the page.<\/strong> Reloading is kept only for withdrawing an already granted purpose, the one case where it is needed (third-party scripts already loaded cannot be unloaded any other way).<\/li>\n<li>Added 12 CSS geometry tests and a real-browser test (Chrome over CDP) walking the whole cycle: no decision \u2192 configure \u2192 close \u2192 accept \u2192 withdraw.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First public version.<\/li>\n<li>Notice without dark patterns, with per-purpose choice and permanent withdrawal (art. 12).<\/li>\n<li>Pre-consent blocking in four layers, compatible with full-page caching and with <code>wp_consent_api<\/code>; embedded content under consent (art. 14 qu\u00e1ter).<\/li>\n<li>Google Consent Mode v2 with a strict or balanced strategy.<\/li>\n<li>Auditable log with the notice fingerprint, optional IP hash, integrity HMAC, CSV export and scheduled purge (art. 12 and art. 14 ter i).<\/li>\n<li>Privacy policy generator and checker against the twelve contents of art. 14 ter.<\/li>\n<li>Rights form with legal deadlines, acknowledgement, full reply kept as evidence and alerts (art. 11).<\/li>\n<li>International transfer register with its safeguard (art. 14 ter h and art. 27).<\/li>\n<li>Record of processing activities, risk matrix and protocols with a printable dossier (art. 3 of regulation D.S. 662).<\/li>\n<li>Site diagnostics: third parties detected, effective blocking, conflicts with other consent managers, policy coverage.<\/li>\n<li>Consent in forms with integration for Contact Form 7, WPForms and Gravity Forms.<\/li>\n<li>Pseudonyms, minimisation and no telemetry: nothing leaves your installation.<\/li>\n<\/ul>","raw_excerpt":"Cookie consent and compliance with Chile's Law 21.719: a plain notice, blocking before consent, and a rights channel with legal deadlines.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/388103","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=388103"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/menteglobal"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=388103"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=388103"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=388103"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=388103"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=388103"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=388103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}