<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: luca kingsley</title>
    <description>The latest articles on DEV Community by luca kingsley (@luca_kingsley).</description>
    <link>https://dev.to/luca_kingsley</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4141345%2F9f890f3f-ceef-4b27-8882-1903addd82a6.png</url>
      <title>DEV Community: luca kingsley</title>
      <link>https://dev.to/luca_kingsley</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luca_kingsley"/>
    <language>en</language>
    <item>
      <title>EU shop rules: what developers need to change this weekend</title>
      <dc:creator>luca kingsley</dc:creator>
      <pubDate>Sat, 26 Sep 2026 03:12:51 +0000</pubDate>
      <link>https://dev.to/luca_kingsley/eu-shop-rules-what-developers-need-to-change-this-weekend-59ca</link>
      <guid>https://dev.to/luca_kingsley/eu-shop-rules-what-developers-need-to-change-this-weekend-59ca</guid>
      <description>&lt;p&gt;If you build or maintain online shops for EU customers, three rules changed this year, and one of them starts tomorrow, &lt;strong&gt;Sunday 27 September 2026&lt;/strong&gt;. Here's what they mean in code, plus two gotchas I ran into while implementing them for WooCommerce.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not legal advice. Everything below is from the official sources linked at the end.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The EU legal guarantee notice (from 27 September 2026)
&lt;/h2&gt;

&lt;p&gt;Every seller of goods to consumers in the EU has to show a harmonised notice about the legal guarantee. You don't design it: the European Commission publishes one official sheet (blue header, short text, QR code) in all 24 EU languages, as SVG, PNG and PDF.&lt;/p&gt;

&lt;p&gt;What the Commission's practical guidelines require online:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;official file, in colour, unchanged&lt;/strong&gt;: no recolouring, cropping, changing fonts or touching the QR code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;legible at default display size&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;always a clickable link&lt;/strong&gt; to the same destination as the QR code&lt;/li&gt;
&lt;li&gt;displayed "prominently", for example a sentence like "Your legal guarantee rights" that opens the notice on the first click&lt;/li&gt;
&lt;li&gt;also in the &lt;strong&gt;order confirmation email&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The simplest markup that works everywhere, even inside site builders that sandbox your HTML in an iframe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;details&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"eu-guarantee"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Your legal guarantee rights&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/eu-guarantee-en.svg"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"noopener"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/eu-guarantee-en.svg"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"595"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"842"&lt;/span&gt;
         &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"EU notice on the legal guarantee: goods sold in the EU come with a legal guarantee of conformity of at least two years."&lt;/span&gt;
         &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:block;width:100%;max-width:595px;height:auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://europa.eu/youreurope/guarantees"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"noopener"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;europa.eu/youreurope/guarantees&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Host the file yourself instead of hotlinking. Each language has its own link target (German is &lt;code&gt;europa.eu/youreurope/garantien&lt;/code&gt;, French &lt;code&gt;.../garanties&lt;/code&gt;, and so on).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gotcha 1: the WooCommerce checkout block ignores the classic hooks.&lt;/strong&gt; Since WooCommerce 8.3 new shops get the block checkout by default, and &lt;code&gt;woocommerce_review_order_before_submit&lt;/code&gt; simply never fires there. The inner part is rendered by React, so HTML you inject inside it can disappear. What worked for me is placing it right before the block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'render_block_woocommerce/checkout'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$html&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;div class="eu-guarantee-checkout"&amp;gt;'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;my_notice_html&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;/div&amp;gt;'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gotcha 2: SVG in emails.&lt;/strong&gt; Many mail clients don't render SVG, so use the Commission's PNG for the order email. Curiously, the PNG package has 23 languages and is missing English, which only exists as SVG and PDF. For English emails I fall back to the sentence plus link.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The withdrawal button (since 19 June 2026)
&lt;/h2&gt;

