Skip to main content
With the $wsProducts module, you can dynamically load and display product data in the frontend.

Module overview

Example / excerpt of $wsProducts
{{= $wsProducts | json }}
JSON output
{
  "load": "ƒ()",
  "loadByNumber": "ƒ()",
  "loadByCustomNumber": "ƒ()",
  "variantInfo": "ƒ()"
}
Note: ƒ() denotes a function. Methods overview
MethodReturn typeDescription
load()mapReturns a product based on the product ID.
loadByNumber()mapReturns a product based on the item number.
loadByCustomNumber()mapReturns a product based on a user-defined number.
variantInfo()mapReturns the variant data for a product.

Templates

By default, products are displayed via the template product.htm. This is located in the views directory. The name product.htm and the storage location must not be changed, as the template is hard-wired in the software and is not configurable or customizable. However, product data can be flexibly integrated on other pages as well, for example:
  • Home page → display of top sellers, offers, or a product selection.
  • Basket page → cross-selling products as purchase recommendations.
  • Category pages & search results → custom product lists with filters.
  • Checkout & order confirmation → display of complementary products or discount campaigns.
With $wsProducts, product information can be retrieved dynamically and integrated individually into various templates to enable targeted presentation of items.

Variables

No variables are available for $wsProducts.

Methods

$wsProducts.load()

Returns a product based on the product ID. Signature
$wsProducts.load(productId)
Return value
map - Product map with all product data.
Parameters
NameTypeRequiredDescription
productIdstringyesID of the product.
Example that loads a product and outputs the product name.
{{ var $myProduct = $wsProducts.load("100-12345") }}
Name: {{= $myProduct.name }}

$wsProducts.loadByNumber()

Returns a product based on the item number. Signature
$wsProducts.loadByNumber(itemNumber)
Return value
map - Product map with all product data.
Parameters
ParameterTypeRequiredDescription
itemNumberstringyesItem number of the product.
Example that loads a product by item number:
{{ var $myProduct = $wsProducts.loadByNumber("ART-001") }}
Name: {{= $myProduct.name }}

$wsProducts.loadByCustomNumber()

Returns a product based on a user-defined number (e.g. EAN, GTIN). Signature
$wsProducts.loadByCustomNumber(customNumber)
Return value
map - Product map with all product data.
Parameters
ParameterTypeRequiredDescription
customNumberstringyesUser-defined number.
Example that loads a product by GTIN.
{{ var $myProduct = $wsProducts.loadByCustomNumber("4006381333931") }}
Name: {{= $myProduct.name }}
By using the $wsProducts.load..() functions, various variables are available to retrieve and output data about the product. Below is an overview of which variables are available.

Product data (return value of $wsProducts.load())

First, it is necessary to assign the map with the product data, as shown in the example above, to a local variable. This can then be used at various places in the template. JSON output of the variable
{
  "id": "...",
  "active": "...",
  "name": "...",
  "descr": "...",
  "itemNumber": "...",
  "price": "...",
  "taxRateId": "...",
  "storeId": "...",
  "custom": { ... },
  "base": null,
  "variantSelection": { }
}
Variables overview
VariableTypeDescription
idstringUnique product ID assigned by the shop.
activestringReturns whether the product is active in the shop.
Return values:
- always - the product is always active.
- never - the product is never active.
- test - the product is active in test mode.
namestringName of the product.
descrstringDescription of the product.
itemNumberstringItem number of the product.
pricefloatPrice of the product.
taxRateIdstringTax rate ID of the product.
storeIdstringStock item number of the product.
custommapContains all configured free product fields of the product.
basemapContains the data of the base product if it is a variant.
variantSelectionmapContains the selected variant attributes (e.g. color, size).

$wsProducts.variantInfo()

Returns the variant data for a product. Signature
$wsProducts.variantInfo(productId)
Return value
map - Map with variant data.
Parameters
NameTypeRequiredDescription
productIdstringyesID of the product whose variants are to be loaded.
Example that loads the variant info of a product.
{{ var $myVariants = $wsProducts.variantInfo("100-12345") }}
Number of variants: {{= $myVariants.numVariants }}
By using the $wsProducts.variantInfo() function, various variables are available to retrieve and output data about the product. Below is an overview of which variables are available.

