From bed86eb2a83a0a954280cb2a9ceac2e37b48777d Mon Sep 17 00:00:00 2001 From: Max Stegmeyer Date: Thu, 17 Sep 2026 14:12:11 +0200 Subject: [PATCH 1/8] docs(apps): add guide for SEO URLs on app storefront routes Documents the new manifest element for static and entity-bound SEO URLs of script-rendered storefront pages, links it from the custom endpoints guide and the manifest reference. --- .../apps/app-scripts/custom-endpoints.md | 2 + guides/plugins/apps/storefront/seo-urls.md | 124 ++++++++++++++++++ .../app-reference/manifest-reference.md | 2 +- snippets/config/app/storefront.xml | 9 ++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 guides/plugins/apps/storefront/seo-urls.md diff --git a/guides/plugins/apps/app-scripts/custom-endpoints.md b/guides/plugins/apps/app-scripts/custom-endpoints.md index 47e5283a26..8e6b712161 100644 --- a/guides/plugins/apps/app-scripts/custom-endpoints.md +++ b/guides/plugins/apps/app-scripts/custom-endpoints.md @@ -129,6 +129,8 @@ Additionally, it is also possible to redirect to an existing route: For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#storefront-hook). +To make such a page reachable under a readable path like `/imprint` or `/blog/my-post`, declare a SEO URL for it in your manifest. See the [SEO URLs for App Routes](../storefront/seo-urls.md) guide. + ## Manipulate HTTP-headers to API responses ::: info diff --git a/guides/plugins/apps/storefront/seo-urls.md b/guides/plugins/apps/storefront/seo-urls.md new file mode 100644 index 0000000000..fc77767703 --- /dev/null +++ b/guides/plugins/apps/storefront/seo-urls.md @@ -0,0 +1,124 @@ +--- +nav: + title: SEO URLs for App Routes + position: 30 + +--- + +# SEO URLs for App Routes + +## Overview + +Storefront pages rendered by [app scripts](../app-scripts/custom-endpoints.md#storefront-endpoints) live under `/storefront/script/{hook}`. That path is technical and cannot carry an entity id. With `` elements in the `` section of your `manifest.xml`, Shopware gives those pages SEO URLs, the same way it does for products and categories. + +::: info +This feature was introduced in Shopware 6.7.15.0 and is not available in earlier versions. +::: + +There are two kinds of SEO URLs: + +- A **static** SEO URL maps a fixed path such as `/imprint` to one of your storefront scripts. +- An **entity-bound** SEO URL generates one URL per entity from a Twig template, for example `/blog/{{ ceBlog.translated.title }}`, and passes the entity id to your script. + +## Prerequisites + +You need an app with at least one storefront script. Read the [App Base Guide](../app-base-guide.md) and the [Custom Endpoints](../app-scripts/custom-endpoints.md) guide first. Both kinds of SEO URLs point at scripts stored in `Resources/scripts/storefront-/`. + +## Static SEO URLs + +Declare a `` with one or more `` elements. The `name` identifies the route inside your app and is also the default script hook. + +```xml + + + + SwagCompanyPages + ... + + + + + + imprint + impressum + + + +``` + +With this manifest, `/imprint` and `/impressum` run the scripts in `Resources/scripts/storefront-imprint/`. Shopware writes one SEO URL per storefront sales channel domain and picks the `` matching the domain language, falling back to the `en-GB` path. Query parameters of the request stay available as `hook.query`. + +Set the `hook` attribute when the script folder should differ from the route name: + +```xml + + imprint + +``` + +## Entity-bound SEO URLs + +Declare a `` with an `entity` attribute and a ``. The entity can be one of your [custom entities](../custom-data/custom-entities.md) or a core entity such as `product`. + +```xml + + + + blog/{{ ceBlog.translated.title }} + + +``` + +Shopware generates one SEO URL per entity and language from the template and keeps it up to date whenever the entity is written. The template context exposes the entity under its camel-cased name, so `ce_blog` becomes `ceBlog` and `product` becomes `product`. Every field of the entity is available, translated fields through `translated`. + +The generated URL resolves to `/storefront/script/blog-detail?id=`, so your script receives the id as `hook.query.id`: + +```twig +// Resources/scripts/storefront-blog-detail/script.twig +{% set post = services.store.search('ce_blog', { 'ids': [hook.query.id] }).first %} + +{% do hook.page.addExtension('post', post) %} + +{% do hook.setResponse( + services.response.render('@SwagBlog/storefront/page/blog/detail.html.twig', { 'page': hook.page }) +) %} +``` + +### Merchant configuration + +Entity-bound routes appear in the Administration under *Settings > SEO* as `storefront.app..`, for example `storefront.app.SwagBlog.blog-detail`. Merchants can adjust the template per sales channel and override single URLs like they do for products. Your `` is only the initial value. An app update replaces it only when the merchant has not changed it. + +## Linking to your pages + +Use the `seoUrl` Twig function with the technical route and parameters in your storefront templates. The placeholder is replaced with the SEO URL when the page is rendered: + +```twig + + {{ post.translated.title }} + + + + {{ 'swag-company-pages.imprint'|trans }} + +``` + +## Lifecycle + +- **Install and update**: Shopware stores the declared routes and creates the default SEO URL template for entity-bound routes. +- **Activation**: The static SEO URLs are written and the entity-bound URLs are generated. This runs through the message queue, so make sure a [worker](../../../hosting/infrastructure/message-queue.md) processes messages. +- **Deactivation and uninstall**: The app's SEO URLs are marked as deleted and stop resolving. Uninstalling also removes the SEO URL templates. +- **New sales channel domains**: Static SEO URLs are written for new domains automatically. + +## Validation rules + +Shopware validates the `` elements when the app is installed: + +- `name` and `hook` must match `[a-z0-9]+(-[a-z0-9]+)*` and `name` must be unique within the manifest. +- A `` declares either an `entity` or at least one ``, never both. +- Entity-bound routes require a non-empty ``. Static routes must not declare one. +- Static paths must only contain characters allowed in URLs and must not collide with an existing route such as `/account` or `/checkout`. + +## Limitations + +- SEO URLs are generated for storefront sales channels only. Headless sales channels are not supported yet. +- No `hreflang` links are generated for app routes. diff --git a/resources/references/app-reference/manifest-reference.md b/resources/references/app-reference/manifest-reference.md index 5766129a9d..914a571cd5 100644 --- a/resources/references/app-reference/manifest-reference.md +++ b/resources/references/app-reference/manifest-reference.md @@ -42,7 +42,7 @@ Validates that the Shopware instance is publicly reachable, which is necessary f ## Storefront -Can be omitted if your app template needs higher load priority than other plugins/apps. For more details, follow the [storefront guide](../../../guides/plugins/apps/storefront/index.md). +Configure the template load priority of your app and declare SEO URLs for pages rendered by your storefront scripts. For more details, follow the [storefront guide](../../../guides/plugins/apps/storefront/index.md) and the [SEO URLs for App Routes](../../../guides/plugins/apps/storefront/seo-urls.md) guide. <<< @/docs/snippets/config/app/storefront.xml diff --git a/snippets/config/app/storefront.xml b/snippets/config/app/storefront.xml index 901ab89800..b0c208443e 100644 --- a/snippets/config/app/storefront.xml +++ b/snippets/config/app/storefront.xml @@ -5,5 +5,14 @@ 100 + + + imprint + impressum + + + + blog/{{ ceBlog.translated.title }} + From 7690b1ef3e14844d99f379f1305363000cd6cf28 Mon Sep 17 00:00:00 2001 From: Max Stegmeyer Date: Thu, 24 Sep 2026 22:23:20 +0200 Subject: [PATCH 2/8] docs(apps): target 6.7.16.0 for app route SEO URLs --- guides/plugins/apps/storefront/seo-urls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/plugins/apps/storefront/seo-urls.md b/guides/plugins/apps/storefront/seo-urls.md index fc77767703..0db18d6cc5 100644 --- a/guides/plugins/apps/storefront/seo-urls.md +++ b/guides/plugins/apps/storefront/seo-urls.md @@ -12,7 +12,7 @@ nav: Storefront pages rendered by [app scripts](../app-scripts/custom-endpoints.md#storefront-endpoints) live under `/storefront/script/{hook}`. That path is technical and cannot carry an entity id. With `` elements in the `` section of your `manifest.xml`, Shopware gives those pages SEO URLs, the same way it does for products and categories. ::: info -This feature was introduced in Shopware 6.7.15.0 and is not available in earlier versions. +This feature was introduced in Shopware 6.7.16.0 and is not available in earlier versions. ::: There are two kinds of SEO URLs: From 9943cb302ca46361b67c2e04a3279d0080ab004a Mon Sep 17 00:00:00 2001 From: Max Stegmeyer Date: Thu, 24 Sep 2026 23:31:48 +0200 Subject: [PATCH 3/8] docs(apps): split app route SEO URLs into seo-url and entity-seo-url --- guides/plugins/apps/storefront/seo-urls.md | 38 ++++++++++------------ snippets/config/app/storefront.xml | 6 ++-- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/guides/plugins/apps/storefront/seo-urls.md b/guides/plugins/apps/storefront/seo-urls.md index 0db18d6cc5..b9f64ffc0f 100644 --- a/guides/plugins/apps/storefront/seo-urls.md +++ b/guides/plugins/apps/storefront/seo-urls.md @@ -9,7 +9,7 @@ nav: ## Overview -Storefront pages rendered by [app scripts](../app-scripts/custom-endpoints.md#storefront-endpoints) live under `/storefront/script/{hook}`. That path is technical and cannot carry an entity id. With `` elements in the `` section of your `manifest.xml`, Shopware gives those pages SEO URLs, the same way it does for products and categories. +Storefront pages rendered by [app scripts](../app-scripts/custom-endpoints.md#storefront-endpoints) live under `/storefront/script/{hook}`. That path is technical and cannot carry an entity id. With `` and `` elements in the `` section of your `manifest.xml`, Shopware gives those pages SEO URLs, the same way it does for products and categories. ::: info This feature was introduced in Shopware 6.7.16.0 and is not available in earlier versions. @@ -17,8 +17,8 @@ This feature was introduced in Shopware 6.7.16.0 and is not available in earlier There are two kinds of SEO URLs: -- A **static** SEO URL maps a fixed path such as `/imprint` to one of your storefront scripts. -- An **entity-bound** SEO URL generates one URL per entity from a Twig template, for example `/blog/{{ ceBlog.translated.title }}`, and passes the entity id to your script. +- A **static** SEO URL (``) maps a fixed path such as `/imprint` to one of your storefront scripts. +- An **entity-bound** SEO URL (``) generates one URL per entity from a Twig template, for example `/blog/{{ ceBlog.translated.title }}`, and passes the entity id to your script. ## Prerequisites @@ -37,8 +37,6 @@ Declare a `` with one or more `` elements. The `name` identifies - - imprint impressum @@ -46,7 +44,7 @@ Declare a `` with one or more `` elements. The `name` identifies ``` -With this manifest, `/imprint` and `/impressum` run the scripts in `Resources/scripts/storefront-imprint/`. Shopware writes one SEO URL per storefront sales channel domain and picks the `` matching the domain language, falling back to the `en-GB` path. Query parameters of the request stay available as `hook.query`. +With this manifest, `/imprint` and `/impressum` run the scripts in `Resources/scripts/storefront-imprint/`. Shopware writes one SEO URL per storefront sales channel domain and picks the `` of the domain language, falling back to its parent language and then to the shop's default language. Query parameters of the request stay available as `hook.query`. Set the `hook` attribute when the script folder should differ from the route name: @@ -58,18 +56,17 @@ Set the `hook` attribute when the script folder should differ from the route nam ## Entity-bound SEO URLs -Declare a `` with an `entity` attribute and a ``. The entity can be one of your [custom entities](../custom-data/custom-entities.md) or a core entity such as `product`. +Declare an `` with an `entity` attribute and a ``. The entity can be one of your [custom entities](../custom-data/custom-entities.md) or a core entity such as `product`. ```xml - - + blog/{{ ceBlog.translated.title }} - + ``` -Shopware generates one SEO URL per entity and language from the template and keeps it up to date whenever the entity is written. The template context exposes the entity under its camel-cased name, so `ce_blog` becomes `ceBlog` and `product` becomes `product`. Every field of the entity is available, translated fields through `translated`. +Shopware generates one SEO URL per entity and language from the template and keeps it up to date whenever the entity is written. Like the SEO URLs of products and categories, this follows the indexing behaviour of the write (for example the `indexing-behavior` header of the Sync API), and `bin/console dal:refresh:index` rebuilds them. The template context exposes the entity under its camel-cased name, so `ce_blog` becomes `ceBlog` and `product` becomes `product`. Every field of the entity is available, translated fields through `translated`. The generated URL resolves to `/storefront/script/blog-detail?id=`, so your script receives the id as `hook.query.id`: @@ -86,7 +83,7 @@ The generated URL resolves to `/storefront/script/blog-detail?id=`, s ### Merchant configuration -Entity-bound routes appear in the Administration under *Settings > SEO* as `storefront.app..`, for example `storefront.app.SwagBlog.blog-detail`. Merchants can adjust the template per sales channel and override single URLs like they do for products. Your `` is only the initial value. An app update replaces it only when the merchant has not changed it. +Entity-bound routes appear in the Administration under *Settings > SEO* as `storefront.app..`, for example `storefront.app.SwagBlog.blog-detail`. Merchants can adjust the template per sales channel and override single URLs like they do for products. Changing a template regenerates the URLs automatically. Your `` is only the initial value: app updates don't overwrite a template that already exists, so declare a new `name` if a route needs a fresh template. ## Linking to your pages @@ -104,19 +101,20 @@ Use the `seoUrl` Twig function with the technical route and parameters in your s ## Lifecycle -- **Install and update**: Shopware stores the declared routes and creates the default SEO URL template for entity-bound routes. -- **Activation**: The static SEO URLs are written and the entity-bound URLs are generated. This runs through the message queue, so make sure a [worker](../../../hosting/infrastructure/message-queue.md) processes messages. -- **Deactivation and uninstall**: The app's SEO URLs are marked as deleted and stop resolving. Uninstalling also removes the SEO URL templates. +- **Install and update**: Shopware stores the declared routes and creates the default SEO URL template for entity-bound routes that don't have one yet. Routes that an update no longer declares lose their SEO URLs and templates. +- **Activation and update**: The static SEO URLs are written and the entity-bound URLs are generated. This runs through the message queue, so make sure a [worker](../../../hosting/infrastructure/message-queue.md) processes messages. +- **Deactivation and uninstall**: The app's SEO URLs are marked as deleted and stop resolving. Uninstalling also removes the SEO URL templates, unless the merchant keeps the app data. - **New sales channel domains**: Static SEO URLs are written for new domains automatically. ## Validation rules -Shopware validates the `` elements when the app is installed: +The manifest schema checks the structure of both elements: -- `name` and `hook` must match `[a-z0-9]+(-[a-z0-9]+)*` and `name` must be unique within the manifest. -- A `` declares either an `entity` or at least one ``, never both. -- Entity-bound routes require a non-empty ``. Static routes must not declare one. -- Static paths must only contain characters allowed in URLs and must not collide with an existing route such as `/account` or `/checkout`. +- `name` and `hook` must match `[a-z0-9]+(-[a-z0-9]+)*`, and `name` must be unique across all `` and `` elements of the app. +- A `` needs at least one non-empty ``. +- An `` needs an `entity` attribute and a non-empty ``. + +On install and update, Shopware rejects static paths that contain characters not allowed in URLs, or that are already used by a storefront route such as `/account`, by another app or by an existing SEO URL. ## Limitations diff --git a/snippets/config/app/storefront.xml b/snippets/config/app/storefront.xml index b0c208443e..c3152265b7 100644 --- a/snippets/config/app/storefront.xml +++ b/snippets/config/app/storefront.xml @@ -6,13 +6,11 @@ 100 - imprint impressum - - + blog/{{ ceBlog.translated.title }} - + From 77607924d941aa6414fc7ce45ac2fed8578d3e53 Mon Sep 17 00:00:00 2001 From: Max Stegmeyer Date: Fri, 25 Sep 2026 00:22:27 +0200 Subject: [PATCH 4/8] docs(apps): mention entity changes and skipping app SEO URL regeneration --- guides/plugins/apps/storefront/seo-urls.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guides/plugins/apps/storefront/seo-urls.md b/guides/plugins/apps/storefront/seo-urls.md index b9f64ffc0f..8bbb94fba8 100644 --- a/guides/plugins/apps/storefront/seo-urls.md +++ b/guides/plugins/apps/storefront/seo-urls.md @@ -66,7 +66,7 @@ Declare an `` with an `entity` attribute and a ` ``` -Shopware generates one SEO URL per entity and language from the template and keeps it up to date whenever the entity is written. Like the SEO URLs of products and categories, this follows the indexing behaviour of the write (for example the `indexing-behavior` header of the Sync API), and `bin/console dal:refresh:index` rebuilds them. The template context exposes the entity under its camel-cased name, so `ce_blog` becomes `ceBlog` and `product` becomes `product`. Every field of the entity is available, translated fields through `translated`. +Shopware generates one SEO URL per entity and language from the template and keeps it up to date whenever the entity is written. Like the SEO URLs of products and categories, this follows the indexing behaviour of the write (for example the `indexing-behavior` header of the Sync API, or `indexing-skip: app_seo_url.seo-url` to skip it), and `bin/console dal:refresh:index` rebuilds them. The template context exposes the entity under its camel-cased name, so `ce_blog` becomes `ceBlog` and `product` becomes `product`. Every field of the entity is available, translated fields through `translated`. The generated URL resolves to `/storefront/script/blog-detail?id=`, so your script receives the id as `hook.query.id`: @@ -83,7 +83,7 @@ The generated URL resolves to `/storefront/script/blog-detail?id=`, s ### Merchant configuration -Entity-bound routes appear in the Administration under *Settings > SEO* as `storefront.app..`, for example `storefront.app.SwagBlog.blog-detail`. Merchants can adjust the template per sales channel and override single URLs like they do for products. Changing a template regenerates the URLs automatically. Your `` is only the initial value: app updates don't overwrite a template that already exists, so declare a new `name` if a route needs a fresh template. +Entity-bound routes appear in the Administration under *Settings > SEO* as `storefront.app..`, for example `storefront.app.SwagBlog.blog-detail`. Merchants can adjust the template per sales channel and override single URLs like they do for products. Changing a template regenerates the URLs automatically. Your `` is only the initial value: app updates don't overwrite a template that already exists, unless the route now points to a different entity. Declare a new `name` if a route needs a fresh template for the same entity. ## Linking to your pages From bf85d9948d74ca9bf850c6e27d5ffe7eda38f10f Mon Sep 17 00:00:00 2001 From: Max Stegmeyer Date: Wed, 30 Sep 2026 19:20:00 +0200 Subject: [PATCH 5/8] docs(apps): describe permissions and hook rules of app SEO URLs --- guides/plugins/apps/storefront/seo-urls.md | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/guides/plugins/apps/storefront/seo-urls.md b/guides/plugins/apps/storefront/seo-urls.md index 8bbb94fba8..128f5d0197 100644 --- a/guides/plugins/apps/storefront/seo-urls.md +++ b/guides/plugins/apps/storefront/seo-urls.md @@ -81,9 +81,27 @@ The generated URL resolves to `/storefront/script/blog-detail?id=`, s ) %} ``` +### Permissions + +Your app needs `` permission for the entity and for every association your `` uses. A template that reads `product.manufacturer.name` needs both entities: + +```xml + + + {{ product.manufacturer.name }}/{{ product.translated.name }} + + + + product + product_manufacturer + +``` + +Your own [custom entities](../custom-data/custom-entities.md#permissions) need no extra permission: your app has full access to them anyway. The generated paths are public, so only use fields in the template that may appear in a URL. + ### Merchant configuration -Entity-bound routes appear in the Administration under *Settings > SEO* as `storefront.app..`, for example `storefront.app.SwagBlog.blog-detail`. Merchants can adjust the template per sales channel and override single URLs like they do for products. Changing a template regenerates the URLs automatically. Your `` is only the initial value: app updates don't overwrite a template that already exists, unless the route now points to a different entity. Declare a new `name` if a route needs a fresh template for the same entity. +Entity-bound routes appear in the Administration under *Settings > SEO* as `storefront.app..`, for example `storefront.app.SwagBlog.blog-detail`. Merchants can adjust the template per sales channel and override single URLs like they do for products. Changing a template regenerates the URLs automatically. Your `` is only the initial value: app updates don't overwrite a template that already exists. Changing the `entity` of a route resets every template of that route, including sales channel overrides. Declare a new `name` if a route needs a fresh template for the same entity. ## Linking to your pages @@ -103,6 +121,7 @@ Use the `seoUrl` Twig function with the technical route and parameters in your s - **Install and update**: Shopware stores the declared routes and creates the default SEO URL template for entity-bound routes that don't have one yet. Routes that an update no longer declares lose their SEO URLs and templates. - **Activation and update**: The static SEO URLs are written and the entity-bound URLs are generated. This runs through the message queue, so make sure a [worker](../../../hosting/infrastructure/message-queue.md) processes messages. +- **Hook changes**: Changing the `hook` of a route keeps its SEO URLs, including the merchant's edits, and points them at the new script. - **Deactivation and uninstall**: The app's SEO URLs are marked as deleted and stop resolving. Uninstalling also removes the SEO URL templates, unless the merchant keeps the app data. - **New sales channel domains**: Static SEO URLs are written for new domains automatically. @@ -114,7 +133,11 @@ The manifest schema checks the structure of both elements: - A `` needs at least one non-empty ``. - An `` needs an `entity` attribute and a non-empty ``. -On install and update, Shopware rejects static paths that contain characters not allowed in URLs, or that are already used by a storefront route such as `/account`, by another app or by an existing SEO URL. +On install and update, Shopware also checks: + +- Static paths must not contain characters that aren't allowed in URLs, and must not already be used by a storefront route such as `/account`, by another app or by an existing SEO URL. +- A script hook belongs to the first app that declares it in an SEO URL. Within your app, a hook can be used by at most one `` and at most one ``. +- The `entity` of an `` must exist and must not be a mapping or translation entity, and your app needs the [permissions](#permissions) described above. ## Limitations From 7ec2adbca451143ad3b5d458d8b47b385c26eb1d Mon Sep 17 00:00:00 2001 From: Max Stegmeyer Date: Mon, 5 Oct 2026 21:21:16 +0200 Subject: [PATCH 6/8] docs(apps): static app SEO URLs follow the index run and the default language --- guides/plugins/apps/storefront/seo-urls.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/guides/plugins/apps/storefront/seo-urls.md b/guides/plugins/apps/storefront/seo-urls.md index 128f5d0197..50d0ac6236 100644 --- a/guides/plugins/apps/storefront/seo-urls.md +++ b/guides/plugins/apps/storefront/seo-urls.md @@ -44,7 +44,7 @@ Declare a `` with one or more `` elements. The `name` identifies ``` -With this manifest, `/imprint` and `/impressum` run the scripts in `Resources/scripts/storefront-imprint/`. Shopware writes one SEO URL per storefront sales channel domain and picks the `` of the domain language, falling back to its parent language and then to the shop's default language. Query parameters of the request stay available as `hook.query`. +With this manifest, `/imprint` and `/impressum` run the scripts in `Resources/scripts/storefront-imprint/`. Shopware writes one SEO URL per storefront sales channel domain. It picks the `` of the domain language and falls back to the shop's default language. Query parameters of the request stay available as `hook.query`. Set the `hook` attribute when the script folder should differ from the route name: @@ -120,10 +120,10 @@ Use the `seoUrl` Twig function with the technical route and parameters in your s ## Lifecycle - **Install and update**: Shopware stores the declared routes and creates the default SEO URL template for entity-bound routes that don't have one yet. Routes that an update no longer declares lose their SEO URLs and templates. -- **Activation and update**: The static SEO URLs are written and the entity-bound URLs are generated. This runs through the message queue, so make sure a [worker](../../../hosting/infrastructure/message-queue.md) processes messages. +- **Activation and update**: The static SEO URLs are written right away. The entity-bound URLs are generated through the message queue, so make sure a [worker](../../../hosting/infrastructure/message-queue.md) processes messages. - **Hook changes**: Changing the `hook` of a route keeps its SEO URLs, including the merchant's edits, and points them at the new script. - **Deactivation and uninstall**: The app's SEO URLs are marked as deleted and stop resolving. Uninstalling also removes the SEO URL templates, unless the merchant keeps the app data. -- **New sales channel domains**: Static SEO URLs are written for new domains automatically. +- **New sales channel domains**: Like product URLs, the static SEO URLs for a new domain show up on the next activation or update of the app, or after `bin/console dal:refresh:index`. ## Validation rules From e29dc9a51977174eed6e8f3a1992acbab32dd821 Mon Sep 17 00:00:00 2001 From: Max Stegmeyer Date: Fri, 9 Oct 2026 12:00:48 +0200 Subject: [PATCH 7/8] fix: typo Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- guides/plugins/apps/app-scripts/custom-endpoints.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/plugins/apps/app-scripts/custom-endpoints.md b/guides/plugins/apps/app-scripts/custom-endpoints.md index 8e6b712161..699def9fd9 100644 --- a/guides/plugins/apps/app-scripts/custom-endpoints.md +++ b/guides/plugins/apps/app-scripts/custom-endpoints.md @@ -129,7 +129,7 @@ Additionally, it is also possible to redirect to an existing route: For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#storefront-hook). -To make such a page reachable under a readable path like `/imprint` or `/blog/my-post`, declare a SEO URL for it in your manifest. See the [SEO URLs for App Routes](../storefront/seo-urls.md) guide. +To make such a page reachable under a readable path like `/imprint` or `/blog/my-post`, declare an SEO URL for it in your manifest. See the [SEO URLs for App Routes](../storefront/seo-urls.md) guide. ## Manipulate HTTP-headers to API responses From dd16db9419e1143905bb70a1a07c65d97a4d95f8 Mon Sep 17 00:00:00 2001 From: Micha Hobert Date: Fri, 9 Oct 2026 13:54:35 +0200 Subject: [PATCH 8/8] adjust/grammar-and-wording --- guides/plugins/apps/storefront/seo-urls.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guides/plugins/apps/storefront/seo-urls.md b/guides/plugins/apps/storefront/seo-urls.md index 50d0ac6236..eb2323b041 100644 --- a/guides/plugins/apps/storefront/seo-urls.md +++ b/guides/plugins/apps/storefront/seo-urls.md @@ -133,9 +133,9 @@ The manifest schema checks the structure of both elements: - A `` needs at least one non-empty ``. - An `` needs an `entity` attribute and a non-empty ``. -On install and update, Shopware also checks: +On app `install` and `update`, Shopware also checks: -- Static paths must not contain characters that aren't allowed in URLs, and must not already be used by a storefront route such as `/account`, by another app or by an existing SEO URL. +- Static paths must not contain characters that aren't allowed in URLs and must not yet be used by a storefront route such as `/account`, by another app or by an existing SEO URL. - A script hook belongs to the first app that declares it in an SEO URL. Within your app, a hook can be used by at most one `` and at most one ``. - The `entity` of an `` must exist and must not be a mapping or translation entity, and your app needs the [permissions](#permissions) described above.