devable / shopware6-sitemap-domain-filter
Symfony bundle that excludes configured domains from the Shopware 6 sitemap generation
Package info
github.com/jmatthiesen81/shopware6-sitemap-domain-filter
Type:symfony-bundle
pkg:composer/devable/shopware6-sitemap-domain-filter
Requires
- php: >=8.2
- shopware/core: ~6.7.0
- symfony/http-kernel: ^7.0
Requires (Dev)
- league/flysystem-memory: ^3.0
- phpunit/phpunit: ^11.0 || ^12.0
- shopware/storefront: ~6.7.0
Suggests
- shopware/storefront: Removes the excluded hosts from the robots.txt sitemap list (Shopware 6.7.1+)
Provides
None
Conflicts
None
Replaces
None
README
Symfony bundle (not a Shopware plugin) that skips the sitemap generation and delivery for configured domains.
Shopware creates one sitemap per domain of a sales channel and language, and lists all of them in the same
sitemap.xml index. If two domains share a sales channel and a language, both sitemaps show up in that index.
This bundle prevents the sitemap of the excluded domains from being written, answers their sitemap.xml with a 404
and removes them from the Sitemap: lines of the robots.txt.
Requirements
- PHP 8.2+
- Shopware 6.7 (
shopware/core ~6.7.0)
Installation
composer require devable/shopware6-sitemap-domain-filter
There is no Flex recipe. Register the bundle in config/bundles.php:
Devable\SitemapDomainFilterBundle\SitemapDomainFilterBundle::class => ['all' => true],
Configuration
# config/packages/devable_sitemap_domain_filter.yaml devable_sitemap_domain_filter: excluded_domains: - devable.me
- Entries are hosts. Full URLs are accepted and reduced to the host (
https://Devable.me/→devable.me). - Matching is case-insensitive but exact:
www.devable.meneeds its own entry. - A host excludes all of its paths (
devable.me/entoo) and ignores the port. - With an empty list the bundle registers nothing.
Regenerate the sitemap and clear the HTTP cache afterwards, since sitemap.xml and robots.txt may be cached:
bin/console sitemap:generate --force bin/console cache:clear
How it works
The bundle decorates Shopware\Core\Content\Sitemap\Service\SitemapHandleFactoryInterface. For an excluded host it
returns a NullSitemapHandle that writes nothing, so no file exists that SitemapLister could list.
Shopware cleans up old sitemap files only through the first handle. If the excluded domain is first, the
NullSitemapHandle does that cleanup itself, so old files of the excluded domain are removed as well.
Delivery
The core lists sitemaps per sales channel and language, not per domain. Without further measures,
devable.me/sitemap.xml would still serve an index that lists the sitemap files of the other domain. Therefore:
SitemapRequestSubscriberanswers the Storefront routesfrontend.sitemap.xmlandfrontend.sitemap.proxywith an empty 404 if the request host is excluded. It runs onkernel.requestbefore the sales channel context is resolved, so the 404 is not stored in the HTTP cache.RobotsSitemapSubscriberremoves theSitemap:lines of excluded hosts from therobots.txt. It is only registered ifRobotsPageLoadedEventexists (Storefront 6.7.1+).
The Store API route /store-api/sitemap is not affected, because it identifies the sales channel by access key, not
by domain. Headless frontends have to handle excluded domains themselves.
SEO note
The excluded domain stays an active, crawlable storefront with the same content as the other domain. If it does not have to stay one, removing it from the sales channel and redirecting it (301) is the cleaner solution.
Maintenance
The bundle relies on internal behavior of SitemapExporter and SitemapHandle. On Shopware updates, check:
SitemapExporter::initSitemapHandles()/finishSitemapHandles()(cleanup still only via the first handle?)SitemapHandle::getPath()/cleanUp()(folder schemesitemap/salesChannel-{sc}-{lang}/)SitemapHandleFactoryInterface::create()signature and its service ID- Route names in
Shopware\Storefront\Controller\SitemapController(frontend.sitemap.xml,frontend.sitemap.proxy) RobotsPageLoader::getSitemaps()/RobotsPage::setSitemaps()
Tests
composer install
composer test