Technical & compliance blocks
Chapter 7 covers the blocks that sell a product. This chapter covers the blocks that describe one: specification tables, compatibility lists, EU energy and safety disclosures, repair and spare-part information, security-update windows, running costs, documents, questions and ratings.
They exist for two reasons:
- Technical shoppers buy on data. A monitor is a resolution, a refresh rate, a panel size and a port list. A table that answers those questions removes the reason to leave for a spec sheet on another site.
- A growing part of that data is legally required. GPSR has applied since 13 December 2024. The EU Right to Repair Directive since 31 July 2026. The Cyber Resilience Act applies in full from 11 December 2027. Energy labelling has to be visible in distance selling. These are not features — they are obligations that a theme can either help with or ignore.
The one rule that governs every block in this chapter
Section titled “The one rule that governs every block in this chapter”The theme displays. It never computes, completes or invents.
No block derives an energy scale from an energy class, fills in a missing address, guesses a manufacturer role, or assumes a load factor for a power calculation. Where the merchant has not maintained a value, nothing is shown. An invented compliance figure is worse than a missing one, because it looks like a checked one.
The practical consequence: a store without the data model shows none of these blocks. That is not a fault. Each block simply renders nothing and, in the theme editor, tells you which field it is missing.
7a.1 Before anything renders — the data model
Section titled “7a.1 Before anything renders — the data model”A Shopify theme cannot ship metafield or metaobject definitions. Shopify only allows a metaobject setting to point at standard definitions, and there is effectively one of those. Everything in this chapter therefore lives where somebody created it: in your store, under Settings → Custom data.
The full set is 8 metaobjects and 43 metafields.
Metaobjects (Settings → Custom data → Metaobjects)
Section titled “Metaobjects (Settings → Custom data → Metaobjects)”| Metaobject | What it is | Used by |
|---|---|---|
spec_field | One specification value — key, label, group, unit, plus three switches that decide where it appears | product-specs, product card, comparison, filters |
spec_sheet | A named, ordered list of spec_field entries. A product shows exactly its sheet | product-specs |
compat_target | One compatibility target — device, vehicle, printer, standard | product-compat, Compatibility finder |
document | A document with title, kind, language, version and date | product-files |
economic_operator | Manufacturer or EU responsible person with a full postal address | product-gpsr |
product_question | A question with its answer, optionally tied to a spec key | product-qa |
spare_part | Part number, name, price, availability, tools | product-parts |
repair_step | Step number, title and instruction lines | product-repair |
⭐ The data model decides, not the theme
Section titled “⭐ The data model decides, not the theme”spec_field carries three booleans: show_in_card, comparable and filterable. That is why no block in this chapter has a “which fields to show” picker — the table, the product card and the comparison all read the same three switches. Add a field once, tick where it should appear, and every surface follows.
If the theme carried its own field picker next to those flags, you would be maintaining the same decision in two places, and the simple-maintenance argument this theme makes would be gone.
Metafields (Settings → Custom data → Products)
Section titled “Metafields (Settings → Custom data → Products)”Five namespaces:
| Namespace | Holds | Count |
|---|---|---|
specs | the specification values themselves plus sheet and questions | 23 |
compliance | energy label, EPREL, durability/repairability index, GPSR operators, warnings, support and repair dates | 15 |
docs | files — the product’s documents | 1 |
compat | targets — what the product fits | 1 |
parts | items — the spare-part catalogue | 1 |
reviews | rating, rating_count — Shopify’s own namespace, written by any compliant review app | 2 |
The namespaces for specs and compliance are configurable once, theme-wide, under Theme settings → Layout:
| Setting | What it does |
|---|---|
🔧 Compliance metafield namespace (compliance_ns) | One namespace for the product card and both compliance blocks. ✅ Default compliance. The keys inside it are fixed. |
⚠️ The second step people forget: Search & Discovery
Section titled “⚠️ The second step people forget: Search & Discovery”Definitions alone do not make a value filterable. To get a spec onto collection and search pages as a filter, release it in Shopify’s own free Search & Discovery app under Filters → Add filter. The same applies to the category attributes Shopify creates by itself.
Nothing breaks without it: the theme checks which filters are actually released and only links a value when it finds one. An unreleased value simply renders as text.
| What | Needs release? |
|---|---|
| Availability, price, product type, vendor, variant options | No — built in |
Your own metafields (specs.*, compat.targets) | Yes |
| Shopify’s category attributes | Yes |
7a.2 Specifications (product-specs)
Section titled “7a.2 Specifications (product-specs)”The specification table. Reads the product’s spec_sheet and renders its fields as a grouped table.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Specifications”. |
🔧 Metafield (sheet_key) | Which product metafield points at the specification sheet. ✅ Default specs.sheet. The fields, their labels and their groups live in the data set, not here. |
🔧 Additional metafields (extra_keys) | Comma-separated namespace.key list, appended after the sheet. Meant for Shopify’s own category attributes. ✅ Default empty. |
🔧 Collection for the filter link (filter_collection) | Handle of the collection that filterable values link into. ✅ Default all. |
🔧 Show group headings (show_groups) | Render the group value of each field as a sub-heading. ✅ Default on. |
Behaviour worth knowing:
- Empty fields are skipped. A product that does not carry a value produces a blank, and a table with empty rows would be worse than no table.
- Unit types format themselves.
weight,power,dimensionandvolumemetafields already return “38.5 W” complete with unit.unit_overrideon thespec_fieldbeats both. - List values are joined. A
list.single_line_text_fieldrenders as “HDMI 2.1 · DisplayPort 1.4 · USB-C”, not run together. - A filterable value becomes a link into the collection named above, pre-filtered to that value — but only if the filter is released in Search & Discovery.
7a.3 Compatible with (product-compat)
Section titled “7a.3 Compatible with (product-compat)”What the product fits: devices, vehicles, printers, standards. One field carries all four, because the shape of the answer is the same.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Compatible with”. |
🔧 Heading size (heading_size) | h2 / h3 / h4. ✅ Default h3. |
🔧 Group by category (show_groups) | Group entries by the category field of each compat_target. ✅ Default on. |
🔧 Note below the list (note) | Optional — for example a hint that the list is not exhaustive. ✅ Default empty. |
🔧 Metafield with the targets (targets_key) | Advanced. ✅ Default compat.targets — a list of compat_target metaobjects. |
🔧 Collection for the filter link (filter_collection) | Advanced. ✅ Default all. |
The reverse view — “show me everything that fits my device” — is the Compatibility finder section, covered in chapter 10.
7a.4 EU energy & durability (product-eu-label)
Section titled “7a.4 EU energy & durability (product-eu-label)”Energy efficiency class, the scale it sits in, the EPREL link, and the French durability / repairability indices.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Energy and durability”. |
Everything else is data. That is deliberate — three constraints shape this block:
- Never derive, only display. The scale is not inferred from the class (“F, so probably A–G”). The same letter sits in a different scale depending on the product group. If the scale is missing, it stays missing. Regulation (EU) 2017/1369 requires the class and the range of the scale wherever the label itself cannot be shown — which is exactly why the range is its own maintained field.
- The official label is a file, not a drawing. The arrow graphic is regulated artwork; EPREL supplies it. The theme prints the class and links the file. The colour bar under it is deliberately a bar and not an arrow — it should look like what it is.
- Liquid cannot call EPREL. The link is built from the two maintained fields
eprel_groupandeprel_id.
The durability index is not a nice-to-have. France’s indice de durabilité has applied to televisions since 8 January 2025 and to washing machines since 8 April 2025, and the regulation requires it on every purchase page, in the same size as the price. That is why the value also appears on the product card.
⛔ Never invent a registration number
Section titled “⛔ Never invent a registration number”EPREL numbers, GTINs, EANs, GS1 and UDI codes sit in a densely populated number space. An invented number either hits a real registration — which belongs to somebody else — or collides with one. There is practically no third outcome.
For demo content: either no identifier, or one of your own. Never a plausible-looking one.
7a.5 Running cost (product-power-cost)
Section titled “7a.5 Running cost (product-power-cost)”Turns specs.power_draw into a yearly and monthly electricity cost the buyer can adjust.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Running cost”. |
🔧 Electricity price per kWh (price_default) | Starting value in the shop currency. Buyers can change it. ✅ Default 0.30. |
🔧 Hours per day (hours_default) | Starting value. ✅ Default 8 — a working day, not around the clock. |
It says what it is computing. power_draw is the maximum power draw, and the block states so under the result. There is deliberately no invented load factor: a made-up “typical usage is 40 %” would turn a measured figure into a marketing one.
Two details that matter in practice:
- The price field is a text input with
inputmode="decimal", not a number input, so it accepts0,30as well as0.30. A number input rejects the comma silently depending on locale. - Money is formatted through the theme’s single money formatter, which follows
shop.money_format. It is never assembled in JavaScript —'$' + (cents/100).toFixed(2)produces$3500.00where the server produces$3,500.00, in the same window.
7a.6 Repair and spare parts (product-repair)
Section titled “7a.6 Repair and spare parts (product-repair)”Repairability index, spare-parts window, repair manual, and — expandable on the page — the actual repair steps.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Repair and spare parts”. |
🔧 Show the guarantee note (show_guarantee) | ✅ Default on. The EU Right to Repair Directive has applied since 31 July 2026, so this is a statement of law, not a product claim. |
The index bands are 8 / 6 / 4 / 2 — repairability_index ≥ 8 renders as band a, ≥ 6 as b, ≥ 4 as c, ≥ 2 as d, below that e. ⛔ These are not the 9 / 7 / 5 / 3 bands of the durability index in 7a.4. Two different scales, two different colour thresholds.
⭐ Why the repair steps are visible and not just in the PDF
Section titled “⭐ Why the repair steps are visible and not just in the PDF”The steps from compliance.repair_steps render on the page inside an expandable <details> block — and they are marked up as HowTo structured data.
That order is not decoration. Google forbids marking up content a reader of the page cannot see. The steps originally existed only inside a downloadable PDF, which meant the strongest argument this kind of store has was the one thing nobody saw. Making them visible was the precondition for the markup, and it turned an SEO task into a better product decision.
One source feeds three consumers: the PDF, the metaobjects, and the page.
7a.7 Spare parts (product-parts)
Section titled “7a.7 Spare parts (product-parts)”The spare-part catalogue: part number, name, price, availability and the tools needed.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Spare parts”. |
🔧 Show the tools column (show_tools) | Which tool, and how the part fits. ✅ Default on — it is the part of a repair that decides whether somebody attempts it. |
Not every part has a price. Soldered sockets and bonded assemblies carry “not available separately” instead of a figure, and the block renders that as written. A catalogue that prices everything implies everything is replaceable.
7a.8 Security updates (product-support)
Section titled “7a.8 Security updates (product-support)”How long the product receives security updates, derived from compliance.support_until.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Security updates”. |
🔧 Show the legal note (show_note) | ✅ Default off. |
Three states, computed from the date:
| Remaining | Renders as |
|---|---|
| more than 365 days | ”still N years” |
| 1–365 days | ”still N months” |
| past | ”ended” |
⛔⛔ Why this note defaults to off and the repair note defaults to on
Section titled “⛔⛔ Why this note defaults to off and the repair note defaults to on”The Cyber Resilience Act, Regulation (EU) 2024/2847, applies in full from 11 December 2027. The Right to Repair Directive has applied since 31 July 2026.
A notice that ships switched on has to be true today. One of these is already law and one is not yet, so one default is on and the other is off. When the CRA takes effect, turn it on.
7a.9 Files & documents (product-files)
Section titled “7a.9 Files & documents (product-files)”Manuals, declarations of conformity, data sheets, dimensional drawings.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Downloads”. |
🔧 Metafield (metafield) | Which product metafield holds the files. ✅ Default docs.files. |
🔧 Label (label) | Only used where an entry brings no title of its own; otherwise the file name is shown. ✅ Default empty. |
🔧 Appearance (style) | link / button. ✅ Default link. |
🔧 Open a preview first (preview) | Show the preview Shopify generates, with open and download from there. ✅ Default on. |
⭐ One setting, five metafield shapes
Section titled “⭐ One setting, five metafield shapes”You enter namespace.key and the block works out what is behind it:
| Shape | Result |
|---|---|
file_reference | one file |
list.file_reference | several files |
metaobject_reference | one document — title, file, kind, language, version, date |
list.metaobject_reference | several documents |
url / list.url | a link to somewhere else |
Images get a viewer with zoom and pan — mouse wheel, double-click, two fingers, three buttons and the keyboard — plus a high-resolution version fetched only on the first zoom. That is what makes a dimensional drawing usable: at 1200 px a plan scaled to window width just gives you bigger pixels.
The download really downloads. A download attribute on a cross-origin link is ignored by the browser, and the Shopify CDN is a different origin from the shop. The preview window therefore downloads through a blob, where the attribute does apply.
7a.10 Product safety, GPSR (product-gpsr)
Section titled “7a.10 Product safety, GPSR (product-gpsr)”Manufacturer, EU responsible person, and safety warnings.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Product safety”. |
This is the block with the widest reach and the smallest effort. The General Product Safety Regulation (EU) 2023/988 has applied since 13 December 2024 to every consumer product, not only electronics. In distance selling the following must be visible before the contract is concluded:
- the manufacturer’s name and postal address, plus an electronic address
- where the manufacturer sits outside the EU, the same details for the responsible person in the Union
- warnings and safety information
The block reads two economic_operator metaobjects and one rich-text field. It fills in nothing: no address is completed, no role is derived. What the merchant has not maintained does not appear.
7a.11 Product questions (product-qa)
Section titled “7a.11 Product questions (product-qa)”Technical questions and their answers, from specs.questions.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Questions about this product”. |
🔧 Open the first question (first_open) | ✅ Default off. |
A product_question can carry a spec_key. Where it does, the question is tied to that specification field and the field’s label is shown as its subject. ⭐ The label comes from spec_field.label and is therefore already translated — which is why it never has to be repeated inside the question text.
7a.12 Product rating (product-rating)
Section titled “7a.12 Product rating (product-rating)”Stars and review count from reviews.rating and reviews.rating_count.
| Setting | What it does |
|---|---|
🔧 Text alignment (alignment) | left / center / right. ✅ Default left. |
🔧 Size (size) | xs / sm / md / lg. ✅ Default sm. |
🔧 Show the number (show_value) | ✅ Default on. |
🔧 Show the review count (show_count) | ✅ Default on. |
reviews is Shopify’s own namespace, and every compliant review app writes into it — so this block works with the app you already have, without an integration.
⭐ Partial stars are two rows, not half glyphs. The filled row is clipped to the exact percentage, so 4.6 / 5 renders as exactly 92 %.
⚠️ A rating metafield returns an object (rating, scale_min, scale_max), not a number. The block reads the parts separately so the maximum is honoured rather than assumed to be 5.
⛔⛔ Never fabricate reviews
Section titled “⛔⛔ Never fabricate reviews”Invented consumer reviews are prohibited under the EU Omnibus Directive. If you are populating a demo store, the demo-data tooling that ships with the theme’s development scripts always has a matching removal path — use it before the store does real business.
7a.13 Back-in-stock notice (product-notify)
Section titled “7a.13 Back-in-stock notice (product-notify)”A short form that lets a visitor be told when a sold-out variant returns. Posts through Shopify’s own {% raw %}{% form 'contact' %}{% endraw %}, so it needs no app and no external service.
| Setting | What it does |
|---|---|
🔧 Heading (heading) | ✅ Default “Sold out — tell me when it is back”. |
The block is always rendered and hidden rather than conditionally rendered. What is not in the DOM cannot be revealed when the visitor switches to a sold-out variant — the form has to exist before it is needed.
Place it where the buy button is: on a sold-out variant the buy button goes away and this takes its place.
7a.14 A recommended block order
Section titled “7a.14 A recommended block order”The order below is thematic, not historical — it walks the buyer from “what is it” through “what does it cost me to own” to “what happens if it breaks”:
vendor · title · rating · price · variant_picker · buy_buttons · notify ·pickup · description ·specs · compat · eu-label · power-cost · repair · parts · support ·files · gpsr · qa · shareStars sit next to the name. The back-in-stock form sits where the buy button was. Then the four lifetime layers in the order a buyer thinks about them — energy → running cost → repair → spare parts → updates. Then documents, safety, questions.
7a.15 What the law requires, and from when
Section titled “7a.15 What the law requires, and from when”| Rule | In force | Blocks |
|---|---|---|
| Energy labelling — Regulation (EU) 2017/1369 | in force; label must be visible in distance selling | product-eu-label |
| French durability index (indice de durabilité) | TVs 8 Jan 2025 · washing machines 8 Apr 2025; must appear on every purchase page at price size | product-eu-label, product card |
| GPSR — Regulation (EU) 2023/988 | 13 December 2024, every consumer product | product-gpsr |
| Right to Repair Directive | 31 July 2026 | product-repair, product-parts |
| Cyber Resilience Act — Regulation (EU) 2024/2847 | 11 December 2027 (full application) | product-support |
| Omnibus Directive — no fabricated reviews | in force | product-rating, product-qa |
⚠️ This table is an orientation, not legal advice. Which rules bind you depends on what you sell and where. Where a date decides whether a notice is switched on by default, this manual says so at the block.
7a.16 What happens when the data is missing
Section titled “7a.16 What happens when the data is missing”Nothing breaks, and nothing is faked. Per block:
| Block | Without its data |
|---|---|
product-specs | renders nothing; individual empty fields are skipped inside an otherwise complete table |
product-compat | renders nothing |
product-eu-label | renders nothing; a missing scale is simply absent next to the class |
product-power-cost | renders nothing when specs.power_draw is unset |
product-repair | renders nothing; the steps <details> appears only where steps exist |
product-parts | renders nothing; a part without a price shows its availability text instead |
product-support | renders nothing when compliance.support_until is unset |
product-files | renders nothing |
product-gpsr | renders only the operators and warnings that are maintained |
product-qa | renders nothing |
product-rating | renders nothing when reviews.rating is unset |
product-notify | present but hidden while the variant is in stock |
In the theme editor each block names the field it is missing, so an empty product page tells you what to fill in rather than leaving you guessing.
See also: Chapter 7 — Product sections · Chapter 10 — Marketing & interaction sections for the Compatibility finder and Product comparison · Chapter 13 — SEO & GEO for the structured data these blocks emit.