Custom Products

Custom Products for Shopware 6 is an extension that is part of the Shopware Rise plan.

The extension offers you the possibility to add individualization options to articles. This is very useful for articles where the simple division into variants is not sufficient and further individualization is desired. These can be articles where an individual lettering is to be used, a special color or a certain date/time specification.

In the extension Custom Products you create product templates with selectable options. In a second step, you link these templates to existing articles. The selectable options from the product template are then displayed on the item detail page so that the customer can individualize the product accordingly.

Optionally, you can freely add user-defined charges to the specific options.

Installation

If at least the Rise Plan is stored for the store domain in the Shopware account, you can download and install the extension under Extensions > My Extensions.
It is important that you have previously logged in with your account in the Shopware Account tab.
After the extension has been installed, you can activate it via the button to the left of the extension.

You can find the installed extension in the Shopware Administration under Catalogues Custom Products.

Product templates

Under Catalogues > Custom Products you will find the overview of the product templates.

Here you can see all the templates that are already created, these can be assigned to your products. Each template has an internal name, a display name and a description. In addition, the overview shows you how many options each template has. 
You can edit, duplicate and delete the templates through the context menu on the right side.

Add template

You can create a new template by clicking the button Add template. Here you set the  general configuration.

Internal name (1): This name is only displayed internally in the template overview. This is useful if there are several product templates that should have the same name in the front end.

Active (2): With this switch the product template can be deactivated. The articles in which this template is used are still available, but cannot be individualized with this template.

Display name (3): This name is used in the frontend on the article detail page.

Description (4): With this description you can summarize on the item detail page for the customer which individual settings can be added to the respective item.

Picture (5): Additionally you can upload a picture for the item detail page or select one from the media management.

Step-by-step mode (6): With the step-by-step mode, the customer is guided step-by-step through the options in the front end, instead of being shown all at once.

Self-collapsing options (7): This function collapses options as soon as the customer has made a valid entry. (Not available in step-by-step mode)

Customers need to confirm their configuration (8): Here you can define whether customers have to confirm their configuration by checking a box on the product page or not. As long as the checkbox is not activated when the function is active, it is not possible to add the product to the shopping cart and the button "Add to cart" is grayed out.

Options

After you have created a new template and saved it, the Options area is available.

In this area you will see the options that are available for the current template. You can also add new options for customization here.

Here you first enter a name for the option and an option type. The following option types are available:

Selection field

In this option type, you can offer the customer one or more selection options, which are then made available in a window and can be selected by mouse click. For example, these can be individual options that can be added to the product.

In the settings of the option you first choose a name (1), this name will be displayed in the storefront and in the order documents.
If you check the mandatory field (2), the customer has to make a choice in the frontend to be able to put the item into the shopping cart. The option No selection is then no longer displayed in the frontend.
In addition, you can optionally enter a description (3) to provide the customer with further information about this option.

Next, you can specify that the selection options should be displayed as a drop-down menu (4) and whether a multiple selection (5) should be possible. However, multiple selection is not possible in the dropdown menu.

Optionally you can add a surcharge that the customer has to pay when selecting the option.For more information, see the section defining option-dependent surcharges.

On the left side of the option settings you can see the created items that the customer can select. With the button Create element (6) you can add further elements. If you click on one of the elements (4), you have the possibility to make further settings for the element.

In addition to a name and an order number, you can define your own surcharge here, just like in the option settings. The surcharge of an element is calculated in addition to the surcharge of the option.

Display in the frontend: 

If it is a mandatory option, the No selection element is not available.

Display in the frontend as drop-down menu: 

If it is a mandatory option, the No selection element is not available.

Image upload

The image upload offers the possibility for your customers to upload their own images, e.g. to use them to individualize the product. The following image formats are supported in version 3.1: JPG, PNG, GIF, WEBP, SVG, BMP, TIFF and EPS.
These image formats are partially only available in the Admin.

First give a name (1) to the option. The name will be displayed in the storefront and on the order documents. The checkbox Mandatory field (2) allows you to determine whether the customer must make a mandatory entry.
With the optional description (3) you can give your customers more information about the option.
In addition, you can enter an order number (4) for the option, which will then be printed on the documents.
For the configuration of the option, you need to specify the maximum number of files (5) and maximum file size (6).

