Adding the GARAN-Label and legal guarantee notice in Magento 2
Two jobs, two mechanisms: a site-wide notice via CMS block and layout XML, and a per-product GARAN-Label via a product attribute. Both work with native Magento means, on Luma and on Hyvä.
As of 11 September 2026, Magento Open Source and Adobe Commerce ship no native feature for the legal guarantee notice or the GARAN-Label. Several marketplace extensions cover the topic. This page shows how to do it with on-board means, so you can decide whether you need an extension at all. It is a recommendation based on the current market situation, not legal advice.
Two jobs, two mechanisms
Legal guarantee notice: site-wide
Identical for every product, but different per language. In Magento terms: a CMS block per store view, inserted once into the product page layout.
GARAN-Label: per product
Different for every model (brand, model, guarantee duration), identical across languages. In Magento terms: a product attribute with global scope, rendered by a small template on the product detail page.
Legal guarantee notice: CMS block plus layout XML
- Under Content > Blocks, create a block with the identifier
legal-guarantee-noticeand upload the notice image for the language of that store view. - Create one block per language, all with the same identifier, and assign each to the matching store views. Magento resolves the identifier per store view, so the layout needs a single reference.
- Insert the block into the product page with a layout update in your theme:
<!-- app/design/frontend/Vendor/theme/Magento_Catalog/layout/catalog_product_view.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="product.info.main">
<block class="Magento\Cms\Block\Block" name="legal.guarantee.notice" after="product.info.overview">
<arguments>
<argument name="block_id" xsi:type="string">legal-guarantee-notice</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page> No theme access? The same result is possible without code: under Content > Widgets, create a widget of type "CMS Static Block", choose the layout update "Catalog Product View" and a container in the main content area. Page Builder can also edit the block content itself, which is handy if marketing rather than development maintains the notice.
GARAN-Label: creating the product attribute
Under Stores > Attributes > Product, add a new attribute with these settings:
| Attribute code | garan_label_url | Lowercase, no spaces. You will reference it in templates and import files. |
| Catalog input type | Text Field | Holds the URL of the self-hosted PNG. See the FAQ on why not a Media Image. |
| Scope | Global | The label is language-neutral: brand, model and duration are the same in every store view. Global scope means one value, one import row per SKU. |
| Visible on Catalog Pages on Storefront | No | Otherwise the raw URL shows up in the "More Information" tab. You render the image yourself instead. |
| Attribute set | All sets that contain guaranteed products | Under Stores > Attributes > Attribute Set, drag the attribute into a group of every relevant set. Products in a set without the attribute cannot store a value. |
The scope decision is the one that matters for the 24-language setup: the notice differs per store view and lives in CMS blocks; the label is global and lives in one attribute. Mixing this up is the most common source of import trouble later.
Rendering the label on the product detail page
You have three options, from most to least control:
- Template plus layout XML. Add a small template to your theme that outputs the image when the attribute is set, and reference it in
catalog_product_view.xmlnext to the notice block. Works on Luma and Hyvä; only the markup differs. - Page Builder or CMS block with a dynamic snippet. Suitable for the notice; not suitable for the per-product label, because a static block cannot read the current product's attribute without custom code.
- Widget. Same limitation as CMS blocks for per-product data. Fine for the notice, not for the label.
<?php /** @var \Magento\Catalog\Block\Product\View $block */
$labelUrl = $block->getProduct()->getData('garan_label_url'); ?>
<?php if ($labelUrl): ?>
<div class="garan-label">
<img src="<?= $block->escapeUrl($labelUrl) ?>"
alt="<?= $block->escapeHtmlAttr(__('EU guarantee label (GARAN) for this product')) ?>"
loading="lazy" />
</div>
<?php endif; ?> Placement rules
- On the product detail page, in the information area near the product image and price, not in the image gallery.
- In colour and at readable size. Do not scale it into an icon.
- Visible without interaction: not behind a hover, not only inside a tab, not only on a linked page.
- Use the PNG version. Why PNG rather than SVG →
Bulk populating the attribute via CSV import
For a large catalogue you do not fill the attribute product by product. Generate the labels in bulk, host the PNG files on your own server or CDN, and import the URLs with Magento's native product import under System > Data Transfer > Import:
- Entity type: Products. Import behaviour: Add/Update.
- The file needs only two columns:
skuandgaran_label_url. All other product data stays untouched. - The attribute must exist before the import. A column for an unknown attribute is not applied.
sku,garan_label_url
GSR18V-55-BLUE,https://cdn.example.com/garan/bosch-gsr-18v-55.png
GSR18V-55-BLACK,https://cdn.example.com/garan/bosch-gsr-18v-55.png
DHP486Z,https://cdn.example.com/garan/makita-dhp486.png The multi-store scope trap: if you created the
attribute with store view scope, rows without a
store_view_code column write to the default scope only,
and individual store views may keep an older value. With global
scope, as recommended above, the column is not needed and this
problem does not arise.
The GARAN-Label CSV run gives you brand, model and label URL per row; joining that onto your SKU list is a lookup in any spreadsheet. How the bulk run works and what it costs →
Cache: refresh after every attribute update
The classic Magento moment: the import reports success, the admin shows the new value, the storefront still shows nothing. Product pages are served from the full-page cache, and an import does not reliably invalidate them.
- Under System > Cache Management, refresh the cache types marked as invalidated, or
- on the command line:
bin/magento cache:clean full_page block_html, and - if your indexers run "Update by Schedule", wait for the cron run or trigger
bin/magento indexer:reindexfor the product indexers.
With Varnish or Fastly in front of the shop the same applies to the edge cache. Make the cache refresh part of your import routine, not an afterthought.
Keeping it in sync: cron plus API for changing catalogues
If new products arrive weekly, a manual CSV round-trip gets old quickly. The automated version has three parts:
- A cron job selects products that have a guarantee duration over two years and an empty
garan_label_url. - For each of them it calls the GARAN-Label API with brand, model and duration and stores the returned PNG on your own storage.
- It writes the URL back through Magento's REST API (
PUT /V1/products/{sku}with the custom attribute) or directly via a repository in a small module, then cleans the cache for that product.
Requests for a combination that already has a label return the existing file without using a credit, so the job can run idempotently. API reference with sample code →
Multi-store and multi-language: which notice per store view
Magento's store view is the natural unit for the notice language. Assign the CMS block with the German notice to the German store views, the French one to the French views, and so on. If a store view serves a country in a language the notice is not provided in, use the official EU language of that country. The GARAN-Label needs no such mapping: one label per model serves every store view.
Shops with one website per country and several store views per website should assign blocks at store view level, not website level, so that a Belgian website can show French and Dutch notices side by side.
How to generate the labels
Start by creating a free account at GARAN-Label.com. Then decide how you want to generate the labels:
Small catalogue
Manual mode: enter brand, model and guarantee duration, download the PNG, upload it to your media storage and paste the URL into the attribute.
Large catalogue
CSV mode for the existing range, API for new products. Both return a URL per label that you host yourself and import.
Ready to label your Magento catalogue?
Register for free and try sandbox mode before you spend a single credit.
Try for freeRunning Shopware instead of Magento? Here's the guide for Shopware →
Frequently asked questions about Magento 2
Do I need a Magento 2 extension for the GARAN-Label?
No. A CMS block plus a layout XML update covers the legal guarantee notice, and a product attribute plus a small template covers the GARAN-Label. Extensions exist and can save time, but nothing here requires one.
Does this work with the Hyvä theme?
Yes. The attribute, the CMS block and the layout XML are theme-independent. Only the template file that renders the image differs: in Hyvä you place it in your child theme and use Tailwind classes instead of Luma markup.
Should the attribute be a Media Image or a text field with a URL?
A text field holding the URL of the self-hosted label is the pragmatic choice. A Media Image attribute adds an image role to the product gallery, which is exactly where the label should not appear, and it is harder to fill via CSV import.
Can I just show the attribute in the "More Information" tab?
Not as the only placement. The label has to be visible on the product detail page in colour, and a tab the customer has to click first is a weak spot. Render it in the main product information area and keep the attribute out of the automatic attribute list.
I imported new attribute values but the storefront still shows the old state. Why?
Full-page cache. An import does not reliably invalidate cached product pages. Refresh the invalidated cache types in System > Cache Management or run bin/magento cache:clean full_page, and reindex if your indexers run on schedule.