Shopware SEO

How SEO works on Shopware 6 — the native controls it ships (Twig-templated SEO URLs, canonical handling, XML sitemaps, hreflang via the Sales Channel/Domain model, and, in recent versions, native robots.txt and JSON-LD), the version gates that decide what you actually get, the traps (rebuild the index after a template change, variant duplicate content, seo_url table growth), and why headless (Composable Frontends) moves the whole SEO checklist into the Nuxt layer.

First published: Jul 2, 2026 · Last updated: Jul 19, 2026 · Advanced
demand #6 in Ecommerce Platforms#27 in Platform SEO#219 in Technical SEO#302 on the site

Shopware 6 ships an unusually large amount of native technical SEO for a self-hosted platform — Twig-templated SEO URLs per entity type, canonical handling, three-strategy XML sitemap generation, and hreflang derived from the Sales Channel/Domain model — but what's 'native' depends heavily on your version: per-domain robots.txt only arrived in 6.7.1.0 and JSON-LD structured data (replacing Microdata) in 6.7.9.0 behind a feature flag. The recurring traps are specific: you must rebuild the SEO index (dal:refresh:index) after changing a URL template, product variants each get their own URL and can't be canonicalized straight to the parent without a template override, and the seo_url table grows roughly with variants times languages. Going headless with Composable Frontends (Vue + Nuxt) moves the entire SEO checklist — sitemap, canonical, meta tags, structured data — into the Nuxt rendering layer, where none of the admin SEO settings apply the same way.

TL;DR — Shopware 6 ships more native technical SEO than most self-hosted platforms — but “native” is heavily version-gated. SEO URLs are Twig templates per entity type (product / category / landing page), configurable globally or per sales channel; change a template and you must rebuild the index (dal:refresh:index) or existing URLs won’t update. Canonical is a separate system from URL templates: automatic for categories, semi-manual for variants (you can point one variant at another as canonical, but not straight at the parent without a template override). The XML sitemap has three refresh strategies (scheduled / live / manual, with sitemap:generate for manual) and Shopware explicitly disclaims any indexing guarantee. robots.txt is nothing-automatic before 6.7.1.0 (manual file + server rewrite) and native per-domain admin editing after. Structured data just migrated from Microdata to JSON-LD in 6.7.9.0 behind the JSON_LD_DATA flag. hreflang comes from the Sales Channel > Domain model, with a cross-sales-channel gap that spawned paid plugins. And going headless (Composable Frontends, Vue + Nuxt) moves the whole SEO checklist into the Nuxt rendering layer.

Evidence for this claim Shopware 6 provides configurable SEO URL templates and sitemap settings, with behavior dependent on version and sales-channel configuration. Scope: Shopware 6 administration; plugins and release versions can change output. Confidence: high · Verified: Shopware documentation: SEO Evidence for this claim Shopware release notes document material SEO-related changes across 6.7 releases, so exact native behavior must be checked by installed version. Scope: Shopware 6.7 release line, not all earlier installations. Confidence: high · Verified: Shopware 6.7 release notes

The frame: native, version-gated, and where you still do the work

Most Shopware SEO content is either a screenshot walkthrough of the admin settings or a pitch from a Shopware agency. Neither tells you the two things that actually matter: what Shopware ships natively depends on your version, and the remaining gaps are specific and predictable. Sort every task into three buckets — native-and-current, native-only-if-you’re-on-a-recent-version, and still-your-job — and the platform stops being mysterious.

Shopware itself frames the native side generously: it says the platform “includes many SEO features out of the box – from country- and language-specific URLs to meta data, hreflang, and performance optimizations, allowing you to build strong SEO without additional plugins.” That’s largely true — with the version caveats below, and with a short list of things (bulk meta, variant canonicals, cross-channel hreflang, headless rendering) that still need plugins or code.

Because Shopware is self-hosted and open-source-core, it sits differently from the hosted platforms. Where Shopify forces /products/ and /collections/ prefixes and won’t let you natively edit robots.txt, and BigCommerce hands you an editable robots.txt and custom URL structures on a managed stack, Shopware gives you more control than any of them — you can override storefront templates directly — at the cost of owning more of the outcome, including your own hosting, indexing rebuilds, and (on headless) your own rendering pipeline. It’s closer in spirit to Magento or a self-hosted WooCommerce store than to Shopify.

URL structure: SEO URL templates

SEO URLs live at Settings > Shop > SEO, and they’re configurable per sales channel or globally. There are three separately-templated entity types — product detail pages, category pages, and landing pages — and the templates use Twig syntax. Shopware’s docs put it plainly: “In the SEO settings you can define the structure for the SEO URLs of the product detail pages and categories. For this purpose you have a variety of variables at your disposal.”

