Webshop Withdrawal Button: New Rule June 2026

Steven | TrustYourWebsite · 6 April 2026 · Last updated: May 2026

Directive (EU) 2023/2673, which amends the Consumer Rights Directive (2011/83/EU), introduces a new requirement for online service providers: a digital button through which consumers can exercise their right of withdrawal (herroepingsrecht). The deadline for implementation is June 19, 2026.

The Background: The Right of Withdrawal

Under Dutch consumer law (implementing the Consumer Rights Directive), consumers who purchase online have a 14-day cooling-off period during which they can withdraw from the contract without giving a reason. This applies to:

  • Distance contracts (purchases made online, by phone, or by catalogue)
  • Off-premises contracts
  • Most B2C purchases of goods and services

For digital services and subscriptions specifically, the right of withdrawal exists for 14 days from the date the contract is concluded, unless the consumer has explicitly consented to immediate delivery and acknowledged that the right of withdrawal is lost upon commencement.

The withdrawal right does not apply to:

  • Custom-made goods
  • Perishable goods
  • Goods that cannot be returned for hygiene reasons after opening
  • Fully delivered digital content where the consumer consented to immediate delivery
  • Some service contracts fully performed before the withdrawal period ends

What Regulation 2023/2673 Adds

Before this regulation, exercising the right of withdrawal typically required consumers to:

  • Find the withdrawal form in the seller's terms and conditions
  • Send an email or letter
  • Fill out a paper withdrawal form

Many consumers did not exercise their rights because the process was deliberately or accidentally made complicated.

Regulation 2023/2673 (Article 11a of the amended Consumer Rights Directive) requires that if a trader provides an online interface (website or app) through which the consumer concluded the contract, the trader must provide a button or equivalent function allowing the consumer to exercise the right of withdrawal online.

Technical Requirements for the Withdrawal Button

The regulation imposes five concrete requirements. Quick checklist for your build:

#RequirementCompliant patternNon-compliant pattern
1Clearly labelled button"Herroep hier" / "Opzeggen" / "Cancel contract here" / "Withdraw here"Generic "Contact us", "Help", or label hidden behind a "Manage" menu
2Single-step accessMaximum 2 navigation clicks from the account/order-history page where the contract was concludedBuried in a help-centre article, requires opening a ticket
3Electronic confirmationImmediate on-screen acknowledgement + email confirmation on a durable mediumConfirmation page that only says "we received your message"
4No additional hurdlesClick triggers the withdrawal directly"Request to cancel" requiring trader approval, retention-team call, or wait period
5Availability throughout the 14-day windowButton visible for the entire withdrawal period after the contract startsButton hidden after first day, "out of office" banner blocking access

These mirror the five conditions in Article 11a of the amended Consumer Rights Directive. A pattern that violates any one of them is non-compliant on its face.

Who This Affects

Primarily affected:

  • SaaS products with consumer subscriptions (software, streaming, cloud storage)
  • Digital content providers (e-books, music, video, if withdrawal still applies)
  • Online course and education platforms
  • Gym membership apps
  • Any subscription-based online service sold directly to consumers

Also affected:

  • Webshops where consumers can initiate returns online (the button facilitates withdrawal for goods too, though goods returns via post remain valid)

Less directly affected:

  • Physical product webshops where the return process is entirely by post (the existing written/email withdrawal process remains valid for goods if consumers can also use it electronically)

The ACM (Autoriteit Consument & Markt) is expected to clarify scope in guidance. The safest interpretation: any platform through which a consumer concluded a contract that carries a withdrawal right should implement the button.

Implementation: What You Need to Build

For a typical subscription service:

  1. In the user account dashboard: A clearly labelled button "Cancel subscription" or "Withdraw from contract", positioned prominently, not buried in settings.

  2. The button triggers: A confirmation screen that explains what withdrawal means (contract ends, refund if applicable, data deletion timeline).

  3. After confirmation: An immediate email confirmation to the consumer stating that their withdrawal has been received and the cancellation date.

  4. Record keeping: Log the withdrawal with timestamp, for your own records and for ACM audit purposes.

Example flow:

  1. Consumer logs into account → Account page has "Cancel subscription" button (one click)
  2. Consumer clicks → Confirmation screen: "Are you sure? Your subscription ends on [date]. You will not be charged further. Click 'Confirm withdrawal' to proceed."
  3. Consumer clicks "Confirm" → Subscription cancelled immediately, email sent
  4. Consumer is on "Subscription cancelled" page with details

The entire process: 2-3 clicks maximum, no contact with a human required, immediate effect.

Per-platform code samples