For more information, see the section defining option-dependent surcharges.

Frontend view of the image upload:

As file types jpg, png and gif can be used.

Access the uploaded files:

The uploaded images are saved in the order. In the admin you can call up the custom product configuration in the order in the section items via the "..." menu. 

The configuration information is displayed in a new modal and gives you the option to download the uploaded files.

Picture selection

Compared to the selection field, the image selection offers you the possibility to make a selection based on images. The image selection has the exact same settings as the selection field. The only difference is that additional elements ar shown in the image and cannot be displayed in a drop down menu.

Frontend view of the picture selection:

If it is a mandatory option, the No selection element is not available.

Checkbox

With the checkbox you can offer your customers an option, which they can select or deselect with the checkbox. Here you can enter an order number next to a name and a description and add a corresponding surcharge.

Frontend view of the checkbox: 

File Upload

The file upload offers the option to upload PDF files. 

The configuration of the file upload is identical to the image upload.

Frontend view of the file upload:

Date field

With the date field you give the customer the possibility to add a date to the order. This can be, for example, a date for an engraving or an event date.

Beside the usual settings for this option, you enter a placeholder (1) which is displayed in the date field before the customer has selected a date. You can also specify an earliest date (2) and a latest date (3).

Frontend view of the date field:

Colour selection

With the colour selection the customer has the possibility to choose one or more colours for the article. Similar to the selection field or the image selection, you can also add sub-elements to the colour selection option, each of which stands for one colour.

After you have added one or more sub-elements to the option on the left side, you can assign a color (1) to the element in addition to the name and order number. You can also define a surcharge for the colour selection for the complete option as well as for the individual elements.

Frontend view of the colour selection:

If it is a mandatory option, the No selection element is not available.

HTML editor

The HTML editor offers the possibility to enter a text with simple formatting functions. The text entered is transmitted in the same form when the order is placed, no conversion takes place.

Apart from the name for the option, no further mandatory information is required.
Optionally, the entry can be marked as a mandatory option in the HTML editor. In this case, the customer can only add the product to the shopping cart if he or she has made an entry.
In addition, a description can be stored to provide the customer with further information.
The option product number can be optionally maintained and is then shown in the order confirmation and invoice.

Information about the possible surcharges for the option can be found here.

Frontend view of the HTML editor:

Access to the data entered by the customer:

You can see the customer's entries in the order in the corresponding position. You can call up the configuration using the "..." menu.

Text area

The text area lets the customer add text to the article. Compared to the text field, the text area will take pagination into account. The customer has the possibility to transfer multi-line texts here.

Here you need to specify how short (2) or how long (3) the text entered by the customer may be. You can also specify a placeholder (1), this will be displayed as long as the customer has not yet entered any text.

Frontend view of the text area:

Text field

With the text field you offer the customer the possibility to add a single-line text to the article. This can be the text for an engraving or similar.

To do this, you specify how short (2) and how long (3) the text may be at most. As with the text area, you also enter a placeholder (1), which is displayed as long as the customer has not yet entered any text.

Frontend view of the text field:

Number field

The number field add the possibility for the customer to add a number to the product. This can be, for example, the number of a certain item.

The minimum value (1) and maximum value (2) indicate which data can be entered in this field by the customer
The step size (3) determines the steps in which the numbers can be entered. Decimal places are also possible. Example: Step size 0.5 - Inputs 0; 0.5; 1; 1.5; 2; 2.5 etc. can be used.

The default value (4) indicates which value is pre-selected 

Frontend view of the number field:

Time field

In the time selection field you can let the customer specify a time. This could be the start time for an event, for example.

The placeholder (1) indicates how the field is filled before the customer enters it. In addition, you use the start time (2) and end time (3) to specify the period of time in which the customer may select a time.

Frontend view of the time field:

Define option-based surcharges

You have the ability to define additional surcharges for each option. To do this, you can use the corresponding functions in the configuration of the individual options to levy either absolute or relative surcharges.

Absolute surcharges

Use the Relative surcharge button (1) to switch between entering absolute and relative surcharges for the selected option. However, only one of the two types of surcharges is available for each option.