The mechanics worth knowing:

  • The default product template is {{ product.name }}, and there are 50+ product variables available (product number, EAN, manufacturer name, breadcrumb/categories, custom fields, release date, and more).
  • Multi-level variables must be typed by hand. Clicking the variable picker only inserts the incomplete parent token — {{ product.translated.name }} has to be finished manually.
  • You can truncate long names. For a product name longer than, say, 50 characters, Shopware documents {{ product.translated.name[:50] }} to shorten it in the URL.
  • The category default uses the breadcrumb: {% for part in category.seoBreadcrumb %}{{ part }}/{% endfor %}.
  • Twig filters work for normalization — for example {{ product.translated.name|lower }}/{{ product.productNumber }} — and Shopware notes “in general you can use the available Twig filters.”
  • Conditional (IF) logic handles missing fields; the docs give a variant-aware example using {% if product.canonicalProductId is not null %}.

The trap almost everyone hits: “After you have made changes to the SEO template, it is necessary to rebuild the index so that the URLs are updated. You can do this from the console using the command php bin/console dal:refresh:index.” Editing a template only affects newly generated URLs — existing products keep their old slugs until you rebuild. If you change the template and “nothing happened,” this is why.

Under the hood, SEO URLs live in a seo_url database table with a dual-URL concept: a technical path_info (the real route) and a human seo_path_info (the slug), plus sales_channel_id, language_id, is_canonical, and is_deleted/is_modified flags. Custom or dynamic SEO URL routes are added by developers via a SeoUrlRouteInterface implementation registered with the shopware.seo_url.route container tag. You don’t need this for a normal store, but it explains the scale behavior in the pitfalls section below.

Canonical tags

Canonicalization on Shopware is a separate mechanism from the URL templates — this is the single most misunderstood part of Shopware SEO. Shopware’s own docs even define the concept the way Google does: “A canonical URL is the URL of the page that the search engine assumes is the most representative of several duplicated pages on your site.”

Three things to keep straight:

  • Categories are canonicalized automatically. When a product is reachable through multiple categories (and therefore multiple URLs), Shopware’s marketing describes it as detecting this and “automatically marks the correct URL, automatically preventing technical SEO issues.” Treat the marketing phrasing as a claim to confirm on your own store, but the automatic-category behavior is real.
  • Variants are only semi-manual. Each variant gets its own SEO URL, and the built-in “Variant for Canonical URL” picker lets you nominate one variant as the canonical target. What it does not do is let you canonicalize a variant straight back to the parent product — a gap practitioners fix by overriding product-detail/meta.html.twig (or with a plugin) so variants canonicalize to the parent’s SEO URL when one exists. If your variant pages are near-duplicates competing with each other, this is the fix.
  • There’s a global 301 behavior toggle. Under “Forwarding behavior,” Shopware can “output an HTTP 301 redirect when URLs are changed” rather than leaving old URLs live after a template edit — the setting that pairs with the dal:refresh:index rebuild above.

This maps directly onto Google’s own stance that canonicalization is a hint and that duplicate variant/parameter URLs are normal in ecommerce — the general mechanics are in canonicalization, which this article is the Shopware-specific companion to.

XML sitemap

The sitemap lives at Settings > Shop > Sitemap. Shopware “generates a standard sitemap that is compressed and cached in the file system,” and for large catalogs “the sitemap is divided into several files and can be generated in the background” — the multi-file split that keeps each file inside the sitemaps.org / Google limits of 50,000 URLs and 50 MB uncompressed.

There are three refresh strategies, and the difference matters:

  1. scheduled — generated automatically on a scheduled task at a set interval.
  2. live — created when none exists, and recreated once the refresh time elapses.
  3. manually — automatic generation is off entirely; “the sitemap will only be created if you call the following command manually: php bin/console sitemap:generate. In this case, it is necessary to run this command again each time a new URL is added or an old one is removed.”

Two things people miss:

  • The public URL is sitemap.xml, and there’s no human-facing /sitemap page. Shopware is explicit: “Shopware 6 does not provide a visitor sitemap (suffix /sitemap after your domain). The index file sitemap.xml is created for evaluation by Google.”
  • A sitemap guarantees nothing. Shopware states outright that it “cannot guarantee that every URL will be crawled and indexed. This always depends on the search engine provider.” A sitemap is a discovery aid, not an indexing promise — same as on every other platform.

Adding or excluding custom URLs (beyond products/categories) isn’t an admin toggle — it’s developer work via custom UrlProvider classes, documented in Shopware’s developer sitemap guides.

robots.txt — check your version first