Below are minimal working implementations for the five most common stacks used by Dutch webshops. Each sample uses the exact label "Withdraw from contract here" (acceptable equivalent: "Cancel contract here"). For pages targeted at Dutch-speaking visitors, use "Hier de overeenkomst ontbinden" instead.

Shopify (Liquid)

Add to customers/order.liquid so the button appears on every customer order detail page:

{%- assign window_seconds = 1209600 -%}
{%- assign order_age = 'now' | date: '%s' | minus: order.created_at | date: '%s' -%}
{%- if order_age < window_seconds and order.cancelled_at == blank -%}
  <a href="{{ shop.url }}/pages/withdraw?order={{ order.name | url_encode }}&email={{ order.email | url_encode }}"
     class="btn btn-primary withdrawal-button">
    Withdraw from contract here
  </a>
{%- endif -%}

On /pages/withdraw, render the confirmation form using Shopify's contact-form helper:

{% form 'contact' %}
  <input type="hidden" name="contact[subject]" value="Withdrawal, Art. 11a CRD" />
  <label>Your name <input type="text" name="contact[name]" required /></label>
  <label>Order number
    <input type="text" name="contact[order_id]" value="{{ request.query_params.order }}" required />
  </label>
  <label>Confirmation email
    <input type="email" name="contact[email]" value="{{ request.query_params.email }}" required />
  </label>
  <button type="submit">Confirm withdrawal</button>
{% endform %}

The acknowledgement email is sent via a Shopify Flow workflow triggered on "Contact us form submitted" with the condition subject contains "Withdrawal".

WooCommerce (PHP / hook)

Add to your child theme's functions.php:

<?php
add_action( 'woocommerce_order_details_after_order_table', 'tyw_render_withdrawal_button', 10, 1 );
function tyw_render_withdrawal_button( $order ) {
    if ( ! is_a( $order, 'WC_Order' ) ) return;
    $age = time() - $order->get_date_created()->getTimestamp();
    if ( $age > 14 * DAY_IN_SECONDS || $order->has_status( array( 'cancelled', 'refunded' ) ) ) {
        return;
    }
    $nonce = wp_create_nonce( 'tyw_withdraw_' . $order->get_id() );
    ?>
    <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
        <input type="hidden" name="action" value="tyw_submit_withdrawal" />
        <input type="hidden" name="order_id" value="<?php echo esc_attr( $order->get_id() ); ?>" />
        <input type="hidden" name="_wpnonce" value="<?php echo esc_attr( $nonce ); ?>" />
        <button type="submit" class="button">Withdraw from contract here</button>
    </form>
    <?php
}

add_action( 'admin_post_tyw_submit_withdrawal', 'tyw_handle_withdrawal' );
add_action( 'admin_post_nopriv_tyw_submit_withdrawal', 'tyw_handle_withdrawal' );
function tyw_handle_withdrawal() {
    $order_id = isset( $_POST['order_id'] ) ? (int) $_POST['order_id'] : 0;
    if ( ! $order_id || ! wp_verify_nonce( $_POST['_wpnonce'], 'tyw_withdraw_' . $order_id ) ) {
        wp_die( 'Invalid request', 400 );
    }
    $order = wc_get_order( $order_id );
    if ( ! $order ) wp_die( 'Order not found', 404 );
    $order->update_status( 'cancelled', 'Withdrawn by customer under Art. 11a CRD.' );

    wp_mail(
        $order->get_billing_email(),
        sprintf( 'Withdrawal received for order %s', $order->get_order_number() ),
        sprintf( "Your withdrawal from order %s was received at %s.\n\nRefund will be processed within 14 days.\n\nThis email is the durable-medium acknowledgement required by Article 11a(5) of the Consumer Rights Directive.",
            $order->get_order_number(), current_time( 'mysql' ) )
    );

    wp_safe_redirect( add_query_arg( 'withdrawal', 'confirmed', $order->get_view_order_url() ) );
    exit;
}

For a true two-step UX, render an intermediate confirmation page before this handler cancels the order.

Lightspeed eCom (template + Apps API)

Lightspeed eCom exposes no server-side form-handler hook. The compliant pattern is to edit the customer orders Rain template and post the form to a backend you control:

{% for order in orders %}
  <div class="order-row">
    {% if order.age_seconds < 1209600 and order.cancelled == false %}
      <a href="/pages/withdraw?order={{ order.number | url_encode }}"
         class="btn btn-primary">Withdraw from contract here</a>
    {% endif %}
  </div>
{% endfor %}

The backend (Node, PHP, Cloudflare Worker) calls PUT /orders/{id}.json on the Lightspeed eCom API with {"order":{"status":"cancelled"}} and then sends an acknowledgement email via your transactional provider.

