{"id":312715,"date":"2026-05-15T09:28:50","date_gmt":"2026-05-15T09:28:50","guid":{"rendered":"https:\/\/es.wordpress.org\/plugins\/eu-withdrawal-compliance\/"},"modified":"2026-05-18T12:04:18","modified_gmt":"2026-05-18T12:04:18","slug":"eu-withdrawal-compliance","status":"publish","type":"plugin","link":"https:\/\/test.wordpress.org\/plugins\/eu-withdrawal-compliance\/","author":1320655,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.6.1","stable_tag":"1.6.1","tested":"7.0","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"EU Withdrawal Compliance","header_author":"Fernando Tellado","header_description":"Adds the EU online withdrawal function required by Directive (EU) 2023\/2673 from June 19, 2026. Includes a shortcode, a Gutenberg-friendly form, a WooCommerce \"My account\" endpoint and a full admin log.","assets_banners_color":"05339b","last_updated":"2026-05-18 12:04:18","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/servicios.ayudawp.com","header_author_uri":"https:\/\/tellado.es","rating":0,"author_block_rating":0,"active_installs":0,"downloads":290,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.4.0":{"tag":"1.4.0","author":"fernandot","date":"2026-05-15 17:32:54"},"1.4.1":{"tag":"1.4.1","author":"fernandot","date":"2026-05-16 07:55:07"},"1.5.0":{"tag":"1.5.0","author":"fernandot","date":"2026-05-16 23:53:15"},"1.6.0":{"tag":"1.6.0","author":"fernandot","date":"2026-05-18 08:37:36"},"1.6.1":{"tag":"1.6.1","author":"fernandot","date":"2026-05-18 12:04:18"}},"upgrade_notice":{"1.6.1":"<p>Sample &quot;Right of withdrawal&quot; page now ships with per-exception sections (only for fresh activations \u2014 existing pages preserved). Excluded-product notice default mentions dated accommodation and rentals. Form no longer auto-centres.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.jpg":{"filename":"icon-128x128.jpg","revision":3535925,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.jpg":{"filename":"icon-256x256.jpg","revision":3535925,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500-es.jpg":{"filename":"banner-1544x500-es.jpg","revision":3535925,"resolution":"1544x500","location":"assets","locale":"es","width":1544,"height":500},"banner-1544x500.jpg":{"filename":"banner-1544x500.jpg","revision":3535925,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250-es.jpg":{"filename":"banner-772x250-es.jpg","revision":3535925,"resolution":"772x250","location":"assets","locale":"es","width":772,"height":250},"banner-772x250.jpg":{"filename":"banner-772x250.jpg","revision":3535925,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3535992,"resolution":false,"location":"assets","locale":"","contents":"{\"landingPage\":\"\\\/wp-admin\\\/plugins.php\",\"preferredVersions\":{\"php\":\"latest\",\"wp\":\"latest\"},\"steps\":[{\"step\":\"login\",\"username\":\"admin\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"woocommerce\"},\"options\":{\"activate\":false}},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"eu-withdrawal-compliance\"},\"options\":{\"activate\":true}}]}"}},"all_blocks":[],"tagged_versions":["1.4.0","1.4.1","1.5.0","1.6.0","1.6.1"],"block_files":[],"assets_screenshots":{"screenshot-1-es.jpg":{"filename":"screenshot-1-es.jpg","revision":3534419,"resolution":"1","location":"assets","locale":"es","width":1920,"height":1387},"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":3534419,"resolution":"1","location":"assets","locale":"","width":1920,"height":1387},"screenshot-10-es.jpg":{"filename":"screenshot-10-es.jpg","revision":3534419,"resolution":"10","location":"assets","locale":"es","width":1920,"height":1337},"screenshot-10.jpg":{"filename":"screenshot-10.jpg","revision":3534419,"resolution":"10","location":"assets","locale":"","width":1920,"height":1316},"screenshot-11-es.jpg":{"filename":"screenshot-11-es.jpg","revision":3534419,"resolution":"11","location":"assets","locale":"es","width":1920,"height":1359},"screenshot-11.jpg":{"filename":"screenshot-11.jpg","revision":3534419,"resolution":"11","location":"assets","locale":"","width":1920,"height":1349},"screenshot-12-es.jpg":{"filename":"screenshot-12-es.jpg","revision":3534419,"resolution":"12","location":"assets","locale":"es","width":1920,"height":2572},"screenshot-12.jpg":{"filename":"screenshot-12.jpg","revision":3534419,"resolution":"12","location":"assets","locale":"","width":1920,"height":2572},"screenshot-2-es.jpg":{"filename":"screenshot-2-es.jpg","revision":3534419,"resolution":"2","location":"assets","locale":"es","width":1920,"height":971},"screenshot-2.jpg":{"filename":"screenshot-2.jpg","revision":3534419,"resolution":"2","location":"assets","locale":"","width":1920,"height":962},"screenshot-3-es.jpg":{"filename":"screenshot-3-es.jpg","revision":3534419,"resolution":"3","location":"assets","locale":"es","width":1920,"height":971},"screenshot-3.jpg":{"filename":"screenshot-3.jpg","revision":3534419,"resolution":"3","location":"assets","locale":"","width":1920,"height":971},"screenshot-4-es.jpg":{"filename":"screenshot-4-es.jpg","revision":3534419,"resolution":"4","location":"assets","locale":"es","width":1920,"height":1136},"screenshot-4.jpg":{"filename":"screenshot-4.jpg","revision":3534419,"resolution":"4","location":"assets","locale":"","width":1920,"height":1129},"screenshot-5-es.jpg":{"filename":"screenshot-5-es.jpg","revision":3534419,"resolution":"5","location":"assets","locale":"es","width":1920,"height":3584},"screenshot-5.jpg":{"filename":"screenshot-5.jpg","revision":3534419,"resolution":"5","location":"assets","locale":"","width":1920,"height":3464},"screenshot-6-es.jpg":{"filename":"screenshot-6-es.jpg","revision":3534419,"resolution":"6","location":"assets","locale":"es","width":1920,"height":2643},"screenshot-6.jpg":{"filename":"screenshot-6.jpg","revision":3534419,"resolution":"6","location":"assets","locale":"","width":1920,"height":2545},"screenshot-7-es.jpg":{"filename":"screenshot-7-es.jpg","revision":3534419,"resolution":"7","location":"assets","locale":"es","width":1920,"height":1070},"screenshot-7.jpg":{"filename":"screenshot-7.jpg","revision":3534419,"resolution":"7","location":"assets","locale":"","width":1920,"height":1019},"screenshot-8-es.jpg":{"filename":"screenshot-8-es.jpg","revision":3534419,"resolution":"8","location":"assets","locale":"es","width":1920,"height":1227},"screenshot-8.jpg":{"filename":"screenshot-8.jpg","revision":3534419,"resolution":"8","location":"assets","locale":"","width":1920,"height":1227},"screenshot-9-es.jpg":{"filename":"screenshot-9-es.jpg","revision":3534419,"resolution":"9","location":"assets","locale":"es","width":1920,"height":1170},"screenshot-9.jpg":{"filename":"screenshot-9.jpg","revision":3534419,"resolution":"9","location":"assets","locale":"","width":1920,"height":1214}},"screenshots":{"1":"Public withdrawal form with all required fields.","2":"Withdrawal log inside the WordPress admin.","3":"Per-request detail screen with status management, including the captured checkout consents (text, accepted\/declined, timestamp, IP, user agent).","4":"WooCommerce My Account integration with per-order Withdraw button.","5":"EU Withdrawal Settings Page (WooCommerce active), with the Checkout consent, Annex I.B model and Excluded products notice sections.","6":"EU Withdrawal Settings Page (Standalone).","7":"Per-product \"Withdrawal status\" dropdown in the WooCommerce product editor (General tab), with the inheritance notice when the value is pulled from the product's category.","8":"Per-category \"Withdrawal status\" dropdown in Products \u2192 Categories edit screen.","9":"Excluded products notice rendered on the public single product page (between price and add-to-cart button).","10":"Mandatory digital-content consent (Art. 16(m)) shown at the WooCommerce checkout.","11":"Optional service-start consent (Art. 14(4)(a)) shown at the WooCommerce checkout.","12":"Annex I.B model withdrawal form rendered as a collapsible block below the public withdrawal form, with a printable view link."},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[14361,255182,131785,245590,286],"plugin_category":[45],"plugin_contributors":[245779,133550],"plugin_business_model":[],"class_list":["post-312715","plugin","type-plugin","status-publish","hentry","plugin_tags-compliance","plugin_tags-consumer-rights","plugin_tags-gdpr","plugin_tags-withdrawal","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-ayudawp","plugin_contributors-fernandot","plugin_committers-ayudawp","plugin_committers-fernandot","plugin_support_reps-ayudawp"],"banners":{"banner":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/banner-772x250.jpg?rev=3535925","banner_2x":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/banner-1544x500.jpg?rev=3535925","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/icon-128x128.jpg?rev=3535925","icon_2x":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/icon-256x256.jpg?rev=3535925","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-1.jpg?rev=3534419","caption":"Public withdrawal form with all required fields."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-2.jpg?rev=3534419","caption":"Withdrawal log inside the WordPress admin."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-3.jpg?rev=3534419","caption":"Per-request detail screen with status management, including the captured checkout consents (text, accepted\/declined, timestamp, IP, user agent)."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-4.jpg?rev=3534419","caption":"WooCommerce My Account integration with per-order Withdraw button."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-5.jpg?rev=3534419","caption":"EU Withdrawal Settings Page (WooCommerce active), with the Checkout consent, Annex I.B model and Excluded products notice sections."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-6.jpg?rev=3534419","caption":"EU Withdrawal Settings Page (Standalone)."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-7.jpg?rev=3534419","caption":"Per-product \"Withdrawal status\" dropdown in the WooCommerce product editor (General tab), with the inheritance notice when the value is pulled from the product's category."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-8.jpg?rev=3534419","caption":"Per-category \"Withdrawal status\" dropdown in Products \u2192 Categories edit screen."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-9.jpg?rev=3534419","caption":"Excluded products notice rendered on the public single product page (between price and add-to-cart button)."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-10.jpg?rev=3534419","caption":"Mandatory digital-content consent (Art. 16(m)) shown at the WooCommerce checkout."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-11.jpg?rev=3534419","caption":"Optional service-start consent (Art. 14(4)(a)) shown at the WooCommerce checkout."},{"src":"https:\/\/ps.w.org\/eu-withdrawal-compliance\/assets\/screenshot-12.jpg?rev=3534419","caption":"Annex I.B model withdrawal form rendered as a collapsible block below the public withdrawal form, with a printable view link."}],"raw_content":"<!--section=description-->\n<p>From <strong>June 19, 2026<\/strong>, EU Directive 2023\/2673 obliges every online retailer in the European Union to offer a digital withdrawal function that is at least as easy to use as the purchase flow itself. Most plugins in the directory stop at \"a button\". This one ships the <strong>complete toolkit<\/strong> every EU store needs to comply \u2014 and a few things competitors don't offer at any price.<\/p>\n\n<h4>Only this plugin in the directory ships, all of it, for free<\/h4>\n\n<ul>\n<li><strong>Verifiable SHA-256 receipt hash<\/strong> sent to the customer in the confirmation email as tamper-evident durable-medium proof of the request \u2014 recomputable from the stored fields if a dispute arises.<\/li>\n<li><strong>Annex I.B model withdrawal form<\/strong> (Directive 2011\/83\/EU) generated dynamically from your shop data, rendered as a collapsible block below the public form, with a printable view on the same URL. Meets the pre-contractual information obligation of Art. 6(1)(h).<\/li>\n<li><strong>Double-consent checkboxes at the WooCommerce checkout<\/strong> for the two consents the directive expects to apply specific exceptions:\n\n<ul>\n<li>Mandatory consent for digital content (Art. 16(m)) \u2014 blocks the place-order step until accepted.<\/li>\n<li>Optional consent for services started within the 14-day window (Art. 14(4)(a)) \u2014 enables pro-rated billing if the customer later withdraws.\nEvery consent is persisted on the order with the exact text shown, accepted\/declined state, timestamp, IP and user agent \u2014 durable proof in case of dispute.<\/li>\n<\/ul><\/li>\n<li><strong>Single \"Withdrawal status\" dropdown per product and per category<\/strong> with four explicit options (Standard, Digital content, Service started early, Other Article 16 exception). Drives both the Article 16 exclusion flag and the matching checkout consent in one place, with full subcategory inheritance.<\/li>\n<li><strong>Configurable public notice on excluded products<\/strong>, rendered between price and add-to-cart, with separate title+body for digital content and other Article 16 exceptions.<\/li>\n<li><strong>Article 16 exclusions with category inheritance<\/strong> \u2014 competing plugins gate this behind a paid Pro tier; here it's free.<\/li>\n<li><strong>Native GDPR integration<\/strong>: suggested Privacy Policy snippet + personal-data exporter + eraser, all keyed on the customer email \u2014 no second GDPR plugin to install.<\/li>\n<li><strong>Standalone mode<\/strong>: the form, shortcode, request log, email notifications, SHA-256 receipt hash, Annex I.B model and GDPR integration all run <strong>without WooCommerce<\/strong>. The plugin always lives in its own top-level <strong>Withdrawals<\/strong> menu (with a <strong>Settings<\/strong> submenu), with or without WooCommerce \u2014 same path on every install.<\/li>\n<\/ul>\n\n<h4>Public-facing pieces<\/h4>\n\n<ul>\n<li>Public withdrawal page automatically created on activation with a neutral, translation-ready template and the form embedded via shortcode (with a \"review with a legal advisor\" disclaimer).<\/li>\n<li><code>[ayudawp_withdrawal_form]<\/code> shortcode for embedding the form anywhere on the site.<\/li>\n<li><code>[ayudawp_withdrawal_link]<\/code> shortcode for a permanent link to the withdrawal page from any widget area, footer or template part \u2014 helps meet the \"clearly identifiable\" requirement of Article 11a of Directive 2023\/2673 without forcing a specific footer layout.<\/li>\n<li>HTML5-semantic form with HTML5 validation, honeypot anti-spam, escaped output, sanitized input and CSRF nonces.<\/li>\n<li>Privacy-policy acceptance checkbox before submit, linked to the WordPress-configured Privacy Policy page.<\/li>\n<li>Frontend and backend links generated by the plugin carry <code>rel=\"noopener nofollow\"<\/code> to keep the site's link equity contained.<\/li>\n<\/ul>\n\n<h4>WooCommerce-specific pieces (auto-activated when WooCommerce is detected)<\/h4>\n\n<ul>\n<li><strong>My Account \u2192 Right of withdrawal<\/strong> endpoint with a per-order \"Withdraw\" button shown only while the configured deadline window is open, deep-linked to the form with the order pre-filled.<\/li>\n<li><strong>Withdrawal notice injected into transactional emails<\/strong> (processing, completed, customer invoice) with a direct link to the form pre-filled with the order number. Eligible order statuses configurable; admin emails never receive the notice.<\/li>\n<li><strong>Automatic verification of the order\/email pair<\/strong> when WooCommerce is active, including the 14-day deadline check.<\/li>\n<li><strong>Configurable deadline calculation<\/strong>: choose order date vs. WooCommerce completion date as the start, plus optional grace days \u2014 all from the settings UI, no code.<\/li>\n<li><strong>Order-number compatibility<\/strong> with Sequential Order Numbers (free and Pro), Custom Order Numbers for WooCommerce (WPFactory) and YITH numbering schemes out of the box; a filter covers any other resolver.<\/li>\n<li><strong>\"Withdrawal\" column<\/strong> on the WooCommerce orders screen (legacy and HPOS) showing the status of any linked request, toggleable from Screen Options.<\/li>\n<li><strong>Private order notes<\/strong> added at every lifecycle step (request received, accepted, rejected, completed) including any admin comment.<\/li>\n<li><strong>HPOS-compatible<\/strong> from day one, declared via <code>FeaturesUtil::declare_compatibility()<\/code>.<\/li>\n<\/ul>\n\n<h4>Admin tooling<\/h4>\n\n<ul>\n<li><strong>Full request log<\/strong> as a private custom post type with status lifecycle (pending \u2192 accepted \u2192 rejected \u2192 completed), customer details, scope (full \/ partial), IP, user agent and UTC submission timestamp for legal traceability.<\/li>\n<li><strong>Bulk actions<\/strong> to mark several requests as accepted, rejected or completed at once, with email notification on transition.<\/li>\n<li><strong>Status metabox<\/strong> with required comment when rejecting, optional comment when completing \u2014 comment forwarded to the customer email.<\/li>\n<li><strong>Confirmation email to the customer<\/strong> on submission (with the SHA-256 hash as proof) and a follow-up email on every status transition.<\/li>\n<li><strong>Notification email to the shop admin<\/strong> with reply-to set to the customer, sanitized against header injection.<\/li>\n<li><strong>Captured checkout consents<\/strong> surfaced in the request detail metabox: exact text, accepted\/declined state, timestamp, IP, user agent \u2014 durable proof on file.<\/li>\n<li><strong>Consistent admin menu<\/strong>: always a top-level <strong>Withdrawals<\/strong> menu with a <strong>Settings<\/strong> submenu, regardless of whether WooCommerce is active. Same path on every install.<\/li>\n<li><strong>Legal disclaimer block<\/strong> in the settings page making it explicit that the plugin provides optional technical tools and does not guarantee legal compliance.<\/li>\n<li><strong>Mandatory \/ Recommended \/ Optional tags<\/strong> on every setting description so the merchant can scan the form quickly.<\/li>\n<\/ul>\n\n<h4>Built for production<\/h4>\n\n<ul>\n<li>Conditional asset loading: CSS only loads on the withdrawal page, single-product pages that actually show the excluded notice, and plugin admin screens.<\/li>\n<li>Translation-ready, bundled es_ES translation, follows WordPress Coding Standards, fully escaped output and sanitized input, capability checks and nonces on every admin action.<\/li>\n<li><strong>6 documented filters and 2 actions<\/strong> for developers and agencies to extend the plugin without forking.<\/li>\n<li>PHP 7.4+, WordPress 6.0+, WooCommerce 7.0+ (optional).<\/li>\n<\/ul>\n\n<h3>Why this plugin?<\/h3>\n\n<p>The EU directive becomes enforceable in every member state on June 19, 2026, so the WordPress.org directory is filling up with \"withdrawal button\" plugins. This one stands out for verifiable reasons:<\/p>\n\n<ul>\n<li><strong>Fully free, no paid tier.<\/strong> No premium add-on, no feature locked behind an upsell, no \"Pro\" version on the horizon. Everything documented on this page is what you get on install.<\/li>\n<li><strong>The only plugin in the directory<\/strong> that issues a SHA-256 receipt hash as durable-medium proof of every withdrawal request, recoverable from the stored fields if a dispute later arises.<\/li>\n<li><strong>The only plugin in the directory<\/strong> that ships the <strong>Annex I.B model withdrawal form<\/strong> dynamically generated from the shop data, with a printable view \u2014 meeting the Art. 6(1)(h) information obligation that the new directive does <em>not<\/em> replace.<\/li>\n<li><strong>The only plugin in the directory<\/strong> that injects the <strong>two consent checkboxes<\/strong> (Art. 16(m) digital content and Art. 14(4)(a) service started early) at the WooCommerce checkout, with durable proof persisted on the order.<\/li>\n<li><strong>The only plugin in the directory<\/strong> that ships <strong>Article 16 product\/category exclusions with full subcategory inheritance<\/strong> \u2014 competing plugins gate this behind their own paid Pro tier.<\/li>\n<li><strong>The only plugin in the directory<\/strong> that integrates natively with the WordPress GDPR tools (Privacy Policy snippet + personal-data exporter and eraser) \u2014 no second GDPR plugin to install.<\/li>\n<li><strong>Standalone or with WooCommerce.<\/strong> Works without WooCommerce as a self-contained tool (form, shortcode, log, emails, SHA-256, GDPR, Annex I.B) and lights up store-specific features automatically when WooCommerce is detected.<\/li>\n<li><strong>Compatible by default<\/strong> with Sequential Order Numbers (free and Pro), Custom Order Numbers for WooCommerce (WPFactory) and YITH numbering schemes.<\/li>\n<li><strong>Configurable from the settings UI<\/strong>, without writing code: deadline basis (order date vs. completion date), grace days, eligible order statuses, withdrawal page, notification email, consent text per type, excluded-notice text per type, Annex I.B trader phone.<\/li>\n<li><strong>Developer-friendly<\/strong>: 6 documented filters + 2 actions so agencies can extend it without forking.<\/li>\n<li><strong>Maintained by a Spanish WordPress trainer with 15+ years on the platform<\/strong>: bundled es_ES translation, prompt replies on the WordPress.org support forum and an active roadmap of free improvements (CSV export, classic widget, Gutenberg block, dashboard widget, custom WC order status and more \u2014 all free).<\/li>\n<\/ul>\n\n<h3>Roadmap<\/h3>\n\n<p>Planned for upcoming free versions:<\/p>\n\n<ul>\n<li><strong>CSV export of withdrawal requests for audit and accounting<\/strong> (top priority for v1.6.0).<\/li>\n<li><strong>WooCommerce Checkout block support<\/strong> for the Art. 16(m) and Art. 14(4)(a) consent checkboxes, using <code>woocommerce_register_additional_checkout_field()<\/code> so the consents work on stores that have already migrated from the classic <code>[woocommerce_checkout]<\/code> shortcode to the block.<\/li>\n<li>Classic widget to surface the withdrawal link in themes with widget areas.<\/li>\n<li>Gutenberg block for the withdrawal link, fully supported in block themes (align, color, typography).<\/li>\n<li>Dashboard widget with counters, pending requests and monthly basic stats.<\/li>\n<li>Custom WooCommerce order status \"Withdrawal requested\" with automatic transition on acceptance.<\/li>\n<li>Urgency indicators in the request list (days remaining, expired).<\/li>\n<li>PDF download of the request with the SHA-256 receipt hash printed on it, reusing the same standalone-print infrastructure as the Annex I.B view.<\/li>\n<li>Signed token in the email link so guest customers can check status without logging in.<\/li>\n<li>Rate limiting on the public form to prevent abuse.<\/li>\n<li>Optional IBAN field to speed up manual refunds.<\/li>\n<li>HTML email templates that inherit the WooCommerce email theme.<\/li>\n<li>Optional modal display mode for the shortcode.<\/li>\n<li>Visible audit log on each request detail screen (status transitions, admin comments, email-delivery timestamps).<\/li>\n<li>Optional opt-in auto-injection of the withdrawal link in <code>wp_footer<\/code>.<\/li>\n<li>Two-step confirmation flow (Germany-style intermediate review page) once the Spanish transposition of Directive 2023\/2673 publishes its sanctioning regime.<\/li>\n<\/ul>\n\n<h3>Privacy<\/h3>\n\n<p>This plugin stores the following personal data for each withdrawal request, exclusively to fulfil the legal traceability of consumer rights and to allow the shop to handle the request:<\/p>\n\n<ul>\n<li>Customer name and email address (required to contact the consumer about the request).<\/li>\n<li>Order reference and order date (required to validate the request against the purchase).<\/li>\n<li>IP address and User-Agent string (required to evidence when and how the request was submitted, in line with the directive's \"durable medium\" requirement).<\/li>\n<li>Submission timestamp (UTC) and SHA-256 receipt hash (required to recompute and verify the integrity of the original submission if disputed).<\/li>\n<\/ul>\n\n<p>Data is stored as a private custom post type entry (<code>ayudawp_withdrawal<\/code>) accessible only to administrators. The plugin does not transmit any data to third-party services; all communication happens between the shop and the customer via standard WordPress emails.<\/p>\n\n<p>You should add a section to your site's privacy policy describing this storage. The plugin contributes a suggested Privacy Policy snippet that you can paste from <strong>Settings \u2192 Privacy \u2192 Policy Guide<\/strong>. Withdrawal data is also exposed to the native WordPress <strong>Tools \u2192 Export Personal Data<\/strong> and <strong>Tools \u2192 Erase Personal Data<\/strong> screens (filtered by customer email).<\/p>\n\n<h3>Support<\/h3>\n\n<p>Need help or have suggestions?<\/p>\n\n<ul>\n<li><a href=\"https:\/\/servicios.ayudawp.com\">Official website<\/a><\/li>\n<li><a href=\"https:\/\/wordpress.org\/support\/plugin\/eu-withdrawal-compliance\/\">WordPress support forum<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/AyudaWordPressES\">YouTube channel<\/a><\/li>\n<li><a href=\"https:\/\/ayudawp.com\">Documentation and tutorials<\/a><\/li>\n<\/ul>\n\n<p>Love the plugin? Please leave us a 5-star review and help spread the word!<\/p>\n\n<h3>About AyudaWP.com<\/h3>\n\n<p>We are specialists in WordPress security, SEO, AI and performance optimization plugins. We create tools that solve real problems for WordPress site owners while maintaining the highest coding standards and accessibility requirements.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin from the <strong>Plugins<\/strong> screen.<\/li>\n<li>The plugin creates a \"Right of withdrawal\" page automatically with a sample legal template. Review and edit it from <strong>Pages<\/strong>.<\/li>\n<li>Go to <strong>Withdrawals \u2192 Settings<\/strong> to configure the notification email address and the page that hosts the form.<\/li>\n<li>Add the URL of the withdrawal page to your footer or to the legal links section so it is visible from any page on your site.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"will%20the%20form%20check%20the%2014-day%20deadline%3F\"><h3>Will the form check the 14-day deadline?<\/h3><\/dt>\n<dd><p>Yes, when WooCommerce is active. If the order is older than the configured window the plugin rejects the request with a clear message. You can configure the calculation basis (order date vs. completion date) and add extra grace days directly from <strong>Withdrawals \u2192 Settings<\/strong>. The legacy <code>ayudawp_euw_grace_days<\/code> and <code>ayudawp_euw_skip_deadline_check<\/code> filters still work for programmatic overrides.<\/p><\/dd>\n<dt id=\"how%20do%20i%20mark%20products%20that%20are%20excluded%20from%20the%20right%20of%20withdrawal%20%28article%2016%29%3F\"><h3>How do I mark products that are excluded from the right of withdrawal (Article 16)?<\/h3><\/dt>\n<dd><p>The plugin uses a single <strong>Withdrawal status<\/strong> dropdown set per category and per product.<\/p>\n\n<ol>\n<li><strong>By category<\/strong>: go to <strong>Products \u2192 Categories<\/strong>, edit the category and pick a \"Withdrawal status\" \u2014 for example <em>Other Article 16 exception<\/em> for perishable or custom-made goods, or <em>Digital content (Art. 16(m))<\/em> for sealed digital content. Every product in that category (and its descendant categories) will inherit the status automatically.<\/li>\n<li><strong>By product<\/strong>: edit the product, scroll to the General tab and pick the \"Withdrawal status\" there. By default it is set to <em>\u2014 Inherit from category<\/em>; pick any other option (including <em>Standard<\/em>) to override the inheritance for that product only.<\/li>\n<\/ol>\n\n<p>The four possible statuses are:<\/p>\n\n<ul>\n<li><strong>Standard<\/strong> \u2014 withdrawal applies normally (default).<\/li>\n<li><strong>Digital content (Art. 16(m))<\/strong> \u2014 product is excluded from the withdrawal right, and a mandatory consent checkbox is shown at the WooCommerce checkout for any cart containing the product.<\/li>\n<li><strong>Service started early (Art. 14(4)(a))<\/strong> \u2014 withdrawal still applies, and an optional consent checkbox is shown at checkout so the trader can charge a pro-rated amount if the customer withdraws after the service has started.<\/li>\n<li><strong>Other Article 16 exception<\/strong> \u2014 product is excluded (perishable, custom-made, hygiene-sealed, etc.), no checkout consent needed.<\/li>\n<\/ul>\n\n<p>When a withdrawal request lands on an order containing excluded items, the plugin flags it in the admin notification email and on the request detail screen. The request is <strong>never auto-rejected<\/strong>, because a partial withdrawal over the non-excluded items in the same order can still be valid. The admin reviews and decides.<\/p>\n\n<p>If the <strong>Excluded products notice<\/strong> is enabled (default: yes), a configurable notice will also appear on the single product page between price and add-to-cart button so the consumer reads it before purchasing.<\/p>\n\n<p><strong>Upgrading from earlier versions:<\/strong> any category that was previously listed in the retired \"Excluded categories\" picker is migrated automatically to the new per-category dropdown (with status <em>Other Article 16 exception<\/em>) on the next admin request. No configuration is lost.<\/p><\/dd>\n<dt id=\"how%20do%20the%20checkout%20consent%20checkboxes%20work%20%28art.%2016%28m%29%20and%20art.%2014%284%29%28a%29%29%3F\"><h3>How do the checkout consent checkboxes work (Art. 16(m) and Art. 14(4)(a))?<\/h3><\/dt>\n<dd><p>From version 1.5.0 the plugin can inject two consent checkboxes at the WooCommerce checkout when the cart contains products flagged for them:<\/p>\n\n<ul>\n<li><strong>Type A (mandatory, Art. 16(m))<\/strong>: digital content. The customer must accept it to complete the order; without acceptance recorded, the customer keeps the 14-day withdrawal right even after accessing the content.<\/li>\n<li><strong>Type B (optional, Art. 14(4)(a))<\/strong>: services started within the 14-day window. If accepted, the trader may charge a pro-rated amount when the customer withdraws after the service has started. Without it, an early withdrawal forces a full refund.<\/li>\n<\/ul>\n\n<p>Each flag is set per product (General tab) or per category (Edit Category screen), with full subcategory inheritance \u2014 the same hierarchy used by the Article 16 exclusions module. The exact text shown to the customer, plus accepted\/declined state, timestamp, IP and user agent, is persisted on the order so the trader has durable proof if the customer later contests the request. The metabox of each withdrawal request also surfaces these consents for the linked order.<\/p>\n\n<p>The two checkboxes can be enabled\/disabled globally from <strong>Withdrawals \u2192 Settings \u2192 Checkout consent<\/strong>, and their text is fully editable.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20include%20the%20annex%20i.b%20model%20withdrawal%20form%20required%20by%20directive%202011%2F83%2Feu%3F\"><h3>Does the plugin include the Annex I.B model withdrawal form required by Directive 2011\/83\/EU?<\/h3><\/dt>\n<dd><p>Yes, from version 1.5.0. The plugin renders the Annex I.B model form dynamically from the shop name, address (from WooCommerce when available) and notification email, with an optional trader phone configurable from settings. It appears as a collapsible block right below the public withdrawal form, with a printable view available from the same page. Providing this model is a pre-contractual information obligation under Art. 6(1)(h) of Directive 2011\/83\/EU \u2014 the online function added by Directive 2023\/2673 complements but does not replace it.<\/p><\/dd>\n<dt id=\"what%20is%20the%20receipt%20verification%20code%20in%20the%20customer%20email%3F\"><h3>What is the receipt verification code in the customer email?<\/h3><\/dt>\n<dd><p>It is a SHA-256 hash computed from the request data (post ID, customer name, email, order reference, scope, order date and submission timestamp). The customer keeps the email as a tamper-evident proof on a durable medium. If a dispute later arises, you can recompute the hash from the stored fields with the <code>ayudawp_euw_compute_receipt_hash()<\/code> helper and confirm the original submission was not altered.<\/p><\/dd>\n<dt id=\"where%20are%20withdrawal%20requests%20stored%3F\"><h3>Where are withdrawal requests stored?<\/h3><\/dt>\n<dd><p>Each request is saved as a private custom post type entry called <code>ayudawp_withdrawal<\/code>. You can manage them under the top-level <strong>Withdrawals<\/strong> menu in your admin area. They are not publicly accessible from the frontend.<\/p><\/dd>\n<dt id=\"does%20it%20support%20hpos%20%28high-performance%20order%20storage%29%3F\"><h3>Does it support HPOS (High-Performance Order Storage)?<\/h3><\/dt>\n<dd><p>Yes. The plugin declares HPOS compatibility on load.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20work%20without%20woocommerce%3F\"><h3>Does the plugin work without WooCommerce?<\/h3><\/dt>\n<dd><p>Yes. The form, shortcode, withdrawal request log, email notifications, SHA-256 receipt hash and native GDPR integration all run as a standalone tool, with their own top-level <strong>Withdrawals<\/strong> menu in the admin and a <strong>Settings<\/strong> submenu. The plugin layers extra features on top automatically when WooCommerce is active: order\/email validation with the 14-day deadline, \"My Account\" withdrawal endpoint, withdrawal notice injected into transactional emails, \"Withdrawal\" column in the orders screen, private order notes on every status change, and Article 16 exclusions by product\/category. Activating WooCommerce later lights those features up; deactivating it leaves the standalone features intact.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20plugins%20that%20change%20the%20woocommerce%20order%20number%20%28sequential%20order%20numbers%2C%20custom%20order%20numbers%2C%20etc.%29%3F\"><h3>Does it work with plugins that change the WooCommerce order number (Sequential Order Numbers, Custom Order Numbers, etc.)?<\/h3><\/dt>\n<dd><p>Yes. The form accepts both the internal WooCommerce order ID and the displayed order number. The resolver looks up the customer-facing number in the standard <code>_order_number<\/code> post meta, which covers WooCommerce Sequential Order Numbers (free and Pro), Custom Order Numbers for WooCommerce (WPFactory) and any plugin that follows the same convention. For plugins that store the number elsewhere or compute it on the fly (e.g. YITH Sequential Order Number, custom integrations), use the <code>ayudawp_euw_pre_resolve_wc_order<\/code> filter to provide your own resolver.<\/p><\/dd>\n<dt id=\"will%20the%20notice%20appear%20on%20every%20woocommerce%20email%3F\"><h3>Will the notice appear on every WooCommerce email?<\/h3><\/dt>\n<dd><p>No. By default the notice is only added to the customer-facing emails relevant to the withdrawal window: order processing, completed and customer invoice (the manually triggered one). Admin emails never receive the notice. The notice is also gated by the configured list of eligible order statuses (default: Processing and Completed) so the manual invoice email only carries it when the order is in one of those statuses. You can change the email list with the <code>ayudawp_euw_email_ids<\/code> filter and the status list under <strong>Withdrawals \u2192 Settings \u2192 Eligible order statuses<\/strong> or with the <code>ayudawp_euw_allowed_statuses<\/code> filter.<\/p><\/dd>\n<dt id=\"in%20which%20languages%20is%20the%20plugin%20available%3F\"><h3>In which languages is the plugin available?<\/h3><\/dt>\n<dd><p>All strings are translation-ready. Translations are managed through the official WordPress.org platform at <a href=\"https:\/\/translate.wordpress.org\/projects\/wp-plugins\/eu-withdrawal-compliance\/\">translate.wordpress.org<\/a>, so any locale with enough translated strings is delivered automatically to your site when the WordPress site language matches. Contributions to existing or new locales are welcome there.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20pass%20gdpr%20requirements%3F\"><h3>Does the plugin pass GDPR requirements?<\/h3><\/dt>\n<dd><p>The plugin asks for explicit privacy policy acceptance before submission and stores the visitor IP and user agent only for the purpose of legal traceability of the request. See the <strong>Privacy<\/strong> section above for the full list of stored fields. From version 1.4.0 the plugin also integrates natively with the WordPress GDPR tools: a suggested Privacy Policy snippet appears in <strong>Settings \u2192 Privacy \u2192 Policy Guide<\/strong>, and withdrawal data is exposed to <strong>Tools \u2192 Export Personal Data<\/strong> and <strong>Tools \u2192 Erase Personal Data<\/strong> so admins can fulfil access and erasure requests without leaving the WordPress admin.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20the%20customer%20deletes%20their%20wordpress%20user%20account%3F\"><h3>What happens if the customer deletes their WordPress user account?<\/h3><\/dt>\n<dd><p>The withdrawal log is independent of the WordPress user table \u2014 it lives as a private custom post type indexed by the customer email. Deleting the user account does not delete the log automatically; the customer must request erasure through <strong>Tools \u2192 Erase Personal Data<\/strong> (where the plugin registers an eraser that removes every withdrawal request matching the customer email) or you can delete the corresponding <code>ayudawp_withdrawal<\/code> entries manually if your retention policy requires it.<\/p><\/dd>\n<dt id=\"can%20i%20customise%20the%20email%20subjects%20and%20bodies%3F\"><h3>Can I customise the email subjects and bodies?<\/h3><\/dt>\n<dd><p>Currently the emails are sent in plain text and their copy is translatable through the standard WordPress text-domain. HTML email templates that respect the WooCommerce email theme are planned for a later release. For now, advanced customisation requires hooking into the wp_mail filters.<\/p><\/dd>\n<dt id=\"which%20hooks%20does%20the%20plugin%20expose%20for%20developers%3F\"><h3>Which hooks does the plugin expose for developers?<\/h3><\/dt>\n<dd><p>Filters:<\/p>\n\n<ul>\n<li><code>ayudawp_euw_grace_days<\/code> \u2014 extra days added to the 14-day deadline. The default is the value stored in settings; the filter receives that value, so returning <code>$days + N<\/code> adds on top of it.<\/li>\n<li><code>ayudawp_euw_skip_deadline_check<\/code> \u2014 return <code>true<\/code> to disable the deadline check entirely. Receives the WC_Order as second argument.<\/li>\n<li><code>ayudawp_euw_email_ids<\/code> \u2014 array of WooCommerce email IDs where the withdrawal notice is injected.<\/li>\n<li><code>ayudawp_euw_allowed_statuses<\/code> \u2014 array of order statuses (without the <code>wc-<\/code> prefix) for which the withdrawal button and email notice are offered. Receives the value stored in settings and the current <code>WC_Order<\/code> (when available).<\/li>\n<li><code>ayudawp_euw_allow_unverified_order<\/code> \u2014 return <code>true<\/code> to accept submissions whose order number cannot be matched against a real WooCommerce order. Useful for sites that also handle non-WC purchases.<\/li>\n<li><code>ayudawp_euw_pre_resolve_wc_order<\/code> \u2014 short-circuit the order resolver. Return a <code>WC_Order<\/code> instance to accept, <code>false<\/code> to reject, or <code>null<\/code> (default) to fall through to the built-in strategies. Useful for plugins that store the displayed order number outside the standard <code>_order_number<\/code> post meta (e.g. YITH Sequential Order Number, custom ERP integrations).<\/li>\n<li><code>ayudawp_euw_resolve_wc_order<\/code> \u2014 late filter that receives the resolved <code>WC_Order<\/code> (or <code>false<\/code>) and the raw reference, for auditing or last-chance overrides.<\/li>\n<\/ul>\n\n<p>Actions:<\/p>\n\n<ul>\n<li><code>ayudawp_euw_after_submission<\/code> \u2014 fires after a withdrawal request has been processed. Arguments: CPT ID, submission data array.<\/li>\n<li><code>ayudawp_euw_after_status_change<\/code> \u2014 fires after a status change (individual or bulk). Arguments: CPT ID, new status, optional admin comment.<\/li>\n<\/ul><\/dd>\n<dt id=\"is%20this%20plugin%20enough%20to%20comply%20with%20eu%20directive%202023%2F2673%3F\"><h3>Is this plugin enough to comply with EU Directive 2023\/2673?<\/h3><\/dt>\n<dd><p>The plugin covers the functional requirements that Directive 2023\/2673 imposes EU-wide from 19 June 2026: a discoverable digital withdrawal function, deadline validation, Article 16 exclusions with subcategory inheritance, durable-medium proof via the SHA-256 receipt hash, the model form from Annex I.B of Directive 2011\/83\/EU and the double-consent checkboxes at checkout that enable the Art. 16(m) and Art. 14(4)(a) exceptions. On top of that it adds operational tools that the directive does not mandate but that make handling requests practical: per-status email injection, status lifecycle with bulk actions, native GDPR integration, public notice on excluded products and full traceability. Member States can layer extra national requirements on top of the EU baseline \u2014 the strictest known so far (Germany) requires a two-step confirmation flow with an intermediate review page, which is not yet implemented because the Spanish transposition is still pending; a future release will adapt to the final Spanish Real Decreto once published. <strong>Legal compliance ultimately depends on your business model, catalog and jurisdiction; the plugin provides the technical building blocks, not legal advice \u2014 consult a consumer-law specialist for your specific case.<\/strong><\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.6.1<\/h4>\n\n<ul>\n<li>Improved: the default text of the \"Other Article 16 exception\" excluded-product notice now lists dated accommodation and rentals among the examples, alongside perishable, custom-made and hygiene-sealed items. Makes the notice immediately recognisable to hotels, vacation rentals, car-rental shops and any other Art. 16(l) merchant without forcing them to rewrite the text from Settings.<\/li>\n<li>Improved: the sample template of the auto-generated \"Right of withdrawal\" page now ships with separate sections for each exception type the plugin covers \u2014 digital content (Art. 16(m)), services started early (Art. 14(4)(a)), custom-made \/ perishable \/ hygiene-sealed (Art. 16(a)(c)(d)(e)) and dated accommodation, rentals, catering or leisure (Art. 16(l)). A non-technical merchant can simply delete the sections that don't apply and keep legally-correct copy for the rest. Existing withdrawal pages are not modified \u2014 only fresh activations see the new template.<\/li>\n<li>Improved: the public withdrawal form no longer forces horizontal centring of its wrapper, so it now flows with the rest of the page content (left-aligned in LTR locales) instead of always sitting visually centred. The form keeps its 640px max-width for readability.<\/li>\n<\/ul>\n\n<h4>1.6.0<\/h4>\n\n<ul>\n<li>Improved: the plugin admin menu is now consistent regardless of WooCommerce being active or not. Both the request log and the settings page always live under a top-level <strong>Withdrawals<\/strong> menu (with a <strong>Settings<\/strong> submenu). The previous behaviour nested everything under <strong>WooCommerce \u2192 EU Withdrawal<\/strong> when WC was active, which made the plugin harder to find for new admins and inconsistent across installs.<\/li>\n<li>Fix: the three editors of the \"Excluded products notice\" section in <strong>Withdrawals \u2192 Settings<\/strong> now show a clear \"WooCommerce is not active\u2026\" message when WC is not installed, matching the rest of the WooCommerce-dependent fields. Before, two of them rendered empty under their labels.<\/li>\n<\/ul>\n\n<p>For older changelog entries, please check the <a href=\"https:\/\/plugins.svn.wordpress.org\/eu-withdrawal-compliance\/trunk\/changelog.txt\">changelog.txt<\/a> file<\/p>","raw_excerpt":"Free, complete EU Directive 2023\/2673 toolkit: withdrawal button, checkout consents, Annex I.B form, Article 16 exclusions, SHA-256 proof.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/312715","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=312715"}],"author":[{"embeddable":true,"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/fernandot"}],"wp:attachment":[{"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=312715"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=312715"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=312715"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=312715"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=312715"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/test.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=312715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}