With the sales channel product comparison you can export products to existing price portals. Furthermore you can create complete connections to new marketplaces. By using an export template that works with Twig variables, you can quickly make adjustments and create new exports.
For most portals, a link to the export file can be provided. Depending on the caching method, the file is regenerated each time it is called up and the portal always receives the most current data status. Alternatively, the file is renewed at regular intervals and the portal can fetch the file much faster.

In the general settings you first enter the name for your product comparison. If you would like to use the product comparison for a large price portal, you can also select one of the available templates here. The template will then be configured correctly for the portal in question.

Here you specify the sales channel (1) and storefront domain (2) to which your product comparison refers. You also specify which currency (3), language (4) and customer group (5) should be used for this product comparison.

In the product export section you specify how the output file of the product export should look like. First you specify a Filename (1).
As encoding (2) you can select UTF-8 or ISO-8859-1. Here you should inform yourself at the corresponding price portal, what is needed here.
As file format (3) you can choose a CSV file or a XML file. Also here you should inform yourself at the price portal, what is desired here.
You also specify whether or not you want to include the product variants (4) in the export and enter a generation interval (5). Set the interval (5) for the generation using the scheduler. The product comparison file is just regenerated automatically if the interval has expired and the option Generate via scheduler (6) is activated. You execute the scheduler by executing the command bin/console scheduled-task:run in your shop main directory.
You can use a dynamic product group (7) to define which items from your shop should be included in the product export. You can find out exactly how to create them here.

In the API Access section you can generate an API Access ID for this product comparison. For more information on how to use your own API accesses, please refer to our developer documentation.
In addition, the export URL for this specific product export is displayed here. This URL can be entered in the price portal.
If an error is displayed when calling up the export URL through the browser, check your dynamic product groups.
Add the conditions of the feed in the product group under "Catalogs > Dynamic product groups", e.g. "Sales price > 0" and " e.g. Price > 0".

Here you can temporarily deactivate the product comparison. The call of the product comparison URL and the API will then be temporarily inaccessible. You can also activate the maintenance mode here. The call is restricted and only available for selected IP addresses that are white listed.

If you delete the product comparison using this button, it will be irrevocably removed. You should only do this if the sales channel is no longer needed.
The template determines the structure of the product export file. The template is divided into a header line, a product line and a footer line.
If you use a template in the General tab, usually no adjustments are necessary here. The correct document templates for the respective comparison portals are already included in the templates.
The Test template button checks whether there are any syntax errors in the template. With Generate preview you can directly view the content of the created export file.
The header row differs depending on the selected format.
For a CSV file, the column descriptions are defined here, for example: id, manufacturer, model_no, name, category, price, etc.
In the case of an XML file, the entire file header is also located here, as well as the start tag, title, description, etc.

Here you define the template for the articles that are to be exported. The template is applied to each article using a loop. For CSV/TXT exports this results in one line per article. With an XML export, e.g. Google, each article is enclosed by a start and end tag. So it is possible to customize the exports, depending on structure and requirements. Note the more calculations are performed in the feed, the slower the generation will be!
The footer is only required for XML exports. This field contains the end tags that are opened in the header.

