I tested all 11 free WooCommerce EU withdrawal-button plugins

The best free WooCommerce EU withdrawal button plugin, tested against Directive 2023/2673 Article 11a

From 19 June 2026, every shop selling to EU consumers has to put a clearly labelled, one-click "withdraw from contract" function in the storefront. That's Directive (EU) 2023/2673, which adds a new Article 11a to the old Consumer Rights Directive. WooCommerce has no native support for it - there's just an open request (#65443) sitting there with no roadmap.

So you need a plugin. The wp.org repo has a pile of them now, all claiming compliance. I didn't trust the readme screenshots. I installed all 11 I could find, one at a time, on a real WooCommerce site and drove the actual withdrawal flow as a guest. Then I scored each one against what the directive literally asks for.

This is the "I did the tedious testing so you don't have to" post. Here's what I found, including two I'd actively avoid for this job.

Updated 25 June 2026: the winner changed after a re-test. In the original round the top pick was Vendidero's EU Order Withdrawal Button (17/18) - WebToffee lost a point because guest partial withdrawal was login-gated. WebToffee then shipped v1.0.4 (24 June 2026), opening guest partial up without login. I re-tested it: it now scores a clean 18/18 and tops the table. Vendidero's plugin is now the runner-up - still an excellent pick, and the better choice if you want the largest install base or partial visible without an email round-trip. Details in the WebToffee and runner-up sections below.

What the law actually wants

First, the thing everyone gets wrong: this is not a new right. The 14-day cooling-off period already existed. Refund timelines, return-shipping rules - all unchanged. What changed is the method. If a customer can buy in a few clicks, they have to be able to withdraw with comparable ease, through a clear electronic function. Not by hunting for a PDF or emailing your support inbox.

In practice the directive boils down to a few hard requirements:

One easy-to-miss knock-on: your pre-contractual info under Art. 6 now has to mention the function exists and where it is. So your return-policy and terms pages need a small update too, not just the UI.

How I tested (and scored)

This wasn't a desk review. I spun up a real WooCommerce site on my local wp-test stack - store country Poland, currency PLN, guest checkout on - and installed each plugin on its own, one at a time. Then I placed a real guest order (#13, [email protected]) and drove the withdrawal flow in a real browser as a logged-out guest.

For the durable-medium step I hooked wp_mail and captured what each plugin actually queued, because the test box can't send real mail. So "email verified" here means "the plugin generated a timestamped customer + admin email", not "it landed in an inbox". That's an honest limitation - confirm deliverability on your own staging with real SMTP.

I scored nine criteria, 0-2 each, mapped straight to Art. 11a (max 18):

C1Site-wide visible button, reachable from every page
C2Guest access - usable without login, by order # + email
C3Two-step flow - initiate, then a separate confirm
C4Durable-medium acknowledgement - timestamped email/record
C5Partial withdrawal - select specific items / quantities
C6No extra mandatory fields - IBAN / reason not forced
C7Admin management - request list / status flag / order-note trail
C8Polish i18n - translatable, label editable to "Odstąp od umowy"
C9Doesn't break the store - no fatal, HPOS-compatible

0 = no, 1 = partial or paywalled, 2 = yes, free.

The scoreboard - all 11

PluginC1C2C3C4C5C6C7C8C9Total
WebToffee EU Order Withdrawal (v1.0.4) ★22222222218
EU Order Withdrawal Button (Vendidero) (runner-up)22122222217
EU Withdrawal Button22222212217
WWU Withdrawal Button (OSS)12222222217
WPify Woo (module)12222222217
Germanized (bundles the runner-up)22122222217
Easy Return22222222117
EU Withdrawal Compliance12221222216
BuddyPilot Withdrawal *12211222215
Bitron Right of Withdrawal12121112213
WP Desk Flexible Refund0011112129

* BuddyPilot: C4/C5 scored conservatively. The architecture (magic-link, partial, PDF declaration) is clearly there, but it doesn't use wp_mail and the access-link step wouldn't complete in my headless harness, so I couldn't verify the end-to-end email live. It's likely higher on a real-mail staging site.

Horizontal bar chart of all 11 WooCommerce withdrawal-button plugins scored out of 18 against Article 11a: WebToffee alone at 18 highlighted as the winner, six tie at 17, down to WP Desk Flexible Refund at 9
The same scores as a picture. WebToffee is the lone 18/18 after the v1.0.4 re-test; six plugins tie at 17/18; the two at the bottom (Bitron, WP Desk) are the ones I'd avoid for this job.

After the re-test, WebToffee is the only clean 18/18. Six plugins tie just behind at 17/18 - including the runner-up - so the top of the table is closer than one point makes it look, and the gaps are in different places. For a Poland-only store the practical pick is still clear, as I get into below.

The winner: WebToffee EU Order Withdrawal Button

EU Order Withdrawal Button for WooCommerce by WebToffee - wordpress.org/plugins/wt-eu-withdrawal-button, v1.0.4, ~20 installs, HPOS-ready, free core. The only plugin in this round to score a clean 18/18.

I had this lower in the first round - WebToffee lost a point because its guest form had no item selection, so partial was effectively login-gated. The vendor flagged that the next release fixed it, and on v1.0.4 (released 24 June 2026) I re-tested and they were right: guest partial now works without login. With that gap closed it satisfies every Art. 11a criterion, and it does it with zero configuration - the site-wide footer link is on by default. Backed by WebToffee, an established WooCommerce-plugin vendor with long support continuity.

WebToffee guest withdrawal form asking for order number and billing email, with help text promising item selection after email verification
Step 1 (guest, logged out): order number + billing email. The help text promises item selection after email verification.
WebToffee guest item-selection step after email verification, with per-item checkboxes and a quantity selector, no login required
After email verification the guest picks items - per-item checkboxes plus a quantity selector. No login required.

What I verified on v1.0.4:

Honest cons: the guest has to complete the email-verification round-trip before the item picker appears, so partial is one step further away than on plugins that show items inline. Records live in the plugin's own tables rather than as WooCommerce order notes/status. No Polish bundled (a .pot only, labels editable). And it's still a small-install (~20) newcomer next to the leaders' track records.

If you want the cleanest score against the directive, this is the one now. A perfect rubric, fully guest-capable partial without login, a site-wide link on by default, email double-opt-in, structured request/log storage and an integrity hash - from an established vendor. If install base or best-in-class admin tooling matters more to you, read the runner-up first.

The runner-up: EU Order Withdrawal Button (Vendidero)

EU Order Withdrawal Button for WooCommerce - wordpress.org/plugins/eu-order-withdrawal-button-for-woocommerce, v2.2.1, ~1,000 installs, ★5, HPOS-ready, free core. This was the #1 pick in the first round and is still an excellent choice - for many stores the better one. It's the same engine Germanized bundles, from a serious legal-compliance vendor, and it's the install leader (~1,000, ★5). Prefer it over WebToffee if you want the largest install base, partial visible without an email round-trip, or the withdrawn items recorded directly on the WooCommerce order.

Vendidero guest withdrawal form with only Email required, plus the site-wide sticky Withdraw from contract button at the bottom
Guest form - only Email is required - and the site-wide sticky "Withdraw from contract" button, bottom centre.
Vendidero WooCommerce Withdrawals admin queue with a Full badge, verified email, Requested status and approve/reject/delete actions
WooCommerce → Withdrawals: a real request queue with full/partial badge, verified email, status and per-row actions.

What I verified on the test site:

Why it's the runner-up now: it scores 17/18 to WebToffee's 18. The single dropped point is C3 - its confirm is a single-page "Confirm withdrawal" rather than a separate review/verification step. Everything else is best-in-class. Site-wide visibility is off by default (flip the toggle), and there's no Polish bundled, though the page title and button label are freely editable to "Odstąp od umowy tutaj".

If you just need to be compliant and move on, this is still a great default. Most complete admin side of the bunch, a real queue with an audit trail, the install leader, and a vendor that does compliance for a living.

Three alternatives worth knowing

Most legally rigorous: WWU Withdrawal Button (OSS) - 17/18

If compliance evidence is your priority, nothing beats this open-source one. Every declaration gets a PDF plus an OpenTimestamps cryptographic timestamp, precise legal wording, EU/EEA applicability rules, exclusions and consent-IP capture. The catch: it's off the wp.org repo (GitHub install, no automatic updates), disabled by default, and has more knobs than the leaders. Great for the audit-minded, more upkeep.

WWU withdrawal form step 2 with withdraw from contract here heading, optional reason and per-item partial selection
WWU step 2 - "withdraw from contract here", reason optional, per-item partial.
Easy Return step 2 wizard with per-item partial selection, shipping Polish out of the box
Easy Return step 2 - polished wizard, per-item partial, and it ships Polish out of the box.

Ships Polish out of the box, now ties the leaders: Easy Return - 17/18

Gorgeous 3-step wizard, good guest order recovery, and the only plugin that ships pl_PL out of the box. A re-audit bumped its score: it does have an automatic site-wide button after all. The Injections setting withbuea_injection_show_footer_button (off by default) drops a sticky "Withdraw from contract" button on every page - verified as a guest. That's a config toggle, not a paywall, exactly like the winner's embed_everywhere, so C1 goes 1→2 and it joins the 17/18 tie.

Easy Return sticky Withdraw from contract footer button shown site-wide on the storefront after enabling the Injections footer-button setting
Easy Return's site-wide footer button, on once you flip the Injections toggle - the same default-off pattern as the winner.

It still sits behind the winner and runner-up, though. It's SaaS-coupled (easyreturn.eu): in free/unconnected mode the confirmation email is literally labelled "This is a test withdrawal confirmation email", and it doesn't declare HPOS. The durable-medium email is the one part of this you can't get wrong, so for a production store I'd still reach for the winner - but it's a genuinely strong option, especially if you want Polish with zero translation work.

Nicest customer UX: EU Withdrawal Button for WooCommerce - 17/18

wordpress.org/plugins/eu-withdrawal-button-for-woocommerce, v2.0.1, freemium - the one the research brief originally picked. This has the nicest customer-facing UX of the lot: a genuine two-step modal (Continue, review, Confirm) and the cleanest inline partial picker I saw - per-item checkboxes and editable quantities with a live total. IBAN and reason are both explicitly optional, with helpful copy.

Two-step withdrawal modal showing order #13 recovered as guest, per-item checkboxes with editable quantity and a live withdrawal total
Step 2: order #13 recovered as a guest, per-item plus quantity partial selection, live total, then Confirm. The cleanest withdrawal UX I tested.

Why it sits here and not higher: the admin side is weak (C7=1). There's no dedicated request dashboard, and the selected partial items aren't stored on the order - they only go out in the email. For a merchant who has to act on each request, that's an operational gap the leaders don't have. It also defaults to "My Account only" and needs a couple of toggles to go truly site-wide. If you care most about the customer experience and you're fine managing requests from the email, it's a genuinely lovely pick.

What I'd avoid for this job

Two plugins came up when I searched but are the wrong tool here:

Bitron logged-in withdrawal form showing a multi-step flow with an items step and quantity-level per-item partial selection
Bitron's logged-in form does have multi-step + quantity-level item partial - but its guest form, the one Art. 11a needs, has neither.

And a note on two more of the 17/18 plugins: WPify Woo and Germanized both do the feature well - Germanized actually bundles the runner-up's engine (Vendidero's). But both are heavy suites (Czech and DACH respectively). Only pick them if you also need the rest of the suite. For a Poland-only store that just wants the button, a standalone pick like the winner or runner-up is a fraction of the weight.