Magento (Adobe Commerce)

Add a small custom module with layout, block, template, and controller. The button template:

<?php /** @var \Acme\Withdrawal\Block\Button $block */
$order = $block->getOrder();
if ( ! $block->isWithinWindow( $order ) ) return;
$action = $block->getUrl( 'withdrawal/cancel/submit', [ 'order_id' => $order->getId() ] );
?>
<form action="<?= $block->escapeUrl( $action ); ?>" method="post">
    <input type="hidden" name="form_key" value="<?= $block->escapeHtml( $block->getFormKey() ); ?>" />
    <button type="submit" class="action primary">Withdraw from contract here</button>
</form>

The controller calls $this->orderManagement->cancel( $orderId ) and triggers a transactional email via TransportBuilder using a custom template that mentions Article 11a(5).

Headless / custom (HTML + serverless)

<form method="post" action="/api/withdraw">
  <input type="hidden" name="order" value="ORD-2026-001" />
  <label>Your name <input type="text" name="name" required /></label>
  <label>Confirmation email <input type="email" name="email" required /></label>
  <button type="submit">Confirm withdrawal</button>
</form>
// api/withdraw.js (Vercel / Cloudflare / Netlify)
export default async function handler(req) {
  if (req.method !== 'POST') return new Response('Method not allowed', { status: 405 });
  const form  = await req.formData();
  const order = form.get('order');
  const email = form.get('email');
  await db.withdrawals.insert({ order, email, at: new Date() });
  await commerce.orders.cancel(order, { reason: 'Art. 11a CRD' });
  await mailer.send({
    to: email,
    subject: `Withdrawal received for order ${order}`,
    text: `Your withdrawal from order ${order} was received. Refund within 14 days. This email is the durable-medium acknowledgement required by Article 11a(5).`,
  });
  return Response.redirect(`/orders/${order}?withdrawal=confirmed`, 303);
}

The serverless pattern is the cleanest because it makes the three obligations, cancel, record, acknowledge, explicit and individually testable.

What the TrustYourWebsite scanner detects

The scanner runs ECOM-02 against your webshop and flags pages with no withdrawal/refund text and no links to a withdrawal/return/terms page in any EU language. The check uses multilingual patterns: English, Dutch (herroeping), German (Widerrufsrecht), French (rétractation), Italian (recesso), Spanish (desistimiento).

The scanner also runs ECOM-02b (Article 11a button-label match against the directive's exact wording per language — HIGH severity on customer-account paths) and ECOM-02c (presence of the model withdrawal form as either a download link or an inline form).

What the scanner still does not verify (manual review required):

  • The two-step process (statement → "Confirm withdrawal") end-to-end.
  • The durable-medium acknowledgement email.
  • The continuous availability of the button during the full 14-day window.

Findings are technical signals, not legal verdicts.

Also effective from July 2025 (ACM enforcement), webshops must clearly display the full shipping cost before the consumer enters checkout. This came into force earlier but is sometimes missed:

  • Shipping costs must appear on the product page or category page, not just in the cart
  • "Calculate in cart" is not compliant if the consumer has no indication of shipping costs before adding to cart
  • Country-based shipping rates must be selectable before checkout

The ACM has issued guidance and begun enforcement on shipping cost transparency as part of its broader e-commerce consumer rights focus.

ACM Enforcement

The ACM is the enforcement authority for consumer rights law in the Netherlands under the Wet handhaving consumentenbescherming (WHC). Since 2024, the ACM has increased enforcement in e-commerce:

  • In 2024-2025, the ACM focused on hidden fees, fake countdown timers, and subscriptions that are difficult to cancel
  • The "subscription trap" problem (moeilijk opzegbare abonnementen) has been a priority, services that make cancellation deliberately difficult
  • The withdrawal button requirement directly addresses this, it is a response to widespread non-compliance with the right of withdrawal

Maximum fine under WHC: €900,000. For consumer rights violations in e-commerce, the ACM typically starts with a compliance order (last-uiting) before imposing a fine.

Checklist: Preparing for June 19, 2026

  • Identify every online service you offer where the right of withdrawal applies
  • For each: locate where in your account/portal the consumer concluded the contract
  • Design and implement a clearly labelled withdrawal button accessible from that area
  • Implement immediate email confirmation of withdrawal
  • Test the entire flow end-to-end as a consumer
  • Update your terms and conditions to reference the digital withdrawal mechanism
  • Update your privacy policy if withdrawal triggers data deletion

Run a free TrustYourWebsite scan to see if ECOM-02 triggers on your webshop today.


This article is technical analysis, not legal advice. Consult a lawyer for advice specific to your situation.

Share this article