DfStreamCategoryTree Documentation for Shopware 6
Install and use the recursive category filter in Shopware 6 dynamic product groups.
DfStreamCategoryTree adds a Category (including subcategories) field to the condition builder of Shopware 6 dynamic product groups. Filtering on a parent category then includes every product assigned to its subcategories, at any depth.
The problem this plugin solves
The native condition builder exposes a Categories field that queries the product.categoriesRo association. That association only holds the categories a product is explicitly assigned to in its Categories tab.
A properly organised catalogue assigns products to leaf categories. A sneaker model sits in Men / Footwear / Sneakers, not in Men. So a filter on Men returns only the few products assigned directly at that level, often none at all.
The native workaround is to tick every subcategory by hand, then reopen the stream configuration every time the tree changes. This plugin removes that maintenance.
How it works
Shopware already maintains a JSON field named categoryTree on every product, holding the IDs of every category along the path from the root down to the assigned category. The native CategoryIndexer recalculates it whenever a category moves or a product assignment changes.
An equalsAny filter on that field with a parent category ID therefore matches every product whose path runs through it. The field exists and works perfectly in the DAL, but the administration does not expose it in the condition builder selector: it is missing from the productStreamConditionService allow list.
The plugin adds one entry to that allow list and ships the matching translated labels. It introduces no service decorator, no product event listener, no table and no migration.
Requirements
- Self-hosted Shopware 6.7.x
- PHP 8.2 or higher
- Command line access or a deployment pipeline able to rebuild the administration
The plugin does not run on Shopware Cloud, since the SaaS version hosted by Shopware does not allow server plugin installation.
Installation
Via ZIP upload
- In the administration, open Extensions then My extensions
- Click Upload extension and select the DfStreamCategoryTree-1.0.0.zip archive
- Install and activate the plugin
- Rebuild the administration (see the next section)
Via folder deployment
Extract the archive into your instance custom plugins directory, then run:
bin/console plugin:refresh
bin/console plugin:install --activate DfStreamCategoryTree
bin/console cache:clear
Rebuilding the administration
The plugin changes administration behaviour. An admin bundle rebuild is required once after installation, otherwise the new field will not appear in the condition selector.
bin/console bundle:dump
./bin/build-administration.sh
bin/console cache:clear
On a production environment managed by a deployment pipeline, this step is usually already part of the standard process. Afterwards, clear your browser cache or open the administration in a private window to make sure you load the updated bundle.
Usage
Creating a recursive dynamic group
- Open Catalogues then Dynamic product groups
- Create a new group or open an existing one
- In the condition builder, expand the field selector
- Pick Category (including subcategories), listed just above the original Categories entry
- Select the Is equal to any of operator
- Choose one or more parent categories in the value field
- Save, then open the Preview tab to check the number of matched products
Available operators
- Is equal to any of: the product belongs to the subtree of at least one selected category
- Is not equal to any of: the product belongs to none of the selected subtrees, useful to exclude a whole department from a campaign
Combining with other conditions
The field behaves like any other stream condition. It combines freely with manufacturer, price, stock, properties and tags, and works inside the nested AND and OR groups of the builder.
A typical clearance setup: Category (including subcategories) is equal to any of Men, AND Stock is greater than 0, AND Price is greater than 50.
Where the group can be used
- Navigation category pages powered by a dynamic group
- Product blocks in Shopping Experiences
- Promotion rule conditions
- Automatic cross-selling on the product page
- Any integration consuming a product stream through the Admin API or the Store API
Using the Admin API
Because the field is native to the DAL, a condition posted directly through the API works even without the plugin. The plugin makes the filter visible and editable in the interface, which matters as soon as a marketing team manages groups without touching the API.
POST /api/product-stream
{
"name": "Whole Men department",
"filters": [
{
"type": "equalsAny",
"field": "product.categoryTree",
"value": "01920f7c8a3d71c2b4e5f6a7b8c9d0e1"
}
]
}
Without the plugin installed, a stream holding this filter still works at DAL level but its field cannot be displayed in the condition builder.
Troubleshooting
The field does not appear in the selector
In the vast majority of cases, the administration was not rebuilt after installation. Run the bundle:dump, build-administration and cache:clear sequence again, then reload the administration with a cleared browser cache. Also check that the plugin is active under Extensions then My extensions.
The group still returns the wrong products
Make sure you selected the new field and not the original Categories entry, since both coexist in the selector. Then open an expected product and check that it is assigned to a subcategory of the chosen parent, and that it is active and visible on the relevant sales channel.
A recently moved product does not show up
The categoryTree field is recalculated by the native CategoryIndexer. If the message queue is lagging or indexing has been paused, force a reindex:
bin/console dal:refresh:index --only=product.indexer,category.indexer
Resetting after a Shopware update
After a minor Shopware version bump, rebuild the administration so the plugin re-registers its allow list entry. Nothing else is needed, since the plugin stores no data.
Uninstalling
Deactivate then uninstall the plugin from Extensions or from the command line. The plugin creates no table and stores no configuration, so uninstalling is entirely neutral.
bin/console plugin:deactivate DfStreamCategoryTree
bin/console plugin:uninstall DfStreamCategoryTree
Dynamic groups already configured with the filter keep working: the condition is stored as a standard DAL filter and remains evaluated by the native engine. Only the field display in the condition builder disappears, which makes the filter non-editable from the interface until the plugin is reactivated. No data is lost.
Known limitations
- The plugin does not apply to storefront listing filters or faceted navigation, which rely on a separate mechanism
- It does not change the category indexing algorithm, it consumes the field Shopware already produces
- It does not run on Shopware Cloud