Variant data (return value of $wsProducts.variantInfo())

First, it is necessary to assign the map with the variant data, as shown in the example above, to a local variable. This can then be used at various places in the template. JSON output of the variable
{
  "numVariants": 5,
  "variantAttributes": [
    {
      "name": "Color",
      "options": [
        { "name": "Red" },
        { "name": "Blue" }
      ]
    }
  ],
  "resolve": "ƒ()"
}
Variables overview
VariableTypeDescription
numVariantsintNumber of variants.
variantAttributesarrayList of variant attributes.
[$i].namestringName of the attribute (e.g. “Color”).
[$i].optionsarrayList of options.
[$i].namestringName of the option (e.g. “Red”).

$wsProducts.variantInfo().resolve()

resolve() is a method of the return value of $wsProducts.variantInfo(). It takes a possibly incomplete or invalid attribute selection and returns the closest matching existing variant. Why resolve() is needed
Variant products only exist in certain attribute combinations.
When a customer changes a single attribute (e.g. color), the previously selected overall combination may no longer be available.
In this case, resolve() finds the next possible valid variant without you having to search through all available combinations yourself.

Example
A T-shirt is available in these combinations:
ColorSize
RedS
BlueS
RedL
The customer currently sees “Red, L” and clicks on “Blue”. However, the combination “Blue, L” does not exist, so resolve() returns “Blue, S” instead – the only valid variant in which the color Blue is preserved.
The fixate parameter controls which attribute is considered immutable – in this case the color, since the user selected the color.
Signature
$variantInfo.resolve(selection, fixate)
Parameters
NameTypeRequiredDescription
selectionmapyesThe currently selected attribute values.
The map contains attribute names as keys and selected option values as values (e.g. {"Color": "Blue", "Size": "L"}).
Not all attributes need to be set.
fixatestringyesName of the attribute that the user just changed.
This value is mandatorily preserved by resolve().
All other attributes are adjusted as needed to produce a valid combination.

Return value
map - A product object that corresponds to the resolved variant. Its structure is identical to the return value of $wsProducts.load(). In case of error (no variant with the fixated attribute value exists), resolve() returns null.

Example
The user had selected “Red, size L” and clicks on “Blue”. Because “Blue, L” does not exist, resolve() returns the closest matching variant with the color Blue.
{{ var $varInfo  = $wsProducts.variantInfo("100-12345") }}
{{ var $resolved = $varInfo.resolve({"Color": "Blue", "Size": "L"}, "Color") }}

{{ if $resolved }}
  <a href="/produkt/{{= $resolved.id }}">Select variant</a>
{{ /if }}

Actions

No actions are available for $wsProducts.

Examples

In the following examples, the product is assigned to a variable $myProduct. This means that all product information can be retrieved and further processed via this variable.

Name and description of the product

Name and description are standard product data fields that are predefined by the shop system. They belong to the essential fields used to record and display basic product information and are indispensable for order processing. The technical field names are firmly defined and are addressed in the following form:
$myProduct.<technical name>
The syntax for accessing the product name and the product description is:
<h1>{{= $myProduct.name }}</h1>
<p>{{= $myProduct.descr }}</p>

Weight as an additional product data field

In contrast to standard product data fields, weight is one of the additional product data fields. These offer extended possibilities for recording and displaying product features that go beyond the basic information. Additional product data fields are:
  • Not mandatorily required for order processing, but helpful for product presentation.
  • Individually customizable and can be added as required.
  • Created via the admin interface or supplied via the product data interface.
The technical names of these fields are addressed in the form:
$myProduct.custom.<technical name>
If a field weight was created in the admin area, the weight of a product can be output like this:
<p>Weight: {{= $myProduct.custom.weight }} kg</p>

Product images