The product comparison is written in the PHP template engine TWIG. The standard already provides you with the most important information about your products. With the TWIG syntax you have the possibility to customise the template completely. You can find detailed documentation on which expressions and commands you can use here.
We have listed the most important commands that you can use in the product comparison here.
if- query:
With the if-query you can check whether a statement is true. This allows you to output the desired content only under certain conditions.
The start tag for an if-query contains if and a condition in a curly bracket and percent sign.
An if-query that checks whether a product is active would look like this:
{% if product.active %}The condition is followed by the section that is to be output only if the condition is fulfilled, followed by a concluding endif tag, which is also enclosed in curly brackets and percent signs.
{% endif %}In the following example, the product number is only output if the item is available.
{% if product.active %}
"{{ product.productNumber }}",{#- -#}
{% endif %}
elseif and else query:
The elseif query corresponds to another if query that is executed if the condition of the first if query is not fulfilled. The content behind an else tag is executed if the conditions of all previous if and elseif queries have not been fulfilled.
In the following example, the content 1 is output if the available stock is greater than 20. If it is not, but still greater than 10, content 2 is output. If the available stock is less than 10 and therefore both conditions are not fulfilled, content 3 is output.
{% if product.availableStock >20 %}
content
{% elseif product.availableStock > 10 %}
content 2
{% else %}
content 3
{% endif %}set
With the set command, you can assign variables that you can then use. For example, with the following command you assign the price of a product to the variable price.
{% set price = product.calculatedPrice %}You can then continue to work with the short variable instead of using branched resources.
"{{ price.unitPrice }}",{#- -#}With the help of variables you can add information about the products and the product export to the template. The necessary variables for the respective export are already created in the templates.
For your own exports you can also add your own information with variables.
Each variable starts with product or productExport and can be extended with a dot, for example product.productNumber for the product number.
The variables can also be multi-level. For example, the variable for the product name is product.translated.name.
If you write a dot after a level, all available sublevels are displayed.

List of available Variables
| Variable | Beschreibung | Verfügbar ab |
|---|---|---|
product.productNumber | Product number. Note the capitalization. | 6.4.0.0 |
product.id | Product ID. | 6.4.0.0 |
product.ean | GTIN / EAN. | 6.4.0.0 |
product.manufacturerNumber | Manufacturer part number (MPN). | 6.4.0.0 |
product.parentId | ID of the parent product; can be used as the item group ID for variants. | 6.4.0.0 |
product.childCount | Number of variants of a parent product. | 6.4.0.0 |
product.type | Indicates whether the product is physical or digital. | 6.7.7.0 |
product.downloads | Download files of a digital product. Use product.downloads|length > 0 to check whether downloads are available. | 6.4.19.0 |
product.translated.name | Translated product name. | 6.4.0.0 |
product.translated.description | Translated product description as HTML. Use the Twig filter |striptags to output plain text. | 6.4.0.0 |
product.translated.descriptionTeaser | Plain-text excerpt of the description, up to 512 characters. Generated when the product is saved. | 6.7.12.0 |
product.translated.keywords | Translated keywords; uses the language fallback. | 6.4.0.0 |
product.translated.metaTitle | Translated SEO title; uses the language fallback. | 6.4.0.0 |
product.translated.metaDescription | Translated SEO description; uses the language fallback. | 6.4.0.0 |
product.translated.ogTitle | Title for social media sharing. | 6.7.10.0 |
product.translated.ogDescription | Description for social media sharing. | 6.7.10.0 |
product.translated.packUnit | Translated packaging unit, singular. | 6.4.0.0 |
product.translated.packUnitPlural | Translated packaging unit, plural. | 6.4.0.0 |
product.translated.customFields.<name> | Value of a product custom field. Replace <name> with the technical name. | 6.4.0.0 |
entitySeoUrl('product', product.id) | Product URL for Storefront and Headless sales channels. For versions before 6.7.14.0, use seoUrl('frontend.detail.page', {'productId': product.id}) for Storefront sales channels. | 6.7.14.0 |
product.cover.media.url | URL of the main image. | 6.4.0.0 |
product.cover.media.translated.alt | Translated alt text of the main image. | 6.4.0.0 |
product.cover.media.thumbnails | Thumbnails of the main image; each includes a URL, width, and height. | 6.4.0.0 |
product.media | Product images. The order is not fixed. To use the order set in the Administration, sort by position. | 6.4.0.0 |
product.coverId | ID of the main image within product.media. | 6.4.0.0 |
product.openGraphMedia.url | Image for social media sharing. | 6.7.10.0 |
product.calculatedPrice.unitPrice | Price for one unit based on the product's default price. When an advanced price rule applies, the Storefront and cart use product.calculatedPrices. | 6.4.0.0 |
product.calculatedPrice.listPrice.price | List price; empty if no list price is set. | 6.4.0.0 |
product.calculatedPrice.listPrice.percentage | Savings compared with the list price, as a percentage. | 6.4.0.0 |
product.calculatedPrice.listPrice.discount | Savings compared with the list price, as a negative amount. | 6.4.0.0 |
product.calculatedPrice.regulationPrice.price | Lowest price in the last 30 days, if maintained for the product. | 6.4.10.0 |
product.calculatedPrice.referencePrice.price | Base price, e.g. price per kilogram. Only set when the required units are maintained and the sales unit differs from the base unit. | 6.4.0.0 |
product.calculatedPrice.referencePrice.referenceUnit | Base unit amount for the base price. | 6.4.0.0 |
product.calculatedPrice.referencePrice.unitName | Name of the base price unit, e.g. “kilogram”. | 6.4.0.0 |
product.calculatedPrices | Advanced prices for the first matching price rule, sorted by quantity tier. .first is the price for one unit; Shopware templates often use .last for the price of the largest tier. | 6.4.0.0 |
product.calculatedCheapestPrice.unitPrice | Lowest price across the product, its variants, and quantity tiers (“from” price). For a variant, this is the lowest price in the product family. | 6.4.0.0 |
product.calculatedCheapestPrice.hasRange | Indicates whether prices differ across variants or quantity tiers. | 6.4.0.0 |
product.tax.taxRate | VAT rate as a percentage. | 6.4.0.0 |
product.active | Indicates whether the product is active. | 6.4.0.0 |
product.available | Indicates whether the product can be ordered. For closeout products with stock below the minimum order quantity, the value may be false. | 6.4.0.0 |
product.stock | Stock level. | 6.4.0.0 |
product.availableStock | Available stock. From 6.6.0.0 onward, this value is the same as product.stock; before that, open order quantities are deducted. | 6.4.0.0 |
product.isCloseout | Indicates whether the product is a closeout item that cannot be ordered when out of stock. | 6.4.0.0 |
product.minPurchase | Minimum order quantity. | 6.4.0.0 |
product.maxPurchase | Maximum order quantity, if set for the product. | 6.4.0.0 |
product.calculatedMaxPurchase | Maximum quantity per order, taking into account the product limit, cart limit, stock for closeout products, and order steps. | 6.4.0.0 |
product.purchaseSteps | Order quantity steps. | 6.4.0.0 |
product.restockTime | Restock time in days. | 6.4.0.0 |
product.deliveryTime.translated.name | Translated delivery time name, e.g. “1–3 days”. | 6.4.0.0 |
product.deliveryTime.min | Minimum value of the delivery time range. | 6.4.14.0 |
product.deliveryTime.max | Maximum value of the delivery time range. | 6.4.14.0 |
product.deliveryTime.unit | Delivery time unit: hour, day, week, month, or year. | 6.4.14.0 |
product.deliveryTimeId | Delivery time ID. Note the lowercase “d” in Id. | 6.4.0.0 |
product.releaseDate | Release date. Format it if needed, e.g. product.releaseDate|date('Y-m-d'). | 6.4.0.0 |
product.isNew | Indicates whether the release date falls within the period for new products defined in the shop settings. | 6.4.0.0 |
product.manufacturer.translated.name | Translated manufacturer name or brand. | 6.4.0.0 |
product.manufacturer.translated.link | Manufacturer website. | 6.4.0.0 |
product.manufacturer.media.url | URL of the manufacturer logo. | 6.4.0.0 |
product.seoCategory | Main product category for the selected sales channel, set in the product's SEO tab. Empty if none is set. | 6.7.14.0 |
product.categories | Active product categories. Before 6.7.11.0, inactive categories could also be included. | 6.4.0.0 |
product.seoCategory.breadcrumb | Category path as a list of names. Use |slice(1)|join(' > ') to remove the root category and join the remaining names. | 6.7.14.0 |
product.tags | Product tags; each entry contains a name. | 6.4.0.0 |
product.options | Variant options with translated names and option groups. | 6.4.0.0 |
product.variation | Variant options as a list of group and option names. Only populated if the template also uses product.options with the corresponding group. | 6.4.0.0 |
product.properties | Product properties. | 6.4.0.0 |
product.sortedProperties | Properties sorted by property group, excluding groups hidden on the product detail page. Only populated if the template also uses product.properties with the group. | 6.4.9.0 |
product.weight | Weight in kg. | 6.4.0.0 |
product.width | Width in mm. | 6.4.0.0 |
product.height | Height in mm. | 6.4.0.0 |
product.length | Length in mm. | 6.4.0.0 |
product.measurements.units.weight.value | Weight converted to the measurement system of the selected sales channel. Equivalent fields are available for width, height, and length. Only maintained values are present. | 6.7.1.0 |
product.measurements.units.weight.unit | Unit of the converted weight measurement. | 6.7.1.0 |
product.unit.translated.name | Translated unit name, e.g. “kilogram”. | 6.4.0.0 |
product.unit.translated.shortCode | Translated unit abbreviation, e.g. “kg”. | 6.4.0.0 |
product.purchaseUnit | Contents of one sales unit, e.g. 0.5. | 6.4.0.0 |
product.referenceUnit | Base unit amount for the base price. The corresponding unit is available through product.unit. | 6.4.0.0 |
product.shippingFree | Indicates whether the product qualifies for free shipping. | 6.4.0.0 |
product.guaranteeMonths | Duration of the manufacturer's commercial durability guarantee in months, in half-year increments from 30 months. Capped at 600 months starting with 6.7.15.0. | 6.7.14.0 |
product.guaranteeConfirmed | Indicates that the merchant has confirmed the guarantee information is accurate and available. | 6.7.14.0 |
product.guaranteeTermsUrl | Link to the guarantee terms; must be an HTTP or HTTPS URL. | 6.7.16.0* |
product.guaranteeTermsMedia.url | Guarantee terms document. | 6.7.16.0* |
product.markAsTopseller | Indicates whether the product is marked as a bestseller. | 6.4.0.0 |
product.sales | Units sold; updated when orders are placed or cancelled. | 6.4.0.0 |
product.ratingAverage | Average product rating. | 6.4.0.0 |
| Variable | Description | Available since |
|---|---|---|
productExport.fileName | Export file name. | 6.4.0.0 |
productExport.accessKey | Access key in the export URL. | 6.4.0.0 |
productExport.encoding | Encoding, e.g. UTF-8 or ISO-8859-1. | 6.4.0.0 |
productExport.fileFormat | File format: CSV or XML. | 6.4.0.0 |
productExport.includeVariants | Indicates whether variants are exported. | 6.4.0.0 |
productExport.feedLabel | Google feed label. | 6.7.12.0 |
productExport.productStream.name | Name of the dynamic product group; empty in the export preview. | 6.4.0.0 |
productExport.generatedAt | Time of the last generation; empty in the export preview. | 6.4.0.0 |
productExport.salesChannel.translated.name | Translated name of the product comparison sales channel. | 6.4.0.0 |
productExport.salesChannelDomain.url | URL of the export domain. | 6.4.0.0 |
productExport.salesChannelDomain.language.locale.code | Locale of the export domain, e.g. de-DE. | 6.4.0.0 |
| Variable | Description | Available since |
|---|---|---|
context.currency.isoCode | Currency code from the export settings, e.g. EUR. | 6.4.0.0 |
context.currency.symbol | Currency symbol, e.g. €. | 6.4.0.0 |
context.currency.itemRounding.decimals | Number of decimal places for prices. | 6.4.0.0 |
context.taxState | Tax display: gross, net, or tax-free. | 6.4.0.0 |
context.currentCustomerGroup.translated.name | Customer group of the selected sales channel; relevant for price calculation. | 6.4.0.0 |
context.measurementSystem.system | Measurement system set on the selected sales channel: metric or imperial. A measurement setting on the export domain is ignored. | 6.7.1.0 |
context.shippingMethod.translated.name | Default shipping method of the selected sales channel. | 6.4.0.0 |
context.shippingLocation.country.iso | ISO code of the default country for the selected sales channel, e.g. DE. | 6.4.0.0 |
context.salesChannel.translated.name | Translated name of the Storefront or Headless sales channel selected in the export settings; uses the language fallback. | 6.4.0.0 |
context.languageInfo.localeCode | Locale of the export language, e.g. de-DE. | 6.6.10.0 |
context.languageInfo.name | Name of the export language. | 6.6.10.0 |
context.paymentMethod.translated.name | Default payment method of the selected sales channel. | 6.4.0.0 |
*The source list marks these variables as upcoming for 6.7.16.0.
You also have the option of including custom fields in the template.
The technical name of the custom field is required for this. You can find this in the settings of the additional field.
The general structure for an custom field variable is as follows:
For a product custom field:
{{ product.translated.customFields.technical_name_of_the_custom_field }}e.g.:
{{ product.translated.customFields.further_information }}It is also possible to query custom fields of the product manufacturer.
{{ product.manufacturer.translated.customFields.technical_name_of_the_custom_field }}e.g.:
{{ product.manufacturer.translated.customFields.manufacturer_information }}It can be useful to include the query of the additional fields in an if-query, so that the output only occurs if the field is also filled.
This is possible, for example, as follows:
{% if product.translated.customFields.technical_name_of_the_custom_field is defined %}
{{ product.translated.customFields.technical_name_of_the_custom_field }}
{% endif %}By adapting the template, properties can also be output and transferred. The product properties are located in the array product.properties. This can show you the properties.
{% for properties in product.properties %}
{{ properties.name }}
{% endfor %}If you want to output a specific property group, you can limit and query it with an additional if query.
For example:
{% for properties in product.properties %}
{% if properties.group.name == "size" %}
{{ properties.name }}
{% endif %}
{% endfor %}By using a condition that ends with an endif tag, you can display multiple image urls of a product. In the following query, five other image urls are output in addition to the cover image, if any are available. You can change the number of Urls to be output as you wish.
{%- if product.media|length > 1 -%}
"{%- for mediaAssociation in product.media|slice(0, 5) -%}
{{ mediaAssociation.media.url }}
{%- if not loop.last -%},{%- endif -%}
{%- endfor -%}"
{%- endif -%}{#- -#}Errors may occur during the product comparison, these are explained here and how to solve them.
By default, some content such as product images are expected. For example, if you have selected Google Shopping (XML) as the template, the export may be canceled if the dynamic product group for the feed contains one or more items that do not have a product image. In such a case, you should make sure to assign a product image to all products.
Alternatively, you can edit the product line in the Template tab.
The product image URL is displayed using this entry:
<g:image_link>{{ product.cover.media.url }}</g:image_link>This should be completely replaced by the following entry:
<g:image_link>
{% if product.cover.media.url is defined and product.cover.media.url is not null %}
{{ product.cover.media.url }}
{% endif %}
</g:image_link>Thus, the first step in a product comparison is to check whether a product image is available. Only if one is available will it be included in the product comparison.
This example can also be applied to other variables.
If there are items in the selected Dynamic Product Group that are not assigned to a valid and available category, the following message may occur:
{"errors":[{"status":"400","code":"FRAMEWORK__STRING_TEMPLATE_RENDERING_FAILED",
"title":"Bad Request","detail":"Failed rendering string template using Twig:
Failed rendering string template using Twig: Impossible to access an attribute (\u0022getBreadCrumb\u0022)
on a null variable in \u0022420463b818562f32a1fd3ff62050d151\u0022 at line 6.",
"meta":{"parameters":
{"message":"Failed rendering string template using Twig: Impossible to access an attribute (\u0022getBreadCrumb\u0022) on a null variable in \u0022420463b818562f32a1fd3ff62050d151\u0022 at line 6."}
}}]}By adjusting the template, you can check in advance whether a category is stored. So this message is bypassed.
To do this, you can edit the product line in the Template tab.
The category is displayed using this entry:
<g:product_type>{{ product.categories.first.getBreadCrumb|slice(1)|join(' > ')|raw|escape }}</g:product_type>To check the category before comparing products, replace this entry with the following:
<g:product_type>
{% if product.categories.first.getBreadCrumb is defined and product.categories.first.getBreadCrumb is not null %}
{{ product.categories.first.getBreadCrumb|slice(1)|join(' > ')|raw|escape }}
{% endif %}
</g:product_type>Thus, when comparing products, the system first checks whether a valid category exists. Only if a category exists is it included in the product comparison.
You can use a whitespace to remove unnecessary spaces or "whitespaces" on the left and right. To do this, you need to add a - at the beginning and end, as shown below.
Example with spaces:
{% for properties in product.properties %}
{% if properties.group.name == "brandname" %}
{{ properties.name }}
{% endif %}
{% endfor %}Example without spaces:
{%- for properties in product.properties -%}
{%- if properties.group.name == "brandname" -%}
{{- properties.name -}}
{%- endif -%}
{%- endfor -%}The Shopware templates for the product comparisons and the social shopping sales channels are delivered in a standard configuration. For some products or providers, additions are necessary. For frequently requested elements, we have collected the corresponding code snippets here.