The withdrawal button has been mandatory for every B2C online shop in Germany since 19 June 2026. Directive (EU) 2023/2673 and its German transposition in Section 356a BGB require a two-step digital withdrawal option whose technical implementation demands far more than a button in the footer. Anyone who fails to provide the function, or provides it incorrectly, risks a formal warning letter from competitors and consumer protection associations; for widespread infringements Art. 246e EGBGB additionally provides for fines of up to 4 percent of annual revenue. This guide shows the concrete technical implementation in Shopware 6, the permitted label wording, the permitted data fields and the requirements for the receipt confirmation.
What applies from 19 June 2026
Directive (EU) 2023/2673 is transposed into German law by Section 356a BGB – electronic withdrawal function for distance contracts. The transposition deadline for member states ended on 19 December 2025; the provisions apply from 19 June 2026. From that date, every B2C shop must provide a functional withdrawal button that makes withdrawal considerably easier than filling a form or writing an e-mail. Further legal background is covered in our article on the Withdrawal Button Requirement 2026.
The scope is broad: Section 356a BGB applies to distance contracts concluded via an online user interface. The underlying directive states explicitly that the obligation applies not only to distance contracts for financial services but to all distance contracts for which a right of withdrawal exists. Anyone running a B2C shop cannot therefore argue that the rule targets financial products only – it applies to the trade in goods just the same.
The withdrawal period of 14 days remains unchanged (Section 355(2) BGB). Where proper withdrawal instructions are missing, the right of withdrawal expires only twelve months and 14 days after the regular start of the period (Section 356(4) BGB). Important: the button does not replace the obligation to provide the withdrawal instructions, it merely offers an additional, low-barrier way to exercise the right. Retailers must offer both channels in parallel – classical withdrawal by text and digital withdrawal by button.
A missing or incorrectly implemented withdrawal button breaches a statutory market conduct rule and can therefore be challenged by competitors and consumer protection associations. In addition, Art. 246e § 1(2) No. 14a EGBGB covers a missing or non-compliant withdrawal function and a missing acknowledgement of receipt; it is prohibited and subject to fines as a widespread infringement within the meaning of Regulation (EU) 2017/2394. Under Art. 246e § 2 EGBGB the range reaches up to 50,000 euros, and above 1.25 million euros of annual revenue up to 4 percent of annual revenue. Fines are imposed only within a coordinated enforcement action under Article 21 of Regulation (EU) 2017/2394 – in an individual case the warning letter is the more likely route.
Button anatomy: two-step flow
The legislator mandates a two-step process: step 1 is the actual button with the click, step 2 is a confirmation form in which identification data is entered and the withdrawal is submitted. Only this way can it be ensured that the customer triggers the withdrawal deliberately and that the retailer can clearly assign the order. A single-step implementation – a button that triggers the withdrawal directly without data collection – is inadmissible because no assignment would be possible.
The two steps must be clearly separated: step 1 is a pure statement of intent by the customer. After clicking "Withdraw from contract", either a dedicated page or a modal dialog containing the form opens. Only with the final click on "Confirm withdrawal" is the withdrawal legally declared and deemed received by the retailer. This moment is legally decisive, because from then on the period for returning the performances received runs – at the latest after 14 days (Section 357(1) BGB).
Technically, the flow can be realized via a dedicated route (e.g. /withdrawal) with a Twig template that first shows the button and then redirects to the form step via POST request. Alternatively, a modal dialog can be opened via JavaScript, as long as the dialog also works as a fallback via a normal page when JS is disabled – accessibility is mandatory anyway under the BFSG. A clean accessibility audit routine checks automatically whether contrast, keyboard navigation and screen-reader labels on the withdrawal form meet WCAG 2.1 AA.
Labels under Section 356a BGB
The law names a label for each of the two buttons and also permits another equivalent unambiguous wording (Section 356a(1) and (3) BGB). There is room for variants only as long as the intent to withdraw remains unmistakable – neutral phrases such as "Contact" or "Send message" do not meet this because they obscure the purpose.
| Element | Suitable | Unsuitable |
|---|---|---|
| Step 1 button | Withdraw contract | Contact us |
| Step 2 button | Confirm withdrawal | Send |
| Alternative step 1 | Declare withdrawal | Send message |
| Alternative step 2 | Trigger withdrawal now | Submit |
| Page title | Declare withdrawal | Return |
| Footer link text | Withdraw contract | Returns |
The wording "Withdraw contract" renders the label that Section 356a(1) BGB names for the primary button; "Confirm withdrawal" renders the label named in subsection (3) for the confirmation button. Using the words of the law saves checking whether an own wording is equivalent. Anyone who has already engaged a Shopware agency with the implementation should deposit these labels in the snippet set and translate them appropriately – for German shops as "Vertrag widerrufen" and "Widerruf bestätigen".
Placement in the shop
The button must be placed permanently, visibly and with high contrast. Burying it inside a nested help section does not suffice. Two placements are recommended: prominently in the footer on every page, plus in the customer account under "My orders". Particularly important: the button must also be reachable for non-logged-in visitors (guest orders) – placement exclusively behind the customer account login is inadmissible.
- Position in the footer of every page, above or next to imprint/terms
- Additionally in the header as a link or in meta navigation
- In the customer account linked directly to every withdrawable order
- Also reachable for guest orders via a separate page without login
- High contrast designed per WCAG 2.1 AA (min. 4.5:1 for body text)
- Fully usable on mobile, tap target at least 44 × 44 px
- Not hidden behind multiple clicks or accordions
- Functional even with JavaScript disabled
If you follow a clean checkout optimization approach, deliberately do NOT place the button inside the active order process. It belongs in the post-purchase phase (customer account, footer, order confirmation e-mail) – not in the phase where purchase decisions are still being made.
Data you are allowed to request
The law strictly limits data collection in the withdrawal form to the minimum needed for clear assignment. Querying withdrawal reasons, satisfaction scales or alternative return options during the withdrawal process is inadmissible and would put you at risk of warning letters.
Name
First and last name for identification of the contracting party – mandatory field
Order number
Unique reference to the order to be withdrawn – mandatory field
E-mail address
Address for the automatic receipt confirmation – mandatory field
These three fields are sufficient. Optionally you may offer a selection of the specific item to be withdrawn if partial withdrawal should be supported – for instance with multiple line items in one order. Under no circumstances may you request: reasons for withdrawal, a request for comment before withdrawal, questions about payment method or alternative offers such as vouchers. A return reason survey may be offered after the completed withdrawal on a voluntary basis – our guide on returns management shows how to collect that data without legal risk.
The strict data minimization follows directly from the statute: Section 356a(2) BGB lists exhaustively which information the withdrawal function may ask for – the consumer's name, details identifying the contract or the part being withdrawn, and details of the electronic means of communication used to send the receipt confirmation. Return reasons are commercially interesting, and it is precisely that relevance which tempts retailers to misuse the withdrawal form as a feedback channel – the statutory list leaves no room for it.
Return reasons therefore belong in a separate process: a separate mail with an optional survey two to three days after the return arrives, clearly voluntary and with no bearing on how the withdrawal is handled. That keeps the withdrawal process and the returns analysis cleanly separated in legal terms, and the analysis rests on answers the customer gave deliberately.
Technical integration in Shopware 6
Since version 6.7.9.0 from April 2026, Shopware ships a revocation form in its core system; the function was backported to Shopware 6.6 and is also available in the Community Edition. Whether the version you run already includes the core function can be checked in its release notes. If you cannot upgrade or need a different flow, implement the feature as a custom plugin. The following minimal implementation shows the controller for the second step (form submission):
<?php declare(strict_types=1);
namespace Xictron\Withdrawal\Storefront\Controller;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Storefront\Controller\StorefrontController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @RouteScope(scopes={"storefront"})
*/
class WithdrawalController extends StorefrontController
{
public function __construct(
private readonly EntityRepository $withdrawalRepository,
private readonly WithdrawalMailService $mailService
) {}
/**
* @Route("/withdrawal", name="frontend.withdrawal.form", methods={"GET"})
*/
public function form(Request $request): Response
{
return $this->renderStorefront('@XictronWithdrawal/storefront/page/withdrawal/index.html.twig');
}
/**
* @Route("/withdrawal/submit", name="frontend.withdrawal.submit", methods={"POST"})
*/
public function submit(Request $request, Context $context): Response
{
$name = trim((string) $request->request->get('name'));
$orderNumber = trim((string) $request->request->get('orderNumber'));
$email = filter_var($request->request->get('email'), FILTER_VALIDATE_EMAIL);
if (!$name || !$orderNumber || !$email) {
$this->addFlash('danger', 'Please fill in all mandatory fields.');
return $this->redirectToRoute('frontend.withdrawal.form');
}
$reference = 'WDR-' . date('Y') . '-' . strtoupper(substr(Uuid::randomHex(), 0, 5));
$this->withdrawalRepository->create([[
'id' => Uuid::randomHex(),
'reference' => $reference,
'customerName' => $name,
'orderNumber' => $orderNumber,
'email' => $email,
'receivedAt' => new \DateTimeImmutable(),
]], $context);
$this->mailService->sendConfirmation($email, $name, $orderNumber, $reference);
$this->mailService->notifyMerchant($name, $orderNumber, $reference);
return $this->redirectToRoute('frontend.withdrawal.success', ['ref' => $reference]);
}
} The database entity withdrawal stores the incoming data with a timestamp for evidence. Additionally, a trigger must be set up in the Shopware Flow Builder that initiates internal processes when a new withdrawal arrives – creating a return in the ERP, pausing pending shipping orders and informing the customer service team. For the form view itself, a slim Twig template with three input fields is enough. Shops running a custom frontend with Vue or Nuxt implement the flow as a separate SPA route with a REST endpoint.
Automating receipt confirmation
The retailer is obliged to confirm receipt of the withdrawal without undue delay on a durable medium. In practice that means: within a few minutes of form submission, an e-mail must go to the customer documenting the receipt. The confirmation must contain at least: the customer's name, order number, timestamp of receipt (date and time), a unique reference ID and brief information about the next steps.
Technically, a mail template in the Shopware mail system with placeholders {{ customerName }}, {{ orderNumber }}, {{ receivedAt|format_datetime }} and {{ reference }} is recommended. To avoid delays, sending should not happen synchronously in the request handler but asynchronously via the Shopware message queue in a worker process. This keeps the customer's response time below 500 ms even when the SMTP server is currently under load.
In parallel with the customer mail, an internal notification system should be set up: a message to the customer service team, optionally a ticket in the ticketing system or a push notification to logistics. The retailer's obligation of proof relates to the receipt confirmation – it must be verifiable when and how the withdrawal was received. A detailed log entry with IP address and user agent (without personal processing beyond order assignment) protects in case of dispute.
The reference ID should meet the following requirements: unique across all withdrawals, not guessable (to prevent enumeration attacks), human-readable for support enquiries and short enough to fit into subject lines. A proven scheme is WDR-YEAR-ABCDE with five random alphanumeric characters (around 60 million combinations per year). This reference code should be used consistently in all follow-up mails (receipt confirmation, return shipping information, refund confirmation) so that customer and support can trace the case at any time.
Exceptions: when the button is not needed
Not every shop needs a withdrawal button. The obligation only applies to contracts for which a statutory right of withdrawal exists. In the following constellations the button obligation is fully or partially waived:
- Pure B2B shops without end-customer sales – no right of withdrawal, no button needed
- Sale of personalized goods (e.g. engraving, individual configuration)
- Easily perishable food with limited shelf life
- Sealed media (CDs, DVDs, software) after the seal has been removed
- Digital content on a non-physical medium once execution has begun
- Financial services with their own withdrawal rules (extended deadlines)
- Goods that have been inseparably combined with other items
- Contracts concluded at public auctions
With mixed assortments (B2C + B2B in one shop, or standard items + personalized items), the button must generally be provided. In our guide on customer-specific assortments in B2B shops we show how customer groups can be cleanly separated so that the obligation only applies to actually affected B2C orders.
Warning letter risk and typical mistakes
Waves of warning letters typically start within days of a deadline because the breach is visible from the outside: whether a shop provides a withdrawal function can be checked without a test order and without a customer account. That is exactly what makes the withdrawal button a convenient ground for a warning letter – unlike, say, faulty background data processing, which only surfaces when somebody reports it.
| Typical mistake | Correct implementation |
|---|---|
| Only a "Contact" link in the footer | Dedicated button "Withdraw contract" |
| Button only in customer account | Also in footer and for guests |
| Single-step process without form | Two-step: click + confirmation |
| Reason for withdrawal is requested | Only name, order number, e-mail |
| No receipt confirmation by mail | Automatic confirmation with reference |
| Button hidden behind login | Accessible without login as well |
| Color contrast too low | WCAG 2.1 AA, min. 4.5:1 |
| Mail sent only after 24 h | Sent without undue delay via worker queue |
This weighs more heavily on small retailers than on large ones: a warning letter ties up time and money that are missing from day-to-day operations, and fixing things under deadline pressure costs more than a clean initial implementation. Early consulting is therefore as a rule the cheaper option compared with a later fix after a warning letter has been issued.
Checklist for implementation and review
- Stocktaking: which order types exist, which customer groups, which exceptions apply; check the Shopware version in use and whether it already includes the core function
- Technical draft: check whether the core form from 6.7.9.0 (backport 6.6) covers the need; otherwise define route, template, controller, data model, mail templates and Flow Builder integration
- Development and code review: install the Shopware update or develop a plugin, adapt the storefront template
- End-to-end test in staging: form flow, confirmation mail, internal notification, Flow trigger, mobile, accessibility
- Legal review: review by a specialist lawyer, label check, privacy review, update of the privacy policy
- Deployment: release to production, cache warm-up, monitoring of error logs
- Operation: for the first 48 hours after go-live watch logs and mail queue closely, prepare the support team for inquiries; retest the flow after every Shopware update
Anyone who does not yet provide the function, or provides it only in part, should close the gap promptly, because the obligation already applies. Where the core form does not fit, a custom implementation is usually a matter of days of pure development work, depending on shop complexity – plus testing and legal review. Those relying on custom programming or running a headless frontend should plan considerably more time, because the API interfaces must be designed along.
This article rests on the legal sources themselves: Directive (EU) 2023/2673 of 22 November 2023 – applicable since 19 June 2026, withdrawal function under Article 11a of Directive 2011/83/EU; Section 356a BGB – electronic withdrawal function, labeling, exhaustive list of the data that may be requested, receipt confirmation on a durable medium; Sections 355 and 356 BGB – withdrawal period of 14 days, expiry at the latest twelve months and 14 days after the start of the period; Art. 246e EGBGB as amended by the Act of 3 February 2026 (BGBl. 2026 I No. 28) – No. 14a covers a missing or non-compliant withdrawal function, fine range up to 50,000 euros, above 1.25 million euros of annual revenue up to 4 percent of annual revenue, only within a coordinated enforcement action. On the state of Shopware: the release notes for version 6.7.9.0 and Shopware's information on the withdrawal button. Market figures on the frequency of warning letters and on return rates are deliberately absent from this guide: they change nothing about the technical requirements. Status: September 2026.
Since 19 June 2026, a missing function can be challenged through warning letters from competitors and consumer protection associations. In addition, a missing or non-compliant withdrawal function is subject to fines under Art. 246e EGBGB as a widespread infringement: up to 50,000 euros, and up to 4 percent of annual revenue for companies with more than 1.25 million euros of annual revenue – but only within a coordinated enforcement action by the competent authorities. Anyone who does not yet fully provide the function should close the gap promptly without skipping testing and legal review. Our Shopware agency supports implementation and review.
The law limits the request to the minimum: name, order number and e-mail address. Asking for the withdrawal reason or alternative offers during the withdrawal process is inadmissible. Typically a form with exactly three input fields suffices. Optionally, selecting individual positions to be withdrawn can be added if partial withdrawal should be offered.
Yes. Placement exclusively behind the customer account login is inadmissible because guest buyers would be disadvantaged. The withdrawal button must be permanently publicly reachable – typically prominently in the footer on every page. In the form itself the customer then identifies themselves via name, order number and e-mail address.
The law mandates confirmation without undue delay on a durable medium. In practice: within a few minutes of form submission, an e-mail must arrive at the customer. Technically, sending should happen asynchronously via the Shopware message queue so the response time for the customer remains short. The confirmation must contain name, order number, time of receipt and a reference ID.
Since version 6.7.9.0 from April 2026, a revocation form has been part of the Shopware core system; the function was backported to Shopware 6.6 and is also available in the Community Edition. Whether the version you run already includes it, and whether the flow in your shop fully meets the requirements of Section 356a BGB – two steps, permitted data, receipt confirmation – should be checked before go-live. Anyone on an older version or needing individual adjustments – for headless setups or specific customer group logic – implements the feature as a custom plugin. Typically such an integration including tests can be realized in 3 to 8 working days. We recommend early consulting on the technical architecture.
Pure B2B shops without end-customer sales are not affected because no statutory right of withdrawal exists for them. With mixed assortments (B2C + B2B in parallel), however, the obligation applies because the shop enables B2C orders. In our article on customer-specific assortments in B2B shops we show how customer groups can be cleanly separated so the obligation applies specifically to the affected orders.