RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling
Description
Highlights
- Bidirectional cross-selling via dynamic product groups
- Add accessories directly to the cart from the product detail page
- Select product variants directly in the accessories section
- Accessories are grouped directly under the associated main product in the cart
- Dynamic product groups can supplement or replace regular cross-selling
Features
- Directly purchasable cross-sellings
- Bidirectional cross-selling via dynamic product groups
- Support for multiple dynamic product groups
- Automatic prevention of duplicate accessory products
- Product-specific cross-selling selection
- Flexible fallback and override logic
- Variant support in the accessories section
- Price and availability checks
- Exclusion of clearance products
- Native Shopware Quick View
- Automatic addition of the main product
- Prevention of duplicate main products in the cart
- Assignment of accessories to the main product
- Grouped display in the shopping cart
- German and English storefront support
About the Extension
Turn cross-selling into a direct sales process
With RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling, you can turn classic Shopware cross-sellings into directly purchasable accessory offers on the product detail page.
Instead of simply redirecting customers to additional product detail pages, matching accessories can be selected, configured, and added directly to the shopping cart. Product variants are also supported. For a more convenient product selection, the native Shopware Quick View can also be used.
A special highlight is automatic bidirectional cross-selling via dynamic product groups. For example, you can define a dynamic product group containing products A, B, and C. RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling automatically detects whether the currently viewed product belongs to the group and recommends the other group members:
- Product A shows B and C
- Product B shows A and C
- Product C shows A and B
No additional assignment for each individual product is required.
Alternatively, regular Shopware cross-sellings can still be used. For individual products, you can specifically define which cross-selling should be used for the accessory display.
Make accessories directly purchasable
Accessories are displayed directly on the product detail page as clearly structured cards. Customers can specify quantities, select the desired variant for variant products, and add accessories to the shopping cart without unnecessary intermediate steps.
If required, the associated main product can automatically be added to the shopping cart when an accessory is added for the first time. If the main product is already in the cart, it will not be added again.
Automatic bidirectional cross-selling
Dynamic product groups can be selected centrally in the plugin configuration for bidirectional cross-selling.
This makes it easy to connect related products with one another. Changes to the rules of a dynamic product group automatically affect the resulting accessory recommendations.
RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling automatically checks whether the currently viewed product is a member of one of the selected dynamic product groups. If a product belongs to several matching groups, the resulting accessory products can be combined.
The currently viewed product itself, as well as products from the same variant family, are excluded from the accessory recommendations.
Depending on the configuration, dynamic product groups can either be used as a fallback for existing cross-sellings or replace the global or default cross-selling.
Clear assignment in the shopping cart
RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling stores the relationship between the main product and its accessories directly on the respective shopping cart line item.
In the off-canvas cart and on the regular shopping cart page, accessory products are therefore grouped directly below the associated main product and additionally marked accordingly:
“Accessory for: Main product”
This makes it easy to identify which accessory belongs to which product, even when several main products and multiple accessories are in the shopping cart.
Variants without complex frontend scraping
Variant and product data are processed server-side via Shopware. The extension does not require recursive requests of complete product detail pages or client-side HTML scraping to determine prices or availability.
This makes RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling suitable for shops that use accessory products with more extensive variant structures.
The purchasability and availability of the respective variants are taken into account, so only suitable variants are offered for direct accessory purchases.
Quick View instead of unnecessary page changes
The product image and product name of an accessory can open the native Shopware Quick View.
Customers can quickly view the accessory without leaving the current product detail page. If required, they can then navigate from the Quick View to the complete product detail page.
Quick View can be disabled in the plugin configuration. In this case, the product image and product name link directly to the regular product detail page.
Flexible cross-selling priorities
RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling supports different methods for determining the appropriate accessories:
- Product-specific Shopware cross-selling selection
- Product-specific dynamic product group
- Centrally configured dynamic product groups
- Globally configured Shopware cross-selling
- First available active Shopware cross-selling
Which source is used depends on the respective configuration.
A cross-selling explicitly selected for an individual product always has the highest priority. The centrally configured dynamic product groups can either be used before the global or default cross-selling or only as a fallback.
This allows RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling to be used both for smaller shops with simple accessory relationships and for large product catalogs with automated cross-selling structures.
Turn cross-selling into a direct sales process
With RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling, you can turn classic Shopware cross-sellings into directly purchasable accessory offers on the product detail page.
Instead of simply redirecting customers to additional product detail pages, matching accessories can be selected, configured, and added directly to the shopping cart. Product variants are also supported. For a more convenient product selection, the native Shopware Quick View can also be used.
A special highlight is automatic bidirectional cross-selling via dynamic product groups. For example, you can define a dynamic product group containing products A, B, and C. RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling automatically detects whether the currently viewed product belongs to the group and recommends the other group members:
- Product A shows B and C
- Product B shows A and C
- Product C shows A and B
No additional assignment for each individual product is required.
Alternatively, regular Shopware cross-sellings can still be used. For individual products, you can specifically define which cross-selling should be used for the accessory display.
Make accessories directly purchasable
Accessories are displayed directly on the product detail page as clearly structured cards. Customers can specify quantities, select the desired variant for variant products, and add accessories to the shopping cart without unnecessary intermediate steps.
If required, the associated main product can automatically be added to the shopping cart when an accessory is added for the first time. If the main product is already in the cart, it will not be added again.
Automatic bidirectional cross-selling
Dynamic product groups can be selected centrally in the plugin configuration for bidirectional cross-selling.
This makes it easy to connect related products with one another. Changes to the rules of a dynamic product group automatically affect the resulting accessory recommendations.
RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling automatically checks whether the currently viewed product is a member of one of the selected dynamic product groups. If a product belongs to several matching groups, the resulting accessory products can be combined.
The currently viewed product itself, as well as products from the same variant family, are excluded from the accessory recommendations.
Depending on the configuration, dynamic product groups can either be used as a fallback for existing cross-sellings or replace the global or default cross-selling.
Clear assignment in the shopping cart
RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling stores the relationship between the main product and its accessories directly on the respective shopping cart line item.
In the off-canvas cart and on the regular shopping cart page, accessory products are therefore grouped directly below the associated main product and additionally marked accordingly:
“Accessory for: Main product”
This makes it easy to identify which accessory belongs to which product, even when several main products and multiple accessories are in the shopping cart.
Variants without complex frontend scraping
Variant and product data are processed server-side via Shopware. The extension does not require recursive requests of complete product detail pages or client-side HTML scraping to determine prices or availability.
This makes RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling suitable for shops that use accessory products with more extensive variant structures.
The purchasability and availability of the respective variants are taken into account, so only suitable variants are offered for direct accessory purchases.
Quick View instead of unnecessary page changes
The product image and product name of an accessory can open the native Shopware Quick View.
Customers can quickly view the accessory without leaving the current product detail page. If required, they can then navigate from the Quick View to the complete product detail page.
Quick View can be disabled in the plugin configuration. In this case, the product image and product name link directly to the regular product detail page.
Flexible cross-selling priorities
RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling supports different methods for determining the appropriate accessories:
- Product-specific Shopware cross-selling selection
- Product-specific dynamic product group
- Centrally configured dynamic product groups
- Globally configured Shopware cross-selling
- First available active Shopware cross-selling
Which source is used depends on the respective configuration.
A cross-selling explicitly selected for an individual product always has the highest priority. The centrally configured dynamic product groups can either be used before the global or default cross-selling or only as a fallback.
This allows RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling to be used both for smaller shops with simple accessory relationships and for large product catalogs with automated cross-selling structures.
Details
- Available: English, German
- Latest update: 10 September 2026
- Version: 2.0.21
- Category: Conversion Optimization
About the Extension Partner
RESPONSE GmbH
Partner Status
-
Shopware
Bronze Partner -
Shopware
Extension Partner
Details
-
Ø-Rating:
4.2
Average rating of 4.2 out of 5 stars
- Partner since: 2018
- Extensions: 1
Support
- Based in: Germany
- Speaks: German, English
- Response time: Quickly
Installation
Installation via “My Extensions”
- Log in to your Shopware Administration.
- Open “Extensions > My Extensions”.
- Search for “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling”.
- Install the extension.
- Then activate “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling” using the status switch.
After installation, the product custom fields required by the extension are created automatically.
Configuration
Configure plugin settings
- Open “Extensions > My Extensions”.
- Search for “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling”.
- Open the extension configuration.
- If you use multiple sales channels, make sure to configure the settings for the desired sales channel.
The following settings are available in the configuration:
Initially visible accessory products:
Define how many accessory products should initially be displayed when the product detail page is opened.
If additional accessory products are available, customers can display them as needed.
Default: 3
Heading:
Enter a custom heading for the accessories section.
If the field is left empty, “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling”
automatically uses the default heading “Order together – matching accessories”.
Global cross-selling name:
Here you can enter the name of a Shopware cross-selling that should be used as the global selection
for displaying accessories.
If no name is entered, the first active cross-selling of the respective product can be used if required.
Show manufacturer:
Decide whether the manufacturer of the accessory product should be displayed in the accessories section.
Default: Yes
Show product number:
Decide whether the product number of the accessory product should be displayed in the accessories section.
Default: Yes
Multiple selection / add together to cart:
Enable this function if customers should be able to select multiple accessory products and add them to the cart together.
For variant products, a specific variant must first be selected.
Default: Yes
Automatically add main product with the first accessory:
Enable this function if the associated main product should automatically be added to the shopping cart
when an accessory product is added and the main product is not yet in the cart.
The main product is not added multiple times.
Default: Yes
Open accessory products in Quick View:
Enable this function if the product image and product name of an accessory product should open the native Shopware Quick View.
If the function is disabled, the corresponding links lead directly to the accessory product detail page.
Default: Yes
Provide tracking events:
Enable this function if technical JavaScript events should be provided for analytics or tracking integrations.
Default: No
Configure bidirectional cross-selling
“RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling” can use Shopware dynamic product groups to assign accessories automatically in both directions.
For example, if products A, B, and C are part of the same selected dynamic product group, the following accessory relationships are created automatically:
- Product A displays Product B and Product C as accessories.
- Product B displays Product A and Product C as accessories.
- Product C displays Product A and Product B as accessories.
No additional manual assignment between each individual product is required.
Dynamic product groups for bidirectional accessories:
Select one or more Shopware dynamic product groups
that should be used to automatically determine accessory products.
If the currently viewed product belongs to multiple selected groups,
the resulting accessory products can be combined.
Enable automatic bidirectional product groups:
Enable this setting so that “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling”
automatically checks whether the currently viewed product is a member of one of the selected dynamic product groups.
Default: No
Dynamic product groups replace global/default cross-selling:
Decide whether matching dynamic product groups should be preferred over the global or
default Shopware cross-selling.
If this setting is disabled, automatic bidirectional cross-selling is used as a fallback when no preferred matching cross-selling is found.
If this setting is enabled, matching dynamic product groups are considered before the global
or default cross-selling.
Default: No
Use dynamic product group name as accessories heading:
Enable this function if the name of exactly one matching dynamic product group should be used
as the heading of the accessories section.
If several dynamic product groups match at the same time, the configured
or default accessories heading is used instead.
Default: No
Maximum number of automatic accessory products:
Define how many accessory families should be loaded at most from the matching dynamic product groups.
Default: 8
Create dynamic product groups
- Open “Catalogues > Dynamic product groups” in the Shopware Administration.
- Create a new dynamic product group.
- Use the Shopware filter rules to define which products should belong to this group.
- Save the dynamic product group.
- Then open the configuration of “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling”.
- Select the desired group under “Dynamic product groups for bidirectional accessories”.
- Enable “Enable automatic bidirectional product groups”.
Configure product-specific cross-selling
In addition to the central configuration, a specific Shopware cross-selling can be selected for individual products for use in the accessories section.
- Open “Catalogues > Products”.
- Open the desired product.
- Create the desired Shopware cross-selling in the “Cross-selling” section and activate it.
- Then open the custom fields section within the product.
- Find the custom field set “RESPONSE Accessory Settings”.
- Under “Cross-selling for accessory display”, select the desired cross-selling.
- Save the product.
A cross-selling selected directly on the product always has the highest priority.
Product-specific dynamic product group
For special cases, the custom field set “RESPONSE Accessory Settings” also contains the field “Optional: Dynamic product group only for this product”.
This allows you to assign a specific dynamic product group to an individual product for the accessory display. This setting is not required for normal bidirectional operation, as dynamic product groups can be selected centrally in the plugin configuration.
Priority of accessory determination
Depending on the selected configuration, “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling” determines the displayed accessory products from different sources.
A Shopware cross-selling selected directly on the product always has the highest priority.
After that, depending on the setting “Dynamic product groups replace global/default cross-selling”, either the automatically determined dynamic product groups or the global or default Shopware cross-selling are considered.
Automatic dynamic product groups can therefore be used either as the preferred source or as a fallback.
Notes on variant products
Variant products are automatically detected by “RESPONSE Add Accessories Directly to Cart | Bidirectional Cross-Selling” and can be selected directly in the accessories section.
Purchasability and availability of the variants are taken into account. For very extensive variant structures, customers may be redirected to the regular product detail page for selection.
Notes on the shopping cart
Accessory products are assigned to the respective main product in the shopping cart. In the off-canvas cart and on the regular shopping cart page, accessories are displayed directly below the associated main product.
In addition, the assignment can be marked with the note “Accessory for: …”. This makes it clear which accessory belongs to which product, even when several main products are in the cart.
Check the configuration
- Open a product detail page with configured cross-selling or a matching dynamic product group.
- Check whether the accessories section is displayed.
- For variant products, test the variant selection.
- Add an accessory product to the shopping cart.
- Check whether the main product is added automatically when the corresponding function is enabled.
- Check the assignment and grouping of accessory products in the off-canvas cart and on the shopping cart page.
If changes are not immediately visible in the storefront, clear the Shopware cache and, if necessary, recompile the active theme or storefront.
2.0.21 6.7.12.0 - 6.7.14.0
Shopware 6.7 plugin for purchasable accessory cards on the product detail page.
Architecture 2.0
Version 2.0 replaces the previous app architecture with client-side HTML scraping by server-side Shopware data:
- Cross-selling selection and the fallback via a dynamic product group are resolved server-side through Shopware Sales Channel routes when the product detail page is loaded.
- There is no longer a browser request to /store-api/product for the fallback.
- There is no recursive variant graph walk, no DOMParser, and no full product detail page requests for determining prices or variants.
- The initial “from” price is validated server-side: the plugin verifies Shopware’s indexed cheapest variant in a bundled Sales Channel query. Only if this result is no longer purchasable is a small structured replacement search performed for that specific variant family.
- Only when “Select variant” is clicked is exactly one custom, HTTP-cacheable JSON endpoint called. It loads the purchasable variants in a structured way through the Sales Channel product route.
- A maximum of 500 purchasable variants per variant family are transferred to the browser. For larger matrices, the user is deliberately referred to the normal product detail page instead of burdening the origin with a huge variant run.
- Repeatedly opening the same variant family within a single page view uses an in-memory cache in the browser.
Selection priority
- Cross-selling explicitly selected on the product (response_csa_cross_selling_selection)
- if the replacement option is enabled: automatically matching, centrally configured dynamic product group(s)
- globally configured cross-selling name or the first active cross-selling
- without the replacement option: automatically matching, centrally configured dynamic product group(s) as a fallback
The dynamic product groups are selected centrally in the plugin configuration. On the product detail page, RESPONSE automatically checks whether the currently opened product family is a member of one or more of these groups. Maintaining csa_compatibility_group on every individual product is no longer required for this. If several selected groups match, their results are merged and deduplicated by product family.
csa_compatibility_group remains available as an optional product-specific override for special cases and for backward compatibility. If a group is selected there, it is used for that specific product before the central automatic detection.
Custom fields
The plugin creates or adopts the response_csa_product_settings set with the following product custom fields:
- response_csa_cross_selling_selection
- csa_compatibility_group – optional product-specific Shopware dynamic product group (product_stream) for special cases
- response_csa_legacy_compatibility_group – internal legacy value from a previous free-text compatibility group (see below); without its own visible field in Administration (this has been the case again since 2.0.20, after it was temporarily available as a visible text field in 2.0.18/2.0.19)
For normal bidirectional operation, no product-level maintenance is required anymore. Select the desired dynamic product groups once in the central plugin configuration. If a selected group contains A, B, and C, RESPONSE automatically detects membership: A shows B+C, B shows A+C, and C shows A+B. The currently opened product and its entire variant family are excluded from the results.
When migrating from the previous app, the plugin adopts the existing set and removes the app assignment (appId) so that existing product values are preserved and the set is managed by the plugin after migration. Older free-text values from csa_compatibility_group are backed up internally under response_csa_legacy_compatibility_group during the update and removed from the visible entity selection field so that Shopware’s product group selector does not get stuck on an invalid legacy ID. If this legacy field is not empty, its value continues to take precedence over the centrally configured automatic group detection – without this being visible in Administration on that product. If this affects a specific product (accessories do not come from the expected dynamic group despite correct central configuration), the field can temporarily be re-enabled as a visible text field for one release if necessary (see 2.0.18–2.0.20).
Migration from App 1.4.x
Recommended sequence:
- Deactivate the existing app, but do not uninstall it yet.
- Install and activate the ResponseCrossSellingAccessoriesPlugin plugin.
- Compile the Storefront/theme and verify functionality.
- Only then uninstall the old app.
During installation/update, the plugin copies the supported settings from ResponseCrossSellingAccessories.config.* to ResponseCrossSellingAccessoriesPlugin.config.*, provided that no value is present at the destination yet. The old app settings storeApiAccessKey and previewConcurrency are deliberately not migrated because they are no longer required in the plugin architecture.
Compatibility
- PHP >= 8.2
- Shopware >= 6.7.12 and < 6.8
The minimum version was raised from 6.7.2 to 6.7.12: as of 6.7.12, this is additionally required because the cache-relevant attribute in config.xml (see “Cache invalidation on configuration changes”) is only supported by Shopware’s own XML schema from this version onward; on older 6.7.x versions, activation would otherwise fail during schema validation. Originally, 6.7.2 was required because the plugin uses Shopware’s CacheTagCollector::addTag() for correct HTTP cache invalidation.
Installation
Upload the ZIP in Shopware under Extensions → My extensions, install it, and activate it. Then recompile the theme/Storefront if Shopware does not do so automatically.
2.0.21
- Fixes all shopware.noEntityRepositoryInLoop violations reported by Shopware’s static code analysis (potential N:1 queries): LegacyConfigMigrator::migrate() now reads source and target values through one bundled query each across all supported configuration keys and writes all changes through a single collected upsert, instead of making repository calls per key inside a loop. VariantPriceResolver::resolve() resolves the replacement price for all still-open variant families through a single bundled query sorted by price, instead of performing a separate repository call per family.
- Confirmed compatible with Shopware 6.7.14: there are no breaking changes for this code, among other reasons because the automatic exclusion logic newly introduced there for native dynamic-product-group cross-selling only affects Shopware’s own mechanism, not this plugin’s product-specific fallback logic.
2.0.20
- Removes the visible text field “Internal legacy value (previous free-text compatibility group)” introduced in 2.0.18 from the custom fields section again, as explicitly requested after the affected legacy value had already been cleared. This happens automatically during the plugin update (the field definition is removed), regardless of whether Shopware’s declarative custom-fields synchronization (from 6.7.13 onward) is applied.
- The underlying mechanism itself remains unchanged: any remaining legacy value on a product still takes precedence over the centrally configured automatic group detection, but is now invisible again without its own Administration field. If a similar case occurs again, the field can temporarily be re-enabled if necessary.
2.0.19
- Removes the data-csa-debug-* attributes introduced in 2.0.17 for diagnostic purposes only, as well as the associated internal debug fields, after the actual cause (see 2.0.18) was confirmed to be fixed. Diagnostic only, no functional change.
2.0.18
- Fixes the actual cause of why “Use dynamic product group name as accessories headline” (and central automatic group detection in general) did not work for individual products: an old free-text value (response_csa_legacy_compatibility_group) originating from the app migration had silently overridden the centrally configured dynamic product groups for that product without any visibility in Administration.
- This internal field is now additionally registered as a normal, visible text field named “Internal legacy value (previous free-text compatibility group)” in the product’s custom fields section. If it contains a value, store operators can clear and save it there directly to return to automatic central detection – without any database access.
- Adds the corresponding field to the declarative Resources/config/custom-fields.xml as well for Shopware lifecycle synchronization from 6.7.13 onward.
2.0.17 (temporary diagnostics)
- Adds five data-* attributes to the accessories container exclusively for diagnostic purposes (data-csa-debug-source, data-csa-debug-stream-ids, data-csa-debug-headline-raw, data-csa-debug-use-stream-headline, data-csa-debug-stream-headline-name), visible only in the HTML source or developer tools. They show which source (cross-selling vs. dynamic product group) was actually used and why the group-name headline may not be taking effect.
- Diagnostic only, no functional change. Will be removed again after troubleshooting of the “Use dynamic product group name as headline” issue has been completed.
2.0.16
- Fixes an issue where changes to the plugin configuration (including “Use dynamic product group name as accessories headline”, as well as headline, visibility, and display options) did not reach product pages that were already HTTP-cached. Since Shopware 6.7.12, system configuration changes invalidate the HTTP cache only for fields explicitly marked with cache-relevant="true" in config.xml. All accessory display options of this plugin are now marked accordingly (except autoAddMainProduct, which is evaluated only when adding to the cart and does not affect cached output).
- For this reason, the minimum version is raised to Shopware 6.7.12 (see “Compatibility”) – on older 6.7.x versions, cache-relevant would not have been a valid schema attribute in config.xml.
- Replaces the deprecated EntitySearchResult::first() call when resolving the name of a dynamic product group with getEntities()->first().
- If the new headline still does not appear after the update, clear the Shopware cache once – future changes to the settings mentioned above will then be reflected automatically.
2.0.15
- The Shopware cross-selling used for the accessories display in the buy widget (selected specifically for the product or global/default) is no longer additionally displayed in the native “Cross Selling” tab on the product detail page. If several active cross-sellings exist on the product, the others remain visible there unchanged.
- If the accessories displayed above instead come from a dynamic product group (automatic fallback), the “Cross Selling” tab remains completely untouched because this fallback has nothing to do with the cross-sellings assigned to the product.
- Technically, the cross-selling resolved on the product detail page as a CMS element (cross-selling) since Shopware 6.7 is filtered directly after the page is loaded; no Twig template adjustment of the Cross Selling tab is required.
2.0.14
- Each accessory card receives its own quantity selector (−/+ and direct input), limited by the minimum/maximum order quantity and purchase quantity intervals of the respective item or selected variant.
- The selected quantity is correctly applied as the line-item quantity both when using the individual “Add to cart” action and when using multi-selection (combined cart).
- When the main product is added automatically, the quantity actually selected on the product detail page is now used instead of always applying the main product’s minimum order quantity. If the customer changes the main quantity, it is continuously synchronized into the accessory forms.
- For variant accessories, a previously entered quantity is retained when switching variants as long as it matches the variant’s minimum/maximum order quantity and purchase interval; otherwise, it is adjusted automatically.
2.0.2
- Fixes the initial installation: lifecycle code no longer accesses plugin-owned services before Shopware has rebuilt the container with the activated plugin.
- Custom fields are managed directly through the available Shopware repositories during installation/update; from Shopware 6.7.13 onward, the declarative Resources/config/custom-fields.xml is also included so that Shopware’s lifecycle synchronization adopts the same fields and does not remove them during updates.
- The app configuration migration also uses the core repository and, during initial installation, only overwrites the plugin default values previously created by Shopware.
2.0.3
- Fixes the Shopware DAL error when directly loading the product parent association during cache invalidation.
- Parent products are now loaded in a separate, bundled repository call via parentId.
- Variant IDs are determined separately and then loaded together through the Sales Channel; no HTML scraping and no individual PDP requests.
- Variants and fallback products use VISIBILITY_LINK, in line with Shopware’s product-detail/cross-selling logic.
2.0.4
- Completely removes the cart icon from the accessory buttons.
- Removes the now-unneeded .csa__cart-icon/icon styles.
2.0.5
- Variant availability is now determined using Shopware’s native AvailableCombinationLoader, which is also used by the core configurator.
- Removes the additional ProductAvailableFilter from the variant endpoint so that inherited variant visibility is not filtered twice or inconsistently.
- Variants continue to be loaded in a single bundled Sales Channel operation; there is still no PDP scraping and no variant HTTP walk.
- For incompatible third-party stock loaders, the endpoint falls back in a controlled manner to the Sales Channel product flags instead of failing with HTTP 500.
- Empty variant responses are no longer cached in the browser and output a technical reason code in the developer console.
- The variant endpoint uses a new /response-accessories/v2/... path so that any existing HTTP cache responses from older plugin versions are safely bypassed.
- Shopware’s stock-aware available flag is used to determine purchasability; availableStock is no longer additionally applied as a contradictory legacy filter.
2.0.8
- Corrects crossSellingAccessories.freeShipping to exactly “versandkostenfrei” and “free shipping” respectively, without a leading comma.
- Structurally separates tax and shipping notices in Twig using a non-breaking space so that the snippets themselves do not need punctuation or spaces as layout hacks.
- Consistently changes German user notices and custom-field help texts to the formal “Sie” form of address.
2.0.7
- Fully registers the Storefront variant controller as a Symfony/Shopware controller service.
- Explicitly sets the service container required for StorefrontController via setContainer, in addition to the controller.service_arguments tag.
- This fixes HTTP 500 on the variant endpoint with “has no container set”.
Cart association (2.0.7)
- Accessory line items in the Shopware cart are associated via line-item payload with the product from whose detail page they were added.
- For such items, “Accessory for: …” is displayed in the cart and off-canvas cart.
- Optionally (enabled by default), the current main product is automatically added to the cart when the first accessory is added, provided it is not already present there as a product line item. Further accessory clicks do not increase the quantity of the main product.
2.0.9
- Groups accessory line items in the off-canvas cart and on the cart page directly below the associated main product.
- The order is generated from the already stored line-item association (responseCsaMainProductId); no additional product or database queries are required.
- Accessory line items are also slightly indented and displayed with a left divider so that the association is immediately recognizable visually.
- Orphaned accessory line items remain visible in their original position if the main product is not present in the cart.
2.0.10
- Changes csa_compatibility_group to a selection of Shopware dynamic product groups (product_stream).
- The fallback evaluates the filter definition of the selected dynamic product group server-side using Shopware’s ProductStreamBuilder.
- The currently opened product and its variant family are always excluded from the accessory list. As a result, using the same group selection for A, B, and C automatically produces A → B+C, B → A+C, and C → A+B.
- Existing free-text values remain functional as a legacy fallback and do not need to be migrated immediately.
- Changes to dynamic product groups or their filters invalidate the RESPONSE fallback cache.
2.0.12
- Closeout items (isCloseout) are consistently excluded from RESPONSE accessories and variant lists, regardless of remaining stock.
- Additional server-side safeguards prevent outdated or manipulated RESPONSE cart requests from adding a closeout item.
- By default, the product image and product name open Shopware’s native Quick View (widgets.quickview.minimal).
- In the RESPONSE Quick View, a clear “Go to product” button leads to the product detail page.
- Quick View can be disabled in the plugin configuration and is enabled by default.
2.0.11
- Fixes the endlessly loading dynamic product group selection after updating from older versions: old free-text values are backed up internally and removed from csa_compatibility_group before the field is converted to a real product_stream entity select.
- For existing installations, csa_compatibility_group is now also explicitly migrated to Shopware’s underlying custom-field type select.
- Adds a new optional setting, “Use dynamic product group name as accessories headline”. If enabled and the accessories come from the product-stream fallback, the translated name of the selected dynamic product group is used as the headline.
- Normal cross-selling continues to use the configured or localized default headline.
2.0.13
- Introduces a central multi-selection for Shopware dynamic product groups in the plugin configuration.
- True bidirectional behavior without maintenance on individual products: RESPONSE automatically detects whether the currently opened product family belongs to a selected group.
- If a product belongs to several selected groups, their accessory items are merged and deduplicated by product family.
- csa_compatibility_group remains only as an optional product-specific override and for backward compatibility.
- A Shopware cross-selling explicitly selected on the product always retains the highest priority; the existing replacement option controls whether automatic groups are used before or after global/default cross-selling.
- The name of the dynamic product group is used as the headline only if exactly one group matches. If several groups match, the configured/default headline remains in place.
- Stream mapping changes invalidate the automatic RESPONSE fallback cache so that newly added or removed group members are reflected correctly even when HTTP caching is enabled.
2.0.13 6.7.2.0 - 6.7.13.1
Shopware 6.7 plugin for purchasable accessory cards on the product detail page.
Architecture 2.0
Version 2.0 replaces the previous app architecture with client-side HTML scraping with server-side Shopware data processing:
- Cross-selling selection and the fallback via a dynamic product group are resolved server-side when loading the product detail page using Shopware sales channel routes.
- There is no longer a browser request to /store-api/product for the fallback.
- There is no recursive variant graph walk, no DOMParser, and no full product detail page requests for determining prices or variants.
- The initial “from” price is validated server-side: The plugin validates Shopware's indexed cheapest variant in a bundled sales channel query. Only if this result is no longer purchasable is a small structured replacement search performed for exactly this variant family.
- Only when clicking “Select variant” is exactly one dedicated, HTTP-cacheable JSON endpoint called. It loads purchasable variants in a structured way via the sales channel product route.
- A maximum of 500 purchasable variants per variant family are transferred to the browser. For larger variant matrices, the customer is deliberately redirected to the regular product detail page instead of putting excessive load on the origin server.
- Repeatedly opening the same variant family within one page view uses an in-memory cache in the browser.
Selection Priority
- Cross-selling explicitly selected on the product (response_csa_cross_selling_selection)
- If the replacement option is enabled: automatically matching, centrally configured dynamic product group(s)
- Globally configured cross-selling name or the first active cross-selling
- If the replacement option is disabled: automatically matching, centrally configured dynamic product group(s) as fallback
Dynamic product groups are selected centrally in the plugin configuration. RESPONSE automatically checks on the product detail page whether the currently opened product family is a member of one or more of these groups. Maintaining csa_compatibility_group on every individual product is no longer required. If several selected groups match, their results are merged and deduplicated by product family.
csa_compatibility_group remains available as an optional product-specific override for special cases and for backward compatibility. If a group is selected there, it is used for the specific product before the central automatic detection is applied.
Custom Fields
The plugin creates or adopts the custom field set response_csa_product_settings with the following product custom fields:
- response_csa_cross_selling_selection
- csa_compatibility_group – optional product-specific Shopware dynamic product group (product_stream) for special cases
For normal bidirectional operation, no individual product maintenance is required. Select the desired dynamic product groups once in the central plugin configuration. If a selected group contains A, B, and C, RESPONSE automatically detects membership: A displays B+C, B displays A+C, and C displays A+B. The currently opened product and its entire variant family are excluded from the results.
When migrating from the previous app, the plugin adopts the existing set and removes the app assignment (appId) so that existing product values are retained and the set can be managed by the plugin after migration. Older free-text values from csa_compatibility_group are backed up internally under response_csa_legacy_compatibility_group during the update and removed from the visible entity selection field. This allows Shopware's product group selector to load without an invalid legacy ID while the old free-text fallback logic remains functional in the background.
Migration from App 1.4.x
Recommended procedure:
- Deactivate the existing app, but do not uninstall it yet.
- Install and activate the plugin ResponseCrossSellingAccessoriesPlugin.
- Compile the storefront/theme and verify functionality.
- Only then uninstall the old app.
During installation/update, the plugin copies the supported settings from ResponseCrossSellingAccessories.config.* to ResponseCrossSellingAccessoriesPlugin.config.*, provided no value already exists at the destination. The old app settings storeApiAccessKey and previewConcurrency are intentionally not migrated because they are no longer required by the plugin architecture.
Compatibility
- PHP >= 8.2
- Shopware >= 6.7.2 and < 6.8
Shopware 6.7.2 is the minimum version because the plugin uses Shopware's CacheTagCollector::addTag() for correct HTTP cache invalidation.
Installation
Upload the ZIP file in Shopware under Extensions → My Extensions, install it, and activate it. Then recompile the theme/storefront if Shopware does not do so automatically.
2.0.2
- Fixes the initial installation: lifecycle code no longer accesses plugin-specific services before Shopware has rebuilt the container with the activated plugin.
- Custom fields are managed directly during installation/update through the available Shopware repositories. From Shopware 6.7.13 onward, the declarative Resources/config/custom-fields.xml is also included so that Shopware's lifecycle synchronization adopts the same fields and does not remove them during updates.
- The app configuration migration also uses the core repository and only overwrites plugin default values previously created by Shopware during the initial installation.
2.0.3
- Fixes the Shopware DAL error when directly loading the product parent association during cache invalidation.
- Parent products are now loaded in a separate, bundled repository query using parentId.
- Variant IDs are determined separately and then loaded collectively via the sales channel; no HTML scraping and no individual PDP requests are used.
- Variants and fallback products use VISIBILITY_LINK, matching Shopware's product detail and cross-selling logic.
2.0.4
- Completely removes the shopping cart icon from the accessory buttons.
- Removes the no longer required .csa__cart-icon and related icon styles.
2.0.5
- Variant availability is now determined using Shopware's native AvailableCombinationLoader, which is also used by the core configurator.
- Removes the additional ProductAvailableFilter from the variant endpoint so that inherited variant visibility is not filtered twice or inconsistently.
- Variants continue to be loaded in a single bundled sales channel operation; there is still no PDP scraping and no variant HTTP walk.
- With incompatible third-party stock loaders, the endpoint now falls back safely to the sales channel product flags instead of failing with HTTP 500.
- Empty variant responses are no longer cached in the browser and output a technical reason code in the developer console.
- The variant endpoint now uses the new /response-accessories/v2/... path so that any HTTP cache responses from older plugin versions are safely bypassed.
- Shopware's stock-aware available flag is used to determine purchasability; availableStock is no longer additionally used as a contradictory legacy filter.
2.0.8
- Corrects crossSellingAccessories.freeShipping to exactly “versandkostenfrei” or “free shipping” without a leading comma.
- Separates tax and shipping information structurally in Twig using protected spacing, so that text snippets themselves no longer require punctuation or spaces as layout workarounds.
- Consistently changes German user messages and custom field help texts to the formal form of address.
2.0.7
- Fully registers the storefront variant controller as a Symfony/Shopware controller service.
- Explicitly sets the service container required by StorefrontController via setContainer, in addition to the controller.service_arguments tag.
- Fixes HTTP 500 errors on the variant endpoint with has no container set.
Shopping Cart Assignment (2.0.7)
- Accessory line items in the Shopware shopping cart are assigned via line item payload to the product detail page from which they were added.
- In the cart and off-canvas cart, these positions display “Zubehör zu: …” or “Accessory for: …”.
- Optionally, and enabled by default, the current main product is automatically added to the cart when the first accessory is added, provided it is not already present as a product line item. Additional accessory clicks do not increase the quantity of the main product.
2.0.9
- Groups accessory line items directly below the associated main product in the off-canvas cart and on the shopping cart page.
- The order is generated from the already stored line item assignment (responseCsaMainProductId); no additional product or database queries are required.
- Accessory line items are also slightly indented and displayed with a left divider so that the relationship is immediately visible.
- Orphaned accessory line items remain visible in their original position if the main product is no longer present in the cart.
2.0.10
- Changes csa_compatibility_group to a selection of Shopware dynamic product groups (product_stream).
- The fallback evaluates the filter definition of the selected dynamic product group server-side using Shopware's ProductStreamBuilder.
- The currently opened product and its variant family are always excluded from the accessories list. As a result, using the same group selection for A, B, and C automatically creates A → B+C, B → A+C, and C → A+B.
- Existing free-text values remain functional as a legacy fallback and do not need to be migrated immediately.
- Changes to dynamic product groups or their filters invalidate the RESPONSE fallback cache.
2.0.12
- Clearance products (isCloseout) are consistently excluded from RESPONSE accessories and variant lists, regardless of remaining stock.
- Additional server-side protection prevents outdated or manipulated RESPONSE cart requests from adding a clearance product.
- Product image and product name open Shopware's native Quick View by default (widgets.quickview.minimal).
- In the RESPONSE Quick View, a clearly labeled “Go to product” button leads to the product detail page.
- Quick View can be disabled in the plugin configuration and is enabled by default.
2.0.11
- Fixes the endlessly loading dynamic product group selector after updating from older versions: old free-text values are backed up internally and removed from csa_compatibility_group before the field is converted to a proper product_stream entity select.
- For existing installations, csa_compatibility_group is now also explicitly migrated to Shopware's underlying custom field type select.
- Adds the optional setting “Use dynamic product group name as accessories heading”. If enabled and the accessories originate from the product stream fallback, the translated name of the selected dynamic product group is used as the heading.
- Regular cross-selling continues to use the configured or localized default heading.
2.0.13
- Adds central multiple selection for Shopware dynamic product groups in the plugin configuration.
- Provides true bidirectional behavior without maintaining individual products: RESPONSE automatically detects whether the currently opened product family is a member of a selected group.
- If a product belongs to several selected groups, their accessory products are merged and deduplicated by product family.
- csa_compatibility_group remains only as an optional product-specific override and for backward compatibility.
- A Shopware cross-selling explicitly selected on the product always retains the highest priority. The existing replacement option determines whether automatic groups are used before or after the global/default cross-selling.
- The dynamic product group name is only used as the heading if exactly one group matches. If several groups match, the configured/default heading is retained.
- Stream mapping changes invalidate the automatic RESPONSE fallback cache, ensuring that newly added or removed group members are displayed correctly even when HTTP caching is enabled.