A reader suggestion, tested after publishing: Withdrawal EU Law (trecenode) - 16/18

After this went up, someone on Reddit pointed me at one I hadn't found: Withdrawal EU Law by 13Node, on GitHub as trecenode/eu-withdrawal-compliance (v1.3.0). So I put it through the exact same test - a real guest order on the live site, with wp_mail captured - and it earns a credible 16/18. It doesn't change the recommendation, but it's a genuinely solid newcomer and worth knowing about.

Name clash, worth flagging. This repo reuses the wp.org slug eu-withdrawal-compliance, which already belongs to ayudawp's "EU Withdrawal Compliance" (the 16/18 one in the scoreboard). Despite the shared slug it's a completely different plugin and codebase - different author (13Node), different text domain (trece-withdrawal-eu). Don't confuse the two when you go looking.

Withdrawal EU Law review step showing order recovered as guest with per-item Items to withdraw checkboxes for structured partial selection
The review step - structured per-item "Items to withdraw" checkboxes, recovered as a guest before the final confirm.
Withdrawal EU Law success screen showing the request reference number and a SHA-256 receipt hash for integrity
Success screen - a reference number plus a SHA-256 receipt hash, billed as integrity proof for the declaration.

What it does well: a genuine form → review → confirm two-step, with structured per-item partial selection on the review screen (better than its namesake's free-text box). It generates a SHA-256 receipt hash, fires durable customer and admin emails (both captured, timestamped), stores each request as a CPT with a custom "Withdrawal requested" order status, and declares HPOS compatibility. The guest flow is clean.

Why it sits at 16 and not higher: it forces a required "Order date" field on top of name, email and order number (C6=1) - that's extra friction Art. 11a doesn't ask for. There's no automatic site-wide button either (C1=1); you place the form or link manually via shortcode or menu. And like WWU, it's off the wp.org repo - GitHub install, no automatic updates - and it's brand new with no track record yet.

Net: it ties ayudawp's EU Withdrawal Compliance at 16/18 - now the only other plugin on that rung - but it doesn't unseat the winner (WebToffee, 18/18) or the runner-up (Vendidero, 17/18). If you like its receipt-hash approach and don't mind manual updates, it's a legitimate option. For a production Polish store I'd still reach for one of the leaders.

The Poland gotcha

Here's where Poland is different from "just install it before the 19th". Poland missed the 19 December 2025 transposition deadline. The withdrawal-button rules were meant to ride into the ustawa o prawach konsumenta via a consumer-credit vehicle (UC82), steered by UOKiK. In May 2026 the government pulled that and said it would start new work. So there's likely no Polish statute in force on 19 June. Commentators are calling the date "nierealne".

Does that mean you can wait? I wouldn't. A few reasons:

So which plugin for a Polish store?

The rubric winner is now WebToffee, and if you want the cleanest 18/18 score it's a fine choice. But for a production Polish store my practical pick is still the runner-up, EU Order Withdrawal Button (Vendidero) - it's the install leader with the best admin tooling, and neither it nor WebToffee ships a Polish translation, so you're typing the labels yourself either way. With Vendidero everything is editable, so the page title and button become "Odstąp od umowy tutaj" and the confirm becomes "Potwierdź odstąpienie od umowy". Two minutes of work, and you get the best admin queue of the bunch.

The only plugin that ships pl_PL out of the box is Easy Return. If you want zero translation work and a polished Polish wizard, it's tempting. I'd still hesitate on the free tier - its confirmation email is labelled "test", and the durable-medium email is the one part of this you can't get wrong. For a Polish store I'd rather spend two minutes translating the winner than rely on Easy Return's free-tier email. If you're already paying for Easy Return's connected service, that calculus changes.

This is a practitioner write-up, not legal advice. For final shop-policy wording, confirm against the Polish transposition once it's published, and for high-value exposure talk to a consumer-law lawyer.

What it costs if you skip it

The penalties vary by member state, but one consequence is EU-wide and it's the one that actually bites day to day: if a compliant withdrawal function is missing, the 14-day cooling-off window can extend to 12 months and 14 days. Customers can send things back the better part of a year after delivery. That's the real commercial risk, well before any regulator gets involved.

On top of that, fines exist where the rule is enforceable:

What I'd actually do

If this were a client store on Poland/PLN, here's the path. It's a 1-2 hour job on staging, not a fire:

  1. Install EU Order Withdrawal Button for WooCommerce on a clone first.
  2. Turn on site-wide embed. Rename the page and button to "Odstąp od umowy tutaj" and the confirm to "Potwierdź odstąpienie od umowy". Labels are editable, no PL pack ships.
  3. Check only name + order ID + email are required. Leave IBAN and reason off.
  4. Wire real SMTP and confirm the timestamped acknowledgement email actually fires. The durable-medium email is the legal bit, so don't skip it.
  5. Update your return-policy / terms pages to disclose the function and where it lives (Art. 6).
  6. Cache-exclude the withdrawal page so the no-login form isn't served stale. If you're on a full-page cache, this matters - I wrote about the cache-bypass cookie logic in my WooCommerce performance stack post.
  7. Keep refunds manual through your existing gateway. The form only registers the legal declaration.

On step 2: the winner lets you edit the button text in its settings and rename the page, which is the simplest route. If you'd rather pin the labels in code - handy when you manage several stores - a small gettext filter does it without a translation file. This works for any plugin that runs its strings through WordPress translation:

// Force Polish labels without shipping a .po file.
// Drop this in a tiny mu-plugin or your theme's functions.php.
add_filter( 'gettext', function ( $translated, $text ) {
	$pl = [
		'Withdraw from contract' => 'Odstąp od umowy tutaj',
		'Confirm withdrawal'     => 'Potwierdź odstąpienie od umowy',
	];
	return $pl[ $text ] ?? $translated;
}, 20, 2 );

That's it. The good news is the hard part - figuring out which plugin to trust - is already done. WooCommerce will probably ship something native eventually, but #65443 has no roadmap, so I wouldn't wait for core on a deadline.

If you want more WooCommerce config wins while you're in there, my 30 WordPress & WooCommerce performance tips is a decent companion read.

FAQ

Do I need the withdrawal button if I'm a small Polish store?

Yes, in practice. The obligation applies to any business selling to EU consumers from 19 June 2026, regardless of size. Poland's own statute is delayed (see above), but the directive is binding and your cross-border EU sales are already covered. There's no small-shop exemption.

Can I just label the button "Cancel" or "Return"?

No. The directive points to clear wording like "withdraw from contract here" to open the form and "confirm withdrawal" to submit. Ambiguous labels like "Cancel" are likely treated as insufficient. In Polish, use "Odstąp od umowy tutaj" and "Potwierdź odstąpienie od umowy".

Is a footer link to my returns policy enough?

Not anymore. A policy page you have to read, or a "email us for the form" line, no longer satisfies the rule. You need a working digital function - reachable from every page, usable by guests without logging in, with a two-step confirm and a timestamped acknowledgement email.

Does the plugin handle the actual refund?

No, and that's fine. The withdrawal function only registers the legal declaration and timestamps it. The refund still goes through your normal WooCommerce flow and payment gateway, and the physical return and inspection rules are unchanged. Keep refunds manual.

Will WooCommerce add this to core?

Maybe eventually. There's an open enhancement request (#65443) but no roadmap or shipped support as of June 2026. I wouldn't wait for core on a deadline - install a plugin.

WooCommerce is my thing

I dig into WooCommerce internals for a living - performance, compliance, the stuff that breaks at the worst time. If you'd rather hand this off, or your store is slow and you're not sure why, I can help. Hands-on, real fixes, not a report.