Product Prices¶
Use product_prices
module to render price(s) of the currently visible product on a page. This module is available only within a product card.
Configuration parameters¶
showRegularPrice¶
int
if set to 1 a regular price will be displayed
showSpecialOfferDuration¶
int
if set to 1 an information about special offer duration will be displayed.
specialOfferDurationType¶
string
if set to promotionsLastingMoreThan30Days
the duration of the special offer will be displayed only after the promotion has lasted for more than 30 days. Otherwise it will be displayed for all promotions.
percentageDiscountValue¶
int
if set to 1 an information about the special offer price in percentage value will be displayed.
Module source code¶
{% from "@macros/product_price.twig" import product_price %}
{% set globalPricesSettings = ObjectApi.getProductPricesSettings() %}
{% set shopUrls = ObjectApi.getShopUrls() %}
{% set product = ObjectApi.getProduct(product_id) %}
{% set productVariant = product %}
{% if product.variants.count == 1 %}
{% set productVariant = product.variants[0] %}
{% endif %}
{% set price = productVariant.price %}
{% set priceInCurrency = productVariant.priceInProductCurrency %}
{% set showPercentageDiscountValue = productVariant.hasSpecialOffer and moduleConfig.percentageDiscountValue %}
{% set specialOffer = productVariant.specialOffer %}
{% set showGrossNetTabs = globalPricesSettings.showGrossPrice and globalPricesSettings.showNetPrice %}
{% set showDifferentCurrency = productVariant.hasDifferentCurrency and productVariant.currency.id != currency_id %}
{% if showDifferentCurrency %}
{% if productVariant.lowestHistoricalPriceInLast30DaysInProductCurrency %}
{% set lowestHistoricalPriceInLast30DaysInProductCurrencyPrice = productVariant.lowestHistoricalPriceInLast30DaysInProductCurrency.getPrice() %}
{% endif %}
{% if productVariant.hasUnitPriceCalculation and globalPricesSettings.showUnitPrice %}
{% set unitPriceInCurrency = productVariant.hasSpecialOffer ? productVariant.specialOfferUnitPriceInProductCurrency : productVariant.unitPriceInProductCurrency %}
{% endif %}
{% endif %}
{% if showPercentageDiscountValue %}
{% set percentageDiscountValue = specialOffer.formatDiscount %}
{% endif %}
{% if productVariant.hasUnitPriceCalculation and globalPricesSettings.showUnitPrice %}
{% set unitPrice = productVariant.hasSpecialOffer ? productVariant.specialOfferUnitPrice : productVariant.unitPrice %}
{% endif %}
{% if productVariant.lowestHistoricalPriceInLast30Days %}
{% set lowestHistoricalPriceInLast30Days = productVariant.lowestHistoricalPriceInLast30Days.getPrice() %}
{% endif %}
{% if lowestHistoricalPriceInLast30Days %}
{% set lowestHistoricalPricePercentage = (100 - price.grossValue * 100 / lowestHistoricalPriceInLast30Days.grossValue)|round() %}
{% set isLowestHistoricalPriceHigherThanCurrent = lowestHistoricalPriceInLast30Days.grossValue > price.grossValue %}
{% endif %}
{% set daysFromPromotionStart = specialOffer.getDetails().startDate.timeDifference(ObjectApi.getNow()).days %}
{% set showSpecialOfferDurationForAllPromotions = moduleConfig.specialOfferDurationType == 'allPromotions' %}
{% set showSpecialOfferDurationForPromotionsLongerThan30Days = moduleConfig.specialOfferDurationType == 'promotionsLastingMoreThan30Days' and daysFromPromotionStart >= 30 %}
{% set showSpecialOfferDuration = moduleConfig.showSpecialOfferDuration and (showSpecialOfferDurationForAllPromotions or showSpecialOfferDurationForPromotionsLongerThan30Days) %}
{% set prices %}
<product-price
class="product-prices"
product-id="{{ product.id }}"
slot="logged-in">
<div class="product-prices__header">
{% if showDifferentCurrency %}
<h-tabs class="tabs">
<h-tab
selected
class="tabs__tab"
panel-name="shop-current-currency-{{ product.id }}">
{{ price.currency }}
</h-tab>
<h-tab
class="tabs__tab"
panel-name="product-currency-{{ product.id }}">
{{ productVariant.currency.code }}
</h-tab>
</h-tabs>
{% endif %}
{% if showGrossNetTabs %}
<h-tabs class="tabs">
<h-tab
selected
class="tabs__tab"
panel-name="price-gross-{{ product.id }}">
{{ translate('with VAT', price.formatTax) }}
</h-tab>
<h-tab
class="tabs__tab"
panel-name="price-net-{{ product.id }}">
{{ translate('without VAT') }}
</h-tab>
</h-tabs>
{% endif %}
</div>
<h-tab-panel
{% if globalPricesSettings.showNetPrice == false or showGrossNetTabs %}hidden{% endif %}
name="price-net-{{ product.id }}"
class="js__product-price-net"
>
{% if showDifferentCurrency %}
<h-tab-panel
hidden
class="js__product-currency-price"
name="product-currency-{{ product.id }}">
{{ product_price({
priceValue: priceInCurrency.formatNet,
basePriceValue: productVariant.basePriceInProductCurrency.formatNet,
otherPriceValue: productVariant.otherPrice.isZero ? null : productVariant.otherPrice.formatNet,
percentageDiscountValue: percentageDiscountValue,
unitPrice: unitPriceInCurrency.formatNet,
unitName: productVariant.unitPriceCalculationUnit.name,
hasSpecialOffer: productVariant.hasSpecialOffer,
specialOffer: specialOffer,
lowestHistoricalPriceInLast30Days: lowestHistoricalPriceInLast30DaysInProductCurrencyPrice ? lowestHistoricalPriceInLast30DaysInProductCurrencyPrice.formatNet : null,
lowestHistoricalPricePercentage: lowestHistoricalPricePercentage ?: null,
isLowestHistoricalPriceHigherThanCurrent: isLowestHistoricalPriceHigherThanCurrent,
priceOutsideTheBundle: productVariant.bundle.originalItemsPrice.formatNet
}, {
showAdditionalTaxInfo: globalPricesSettings.showAdditionalTaxInfo,
showSpecialOfferDuration,
showLowestPriceIn30Days: globalPricesSettings.showLowestPriceIn30Days,
showPriceWithoutShippingCostInfo: globalPricesSettings.showAdditionalTaxInfo,
showRegularPrice: moduleConfig.showRegularPrice,
showPercentageDiscountValue: moduleConfig.percentageDiscountValue
}) }}
</h-tab-panel>
{% endif %}
<h-tab-panel
class="js__product-price"
name="shop-current-currency-{{ product.id }}">
{{ product_price({
priceValue: price.formatNet,
basePriceValue: productVariant.basePrice.formatNet,
otherPriceValue: productVariant.otherPrice.isZero ? null : productVariant.otherPrice.formatNet,
percentageDiscountValue: percentageDiscountValue,
unitPrice: unitPrice.formatNet,
unitName: productVariant.unitPriceCalculationUnit.name,
hasSpecialOffer: productVariant.hasSpecialOffer,
specialOffer: specialOffer,
lowestHistoricalPriceInLast30Days: lowestHistoricalPriceInLast30Days ? lowestHistoricalPriceInLast30Days.formatNet : null,
lowestHistoricalPricePercentage: lowestHistoricalPricePercentage ?: null,
isLowestHistoricalPriceHigherThanCurrent: isLowestHistoricalPriceHigherThanCurrent,
priceOutsideTheBundle: productVariant.bundle.originalItemsPrice.formatNet
}, {
showAdditionalTaxInfo: globalPricesSettings.showAdditionalTaxInfo,
showSpecialOfferDuration,
showLowestPriceIn30Days: globalPricesSettings.showLowestPriceIn30Days,
showPriceWithoutShippingCostInfo: globalPricesSettings.showAdditionalTaxInfo,
showRegularPrice: moduleConfig.showRegularPrice,
showPercentageDiscountValue: moduleConfig.percentageDiscountValue
}) }}
</h-tab-panel>
</h-tab-panel>
<h-tab-panel
{% if globalPricesSettings.showGrossPrice == false %}hidden{% endif %}
name="price-gross-{{ product.id }}"
class="js__product-price-gross"
>
{% if showDifferentCurrency %}
<h-tab-panel
hidden
class="js__product-currency-price"
name="product-currency-{{ product.id }}">
{{ product_price({
priceValue: priceInCurrency.formatGross,
basePriceValue: productVariant.basePriceInProductCurrency.formatGross,
otherPriceValue: productVariant.otherPrice.isZero ? null : productVariant.otherPrice.formatGross,
percentageDiscountValue: percentageDiscountValue,
unitPrice: unitPriceInCurrency.formatGross,
unitName: productVariant.unitPriceCalculationUnit.name,
hasSpecialOffer: productVariant.hasSpecialOffer,
specialOffer: specialOffer,
priceFormatTax: price.formatTax,
lowestHistoricalPriceInLast30Days: lowestHistoricalPriceInLast30DaysInProductCurrencyPrice ? lowestHistoricalPriceInLast30DaysInProductCurrencyPrice.formatGross : null,
lowestHistoricalPricePercentage: lowestHistoricalPricePercentage ?: null,
isLowestHistoricalPriceHigherThanCurrent: isLowestHistoricalPriceHigherThanCurrent,
priceOutsideTheBundle: productVariant.bundle.originalItemsPrice.formatGross
}, {
showAdditionalTaxInfo: globalPricesSettings.showAdditionalTaxInfo,
showSpecialOfferDuration,
showLowestPriceIn30Days: globalPricesSettings.showLowestPriceIn30Days,
showPriceWithoutShippingCostInfo: globalPricesSettings.showAdditionalTaxInfo,
showRegularPrice: moduleConfig.showRegularPrice,
showPercentageDiscountValue: moduleConfig.percentageDiscountValue
}) }}
</h-tab-panel>
{% endif %}
<h-tab-panel
class="js__product-price"
name="shop-current-currency-{{ product.id }}">
{{ product_price({
priceValue: price.formatGross,
basePriceValue: productVariant.basePrice.formatGross,
otherPriceValue: productVariant.otherPrice.isZero ? null : productVariant.otherPrice.formatGross,
percentageDiscountValue: percentageDiscountValue,
unitPrice: unitPrice.formatGross,
unitName: productVariant.unitPriceCalculationUnit.name,
hasSpecialOffer: productVariant.hasSpecialOffer,
specialOffer: specialOffer,
priceFormatTax: price.formatTax,
lowestHistoricalPriceInLast30Days: lowestHistoricalPriceInLast30Days ?: null,
lowestHistoricalPricePercentage: lowestHistoricalPricePercentage ?: null,
isLowestHistoricalPriceHigherThanCurrent: isLowestHistoricalPriceHigherThanCurrent,
priceOutsideTheBundle: productVariant.bundle.originalItemsPrice.formatGross
}, {
showAdditionalTaxInfo: globalPricesSettings.showAdditionalTaxInfo,
showSpecialOfferDuration,
showLowestPriceIn30Days: globalPricesSettings.showLowestPriceIn30Days,
showPriceWithoutShippingCostInfo: globalPricesSettings.showAdditionalTaxInfo,
showRegularPrice: moduleConfig.showRegularPrice,
showPercentageDiscountValue: moduleConfig.percentageDiscountValue
}) }}
</h-tab-panel>
</h-tab-panel>
</product-price>
{% if globalPricesSettings.showPricesToUnregistered %}
{% set priceSpecifications = [] %}
{% set specialOfferStartDate = productVariant.hasSpecialOffer ? specialOffer.getDetails().startDate.dateShort : null %}
{% set specialOfferEndDate = productVariant.hasSpecialOffer ? specialOffer.getDetails().endDate.dateShort : null %}
{% if globalPricesSettings.showGrossPrice %}
{% set priceSpecifications = priceSpecifications|merge([
{
"@type": "PriceSpecification",
"price": price.grossValue,
"priceCurrency": price.currency,
"valueAddedTaxIncluded": true,
"validFrom": specialOfferStartDate,
"validThrough": specialOfferEndDate
}
]) %}
{% if unitPrice %}
{% set priceSpecifications = priceSpecifications|merge([
{
"@type": "UnitPriceSpecification",
"price": unitPrice.grossValue,
"priceCurrency": unitPrice.currency.code,
"unitText": productVariant.unitPriceCalculationUnit.name,
"valueAddedTaxIncluded": true,
"validFrom": specialOfferStartDate,
"validThrough": specialOfferEndDate
}
]) %}
{% endif %}
{% if showDifferentCurrency %}
{% set priceSpecifications = priceSpecifications|merge([
{
"@type": "PriceSpecification",
"price": priceInCurrency.netValue,
"priceCurrency": productVariant.currency.code,
"valueAddedTaxIncluded": false,
"validFrom": specialOfferStartDate,
"validThrough": specialOfferEndDate
}
]) %}
{% endif %}
{% endif %}
{% if globalPricesSettings.showNetPrice %}
{% set priceSpecifications = priceSpecifications|merge([
{
"@type": "PriceSpecification",
"price": price.netValue,
"priceCurrency": price.currency,
"valueAddedTaxIncluded": false,
"validFrom": specialOfferStartDate,
"validThrough": specialOfferEndDate
}
]) %}
{% if unitPrice %}
{% set priceSpecifications = priceSpecifications|merge([
{
"@type": "UnitPriceSpecification",
"price": unitPrice.netValue,
"priceCurrency": unitPrice.currency.code,
"unitText": productVariant.unitPriceCalculationUnit.name,
"valueAddedTaxIncluded": false,
"validFrom": specialOfferStartDate,
"validThrough": specialOfferEndDate
}
]) %}
{% endif %}
{% if showDifferentCurrency %}
{% set priceSpecifications = priceSpecifications|merge([
{
"@type": "PriceSpecification",
"price": priceInCurrency.netValue,
"priceCurrency": productVariant.currency.code,
"valueAddedTaxIncluded": false,
"validFrom": specialOfferStartDate,
"validThrough": specialOfferEndDate
}
]) %}
{% endif %}
{% endif %}
{% set productPricesJsonLd = {
"@context": [
"http://schema.org/",
{
"@base": "#{shopUrls.mainPageUrl.absolute}"
}
],
"@id": "#{productVariant.url.relative}",
"offers": {
"@id": "#{productVariant.url.relative}",
"@type": "Offer",
"priceValidUntil": specialOfferEndDate,
"PriceSpecification": priceSpecifications
}
}%}
<script type="application/ld+json">
{{ productPricesJsonLd | json_encode | raw }}
</script>
{% endif %}
{% endset %}
{% if globalPricesSettings.showPricesToUnregistered %}
{{ prices }}
{% else %}
<auth-controller>
<div slot="logged-in" hidden>
{{ prices }}
</div>
<div slot="logged-out">
<div class="flash-message flash-message__warning">
<h-icon
icon-name="icon-alert-triangle"
css-classes="flash-message__icon"
role="button"
></h-icon>
<p>{{ translate('Please %slog in%s to view the product price', ['<login-modal-opener class="link link_regular link_underline" tabindex="0" role="button">', '</login-modal-opener>']) }}</p>
</div>
</div>
</auth-controller>
{% endif %}
The module uses JSON-LD and Microdata from schema.org to optimize search results in browsers.
Macros reference¶
Webcomponents reference¶
Used Object Api methods¶
Used styles¶
Module configuration schema¶
[
{
"state": "unfolded",
"label": "General settings",
"elements": [
{
"type": "infobox",
"name": "infobox",
"options": {
"type": "blank",
"message": "%s Related settings in the admin panel%s- changing phrases in [translations](%s)%s- showing net\/gross prices in [tax rates settings](%s)%s- enabling different currency and unit price calculation in [product settings](%s)%s- enabling information about the lowest price on the product page in [product settings](%s)",
"placeholderValues": [
"####",
"\n",
"\/admin\/configLanguages\/list",
"\n",
"\/admin\/configTax\/list",
"\n",
"\/admin\/configProducts",
"\n",
"\/admin\/configProducts"
]
}
}
]
},
{
"state": "unfolded",
"label": "Promotions",
"elements": [
{
"type": "checkbox",
"name": "showRegularPrice",
"label": "Display regular price (for products on sale)",
"defaultValue": 0
},
{
"type": "checkbox",
"name": "percentageDiscountValue",
"label": "Display the percentage change in price",
"defaultValue": 0,
"hint": {
"message": "For products on sale, an additional information (e.g. - 20%s) will be displayed next to the crossed-out regular price and the lowest price.",
"placeholderValues": ["%"]
}
},
{
"type": "checkbox",
"name": "showSpecialOfferDuration",
"label": "Display promotion end date",
"defaultValue": 1,
"children": [
{
"type": "radio",
"name": "specialOfferDurationType",
"label": "Show for:",
"defaultValue": "allPromotions",
"options": {
"radioOptions": [
{ "key": "allPromotions", "label": "all promotions" },
{ "key": "promotionsLastingMoreThan30Days", "label": "promotions lasting more than 30 days" }
]
},
"relations": [
{
"parentName": "showSpecialOfferDuration",
"parentValueToActionsMap": [
{
"value": 0,
"actions": ["setHidden", "setDisabled", "setOptional"]
},
{
"value": 1,
"actions": ["setVisible", "setAvailable", "setRequired"]
}
]
}
]
}
]
}
]
}
]