Before you can enter the amount of the surcharge, it is necessary to select the tax rate (2) for the surcharge. Then you can enter the gross price (3). If the lock symbol is closed between gross and net price (4), the net price will be determined automatically based on the values entered. To enter a different net price, click once on the lock symbol to open it. The net price is no longer bound to the gross price.

The extended surcharge (5) is only available for absolute surcharges after selecting a tax rate and offers you the possibility to define your own surcharges for the different currencies stored in the shop using rule builder.

With the checkbox Surcharge once per order (6) you can determine whether the surcharge should only be calculated once in an order, even if the option is used several times.

After you have selected a tax rate, the function of currency dependent prices (7) is also available. Here, you can define a separate surcharge for each currency stored. In the standard system, the price of the standard currency is inherited and calculated using the conversion factor stored in the currencies. If you want to define different surcharges for a currency, you can cancel the inheritance by clicking on the chain symbol in front of the currency name and enter your own surcharge.

Relative surcharges

Relative surcharges are calculated dynamically based on the product price and the stored percentage rate for the surcharge.

To use a relative allowance, activate the Relative allowancecheck box (1).

To calculate the surcharge, store a tax rate (2) and the relative surcharge (3).

If you want to use more detailed configurations for the surcharge, you can activate the Extended Surcharge (4).
Here you have the option of defining different surcharges using rules that are setup with the rule builder.

With the checkbox Surcharge once per order (6) you can determine whether the surcharge should only be calculated once in an order, even if the option is used several times.

Exclude options from each other

If you have created at least 2 options, which are not marked as mandatory options, the possibility for mutual exclusion of options is shown.

To create an exclusion combination, click the Add excluded combination button. In the modal that now opens you can do the further configuration.

First, give a name for the combination, so that you can later on recognize, what you have configured here.

For the actual configuration you can now choose from the options that are not mandatory or multiple options.
With these options you can also choose whether the exclusion should take place if the customer has made an entry there or if the field is empty. Thus it is also possible to combine options with each other and to require an entry in one field if another field has also been filled.

Assign template to a product

After you have created a template with the desired options, you can assign it to a product so that the customer can individualize this product.

To assign the product configuration to a spefic product so that this can be individualization. In the tab Specifications you will find the menu item Custom Products, where you can now assign a product template from Custom Products.

Frontend

Normal mode

In the frontend the options from Custom Products are displayed in the standard respsonsive theme above the Add to shopping cart button.

Here, the individual options of the product template can be folded out (1) and edited individually by the customer.
If an option is a mandatory field (2), this is displayed accordingly. Any surcharges (3) for an option are also displayed. (Surcharges for an element within an option are displayed next to the element). If a customer has selected an option or an element with a surcharge, this is summarized in the Per Unit Surcharges (4) overview below. The customer now has the possibility to share the configuration of a Custom Products product via link (5). In addition, the button can be used to determine whether this link can only be called up once or not.

Step by step mode

If you have activated the step-by-step mode in the product template, the available options are not directly displayed in the frontend. Instead, the area for customization (1) of the product is located above the In the shopping cart button. By clicking on the Configure product button (2), the customer is then guided step by step through the options. If a customer has selected an option or an element with a surcharge, this is summarized in the Per unit surcharges (3) overview below. The customer now has the possibility to share the configuration of a Custom Products product via link (4). In addition, the button can be used to determine whether this link can only be called up once or not.

The customer is guided step by step through the options and can then place the item in the shopping cart once all mandatory options have been filled out.

Display of Custom Products options on the invoice

The individual Custom Products options are listed as separate items in the accounts. If you have assigned a separate product number for the option, this is also displayed.

If you want to further customize the invoice and other documents, it is necessary to customize the document template. You can find all information about this in our detailed developer documentation.

Customise order confirmation

By default, the order confirmation that the customer receives by e-mail lists all options, indicating which Custom Products options the customer has selected. In the standard template, all options are listed in the order confirmation that the customer receives by mail, which Custom Products options the customer has selected. As of extension version 3.1.1, the exact contents such as the text in the text field, the number in the number field or the selected date from the date field are also output in the standard template in the invoice and the order confirmation. Nevertheless, adjustments are possible here in the e-mail template of the order confirmation.

If you are using a version of the extension older than 3.1.1, these adjustments are necessary so that the Custom Products details are displayed in the order confirmation and in the invoice.