This is the most version-sensitive part of Shopware SEO, so date-stamp it before you advise anyone.

  • Before 6.7.1.0 (most older installs): nothing is generated automatically. Shopware’s docs say “the robots file is not created automatically in Shopware 6, but has to be created manually as a text file” placed in /public/. For multi-domain setups you serve a per-domain file with a server rewrite — Apache RewriteRule ^robots\.txt$ robots/%{HTTP_HOST}.txt [NS] or the NGINX equivalent rewrite ^/robots\.txt$ /robots/$host.txt — pointing at a /public/robots/<domain>.txt structure.
  • From 6.7.1.0 onward (July 2025 release): native per-domain robots.txt management shipped in the admin — you “can define individual robots.txt rules for each domain in the Admin under Settings > General > Basic information.” This started as a Hacktoberfest 2024 community contribution.

So the myth “Shopware doesn’t let you edit robots.txt” is only true pre-6.7.1.0. Confirm the store’s version before telling someone to “just edit it in the admin” — older stores still need the manual-file-plus-rewrite approach. The admin field (“Rules for robots.txt” under Settings > General > Basic information) is a free-text area merged straight into that domain’s robots.txt, so it accepts full User-agent: / Allow: / Disallow: blocks, not just flat rules — confirmed both in Shopware’s current docs and in a 6.7.10.0 fix (avoid duplicate robots.txt directives for user-agent blocks) that specifically reproduces the bug using per-user-agent blocks in that field.

Structured data: the Microdata → JSON-LD migration

Shopware went through a real architecture shift here in 6.7.9.0: the storefront moved from scattered inline Microdata to JSON-LD emitted as a <script type="application/ld+json"> block in the <head>. It’s behind a feature flag, JSON_LD_DATA, and is off by default — with the flag on, JSON-LD is injected and the old Microdata is removed. The Microdata is deprecated and slated for removal in 6.8.0.0.

Once you flip the flag, the JSON-LD output is substantially richer than the old Microdata:

  • Product — all product images, VideoObject for product videos, AggregateRating with ratingCount, up to the 10 most recent Review items, OfferShippingDetails/ShippingDeliveryTime for single-price products, Dimensions as QuantitativeValue, itemCondition, typed seller info, and gtin13 (EAN) / mpn when present.
  • WebSite with SearchAction (enables Google’s Sitelinks search box).
  • Top-level Organization (shop logo).
  • ItemList on category / search-result pages, plus BreadcrumbList.

Each schema type lives in its own overridable Twig template under storefront/layout/structured-data/. The same 6.7.9.0 release also added per-product Open Graph fields in the admin SEO tab — custom og:title, og:description, and og:image, defaulting to the product’s meta title/description/cover image when unset — so social shares and some search-result previews can now diverge intentionally from the meta tags without a plugin.

The practical takeaway: this is a myth-buster. Plenty of practitioner posts and paid Store extensions (“JSON-LD Rich Snippets for product pages”) predate the native feature. If you’re on 6.7.9.0+, check whether you still need that plugin before buying it — and if you’re on an older version, that’s exactly when a plugin still earns its keep. Google’s Product structured data guidelines are the spec this output targets, and Google requires structured data to reflect visible page content — so fill the fields you want in the markup.

International SEO: hreflang via Sales Channel + Domain

Shopware doesn’t have a standalone hreflang editor. hreflang is derived from the Sales Channel > Domain model: each sales channel can have multiple domains, and each domain maps to one language, one currency, a snippet set, and a unit system — set up with its “own virtual URL, language, currency, snippet set and its own unit system.”

Two settings do the SEO work:

  • A localization mode dropdown with two options: ISO standard, “useful, for example, if you use different (country-specific) language variants that may use their own country-specific terms,” which produces full region-language codes like en-US vs en-GB; and browser language localization, which is language-only (plain en). Use ISO standard when you genuinely have regional variants.
  • A default domain that, after you enable the hreflang meta tag, “will serve as a fallback for all languages” — Shopware’s version of Google’s x-default.

The known weak spot: this works within a single sales channel’s domains, but cross-sales-channel hreflang — separate sales channels per country/TLD running near-duplicate catalogs — is not natively linked. That gap is exactly what paid “Hreflang Manager” store extensions exist to solve. I’d treat the cross-channel gap as a strong community/marketplace signal rather than a documented Shopware limitation, but it’s a recurring pain point on the forums.

One thing Shopware’s own docs don’t spell out that Google requires: hreflang must be bidirectional (return tags) and include an x-default. If you’re new to the return-tag requirement, the general mechanics are in hreflang — Shopware’s default-domain setting handles the x-default side, but you still want to verify the return tags resolve.

