Release notes Shopware 6.7.12.0
Do not install
This release cannot be installed or updated to because it contains a breaking issue discovered shortly after release. Please use v6.7.12.1 instead.
We kept the regular release cycle to avoid disrupting continuous integration and versioning for our community. The changes from this version are still listed below, but they are only available by installing v6.7.12.1, which includes a fix for the issue.
Abstract
Shopware 6.7.12.0 closes 332 issues, focusing heavily on operational stability and AI readiness. It improves checkout fallbacks, order handling, product feeds, media uploads, customer data, Administration usability, accessibility, caching, Elasticsearch/OpenSearch behavior, and migration reliability. The release also expands platform capabilities with agent-facing sales-channel files, MCP endpoints, improved webhooks, enhanced rule builder features, richer product comparison data, and standardized CLI output options.
System requirements
- tested on PHP 8.2, 8.4 and 8.5
- tested on MySQL 8 and MariaDB 11
Improvements
Features
Agentic files for sales channels
Sales channels can now publish opt-in agentic files such as /llms.txt and /agents.md. Merchants can manage these files in the sales channel details, enable them per sales channel, preview the generated content, and add custom notes without replacing the default content provided by Shopware or extensions.
Core ships the initial agentic file family. The files are rendered from Twig templates, so Shopware, plugins, apps, and themes can contribute or extend content through normal Shopware Twig inheritance. Extensions can add additional templates under Resources/views/files/agentic/**.twig, including nested paths such as .well-known/*.
The Admin API exposes documented action routes for listing, reading details, and previewing sales-channel files under /api/_action/sales-channel-file/{fileFamily}/{salesChannelId}.
Storefront
Storefront cache hash no longer varies by language
The HTTP cache hash no longer includes the language id for storefront requests, because the storefront language is derived from the resolved domain URL. Store API requests still include the language id in the cache hash, as the same Store API URL can return different languages via the sw-language-id header.
Central extension point for content before/after list prices
A new template @Storefront/storefront/component/product/list-price-affix.html.twig is rendered inside every list price display (product box, product detail buy widget, advanced pricing table). It replaces the deprecated listing.beforeListPrice / listing.afterListPrice snippets as the single place to inject content around list prices.
Content can be provided in two ways:
- Without code: create a translation snippet with a custom key and enter that key in the new sales-channel-aware system config settings
core.listing.beforeListPriceSnippetKey/core.listing.afterListPriceSnippetKey. The snippet content is rendered sanitized, wrapped in alist-price-affix list-price-affix-{before|after}span. - In a theme or plugin: override the block
component_list_price_affix_contentonce; thepositionvariable (before/after) allows position-specific output.
Thumbnail sizes attribute now emits a value for the XXL breakpoint
The auto-generated sizes attribute produced by thumbnail.html.twig now includes a value for the XXL breakpoint. The xxl key is the open-ended top (container / columns), and xl is a closed range bounded by breakpoint.xxl - 1, matching the pattern used by smaller breakpoints. Templates that pass a manual sizes map to sw_thumbnails should add an xxl entry to keep parity.
Use Bootstrap variable for headings spacing
The hard-coded CSS margin-bottom was removed from HTML headlines H1-H6. The bootstrap variable $headings-margin-bottom can now be used to set the bottom spacing of headlines.
Storefront XHR login failures now keep HTTP 403
Storefront requests that require a logged-in customer no longer redirect to the login page for XMLHttpRequests when the customer session is no longer valid. The original 403 Forbidden response is preserved. Regular page requests still redirect to the login page. This prevents expired sessions from creating redirect chains from XHR endpoints to page controllers and fixes the follow-up failure where the redirected XHR request reaches the login page, which does not allow XHR access. JavaScript clients can now handle the failed unauthenticated XHR response explicitly.
Mail templates can access storefront theme configuration
Mail templates rendered for a sales channel now receive a temporary salesChannelContext and the assigned themeId. This allows Twig helpers such as theme_config() to resolve storefront theme configuration in mails without replacing the existing core context variable. The shared MailTemplateRenderContextEvent is dispatched for both sent mails and preview/simulation rendering so extensions can enrich mail template data through one hook.
Google Ads Enhanced Conversions
A new Enhanced Conversions option was added to the Google Analytics integration. When enabled in the sales channel analytics settings, the checkout finish page sends the SHA256-hashed customer email address via gtag('set', 'user_data', ...) to support Google Ads Enhanced Conversions. Email addresses are normalized according to Google's requirements before hashing.
A new enhanced_conversions boolean field was added to SalesChannelAnalyticsDefinition and SalesChannelAnalyticsEntity.
New extensible Twig block page_checkout_finish_enhanced_conversions has been added to finish-details.html.twig.
Country state field visibility in address forms
Storefront address forms now respect the country displayStateInRegistration setting. When disabled, the country state field is hidden unless forceStateInRegistration is enabled, in which case the required state field is still shown. During the update, displayStateInRegistration is activated for every country that has at least one configured state/region. This keeps existing storefront address forms showing their state selector until the setting is disabled explicitly.
Checkout gateway blocked method fallback
Storefront checkout cart and confirm page loading now resolves payment and shipping methods blocked by the checkout gateway before rendering the page. The fallback method is selected from the checkout gateway response, preferring the sales-channel default method when available and otherwise using the first available method declared by the gateway.
Customer address fields are trimmed on new writes
Customer address fields submitted through storefront registration and address updates are now trimmed before they are written. This prevents leading or trailing whitespace from being stored in standard address fields such as first name, last name, street, city, and zipcode.
Existing customer address records are not changed.
New contentSelector option for the AlertAriaPlugin
The AlertAriaPlugin now supports a contentSelector option to define the content element inside the aria-live region that is toggled to trigger the screenreader. It defaults to .alert-content-container. Override it when applying the plugin to custom markup that is not based on the alert template:
<div class="cart-live-update visually-hidden"
role="status"
aria-live="polite"
data-alert-aria="true"
data-alert-aria-options='{{ { contentSelector: ".cart-live-update-content" }|json_encode }}'>
<div class="cart-live-update-content">
{# ... content that should be announced ... #}
</div>
</div>API
Plain JSON API includes preserve extension wrappers
The Admin API plain JSON encoder now keeps extension association fields inside the extensions object when they are selected through includes. For example, including an extension association such as toOne on an entity returns extensions.toOne instead of promoting toOne to the top-level response. Nested extension entities also respect their own include definitions, so API clients can filter extension payload fields consistently.
Customer email uniqueness is enforced on writes
Admin API and Sync API customer writes now enforce the same non-guest customer email uniqueness rules as the Administration customer form and Store API registration flows. When core.systemWideLoginRegistration.isCustomerBoundToSalesChannel is disabled, a non-guest customer email must be unique globally. When the setting is enabled, duplicate non-guest emails are only accepted for customers bound to different sales channels. Extensions can use Shopware\Core\Checkout\Customer\Validation\CustomerEmailUniqueChecker with CustomerEmailUniqueCheck to apply the same configuration-aware uniqueness rules.
Number range previews can target a concrete number range
The Admin API now supports previewing a persisted number range by id via /api/_action/number-range/{numberRangeId}/preview-pattern. Use this route when editing an existing number range, because it reads the state for the concrete number_range.id.
The previous type-based preview route /api/_action/number-range/preview-pattern/{type} remains available in 6.7 for backwards compatibility, but is deprecated and will be removed in 6.8. It can only resolve global number ranges and therefore does not support non-global number range state. The allocation route /api/_action/number-range/reserve/{type} is unchanged.
Empty sw-* id headers are treated as unset
Admin API and Store API requests now treat empty ID headers such as sw-language-id, sw-currency-id, sw-app-integration-id, and sw-app-user-id the same as missing headers. Empty values fall back to the default request context instead of being forwarded as invalid UUIDs. Whitespace-only values are still rejected as malformed IDs.
For cache efficiency, clients should consistently either omit sw-language-id and sw-currency-id or send them empty when they intentionally want default context resolution, because these headers can participate in reverse-proxy cache keys.
Administration users receive default runtime privileges
Authenticated Administration users now receive the default privileges required by global Admin helpers: language:read, locale:read, message_queue_stats:read, log_entry:create, currency:read, and country:read. The Administration role editor also adds these privileges to newly generated role permission sets.
Core
Rule Builder: new "Quantity per item" condition
A new line item rule condition LineItemPerItemQuantityRule (cartLineItemPerItemQuantity) was added. It matches the cart against the quantity of each individual line item, without selecting a specific product.
Storefront snippets of self-managed apps are loaded
Storefront snippet files (Resources/snippet/*.json) shipped by self-managed apps (services) are now loaded. Previously, the snippet loader resolved app snippets only from the local app directory, which self-managed apps do not have, so their storefront snippets were silently ignored. The snippet files are now resolved through the app source system, the same way assets, scripts, and admin snippets of self-managed apps already are. Service developers no longer need to work around missing storefront translations; the same app zip now behaves identically whether installed as a regular app or as a service.
Deprecation of shopware.cache.cache_compression and shopware.cache.cache_compression_method config options
The shopware.cache.cache_compression and shopware.cache.cache_compression_method configuration options are deprecated and will be removed in v6.8.0.0. Please use the new shopware.cache.compress and shopware.cache.compression_method options instead.
Before
shopware:
cache:
cache_compression: true
cache_compression_method: 'gzip'After
shopware:
cache:
compress: true
compression_method: 'gzip'Stored mail template type data deprecated
The persisted mail_template_type.template_data column is deprecated and will be removed in Shopware 6.8. It was only used as stored preview data and is no longer needed after the mail template preview refactoring.
Use explicit templateData in the mail preview and send APIs, or generated data from the simulate endpoint, instead. The mail API request payloads templateData and mailTemplateData remain supported and are not part of this deprecation.
Pluggable thumbnail image processor
The thumbnail generation pipeline now uses a ThumbnailProcessorInterface instead of a hardwired GD implementation. Two processors ship out of the box:
GdImageThumbnailProcessor— uses the PHP GD extension and is the default.ImagickThumbnailProcessor— uses the PHP Imagick extension, if installed.
Switch between them in config/packages/shopware.yaml:
shopware:
media:
thumbnail_processor: imagick # or "gd" (default)
Both processors work with the new ThumbnailImage DTO (Shopware\Core\Content\Media\Thumbnail\DTO\ThumbnailImage), which is a thin wrapper carrying the underlying image resource. ThumbnailService only ever deals with ThumbnailImage objects and is fully agnostic of the concrete library.
Core Twig config() helper
The Twig config() helper is now provided by the core Twig environment so non-storefront templates can read sales-channel-aware system configuration. Twig templates can continue using config('my.config.key') unchanged.
The PHP methods Shopware\Storefront\Framework\Twig\Extension\ConfigExtension::config() and Shopware\Storefront\Framework\Twig\TemplateConfigAccessor::config() are deprecated. PHP code should use SystemConfigService directly instead.
Number range value generator interface deprecated
NumberRangeValueGeneratorInterface is deprecated in favor of AbstractNumberRangeValueGenerator. Custom number range value generator implementations and decorators should extend the abstract class instead. Implement previewPatternByNumberRangeId() for persisted number-range previews and continue using getValue() for actual number allocation.
The type-based previewPattern() method remains available for backwards compatibility in 6.7, but is deprecated and will be removed in 6.8. Use previewPatternByNumberRangeId() when previewing or editing an existing number range.
Orders no longer break on missing rule conditions in price definitions
If an order's AbsolutePriceDefinition, CurrencyPriceDefinition, or PercentagePriceDefinition references a rule condition that is no longer registered (e.g. a plugin contributing it has been uninstalled), PriceDefinitionFieldSerializer no longer throws ConditionTypeNotFound/InvalidConditionException. Such conditions are substituted with a new internal UnknownConditionRule whose match() always returns false.
The original rule payload is preserved verbatim on reads, order versioning and normal saves, so the order stays fully accessible and editable in the Administration and is restored automatically once the contributing plugin is reinstalled. Recalculation also succeeds, but because it recomputes the cart, a discount whose missing condition no longer matches any line item is removed (fail-closed) rather than preserved — so an order that is recalculated and saved may lose that discount line. When that happens, the recalculation result now contains a promotion-discount-unknown-condition warning (PromotionDiscountUnknownConditionError, shown as a notification in the Administration order detail page), so the discount is not removed silently.
Note that match() returning false only yields a fail-closed result for a standalone condition or inside an AndRule. Inside an OrRule/XorRule the surrounding container can still match through its other branches, and inside a NotRule the result is inverted to always-match.
Note for API consumers: writes to price-definition fields that reference an unregistered rule condition are now accepted instead of rejected, so order versioning and saves keep working. A mistyped condition name in an Admin API write is therefore no longer reported as a validation error — the condition is stored as-is and will simply never match.
Elasticsearch: Dedicated completion field for admin-search autocomplete
Admin-search autocomplete now flows through a new completion field (ngram-indexed, populated with name-shaped values per entity). The ngram subfield has been dropped from text/textBoosted so identifiers (EAN, productNumber, orderNumber, etc.) no longer feed ngram scoring — fixing a regression where a full GTIN search could be outranked by unrelated products with overlapping digit substrings.
Run bin/console es:admin:index after deploying. Identifier search works immediately on the old index; substring autocomplete is degraded to prefix-only until the reindex completes.
Type-safe subscription helpers on Extension
Shopware\Core\Framework\Extensions\Extension now exposes three static helpers — onPre(), onPost(), and onError() — that return the dispatched event name for the corresponding phase. Extensions need ::NAME constant for the methods to work.
Use them in getSubscribedEvents() instead of string concatenation or ExtensionDispatcher::pre/post/error():
public static function getSubscribedEvents(): array
{
return [
ResolveListingExtension::onPre() => 'method1',
ResolveListingExtension::onPost() => 'method2',
ResolveListingExtension::onError() => 'method3',
];
}Dispatchers and subscribers no longer have to concatenate event-name strings - it gives type safety, IDE autocomplete, and rename-refactor support. Also subscribers don't have to depend on ExtensionDispatcher.
The previous styles — MyExtension::NAME . '.post' and ExtensionDispatcher::post(MyExtension::NAME) — continue to work and are not deprecated. No migration is required.
Telemetry metrics evolution
The telemetry metrics abstraction behind the TELEMETRY_METRICS feature flag received several improvements ahead of stabilization in 6.8. See ADR 2026-04-23 for the full reasoning.
- Breaking:
MetricTransportInterfacenow requires aflush()method. Implement it as a no-op if the transport does not need lifecycle management. A newTelemetryFlushListenercallsflush()onkernel.terminate,console.terminate, and (throttled) onWorkerRunningEventso emissions from long-running workers reach the backend. - Global kill-switch
shopware.telemetry.metrics.enableddisables emission and removes services taggedshopware.telemetry.subscriber/shopware.telemetry.periodic_metric_collectorvia a compiler pass — zero overhead when off. - Per-label validation policies: each label in a metric definition must declare either
allowed_valuesorpolicy: open. Unknown values are handled perpolicy(replace/discard/open), with type-aware defaults (additive types replace, gauges discard). Unknown label names throw in dev/test and log at error level in production; replacements log at notice level in dev/test so typos likeGETTvsGETsurface during development. PeriodicMetricCollectorInterface: tag a service withshopware.telemetry.periodic_metric_collectorto have its metrics collected by thetelemetry.collect_periodic_metricsscheduled task (default 5 minutes, tunable via the standard scheduled-task administration). Useful for expensive aggregations and info metrics.- New
Telemetryfacade: injectTelemetryto callemit(ConfiguredMetric)andinstrument(callback, DurationMetric?, Span?)for combined duration metrics and profiler spans through a single entry point. - Config cleanup:
allow_unknown_labels,allow_unknown_label_values, andenable_internal_metricsare deprecated (superseded by per-label policies and per-metricenabled).
Auto-resend double opt-in confirmation email on failed login
When a customer with an unconfirmed double opt-in account tries to log in, Shopware now automatically resends the confirmation email if the original was sent more than a configurable interval ago.
The interval is controlled by the new system config setting core.loginRegistration.doubleOptInResendInterval (default: 24 hours). Setting it to 0 disables the auto-resend entirely.
Successful password recovery now also confirms an unconfirmed double opt-in customer account, because completing the recovery flow proves access to the account email address.
Standardized CLI JSON output flag
CLI commands now consistently use --format json to request JSON output. The previously used --json and --output json options are deprecated and will be removed in Shopware 6.8.0.0.
Affected commands:
bin/console user:list --json→bin/console user:list --format jsonbin/console app:list --json→bin/console app:list --format jsonbin/console plugin:list --json→bin/console plugin:list --format jsonbin/console dal:validate --json→bin/console dal:validate --format jsonbin/console sales-channel:list --output json→bin/console sales-channel:list --format json
cache:watch:delayed shuts down gracefully
The cache:watch:delayed command now stops cleanly on SIGINT/SIGTERM instead of being killed mid-loop, and exposes a configurable --interval option (microseconds) for the poll frequency.
New sha256 Twig filter
A new sha256 Twig filter is available alongside the existing md5 filter. Both accept strings and arrays (arrays are JSON-encoded before hashing) and return the hex-encoded hash.
Variants can now be searched by parent product name
The new parent.name search field allows variants to be found through their parent product name and ranked independently from the variant's own name.
The field is disabled by default. Enable parent.name in the product search configuration to make this behavior active and adjust its ranking there.
Reduced product data in listings via description teaser
Product listings can now load a shortened, HTML-free excerpt of the product description instead of the full text, which significantly reduces database load, transfer size and memory usage for catalogs with large descriptions. Previously the complete description was loaded for every product box even though the storefront only displays a few clamped lines.
This reduced loading is enabled for fresh installations and disabled for existing shops, which keep the full listing loading on update and can opt in per sales channel via the new core.listing.partialDataLoading setting (Settings > Products). When enabled, the product listing route loads a curated, reduced field set covering the default product boxes; listing products are then partial entities. Only enable it if your theme and extensions work with the reduced product data in listings.
A new read-only, translatable descriptionTeaser field is available on product (and product_translation). It is derived from the description on write (HTML stripped, truncated to 512 characters) and exposed via the Store and Admin API. The stripping is configurable through the html_sanitizer field set product_translation.descriptionTeaser. Existing products are backfilled asynchronously: the migration schedules the product.description_teaser.indexer, which runs over the message queue after the update (or manually via bin/console dal:refresh:index).
Agentic Commerce product export and tracking classes deprecated
The following classes related to Agentic Commerce product exports, providers, and sales channel tracking are deprecated and will be removed in Shopware 6.8.0:
Shopware\Core\Content\ProductExport\Provider\AbstractAgenticCommerceProductExportProviderShopware\Core\Content\ProductExport\Provider\AgenticCommerceProductExportProviderRegistryShopware\Core\Content\ProductExport\Provider\GoogleProductExportProviderShopware\Core\Content\ProductExport\Provider\OpenAiProductExportProviderShopware\Core\Content\ProductExport\Validator\JsonlRowParserShopware\Core\Content\ProductExport\Validator\OpenAiProductExportValidatorShopware\Core\Content\ProductExport\Validator\GoogleProductExportValidator
This functionality will be available in the Agentic Commerce extension (SwagAgenticCommerce) instead.
Administration
sw-select-field forwards aria-label to the native select
The deprecated sw-select-field now passes through aria-label and aria-labelledby attributes to the underlying native <select> element. Previously these attributes were applied to the wrapping field component but never reached the form control, leaving selects without an accessible name (e.g. the range picker of sw-chart-card). Plugins that render a sw-select-field without a visible <label> can now give it an accessible name by passing aria-label / aria-labelledby.
Cache-relevant extension configuration fields
As a follow-up to Reduced HTTP cache invalidation on system config changes, plugin and app Resources/config/config.xml files can now mark fields that affect cached storefront output with the cache-relevant="true" attribute on <input-field> or <component>.
When a marked field is changed in the Administration system config renderer, the save request explicitly sends silent=false, so HTTP cache entries tagged with system.config-{salesChannelId} are invalidated. Unmarked fields keep the default system config write behavior.
Storefront icon cache and speculation rules can be configured per sales channel
The Storefront settings Administration page now allows the icon cache and speculation rules settings (core.storefrontSettings.iconCache and core.storefrontSettings.speculationRules) to be configured per sales channel. core.storefrontSettings.asyncThemeCompilation remains a global setting and was moved into a separate Theme configuration card.
The storefront runtime now resolves the icon cache setting with the active sales channel id, matching the sales-channel-aware speculation rules lookup. The old sw_settings_storefront_smtp_settings block is deprecated and will be removed in v6.8.0.
Analytics settings split into Configuration and Tracking cards
The analytics settings view in sw-sales-channel-detail-analytics was split into two cards: Configuration (general settings like tracking ID, active state, anonymize IP) and Tracking (order tracking, offcanvas cart tracking, enhanced conversions).
New extensible Twig blocks sw_sales_channel_detail_analytics_configuration, sw_sales_channel_detail_analytics_tracking, sw_sales_channel_detail_analytics_tracking_description, and sw_sales_channel_detail_analytics_fields_enhanced_conversions have been added.
Rule Builder cart total condition labels adjusted
Rule Builder cart total condition labels now describe more clearly which cart value they evaluate. The internal condition names remain unchanged for backwards compatibility.
| Internal name | EN old -> new | DE old -> new | What it checks |
|---|---|---|---|
cartCartAmount | Grand total -> Cart total (incl. shipping) | Gesamtsumme -> Warenkorb-Gesamtsumme (inkl. Versand) | cart.price.totalPrice - final cart price incl. shipping/tax/discounts |
cartPositionPrice | Total -> Cart sum of items (excl. shipping) | Summe -> Summe der Positionen (ohne Versand) | cart.price.positionPrice - sum of all items, no shipping |
cartGoodsPrice | Subtotal of all items -> Subtotal of goods (excl. discounts/fees) | Zwischensumme aller Positionen -> Zwischensumme der Warenpositionen (ohne Rabatte/Zuschläge) | Sum of goods item prices, excl. shipping/promotions |
cartTotalPurchasePrice | Total of all purchase prices -> Sum of purchase prices | Summe aller Einkaufspreise -> Summe der Einkaufspreise | Sum of purchase/cost prices across all items |
cartLineItemTotalPrice | Item subtotal -> Item total (qty × price) | Positionszwischensumme -> Positionssumme (Menge × Preis) | One item's total, quantity multiplied by unit price |
cartLineItemGoodsTotal | Total quantity of all products -> Total product quantity (units) | Gesamtanzahl aller Produkte -> Gesamtmenge der Produkte (Stück) | Total unit count of goods in the cart |
cartGoodsCount | Total quantity of distinct products -> Number of distinct products | Gesamtanzahl unterschiedlicher Produkte -> Anzahl unterschiedlicher Produkte | Number of distinct products in the cart |
Rule Builder quantity condition labels disambiguated
| Internal name | EN old -> new | DE old -> new | What it checks |
|---|---|---|---|
cartLineItemWithQuantity | Item quantity -> Item with quantity | Positionsanzahl -> Position mit Menge | A specific selected product's quantity |
cartLineItemsInCartCount | Quantity of distinct items -> Number of distinct items | Anzahl unterschiedlicher Positionen (unchanged) | Number of distinct line items (all types) |
promotionsInCartCount | Quantity of discounts -> Number of discounts | Anzahl der Rabatte (unchanged) | Number of discount line items |
sw-data-grid column labels fall back to the default locale
Column headers and the column visibility settings in sw-data-grid now resolve their labels against the configured i18n fallback locale when the snippet is missing in the current locale, instead of rendering the raw snippet key. This matches the behavior users expect when a translation is only available in English.
Rule builder shows per-field errors on conditions
Invalid condition inputs are now highlighted individually with a list of the affected fields below the row. All reversed date ranges are reported in one save instead of one at a time.
Reworked timeframe options in sw-date-filter
The order date filter dropdown now offers a 15-entry list, in display order:
- Today
- Yesterday
- Current week
- Last 7 days
- Previous week
- Current month
- Last 30 days
- Previous month
- Current quarter
- Previous quarter
- Last 3 months
- Last 6 months
- Last 12 months
- Current year
- Previous year
"Current ..." entries span the start of the period through today (e.g., current quarter = first day of the quarter through today). "Previous ..." entries cover the full prior period (e.g., previous quarter = the three months before this one). "Last N days/months" remain rolling windows ending today, with calendar-month math (and last-day-of-month clamping) for the months variants so May 31 - 3 months lands on Feb 29 (leap) or Feb 28 (non-leap) rather than rolling forward to March 3.
The previous rolling lastDay (-1) and lastYear (-365) entries are no longer in the dropdown, but saved filter states keep working: the component now aliases -1 to yesterday and -365 to last12Months on both hydration and programmatic selection. The persisted from/to are preserved so existing filters continue to resolve the same data, while the dropdown label catches up to the new vocabulary. All boundaries continue to be normalized to the user's timezone.
Support test file splitting
Administration Jest tests can now be split into multiple files using *.spec/ directories. ESLint now warns for Administration test files with 500 lines or more and errors for test files with 1000 lines or more.
App action button icons are aligned in Administration context menus
App action buttons that use an app manifest icon now render the icon at the normal context-menu size and align it on the same row as the action label. Previously, the app logo could render oversized or stacked above the action text in Administration action menus, for example on order detail pages.
Product variants are easier to distinguish in sw-entity-multi-id-select
sw-entity-multi-id-select now displays product variant option details for product repositories in the selected labels and dropdown results. This helps extensions and plugin configuration UIs that let merchants select multiple products, because variants with inherited product names no longer appear as identical entries.
Outside clicks in dropdowns are identified correctly
Administration dropdowns now identify outside clicks correctly when the browser reports a click target outside the dropdown even though the pointer is still over the dropdown.
Resolving download errors by renaming media
When merchants rename a media file, its URL automatically updates so they can download it without issues.
Agentic Commerce Administration components deprecated
The following Administration component, methods, and computed properties are deprecated and will be removed in Shopware 6.8:
sw-agentic-commerce-tracking-config — entire component deprecated.
sw-sales-channel-modal-grid:
- computed
salesChannelRepository - method
isAgenticCommerceSalesChannelType() - method
showAgenticCommerceType()
sw-sales-channel-detail:
- provide
swSalesChannelDetailGetAgenticCommerceExportConfig - data
agenticCommerceExportConfig - computed
isAgenticCommerce - computed
defaultAgenticCommerceExportConfig - method
validateAgenticCommerceExportConfig() - method
loadAgenticCommerceExportConfig() - method
saveAgenticCommerceExportConfig()
sw-sales-channel-create-base:
- method
prefillAgenticCommerceDefaults()
sw-sales-channel-detail-base:
- inject
swSalesChannelDetailGetAgenticCommerceExportConfig - computed
isAgenticCommerce - computed
resolvedAgenticCommerceExportConfig - method
getAgenticCommerceExportElementBind() - method
getAgenticCommerceExportCardTitle() - method
getAgenticCommerceExportCardPositionIdentifier() - method
onAgenticCommerceExportFieldUpdate()
sw-sales-channel-detail-product-comparison:
- computed
isAgenticCommerce
This functionality will be available in the Agentic Commerce extension (SwagAgenticCommerce) instead.
App System
[Opt-in] Webhook delivery rework
Webhook delivery moves to a new dedicated webhook Messenger transport, rolled out behind the WEBHOOKS_REWORK feature flag. When the flag is disabled (which is the default), the webhook transport forwards to async and Messenger owns retries. When the flag is enabled, every webhook is persisted to a database-backed outbox before the first HTTP attempt, and Shopware controls when and how often each delivery is retried.
With the flag enabled:
- Failed deliveries are retried for up to four hours. Failures back off on a fixed
5s → 30s → 5min → 30min → 4hschedule, so a brief DNS outage or upstream restart does not exhaust retries before the endpoint recovers. - Synchronous deliveries are audited. Deliveries that bypass the queue — those triggered by the admin worker or by forced-sync app lifecycle calls — produce the same audit row as async deliveries, so failures on those paths are inspectable in the database and via the Admin API.
- In-flight deliveries survive worker crashes. If a worker dies while sending a webhook, the next worker picks up the in-flight delivery and retries it.
- Identity headers on every HTTP POST. Every request carries
X-Shopware-Event-Id,X-Shopware-Sequence, andX-Shopware-Attemptheaders plus asource.sequencefield in the body. Consumers can use them to deduplicate retries and reorder events independent of HTTP arrival order. The same headers ship for every webhook, regardless of how it is delivered.
Enabling the flag requires configuration changes — the worker consume command must list the new webhook transport, and shopware.admin_worker.transports may need updating if it was overridden. Rolling the flag back off also has its own steps. See UPGRADE-6.7.md for the full procedure.
Tracked in shopware/shopware#16560.
Tax provider priority is preserved across app updates
An app tax provider's priority is now only seeded from the manifest when the provider is first installed. App updates no longer touch the priority, so the merchant's manual ordering is retained.
Hosting & Configuration
Google Storage supports application default credentials
Google Storage filesystem configurations can now omit keyFile and keyFilePath. When neither option is configured, Shopware lets the Google Cloud PHP SDK resolve credentials through Application Default Credentials, such as GOOGLE_APPLICATION_CREDENTIALS, local ADC files, or attached service accounts in Google Cloud environments. See Google's PHP client authentication guide for the PHP library lookup behavior.
Critical Fixes
Admin worker no longer blocks same-session API requests on PHP session locks
Fixed a session-locking issue that could slow down concurrent Administration requests when the browser-based admin worker is used together with native PHP file session storage. In that setup, an admin queue worker request could initialize the current PHP session while consuming messages and keep the session file locked until the long-poll request returned. Concurrent Admin API requests from the same browser session, for example sync or save requests, no longer wait for that admin worker session lock.
Fixed bugs
- Prevented Shopware Administration from crashing after Composer installs Twig 3.28 by blocking the incompatible dependency version (#18034)
- Stopped product purchase prices from being exposed in customer-facing Store API order line item payloads (#17583)
- Prevented checkout orders from returning a 500 error when Elasticsearch/OpenSearch is temporarily unavailable after stock changes (#16974)
- Fixed storefront checkout so unavailable payment or shipping methods are replaced correctly when Checkout Gateway rules block the selected method (#16780)
- Fixed product exports so feeds are no longer empty or incomplete when variants are excluded from export output (#17083)
See all fixed bugs in this release: https://github.com/shopware/shopware/milestone/38?closed=1
Credits
Thanks to all diligent friends for helping us make Shopware better and better with each pull request!
See all contributors on this page: https://github.com/shopware/shopware/releases/tag/v6.7.12.0#Contributors
More resources
- Detailed diff on Github to the former version
- Changelog on GitHub for this version.
- Release News corporate blog post
- Installation overview
- Update from a previous installation
Get in touch
Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there 😉