The data fields for product images are not standard fields but additional product data fields. To output product images flexibly and in different sizes, these fields must be created as the MultiFormatImage data type. This field type enables storing an image in multiple formats and at the same time provides automatic conversion, so the images are available in the desired sizes. The number of additional product data fields with this type is not limited, so any number of images can be stored for a product. The configuration of the image sizes is done in the admin interface in the image converter service. There you can define the desired formats needed for various areas of use. Typically, four image sizes are used:
  • mini (thumbnail)
  • small
  • normal and
  • large
In the admin interface image converter service, you also define the storage directory for the images on the server. The path to the image is then output directly via the corresponding variable. Product images are accessed according to the following scheme
  • $myProduct.custom.<technical field name>.<defined format>
If, for example, the field image01 was created for the main image of the product, the images can be output in the various sizes as follows:
<img src="{{= $myProduct.custom.image01.mini}}" alt="{{= $myProduct.name }}">
<img src="{{= $myProduct.custom.image01.small}}" alt="{{= $myProduct.name }}">
<img src="{{= $myProduct.custom.image01.normal}}" alt="{{= $myProduct.name }}">
<img src="{{= $myProduct.custom.image01.large}}" alt="{{= $myProduct.name }}">

Variants of a product

Products that are available in different versions such as size, color, or material are created as variant products. Variants are not standalone items, but subordinate versions of a main product that differ in certain features. So that variants can be correctly managed and displayed in the shop, special product data fields are used, which are referred to as type-specific product data fields. These fields are specifically designed to support the requirements of variant products, set products, and other complex product structures. They are deeply anchored in the shop software, firmly predefined, and cannot be changed technically. This means that both the designation and the specifications of these fields – such as allowed values, field types, or inheritance mechanisms – cannot be adjusted. The actual product information of a variant, such as name, description, price, or images, is maintained via the standard and additional product data fields defined for the variants. This data can either be set individually per variant or – if no specific values are stored – automatically inherited from the main product. The following syntax is used to access variants of a product:
{{ var $myProductVariant = $wsProducts.variantInfo($myProduct.id) }}
{{ foreach $myVariant in $myProductVariant.variantAttributes }}
   <p>Variant name: {{= $myVariant.name }}</p>
{{ /foreach }}

Price of a product

Each product has a sales price displayed in the shop. In addition to the regular price, additional prices and discounts can also be taken into account, displayed either as a fixed amount or as a percentage discount. The following data fields are available for the price calculation, for example:
  • price → The current sales price of the product.
  • setDiscount → The discount in percent, i.e. “You save X%”.
  • setDiscountPrice → The reduced price after deduction of the discount, i.e. “You save X euros”.
  • setOrgPrice → The original price before the discount, i.e. the strikethrough price.
So that the prices are output with the correct currency, the currency formatting is automatically taken from the shop settings in the admin interface. This means that the currency is displayed either as an ISO code (EUR) or as a symbol (), depending on the configuration of the shop. Whether the prices in the shop are treated net (excl. VAT) or gross (incl. VAT) is also a setting that can be configured in the admin interface. The syntax for accessing the prices and discounts is:
<p>Price: {{= $myProduct.price | currency }}</p>
<p>Discount in percent: {{= $myProduct.setDiscount }} %</p>
<p>Discount in numbers: {{= $myProduct.setDiscountPrice | currency }}</p>
<p>Original price: {{= $myProduct.setOrgPrice | currency }}</p>

Availability of a product

In addition to all other product information, the availability of a product is one of the most important pieces of information for the buyer. Each product can be given a stock level that determines whether and in what quantity an item can be ordered. Additionally, the current stock and the corresponding delivery status can be displayed in the shop. Access to the stock is not made directly via $wsProducts, but via the separate module $wsInventory.
{{ var $myProductInventoryInfo = $wsInventory.load($myProduct.id) }}
{{ if $myProductInventoryInfo.active }}
      Current quantity: {{= $myProductInventoryInfo.amount }}
{{ /if }}
You can find detailed information about data access of the stock module here. You can find more practical examples for implementing products and product variants here: Practical examples: products