Title: EU Withdrawal Button for WooCommerce &#8211; Octoplug
Author: Octoplug
Published: <strong>August 16, 2026</strong>
Last modified: August 16, 2026

---

Search plugins

![](https://ps.w.org/octoplug-withdrawal-button/assets/banner-772x250.png?rev=3649312)

![](https://ps.w.org/octoplug-withdrawal-button/assets/icon-256x256.gif?rev=3649312)

# EU Withdrawal Button for WooCommerce – Octoplug

 By [Octoplug](https://profiles.wordpress.org/octoplug/)

[Download](https://downloads.wordpress.org/plugin/octoplug-withdrawal-button.1.3.3.zip)

 * [Details](https://wordpress.org/plugins/octoplug-withdrawal-button/#description)
 * [Reviews](https://wordpress.org/plugins/octoplug-withdrawal-button/#reviews)
 *  [Installation](https://wordpress.org/plugins/octoplug-withdrawal-button/#installation)
 * [Development](https://wordpress.org/plugins/octoplug-withdrawal-button/#developers)

 [Support](https://wordpress.org/support/plugin/octoplug-withdrawal-button/)

## Description

Directive (EU) 2023/2673 requires online stores selling to EU consumers to offer
a clearly visible **withdrawal function** — a “withdrawal button” — so customers
can withdraw from a contract as easily as they entered it. Octoplug adds that function
to WooCommerce, end to end.

Also known across the EU as: **pulsante di recesso / recesso digitale (art. 54-bis
Codice del Consumo)** in Italy, **Widerrufsbutton / Widerrufsfunktion** in Germany
and Austria, **bouton de rétractation** in France, **botón de desistimiento** in
Spain, **przycisk odstąpienia od umowy** in Poland. Whatever your market calls it,
this plugin implements it.

**What it does**

 * Adds a **“Withdraw from contract here”** button (or link) to the customer’s account
   area: on the order page and, optionally, as an action in the order list.
 * Optional **footer link** on every page and a **dedicated withdrawal page** you
   can place anywhere with the `octoplug/withdrawal` block or the `[opwb_withdrawal]`
   shortcode — the page is created for you.
 * **Two-step flow**: the customer reviews the order, can select specific items 
   and add an optional note (no reason required), then confirms. Works without JavaScript.
 * **Durable receipt**: after confirming, the customer receives a confirmation email
   with the exact date and time of the withdrawal (site timezone plus UTC) and a
   SHA-256 integrity fingerprint — the proof the Directive requires. Delivery failures
   are logged and surfaced, never silent.
 * **Guest-friendly**: customers without an account can find their order with the
   order number and billing email. The lookup is POST-only, rate-limited, honeypot-
   protected and always answers generically — no personal data leaks.
 * **Request queue** under WooCommerce: statuses (New, In progress, Completed, Rejected,
   Cancelled by customer), filters, bulk actions, request detail with timeline, 
   CSV export (injection-safe). A rejection always requires a note, which is sent
   to the customer.
 * **Lifecycle emails** to the customer (completed, rejected, cancelled) and notifications
   to the store, in the language of the order (WPML and Polylang aware).
 * **Withdrawal window** handling: 14 days minimum (configurable upwards), anchored
   to delivery/completion or order date, end-of-day deadlines, grace buffer. You
   decide what happens afterwards, with three modes:
    - _Refuse late requests_ (the default): past the deadline nothing can be submitted
      online. The customer is not left in front of a page that lost its button —
      a notice states when the period ended and invites them to write to your contact
      address.
    - _Hide the button but accept late requests_: the button disappears, as you 
      asked, and the notice says when the period ended — followed by a discreet 
      link for the customer who wants to send the request anyway. It is registered
      with its date and flagged “out of window” for your review, which is exactly
      what the setting promises.
    - _Keep it visible and accept late requests_: the button stays, above a banner
      saying the deadline appears to have passed and that the store will review 
      the request.
       In no mode does the plugin tell a customer that the right of
      withdrawal is gone: when the consumer was not informed of that right the period
      extends to twelve months, and only you can judge the case. Requests accepted
      after the deadline are registered inside a configurable cut-off and flagged“
      out of window” for your review.
 * **Late attempts counter** on the dashboard: how many orders reached the withdrawal
   function after the deadline in the last 30 days, counted once a day each. They
   are not requests and nothing lands in your queue — it is an early warning that
   deliveries or your pre-contractual information may need a look. The counter is
   a plain daily total: it stores no order number, no name and no IP address.
 * Optional WooCommerce **order statuses** “Withdrawal requested” / “Withdrawal 
   completed” with automatic revert.
 * **Simple exclusions**: flag single products, whole categories or product types(
   virtual/downloadable) as exempt; flagged requests are marked for your review —
   never auto-rejected. Optional exemption note on the product page.
 * **Legal wording packs** in English, Italian, German, French, Spanish and Polish:
   button label, confirmation texts, receipt template, suggested Terms & Conditions
   snippet — all editable.
 * **Setup wizard (5 minutes)** and a **compliance checklist** that shows exactly
   what still needs attention.
 * **GDPR tools**: integration with the WordPress personal data exporter/eraser (
   requests are anonymized, not destroyed — they are legal evidence) and an optional
   retention policy.

**What it does NOT do**

 * It does not rewrite your Terms & Conditions (it suggests a snippet you can copy).
 * It does not process refunds automatically — you stay in control in WooCommerce.
 * It is a **compliance tool, not legal advice**. For specific legal questions, 
   consult a qualified professional.

**Privacy & transparency**

 * **No external calls, no tracking, no accounts**: everything runs on your site
   and your data never leaves it.
 * Data stored per request: customer name and billing email, optional note, IP address(
   full, truncated or omitted — your choice), timestamps (GMT), order reference,
   receipt fingerprint. Stored in a dedicated table on your database.
 * Uninstall is **conservative by default**: your withdrawal records are kept unless
   you explicitly enable “Delete all data on uninstall”.

**Multisite**: network activation installs on existing sites; sites created afterwards
need the plugin activated individually (planned for a future release). Uninstall
cleans the current site only.

**Translations**

 * The **customer-facing legal wording** (button label, confirmation page, receipt
   email, T&C snippet) ships in English, Italian, German, French, Spanish and Polish
   and always follows the language of the order — independent of the interface translation.
 * The **plugin interface** is fully internationalized and translated through translate.
   wordpress.org, so WordPress installs and updates the language packs on its own.
   Italian, German, French and Spanish are contributed there by the author; any 
   other language is open to the community.

## Screenshots

[⌊Setup wizard — final step with the compliance checklist.⌉⌊Setup wizard — final
step with the compliance checklist.⌉[

Setup wizard — final step with the compliance checklist.

[⌊Requests dashboard: compliance card, counters and queue.⌉⌊Requests dashboard: 
compliance card, counters and queue.⌉[

Requests dashboard: compliance card, counters and queue.

[⌊Request detail with timeline and receipt controls.⌉⌊Request detail with timeline
and receipt controls.⌉[

Request detail with timeline and receipt controls.

[⌊Settings — button & placement.⌉⌊Settings — button & placement.⌉[

Settings — button & placement.

[⌊Customer flow: two-step withdrawal in the account area.⌉⌊Customer flow: two-step
withdrawal in the account area.⌉[

Customer flow: two-step withdrawal in the account area.

[⌊Guest withdrawal page with order lookup.⌉⌊Guest withdrawal page with order lookup
.⌉[

Guest withdrawal page with order lookup.

## Blocks

This plugin provides 1 block.

 *   Octoplug: Withdrawal Renders the EU withdrawal flow: eligible orders for logged-
   in customers, order lookup for guests.

## Installation

 1. Upload the plugin through Plugins  Add New, or unzip it into `/wp-content/plugins/`.
 2. Activate it. PHP 8.0+ and an active WooCommerce 7.0+ are required.
 3. Follow the 5-minute setup wizard: store country and languages, button placement,
    receipt email, compliance checklist.
 4. Done — the button appears in the customer account area, and the withdrawal page
    and footer link are in place.

You can re-run the wizard at any time, or configure everything manually under WooCommerce
Withdrawal Button.

## FAQ

### Is this legal advice?

No. Octoplug is a compliance tool: it implements the withdrawal function required
by Directive (EU) 2023/2673, but it is not legal advice. For specific questions 
about your obligations, consult a qualified professional.

### The withdrawal button is not visible on an order. Why?

Check that the master switch is on, that the order status is one of the eligible
statuses (processing, completed, on hold) and that the order is still within the
withdrawal window (plus the visibility buffer). Orders that are fully refunded, 
cancelled or failed do not show the button.

### What happens when the withdrawal period has expired?

By default the plugin refuses late requests online: the button is replaced by a 
notice that says when the period ended and invites the customer to contact you at
the address you configure (Settings  Withdrawal window  “Contact email for late 
requests”). If you choose to hide the button but still accept late requests, the
same notice is followed by a discreet link that lets the customer send the request
anyway: it arrives flagged “out of window” for you to decide. If you keep the button
visible, it stays and the request is registered and flagged “out of window”. In 
all three cases the customer gets an explanation, and in none of them does the notice
state that the right of withdrawal no longer exists — that is a judgement only you
can make, and the statutory period extends to twelve months when the consumer was
not informed of the right.

### A guest customer cannot find their order.

The lookup matches the order number together with the **billing** email used at 
checkout — a different email will not match, on purpose. Sequential order number
plugins are supported.

### Emails are not arriving.

The plugin sends through `wp_mail()` like WooCommerce does. If WooCommerce emails
also fail, configure an SMTP plugin. Failed receipt deliveries are flagged in the
dashboard so you can resend them from the request page.

### Does uninstalling delete my withdrawal records?

No. By default everything is kept, because the records are your legal evidence. 
Data is removed only if an administrator enables “Delete all data on uninstall” 
before deleting the plugin.

### Is the plugin translated?

The legal wording the customer sees (button label, confirmation, receipt) ships 
localized in EN/IT/DE/FR/ES/PL and follows the language of the order. The admin 
interface is translated into Italian (complete, manual included), German, French
and Spanish; in the last three, a few admin texts added in the most recent release
still fall back to English.

### What happens to personal data (GDPR)?

The plugin integrates with the WordPress privacy tools: exports include the customer’s
withdrawal requests, and erasure requests anonymize them (name, email, note, IP 
are cleared) while the reference, timestamps and receipt fingerprint are retained
as the store’s legal evidence. An optional retention policy anonymizes old requests
automatically. No data ever leaves your site.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“EU Withdrawal Button for WooCommerce – Octoplug” is open source software. The following
people have contributed to this plugin.

Contributors

 *   [ Octoplug ](https://profiles.wordpress.org/octoplug/)

[Translate “EU Withdrawal Button for WooCommerce – Octoplug” into your language.](https://translate.wordpress.org/projects/wp-plugins/octoplug-withdrawal-button)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/octoplug-withdrawal-button/),
check out the [SVN repository](https://plugins.svn.wordpress.org/octoplug-withdrawal-button/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/octoplug-withdrawal-button/)
by [RSS](https://plugins.trac.wordpress.org/log/octoplug-withdrawal-button/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.3.3

 * Display name only: the plugin is now listed as “EU Withdrawal Button for WooCommerce–
   Octoplug”, which says what it does. Nothing else changed — same plugin, same 
   folder, same settings, same data. The directory URL and the text domain stay `
   octoplug-withdrawal-button`.

#### 1.3.2

 * Hardening: every admin and front-end output is now escaped at the point it is
   echoed, and the settings-save hook passes sanitized data to add-ons instead of
   the raw request. No change to behaviour, receipts or stored data.
 * The dedicated-page shortcode is now `[opwb_withdrawal]` (was `[octoplug_withdrawal]`).
   The `octoplug/withdrawal` block and the auto-created page are unchanged; update
   the tag only if you placed the shortcode by hand.

#### 1.3.1

 * The two remaining inline scripts (the outcome focus on the front end, the setup
   wizard enhancements) now go out through `wp_add_inline_script()` on their own
   registered handle.
 * Translations are no longer bundled: the interface language packs come from translate.
   wordpress.org, so `load_plugin_textdomain()` is gone as well (WordPress loads
   the domain just in time). The customer-facing legal wording is unaffected — it
   is plugin data, not a translation file, and still ships in six languages.
 * No change to the withdrawal flow, the receipts or the stored data.

#### 1.3.0

 * Minimum PHP raised to 8.0. We test and lint on PHP 8.0 to 8.4: 7.4 was declared
   without ever being tested on it, and it has had no security updates since the
   end of 2022 — not a place to keep a plugin that handles consumer data. WordPress
   6.5 remains the minimum.
 * “Hide the button, accept late requests” now does both halves of what its name
   says. The button stays hidden — that is the point of the setting — but the notice
   is followed by a discreet link, and the request sent through it is registered
   and flagged “out of window”. Before, that mode behaved exactly like “refuse”:
   the customer read that late requests were accepted and had no way to send one.
 * Out-of-window orders are no longer silent, in either of the modes that take the
   button away. Where late requests are refused, the customer reads when the withdrawal
   period ended and where to write; where the button is hidden but late requests
   are still accepted, the customer reads that the period ended and that the store
   can still consider a late request. Both appear in all three entry points (account
   order page, dedicated page/shortcode, guest lookup). The wording never denies
   the right of withdrawal: the period extends to twelve months when the consumer
   was not informed of it, and that call belongs to the shop owner.
 * New setting “Contact email for late requests”, required when late requests are
   refused: validated on save and checked by the compliance checklist. No fallback
   address is ever invented. When the button is only hidden, the address stays optional
   and is shown only if you set one.
 * New dashboard counter “Late attempts (30 days)”: orders that arrived after the
   deadline, counted once a day each. They are a number, not a queue — nothing to
   process. The counter stores a daily total only: no order number, no name, no 
   IP address, nothing to export or erase.
 * Accessibility fix (WCAG 2.4.7): the focus ring on “Confirm withdrawal” was drawn
   in white on a white background, i.e. invisible to keyboard users on the final,
   irreversible action. Every focusable element of the customer flow now has a double
   ring that holds on any theme.
 * The Terms & Conditions step is now actionable everywhere it appears (dashboard
   card, step board, compliance screen, wizard): “Open the suggested text” really
   shows the paragraph in a selectable field, the copy result is announced, and 
   a second button leads straight to the WooCommerce setting that holds the Terms
   page.
 * The Terms & Conditions step can no longer be green while WooCommerce has no Terms
   page at all: the self-declared step regresses and says why.
 * One single form and one single save button on the Settings screen: add-on settings
   are saved by the same click, so no half of the screen can be thrown away silently
   any more.
 * The setup wizard now asks for the two settings with legal consequences it used
   to skip while grading them: how long the period lasts and whether it starts from
   the order or from the delivery.
 * The requests queue tells “no results for these filters” (with a reset link) apart
   from “no requests at all” — it used to congratulate stores that had five open
   requests.
 * The withdrawal reference (WD-…) is now shown to the customer on the order page,
   not only in the receipt email.
 * Rejecting a request without a note no longer loses the choice: the status comes
   back selected, the note is marked required and the page lands on the form.
 * Guest lookup: after a failed attempt the order number is kept, the focus moves
   to the field to correct and the error is announced assertively. The billing email
   is still never carried in a URL.
 * Orders left in a withdrawal order status without a request now show their real
   situation instead of nothing.
 * Smaller fixes: the checklist title follows the configured number of days, the
   sentence “counted from the delivery date” is one translatable sentence instead
   of glued fragments, the retention “years” field is hidden when all records are
   kept, the screens table in the manual is generated from the real tab list (it
   listed four out of eight).

#### 1.2.1

 * Fixed: the withdrawal outcome emails (request completed, more information needed,
   request cancelled) now reach the customer in the language of their order, also
   on shops that do not have that language installed in WordPress itself. Before,
   they went out in the shop language. The withdrawal receipt was never affected.
 * Translations are now loaded from wp-content/languages/plugins first, so a translation
   you install or override there wins over the bundled one.

#### 1.2.0

 * Added: extension points that let the EU Withdrawal Button PRO add-on plug in 
   cleanly — request-detail actions and audit timeline hooks, the receipt body passed
   to `opwb_receipt_sent`, an `opwb_exclusion_note` filter for per-clause product
   notes, an `opwb_order_email_link_html` filter for the order-email button, and
   an `opwb_bulk_actions` filter on the requests queue.
 * The public contract version (`OPWB_CORE_API`) moves to 1.1. Fully backward compatible:
   with the Pro add-on inactive the plugin behaves exactly as before.
 * No change to the withdrawal flow, the receipts or the stored data.

#### 1.1.0

 * Dashboard redesigned around a setup progress card: completion ring, level, and
   the single next action to take — so it is always clear what is left before the
   store is compliant.
 * New step board: open steps first (numbered, each with its fix action), completed
   ones folded away. A one-time confirmation is shown when the setup first reaches
   100%.
 * Documentation rebuilt as a real product manual: sticky section index, numbered
   steps, callouts, tables and code examples; new sections on the withdrawal window
   and on the developer hooks.
 * Per-tab admin assets: the dashboard and documentation stylesheets load only on
   their own tab.
 * No change to the withdrawal flow, the receipts or the stored data.

#### 1.0.0

 * Initial release.

## Meta

 *  Version **1.3.3**
 *  Last updated **7 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.5 or higher **
 *  Tested up to **7.0.4**
 *  PHP version ** 8.0 or higher **
 * Tags
 * [consumer rights](https://wordpress.org/plugins/tags/consumer-rights/)[eu](https://wordpress.org/plugins/tags/eu/)
   [right of withdrawal](https://wordpress.org/plugins/tags/right-of-withdrawal/)
   [withdrawal](https://wordpress.org/plugins/tags/withdrawal/)[woocommerce](https://wordpress.org/plugins/tags/woocommerce/)
 *  [Advanced View](https://wordpress.org/plugins/octoplug-withdrawal-button/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/octoplug-withdrawal-button/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/octoplug-withdrawal-button/reviews/)

## Contributors

 *   [ Octoplug ](https://profiles.wordpress.org/octoplug/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/octoplug-withdrawal-button/)