In the standard email template, the individual custom product options are listed as a single item. This is made possible by a for loop, which creates a new row for each option. The table with the integrated for loop looks like this in the standard HTML e-mail template:


<table width="80%" border="0" style="font-family:Arial, Helvetica, sans-serif; font-size:12px;">
    <tr>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Pos.</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Bezeichnung</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Menge</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Preis</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Summe</strong></td>
    </tr>

    {% for lineItem in order.lineItems %}
    <tr>
        <td style="border-bottom:1px solid #cccccc;">{{ loop.index }} </td>
        <td style="border-bottom:1px solid #cccccc;">
          {{ lineItem.label|u.wordwrap(80) }}<br>
            {% if lineItem.payload.options is defined and lineItem.payload.options|length >= 1 %}
                {% for option in lineItem.payload.options %}
                    {{ option.group }}: {{ option.option }}
                    {% if lineItem.payload.options|last != option %}
                        {{ " | " }}
                    {% endif %}
                {% endfor %}
                <br/>
            {% endif %}
          {% if lineItem.payload.productNumber is defined %}Artikel-Nr: {{ lineItem.payload.productNumber|u.wordwrap(80) }}{% endif %}
        </td>
        <td style="border-bottom:1px solid #cccccc;">{{ lineItem.quantity }}</td>
        <td style="border-bottom:1px solid #cccccc;">{{ lineItem.unitPrice|currency(currencyIsoCode) }}</td>
        <td style="border-bottom:1px solid #cccccc;">{{ lineItem.totalPrice|currency(currencyIsoCode) }}</td>
    </tr>
    {% endfor %}
</table>

In order to output the corresponding content for each selected Custom Products option, you can insert the following code at the appropriate place.


            {% if lineItem.payload.type is defined %}
    {% if lineItem.payload.type == "textfield" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "textarea" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "numberfield" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "datetime" %}
        {{ lineItem.payload.value|date("Y.m.d") }}
        <br/>
    {% elseif lineItem.payload.type == "timestamp" %}
        {{ lineItem.payload.value|date("H:i:s") }}
        <br/>
    {% elseif lineItem.payload.type == "htmleditor" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "imageupload" %}
            {% for media in lineItem.payload.media %}
                {{ media.filename }} <br/>
            {% endfor %}
        <br/>
    {% elseif lineItem.payload.type == "fileupload" %}
            {% for media in lineItem.payload.media %}
                {{ media.filename }} <br/>
            {% endfor %}
        <br/>
    {% endif %}
{% endif %}

As you can see, the code contains a separate if- or ifelse query for each possible custom products option. For the options selection field, image selection, checkboxand colour selection, no specification of the content is necessary. Here, the customer selects an already existing selection, the name of which is output in the respective position.

Example in the default e-mail template

If you insert the code into the default HTML email template, the template will look like this:


<div style="font-family:arial; font-size:12px;">

{% set currencyIsoCode = order.currency.isoCode %}

Hello {{order.orderCustomer.salutation.letterName }} {{order.orderCustomer.firstName}} {{order.orderCustomer.lastName}},<br>
<br>
We received your order on {{ order.orderDateTime|date }}.<br>
<br>
Order number: {{ order.orderNumber }}<br>
<br>
As soon as payment is received, you will receive a separate notification and your order will be processed.<br>
<br>
You can check the current status of your order at any time using this link: {{ rawUrl('frontend.account.order.single.page', { 'deepLinkCode': order.deepLinkCode}, salesChannel.domains|first.url) }}<br>.
You can also use this link to edit the order, change the payment method or make a payment afterwards.<br>
<br>
<strong>Information on your order:</strong><br>
<br>