&lt;p&gt;Directive (EU) 2023/2673 added a "withdrawal function" for contracts concluded online. Germany implemented it in § 356a BGB. The flow is fixed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;a clearly labelled &lt;strong&gt;"withdraw from contract"&lt;/strong&gt; button or link, available during the whole withdrawal period&lt;/li&gt;
&lt;li&gt;a short form: name, which contract/order, where to send the confirmation&lt;/li&gt;
&lt;li&gt;a second button, &lt;strong&gt;"confirm withdrawal"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;immediate acknowledgement&lt;/strong&gt; on a durable medium (in practice an email) with the content of the withdrawal and the &lt;strong&gt;date and time&lt;/strong&gt; it was received&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;According to the German legislative reasoning, it should be reachable from every page, must not force a login if customers can order as guests, and must not ask for a reason. Shopify, Shopware, JTL and the German legal plugins for WooCommerce ship implementations; check the version you're on.&lt;/p&gt;

&lt;p&gt;The part nobody tests is step 4. Actually submit a test withdrawal and read the email: does it contain the date &lt;strong&gt;and&lt;/strong&gt; the time? Does it say which order? Wording like "your withdrawal is hereby confirmed" is discouraged: say it was &lt;em&gt;received&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Green claims (from 27 September 2026)
&lt;/h2&gt;

&lt;p&gt;Directive (EU) 2024/825 adds several claims to the list of practices that are always banned towards consumers, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;generic environmental claims ("eco-friendly", "green", "climate friendly") without recognised excellent environmental performance&lt;/li&gt;
&lt;li&gt;"climate neutral" and similar claims based on offsetting emissions&lt;/li&gt;
&lt;li&gt;self-made sustainability labels that aren't based on a certification scheme&lt;/li&gt;
&lt;li&gt;claims about the whole product when they're only true for a part&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For developers this is mostly a content audit, but a catalogue with hundreds of products needs tooling. One detail if you grep product texts in JavaScript: &lt;code&gt;\b&lt;/code&gt; doesn't treat umlauts as word characters, so &lt;code&gt;\bökologisch&lt;/code&gt; never matches. Unicode-aware boundaries do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(?&amp;lt;![&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;p{L}&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;p{N}])&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(?![&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;p{L}&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;p{N}])&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;(?:umweltfreundlich|eco-friendly)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;p{L}*&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;giu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A hit means "check this", not "banned": whether "climate neutral" is illegal depends on whether it rests on offsetting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;I put all of this into a small, free hub, one chapter per rule with sources and dates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shop rules check:&lt;/strong&gt; enter a shop URL, see what's there and what's missing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ad copy checker:&lt;/strong&gt; paste texts or a Shopify/WooCommerce CSV export; runs in the browser&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notice builder:&lt;/strong&gt; the official file in 24 languages with ready-made code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;a href="https://kingsley-ym.de/en/shop-rules" rel="noopener noreferrer"&gt;https://kingsley-ym.de/en/shop-rules&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear what breaks: false positives, shop systems I got wrong, anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;European Commission: &lt;a href="https://commission.europa.eu/publications/practical-guidelines-and-high-resolution-vector-files-eu-notice-and-label-product-guarantees_en" rel="noopener noreferrer"&gt;practical guidelines and official files for the notice and label&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Your Europe: &lt;a href="https://europa.eu/youreurope/business/selling-in-eu/consumer-contracts-guarantees/eu-legal-guarantee-notice-and-garan-label/index_en.htm" rel="noopener noreferrer"&gt;EU legal guarantee notice and GARAN label&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://eur-lex.europa.eu/eli/dir/2024/825/oj" rel="noopener noreferrer"&gt;Directive (EU) 2024/825&lt;/a&gt; (green claims) and &lt;a href="https://eur-lex.europa.eu/eli/reg_impl/2025/1960/oj" rel="noopener noreferrer"&gt;Implementing Regulation (EU) 2025/1960&lt;/a&gt; (notice and label)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gesetze-im-internet.de/bgb/__356a.html" rel="noopener noreferrer"&gt;§ 356a BGB&lt;/a&gt; (German implementation of the withdrawal function)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>ecommerce</category>
      <category>woocommerce</category>
      <category>shopify</category>
    </item>
  </channel>
</rss>