Headless: Composable Frontends (Shopware Frontends)

Shopware’s headless option is “Shopware Frontends” (formerly “Composable Frontends” / “PWA”) — a Vue.js + Nuxt toolkit that consumes the Shopware Store API, distinct from the default Twig/Symfony storefront. It ships a component library, an API client, reusable “composables,” and generated TypeScript types; the reference “Vue Demo Store” is built on Nuxt + Tailwind.

Here’s the part every other guide skips: going headless moves essentially all SEO responsibility into the Nuxt layer, and none of the admin SEO settings apply the same way. The SEO URL templates, the canonical settings, the sitemap admin toggle, and the new robots.txt admin panel are all Symfony-storefront (Twig) features. A Composable Frontends build needs its own:

  • Rendering mode that produces crawlable HTML — Nuxt SSR (or hybrid / ISR / edge rendering) for SEO-relevant pages. A pure client-side-rendered (SPA) build reintroduces the classic JavaScript-rendering SEO risk, so headless is not automatically better for SEO — a badly configured headless storefront can be worse than the default Twig one.
  • Sitemap generation, canonical tags, structured data, and meta-tag injection implemented in the Nuxt app (typically via Nuxt’s head/SEO-meta composables), usually still pulling slugs and product data from the same Shopware SEO URL / Store API data.

So the myth “going headless with Shopware fixes/improves SEO” is false as stated. SEO outcome depends entirely on how you configure rendering in Nuxt. This is the same trap as any headless build — the platform-agnostic version lives in JavaScript SEO and headless CMS SEO.

Common pitfalls at scale

The practitioner pain points cluster in three places:

  • Default misconfigurations. Practitioner audits flag that “Remove Category ID from URL” ships set to No by default (worth enabling for cleaner URLs), that pagination signals are off by default, and that blog/archive pagination pages are worth noindex-ing because they “add no value; they only take up crawl budget.” One widely repeated claim — that Shopware auto-adds nofollow to all external links — I’d verify against a real install before repeating; it wasn’t confirmed against Shopware’s own docs.
  • Product-variant duplicate content. This is the single most recurring Shopware SEO complaint. Each variant gets its own URL (/SW10000.1, /SW10000.2, …) with inherited, near-identical descriptions, so variants compete unless you canonicalize them — and, per the canonical section above, the built-in picker can’t point straight at the parent without a template override.
  • seo_url table growth on large multilingual catalogs. Row count roughly follows (parent + active variants) × number of languages — a practitioner deep dive puts a 9-variant product across 17 languages at ~153 rows for a single product family. Frequent template edits multiply history rows further. At scale the fixes are: generate SEO URLs for parent products only (not every variant), prune soft-deleted / non-canonical rows periodically, and add composite indexes. This is why a large Shopware store can feel slow and accumulate odd duplicate SEO URLs.

When native tools are enough vs. when you need a plugin or dev work

The rough threshold echoed across practitioner sources: native tools are enough for small, simple catalogs (on the order of a few hundred products), and plugins or custom development become necessary at meaningful scale — thousands of SKUs, deep variant matrices, many languages, or cross-sales-channel international setups. Concretely, reach for a plugin or code when you need bulk title/meta patterns, canonical-to-parent for variants, cross-sales-channel hreflang, custom sitemap entries, or JSON-LD on a pre-6.7.9.0 version. Everything else — SEO URL templates, category canonicals, the sitemap, single-channel multi-domain hreflang, and (on current versions) robots.txt and JSON-LD — is native.

Shopware vs the hosted platforms — the honest version

ShopwareShopifyBigCommerce
HostingSelf-hosted / Shopware cloudHosted SaaSHosted SaaS
URL structureTwig templates, fully customForces /products/, /collections/Fully custom, no forced prefixes
robots.txtNative admin from 6.7.1.0 (manual before)Not natively editableEditable in admin
Built-in schemaNative JSON-LD from 6.7.9.0 (flagged)App requiredYes (Cornerstone)
hreflangNative via Sales Channel/Domain (single-channel)App / theme workManual
Headless optionComposable Frontends (Vue + Nuxt)HydrogenCatalyst (Next.js)
Index rebuild stepYes (dal:refresh:index)Not exposedNot exposed

All of them rank fine. Shopware’s genuine advantage is control — Twig-templated URLs, overridable storefront templates, and a large native feature set that keeps growing by version. Its genuine cost is that you own more of the pipeline: your hosting, your index rebuilds, your version awareness, and — if you go headless — your entire rendering and SEO-tag layer. Like Magento and self-hosted WooCommerce, and unlike Shopify or PrestaShop’s simpler defaults, that trade favors teams with development capacity.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin an expert quote first.