# EU right of withdrawal

> Add the withdrawal button that EU Directive 2023/2673 requires from 19 June 2026. Covers what the rule asks, a withdrawal page on your Webflow site with the metaobject creator and Shopify Flow, and a withdrawal app on a page hosted by Shopify.

Status: Ready (Smootify 2.0)  
1.x page: https://docs.smootify.io/docs/internationalization/eu-withdrawal-compliance  
URL: https://www.smootify.io/docs/features/eu-withdrawal  
Updated: 2026-10-11

Since **19 June 2026**, a store that sells online to consumers in the European Union must offer an electronic withdrawal function, such as a button or a link, that customers use to withdraw from a purchase within their 14 days. This page says what the rule asks and gives two ways to meet it on a Webflow site: a withdrawal page on your site, built with Smootify’s metaobject creator and Shopify Flow, or the form of a withdrawal app on a page hosted by Shopify.

> [!WARNING]
> This page is guidance, not legal advice. Following it does not guarantee that your store meets EU Directive 2023/2673, and Smootify takes no responsibility for fines, penalties or other legal consequences. Check your setup with a lawyer who knows the rules of the countries you sell to.

## What the rule asks

[EU Directive 2023/2673](https://help.shopify.com/en/manual/compliance/legal/eu-right-of-withdrawal) asks for:

- **A visible withdrawal button.** A clearly labelled function that is easy to find and works without logging in.
- **Two steps.** After the withdrawal button, the customer confirms the withdrawal and gives their name and order details.
- **A confirmation on a durable medium, without delay.** Your store sends the customer an acknowledgement of receipt, for example by email, with the content of their request and the date and time it was received.

**Who must comply.** Any business that sells goods, services or digital content online to consumers in the EU, wherever the business is based.

**Exemptions.** Some products are exempt from the 14-day right of withdrawal. Which of your products are exempt is your decision, with your lawyer.

**Penalties.** A store without the withdrawal function can face:

- legal warnings;
- fines of up to 4% of annual turnover in some EU countries;
- a longer withdrawal period: the 14 days can become 12 months and 14 days.

## Shopify’s own option

Shopify’s new customer accounts have self-serve returns, which can help with the rule: see [Shopify’s setup guide](https://help.shopify.com/en/manual/fulfillment/managing-orders/returns/self-serve-returns/setup). They need the customer to log in, and the rule asks for a function that works without logging in, so check with your lawyer whether they are enough for your store.

## Two ways on a Webflow site

Withdrawal apps for Shopify draw their button inside a Shopify theme, and a Webflow site has no theme. So the withdrawal form goes in one of two places:

- **A. A page on your Webflow site.** A Webflow form saves each request in Shopify as a metaobject entry, and a Shopify Flow workflow checks the order and sends the emails. The page has your design and your domain. It needs the **Server** plan and **Metaobject creator** turned on in the Smootify dashboard.
- **B. A page hosted by Shopify.** A withdrawal app shows its form on a page of your Shopify store, and your site links to it. It works on every Smootify plan, and the app sends the confirmation.

## A. A withdrawal page on your site

> [!NOTE]
> This way needs the **Server** plan, **Metaobject creator** turned on in the Smootify dashboard, and the free **Shopify Flow** app. The form runs on the site's licensed domain. See [Collect data with forms](https://www.smootify.io/docs/features/metaobject-creator).

### 1. Create the definition in Shopify

Under **Settings > Custom data > Metaobjects**, add a definition with the type `withdrawal_request` and these fields:

- `name`: Single line text;
- `email`: Single line text;
- `order_number`: Single line text;
- `products`: Multi-line text, for the products the request is about (optional for the customer).

The definition needs no Storefronts access: the site never shows the requests.

### 2. Build the page

Create a page such as `/withdrawal`, open to everyone. Smootify needs only the form; the two steps are up to your design:

1. A first button, “Withdraw from the contract”, opens the form. A Custom element with the tag `details`, holding a Custom element with the tag `summary` and the form, does it without interactions. A popover works too: see [Popovers](https://www.smootify.io/docs/build/popovers).
2. The form: a Custom element with the tag `metaobject-creator` and the custom attribute `data-type="withdrawal_request"`, with a Webflow Form Block inside. Its Form Button, “Confirm withdrawal”, is the second step.

```html
<details>
  <summary>Withdraw from the contract</summary>
  <metaobject-creator data-type="withdrawal_request">
    <div class="w-form">
      <form>
        <input name="name">
        <input name="email">
        <input name="order_number">
        <textarea name="products"></textarea>
        <input type="submit" value="Confirm withdrawal" data-wait="Sending…">
      </form>
      <div class="w-form-done"><div>We have received your withdrawal request. A confirmation is on its way to your email.</div></div>
      <div class="w-form-fail"><div>Something went wrong. Please try again.</div></div>
    </div>
  </metaobject-creator>
</details>
```

- **Field names are the keys.** Each field’s **Name**, in its element settings, is the key of a field of the definition. Webflow renames fields when you copy a form: check every Name after pasting.
- **Required fields.** Turn on **Required** for the name, the email and the order number, and set the email field’s Type to **Email**, in the element settings.
- **The order number.** Ask for it as it shows on the order confirmation, such as `#1001`, and say so in the field’s label or placeholder.
- **No `customer-field`.** It would hide the form from visitors who are not logged in, and the rule asks for a function that works without logging in.
- **The Success message** says the request has arrived and that a confirmation follows by email. The email itself comes from the workflow, step 4.

### 3. Link the page

Link `/withdrawal` from the places your customers look: see [Where to link the withdrawal form](#where-to-link-the-withdrawal-form).

### 4. Build the workflow in Shopify Flow

The workflow sends the customer the acknowledgement of receipt, then finds the order and marks it. Import it ready-made from [EU withdrawal request](https://www.smootify.io/flows/eu-withdrawal-request); its steps are also in [The withdrawal workflow](#the-withdrawal-workflow) at the end of this page.

## B. An app on a page hosted by Shopify

The withdrawal app shows its form on a page of your Shopify store, and your Webflow site links to it. Several apps on the Shopify App Store offer the form, each with a free plan:

- [Revoq - EU Withdrawal Button](https://apps.shopify.com/eu-withdrawal-form): tested and recommended by Smootify;
- [EU Withdrawal Button & Form](https://apps.shopify.com/eu-widerrufsbutton);
- [Retractly: EU Withdrawal](https://apps.shopify.com/revoka).

The steps below use Revoq, the app the Smootify team tested. They work with Smootify’s [Redirect theme](https://www.smootify.io/docs/start/domains) as the live theme of your store. Every page of that theme sends visitors to your Webflow site, so the withdrawal page gets a layout of its own, which does not redirect. The current version of the theme, 1.1.1, does not include this layout: you create it once.

### 1. Create the layout

In Shopify, go to **Online Store > Themes**, open the menu (**…**) of the Smootify Redirect theme and choose **Edit code**. Under **Layout**, add a new layout named `eu`, so the file is `eu.liquid`, and paste:

```liquid
<!doctype html>
<html lang="{{ request.locale.iso_code }}">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="preconnect" href="https://cdn.shopify.com" crossorigin>
    <meta name="robots" content="noindex">
    <title>
      {{ page_title }}
    </title>
    {%- if settings.favicon != blank -%}
      <link
        rel="icon"
        type="image/png"
        href="{{ settings.favicon | image_url: width: 32, height: 32 }}"
      >
    {%- endif -%}

    {{ content_for_header }}
    <style>
      body {
        font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
      }
    </style>
  </head>
  <body>
    {{ content_for_layout }}
  </body>
</html>
```

The layout shows only the content of the page, with no theme styles, and `noindex` keeps the page out of search engines: it is a form, not content.

### 2. Create the page and its template

The template must hold the app’s block, so it is made in the theme editor, not in code:

1. Go to **Online Store > Pages** and create a page with any title, such as “EU Withdrawal”.
2. In **Online Store > Themes**, click **Customize** on the Smootify Redirect theme.
3. From the menu at the top, open **Pages** and create a template named `eu`. Save: Shopify creates the file `page.eu.json`.
4. Back in **Online Store > Pages**, open your page and set its **Theme template** to `eu`.
5. In **Edit code**, under **Templates**, open `page.eu.json` and change the value of `"layout"` to `"eu"`:

```json
{
  "layout": "eu",
  ...rest of the file
}
```

The page now uses the `eu.liquid` layout instead of the theme’s own, which would redirect it.

### 3. Add the app’s form

Install [Revoq](https://apps.shopify.com/eu-withdrawal-form) from the Shopify App Store. In the theme editor, open your page and add the **Revoq withdrawal form** app block. Set up the app as you need, such as its look and languages: Revoq comes with all 24 EU languages.

### 4. Link the page

The page’s address is your Shopify store’s address followed by the page’s, such as `https://your-store.myshopify.com/pages/eu-withdrawal`. Open it to check that the form shows and that it does not redirect, then link it: see the next section.

## Where to link the withdrawal form

Customers must find the form easily. Link the page, `/withdrawal` for way A or the Shopify page for way B:

- **In the footer.** A Text link or a Link block in the footer Component, so it is on every page.
- **On your legal pages**, such as the returns page. If that page shows Shopify’s refund policy with the `policy="refund"` attribute, put the link next to it: see [policy](https://www.smootify.io/docs/reference/attributes/policy).
- **In the order confirmation email.** In Shopify, go to **Settings > Notifications > Customer notifications > Order confirmation**, edit the template and add the link.

## The withdrawal workflow

The ready-made file is on [EU withdrawal request](https://www.smootify.io/flows/eu-withdrawal-request): import it in Shopify Flow, set your email service and your address, and turn it on. These are its steps.

For way A. In Shopify Flow, create a workflow with these steps. The emails need an app that sends emails from Flow, such as Workflow Email, or, on the Grow, Advanced and Plus plans, Flow’s **Send HTTP request** to an email service such as Resend. Flow’s **Send internal email** writes only to your staff, not to the customer.

1. **Trigger: Metaobject entry created**, set to the `withdrawal_request` definition.
2. **Send the customer the acknowledgement of receipt**, to the email of the entry, right away and for every request. It repeats what they sent (name, email, order number, products) and the date and time it was received: use the entry’s creation time (`createdAt`), which Shopify sets on its servers when the request is saved, not the time the workflow runs. Show it in your store’s time zone, with the zone written next to it. This email is the durable medium the rule asks for.
3. **Get order data**, searching for the order with the order number of the entry.
4. **Condition:** an order was found and its email is the email of the entry.
5. **If yes:**
   - add the tag `withdrawal-requested` to the order, with **Add order tags**;
   - write a note on the order with the date and time of the request and the products it names, with Flow’s order note action or a **Send Admin API request** (`orderUpdate`);
   - send your store an email with the request’s details and a link to the order in your Shopify admin.
6. **If no:** send your store an email with the request’s details, so someone finds the order and follows up with the customer. The customer already has their acknowledgement from step 2.

Test it with a real order of your own: send the form with its number and email, then check the tag, the note and both emails.

## Before you publish

> [!STUCK]
> - **The withdrawal form is hidden for visitors who are not logged in.** The `metaobject-creator` has `customer-field`. Remove it: the rule asks for a form that works without logging in.
> - **Nothing is saved, and the Error message names a field.** A field's Name is not the key in Shopify. Webflow renames fields when you copy a form: fix each Name.
> - **The form disappears on the live site.** The Server plan or Metaobject creator is missing, or the page is not on the licensed domain.
> - **Requests arrive, but the customer gets no email.** The workflow sends it with **Send internal email**, which writes only to your staff. Use an email app for Flow, or a **Send HTTP request** to an email service.
> - **The Shopify page sends visitors to the Webflow site.** The page's template still uses the theme's layout. Set `"layout": "eu"` in `page.eu.json`, and the page's Theme template to `eu`.
> - **The app's block is missing in the theme editor.** The page is not on the `eu` template, or the app is not installed yet.