<table width="80%" border="0" style="font-family:Arial, Helvetica, sans-serif; font-size:12px;">
    <tr>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Pos.</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Bezeichnung</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Menge</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Preis</strong></td>
        <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Summe</strong></td>
    </tr>

    {% for lineItem in order.lineItems %}
    <tr>
        <td style="border-bottom:1px solid #cccccc;">{{ loop.index }} </td>
        <td style="border-bottom:1px solid #cccccc;">
          {{ lineItem.label|u.wordwrap(80) }}<br>
            {% if lineItem.payload.options is defined and lineItem.payload.options|length >= 1 %}
                {% for option in lineItem.payload.options %}
                    {{ option.group }}: {{ option.option }}
                    {% if lineItem.payload.options|last != option %}
                        {{ " | " }}
                    {% endif %}
                {% endfor %}
                <br/>
            {% endif %}
            {% if lineItem.payload.type is defined %}
    {% if lineItem.payload.type == "textfield" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "textarea" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "numberfield" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "datetime" %}
        {{ lineItem.payload.value|date("Y.m.d") }}
        <br/>
    {% elseif lineItem.payload.type == "timestamp" %}
        {{ lineItem.payload.value|date("H:i:s") }}
        <br/>
    {% elseif lineItem.payload.type == "htmleditor" %}
        {{ lineItem.payload.value }}
        <br/>
    {% elseif lineItem.payload.type == "imageupload" %}
            {% for media in lineItem.payload.media %}
                {{ media.filename }} <br/>
            {% endfor %}
        <br/>
    {% elseif lineItem.payload.type == "fileupload" %}
            {% for media in lineItem.payload.media %}
                {{ media.filename }} <br/>
            {% endfor %}
        <br/>
    {% endif %}
{% endif %}
          {% if lineItem.payload.productNumber is defined %}Artikel-Nr: {{ lineItem.payload.productNumber|slice(0,9) }}{% endif %}
        </td>
        <td style="border-bottom:1px solid #cccccc;">{{ lineItem.quantity }}</td>
        <td style="border-bottom:1px solid #cccccc;">{{ lineItem.unitPrice|currency(currencyIsoCode) }}</td>
        <td style="border-bottom:1px solid #cccccc;">{{ lineItem.totalPrice|currency(currencyIsoCode) }}</td>
    </tr>
    {% endfor %}
</table>

{% set delivery = order.deliveries.first %}
<p>
    <br>
    <br>
    Shipping costs: {{order.deliveries.first.shippingCosts.totalPrice|currency(currencyIsoCode) }}<br>
    Total costs net: {{ order.amountNet|currency(currencyIsoCode) }}<br>
        {% for calculatedTax in order.price.calculatedTaxes %}
            {% if order.taxStatus is same as('net') %}zzgl.{% else %}inkl.{% endif %} {{ calculatedTax.taxRate }}% MwSt. {{ calculatedTax.tax|currency(currencyIsoCode) }}<br>
        {% endfor %}
    <strong>Total costs gross: {{ order.amountTotal|currency(currencyIsoCode) }}</strong><br>
    <br>

    <strong>Chosen shipping method:</strong> {{ delivery.shippingMethod.name }}<br>
    {{ delivery.shippingMethod.description }}<br>
    <br>

    {% set billingAddress = order.addresses.get(order.billingAddressId) %}
    <strong>Billing address:</strong><br>
    {{ billingAddress.company }}<br>
    {{ billingAddress.firstName }} {{ billingAddress.lastName }}<br>
    {{ billingAddress.street }} <br>
    {{ billingAddress.zipcode }} {{ billingAddress.city }}<br>
    {{ billingAddress.country.name }}<br>
    <br>

    <strong>Shipping address:</strong><br>
    {{ delivery.shippingOrderAddress.company }}<br>
    {{ delivery.shippingOrderAddress.firstName }} {{ delivery.shippingOrderAddress.lastName }}<br>
    {{ delivery.shippingOrderAddress.street }} <br>
    {{ delivery.shippingOrderAddress.zipcode}} {{ delivery.shippingOrderAddress.city }}<br>
    {{ delivery.shippingOrderAddress.country.name }}<br>
    <br>
    {% if billingAddress.vatId %}
        Your VAT ID: {{ billingAddress.vatId }}
        If the check is successful and if you are ordering from an EU country
        you will receive your goods exempt from VAT. <br>
    {% endif %}
    <br/>
    You can also check the current status of your order at any time on our website in the "My account" - "My orders" section: {{ rawUrl('frontend.account.order.single.page', { 'deepLinkCode': order.deepLinkCode}, salesChannel.domains|first.url) }}
    </br>
    If you have any questions, please do not hesitate to contact us.
</p>
<br>
</div>

Example in the HTML e-mail

In an example where a text field and a date field have been filled in, the order confirmation with the code inserted above looks like this:

Was this article helpful?