Storefront Reference Architecture (SFRA)
Customizing the ESW integration in SFRA
1. Customizing the code
When customizing the ESW integration in SFRA, ensure changes are applied to the correct cartridge and file paths. Below are the referenced customization touchpoints from the PDF.
Templates
File Path
int_eshopworld_sfra/cartridge/templates/default/common/layout/page.isml
Description
Base SFRA page layout template (referenced as a customization touchpoint in the overlay cartridge).
File Path
int_eshopworld_sfra/cartridge/templates/default/components/header/pageHeader.isml
Description
Header integration points. Includes ESW helper and injects ESW footer include as shown in the PDF.
<isinclude template="/components/footer/pageFooterESW" />
<isset name="eswHelper" value="${require('*/cartridge/scripts/helper/eswHelper').getEswHelper()}" scope="page" />
File Path
int_eshopworld_sfra/cartridge/templates/default/components/footer/pageFooterESW.isml
Description
Loads ESW footer content when ESW module is enabled.
<isif condition="${eswHelper.getEShopWorldModuleEnabled()}">
<isinclude url="${URLUtils.url('EShopWorld-GetEswFooter',dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam'), pdict.CurrentHttpParameterMap.get(dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam')))}"/>
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/common/htmlHead.isml
Description
Injects ESW landing/header/app resources + loader (based on module enablement and preferences) and injects ESW frontend scripts/styles.
<isif condition="${isEswEnabled && eswHelper.getEnableLandingPage()}">
<isinclude url="${URLUtils.url('EShopWorld-GetEswLandingPage',dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam'), pdict.CurrentHttpParameterMap.get(dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam')))}"/>
</isif>
<isif condition="${isEswEnabled}">
<isinclude url="${URLUtils.url('EShopWorld-GetEswHeader', dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam'), pdict.CurrentHttpParameterMap.get(dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam')))}"/>
</isif>
<isif condition="${isEswEnabled && eswHelper.isFrontendConversionEnabled()}">
<isinclude url="${URLUtils.url('EShopWorld-GetEswAppResources', dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam'), pdict.CurrentHttpParameterMap.get(dw.system.Site.current.getCustomPreferenceValue('eswCountryUrlParam')))}"/>
</isif>
<isif condition="${isEswEnabled && eswHelper.isESWSupportedCountry()}">
<i class="eshopworld-loader d-none"></i>
</isif>
<script defer type="text/javascript" src="${URLUtils.staticURL('/js/EswHooks.js')}"></script>
<link rel="stylesheet" href="${URLUtils.staticURL('/css/EswCss.css')}" />
File Path
int_eshopworld_sfra/cartridge/templates/default/cart/cart.isml
Description
Cart template with ESW enablement logic affecting shipping method selection / rendering.
<isset name="eswHelper" value="${require('*/cartridge/scripts/helper/eswHelper').getEswHelper()}" scope="page" />
<isif condition="${!eswHelper.getEShopWorldModuleEnabled() || !eswHelper.isESWSupportedCountry()}">
<div class="row">
<isinclude template="cart/cartShippingMethodSelection" />
</div>
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/cart/cartTotals.isml
Description
Cart totals rendering; shows tax total block in non-ESW/non-supported cases.
<isif condition="${!eswHelper.getEShopWorldModuleEnabled() || !eswHelper.isESWSupportedCountry()}">
<div class="row">
<div class="col-8">
<p>${Resource.msg('label.sales.tax','cart',null)}</p>
</div>
<div class="col-4">
<p class="text-right tax-total">${pdict.totals.totalTax}</p>
</div>
</div>
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/cart/cartCouponDisplay.isml
Description
Coupon display template referenced as a customization touchpoint in the overlay cartridge.
File Path
int_eshopworld_sfra/cartridge/templates/default/cart/checkoutButtons.isml
Description
Checkout CTA behavior when ESW is enabled; includes ESW disclaimer message content asset.
<a href="${URLUtils.https('Checkout-Login')}" data-url="${dw.web.URLUtils.https('Checkout-Login')}">
<isif condition="${eswHelper.getEShopWorldModuleEnabled() && !!eswHelper.isESWSupportedCountry()}">
<!-- ESW-enabled checkout behavior -->
</isif>
</a>
<isif condition="${eswHelper.getEShopWorldModuleEnabled() && eswHelper.isESWSupportedCountry()}">
<iscontentasset aid="esw-checkout-disclaimer-message" />
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/product/components/pricing/main.isml
Description
Product pricing component entry point; includes restriction-aware price wrapper.
<div class="price <isif condition="${product.isProductRestricted}">d-none</isif>">
<!-- pricing markup -->
</div>
File Path
int_eshopworld_sfra/cartridge/templates/default/product/components/pricing/default.isml
Description
Default pricing component; when ESW is enabled, includes ESW pricing template.
<isset name="eswHelper" value="${require('*/cartridge/scripts/helper/eswHelper').getEswHelper()}" scope="page" />
<isif condition="${eswHelper.getEShopWorldModuleEnabled() && eswHelper.isESWSupportedCountry()}">
<isinclude template="/product/components/pricing/defaultESW" />
<iselse>
<!-- non-ESW pricing -->
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/product/components/pricing/setPrice.isml
Description
Displays “starting from” for product sets.
<div class="price">
<span class="starting">
${Resource.msg('label.starting_from', 'pricing', null)}
<isif condition="${product.price.min}">
${product.price.min.sales.formatted}
<iselse>
${product.price.sales.formatted}
</isif>
</span>
</div>
File Path
int_eshopworld_sfra/cartridge/templates/default/search/components/productTiles.isml
Description
Product tiles template referenced as a customization touchpoint in the overlay cartridge.
File Path
int_eshopworld_sfra/cartridge/templates/default/slots/product/homePageProductSlot.isml
Description
Slot include uses ESW cache include URL as shown.
<isinclude url="${URLUtils.url('EShopWorld-Cache', 'remoteIncludeUrl', /* remote include URL */)}" />
File Path
int_eshopworld_sfra/cartridge/templates/default/cart/productCard/cartProductCardProductPrice.isml
Description
Cart product card price uses ESW cache include URL as shown.
<isinclude url="${URLUtils.url('EShopWorld-Cache', 'remoteIncludeUrl', /* remote include URL */)}" />
File Path
int_eshopworld_sfra/cartridge/templates/default/checkout/shipping/shippingSummary.isml
Description
Shipping summary includes restriction messaging and renders shipping cost total.
<!--- product restriction - product not available msg --->
<isif condition="${pdict.valid.error && lineItem.id == session.privacy.restrictedProductLineItemID}">
<div class="product-not-available-msg-cart">
${Resource.msg('esw.product.notavailable','esw',null)}
</div>
</isif>
${pdict.order.totals.totalShippingCost}
File Path
int_eshopworld_sfra/cartridge/templates/default/product/components/addToCartGlobal.isml
Description
Global add-to-cart area includes ESW order/package tracking information block.
<!--- ESW Order/Package Tracking information --->
<isif condition="${!empty(pdict.order.totals.eswTrackingNumber)}">
<isset name="eswTrackingUrl" value="${!empty(dw.system.Site.current.preferences.custom.eswTrackingUrl) ? dw.system.Site.current.preferences.custom.eswTrackingUrl + pdict.order.totals.eswTrackingNumber : '#'}" scope="page" />
<a class="shipping-addr-label" target="_blank" href="${eswTrackingUrl}">
${pdict.order.totals.eswTrackingNumber}
</a>
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/product/components/addToCartProduct.isml
Description
Product add-to-cart template; contains restriction-aware button/message.
<button class="add-to-cart-global btn btn-primary <isif condition="${product.isProductRestricted}">disabled</isif>">
<!-- add to cart -->
</button>
<div class="product-not-available-msg <isif condition="${!product.isProductRestricted}">d-none</isif>">
${Resource.msg('esw.product.notavailable','esw',null)}
</div>
File Path
int_eshopworld_sfra/cartridge/templates/default/product/components/updateCartProduct.isml
Description
Update-cart UI; includes restriction-aware message block.
<button class="update-cart-product-global btn btn-primary <isif condition="${product.isProductRestricted}">disabled</isif>">
<!-- update cart -->
</button>
<div class="product-not-available-msg <isif condition="${!product.isProductRestricted}">d-none</isif>">
${Resource.msg('esw.product.notavailable','esw',null)}
</div>
File Path
int_eshopworld_sfra/cartridge/templates/default/checkout/productCard/productCardProductTotalPrice.isml
Description
Line item total pricing shows ESW converted totals when enabled; otherwise uses platform totals.
<isset name="isEswEnabled" value="${!empty(dw.system.Site.current.preferences.custom.eswEshopworldModuleEnabled)}" scope="page" />
<isif condition="${isEswEnabled}">
<isset name="eswHelper" value="${require('*/cartridge/scripts/helper/eswHelper').getEswHelper()}" scope="page" />
<isset name="formatMoney" value="${require('dw/util/StringUtils').formatMoney}" scope="page" />
<isset name="matchingLineItem" value="${eswHelper.getMatchingLineItem(lineItem)}" scope="page" />
<div class="strike-through <isif condition=${!lineItem.priceTotal.nonAdjustedPrice}>d-none</isif>">
<isif condition=${lineItem.priceTotal.nonAdjustedPrice}>
${formatMoney(lineItem.priceTotal.nonAdjustedPrice)}
</isif>
</div>
<div class="pricing line-item-total-price-amount item-total-${lineItem.id}">
<isif condition="${!empty(matchingLineItem)}">
${formatMoney(eswHelper.getSubtotalObject(matchingLineItem /* ... */))}
<iselse>
${lineItem.priceTotal.price}
</isif>
</div>
<iselse>
<div class="strike-through <isif condition=${!lineItem.priceTotal.nonAdjustedPrice}>d-none</isif>">
${lineItem.priceTotal.nonAdjustedPrice}
</div>
<div class="pricing line-item-total-price-amount item-total-${lineItem.id}">
${lineItem.priceTotal.price}
</div>
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/components/header/mobileCountrySelector.isml
Description
Mobile country selector integrates ESW header bar when enabled; otherwise renders standard locale dropdown.
<isset name="isEswEnabled" value="${!empty(dw.system.Site.current.preferences.custom.eswEshopworldModuleEnabled)}" scope="page" />
<isif condition="${!isEswEnabled && pdict.localeModel.locale.localeLinks}">
<li class="menu-item dropdown country-selector d-md-none" data-url="...">
<span class="btn dropdown-toggle" id="dropdownCountrySelector">
<i class="flag-icon flag-icon-${pdict.localeModel.locale.country}"></i>
${pdict.localeModel.locale.displayName}
</span>
<div class="dropdown-menu dropdown-country-selector" aria-label="...">
<isloop items="${pdict.localeModel.locale.localeLinks}" var="localeLink">
<a class="dropdown-item" href="${'#'}" data-locale="${localeLink.locale}">
<i class="flag-icon flag-icon-${localeLink.country}"></i>
${localeLink.displayName}
</a>
</isloop>
</div>
</li>
</isif>
<isif condition="${isEswEnabled && eswHelper.getEnableHeaderBar()}">
<li class="menu-item dropdown country-selector d-md-none">
<isinclude url="${URLUtils.url('EShopWorld-GetEswHeader')}"/>
</li>
</isif>
File Path
int_eshopworld_sfra/cartridge/templates/default/product/bundleDetails.isml
Description
Bundle PDP template referenced; includes modules include (toolkit off).
<isinclude template="/components/modules" sf-toolkit="off" />
File Path
int_eshopworld_sfra/cartridge/templates/default/product/setDetails.isml
Description
Set PDP includes return-prohibited message content asset.
<div class="esw-display-return-prohibited-message <isif condition='${!pdict.product.isReturnProhibited}'>d-none</isif>">
<iscontentasset aid="esw-display-return-prohibited-message" />
</div>
Controllers
File Path
int_eshopworld_sfra/cartridge/controllers/Page.js
Description
SFRA controller referenced as an ESW customization touchpoint.
File Path
int_eshopworld_sfra/cartridge/controllers/Cart.js
Description
SFRA controller referenced as an ESW customization touchpoint.
File Path
int_eshopworld_sfra/cartridge/controllers/Checkout.js
Description
SFRA controller referenced as an ESW customization touchpoint.
File Path
int_eshopworld_sfra/cartridge/controllers/Tile.js
Description
SFRA controller referenced as an ESW customization touchpoint.
Models
File Path
int_eshopworld_sfra/cartridge/models/productLineItem/decorators/priceTotal.js
Description
Line item price decorator adds ESW-aware non-adjusted/adjusted pricing logic (order history vs live basket).
var eswHelper = require('*/cartridge/scripts/helper/eswSFRAHelper');
var orderHistoryFlag = false;
var eswShopperCurrencyCode = null;
var eswModuleEnabled = eswHelper.getEShopWorldModuleEnabled();
if (lineItem.lineItemCtnr && Object.hasOwnProperty.call(lineItem.lineItemCtnr, 'orderNo')) {
if (lineItem.lineItemCtnr.orderNo != null) {
orderHistoryFlag = true;
eswShopperCurrencyCode = lineItem.lineItemCtnr.originalOrder.custom.eswShopperCurrencyCode;
}
}
if (lineItem.priceAdjustments.getLength() > 0) {
if (orderHistoryFlag) {
result.nonAdjustedPrice = (eswShopperCurrencyCode != null) ? /* ... */ : /* ... */;
} else {
var nonAdjustedPrice = (eswModuleEnabled) ? eswHelper.getMoneyObject(/* ... */) : /* ... */;
result.nonAdjustedPrice = (eswModuleEnabled) ? new Money(nonAdjustedPrice) : /* ... */;
}
}
if (!orderHistoryFlag) {
price = lineItem.adjustedPrice;
// The platform does not include prices for selected option value price by default.
// So, we must add the option price to get the ...
collections.forEach(lineItem.optionProductLineItems, function (item) {
price = price.add(item.adjustedNetPrice);
});
}
File Path
int_eshopworld_sfra/cartridge/models/product/decorators/searchPrice.js
Description
Search/listing price decorator outputs ESW-formatted prices (handles quantity, history orders, and option prices).
var eswHelper = require('*/cartridge/scripts/helper/eswSFRAHelper');
// ...
if (lineItem.quantityValue !== 1) {
result.price = (eswModuleEnabled) ? formatMoney(eswHelper.get/* ... */) : /* ... */;
} else {
result.price = (eswModuleEnabled) ? formatMoney(eswHelper.get/* ... */) : /* ... */;
}
// ...
// If order placed using calculated price model
if (eswShopperCurrencyCode != null) {
price = new Number((lineItem.custom.eswShopperCurrencyItemPriceInfo /* ... */));
result.price = formatMoney(new dw.value.Money(price, eswShopperCurrencyCode));
} else {
price = lineItem.adjustedPrice;
// The platform does not include prices for selected option value price by default.
// So, we must add the option price to get ...
collections.forEach(lineItem.optionProductLineItems, function (item) {
price = price.add(item.adjustedPrice);
});
result.price = formatMoney(price);
}
File Path
int_eshopworld_sfra/cartridge/models/product/decorators/base.js
Description
Base product decorator sets applicable price books based on ESW enablement and override country mapping.
if (eswHelper.getEShopWorldModuleEnabled()) {
var arrPricebooks = [];
var overrideCountry = eswHelper.getOverrideCountry(eswHelper.getAvailableCountry());
if (overrideCountry != null && overrideCountry[0].priceBooks != null) {
overrideCountry[0].priceBooks.map(function (pricebookId) {
arrPricebooks.push(PriceBookMgr.getPriceBook(pricebookId));
});
PriceBookMgr.setApplicablePriceBooks(arrPricebooks);
}
} else if (currentApplicablePriceBooks && currentApplicablePriceBooks.length > 0) {
PriceBookMgr.setApplicablePriceBooks(currentApplicablePriceBooks.toArray());
} else {
PriceBookMgr.setApplicablePriceBooks();
}
File Path
int_eshopworld_sfra/cartridge/models/product/decorators/fullProduct.js
Description
Customization to models is extended to fullProduct.js (and other product models listed in the client section).
Scripts and JSON
File Path
modules/server/request.js
Description
Server request hook behavior: sets currency/locale normally when ESW disabled; sets ESW location when enabled.
var Site = require('dw/system/Site').getCurrent();
var eswEnabled = Site.getCustomPreferenceValue('eswEshopworldModuleEnabled');
var eswHelper = require('*/cartridge/scripts/helper/eswHelper').getEswHelper();
if (!eswEnabled) {
setCurrency(request, session);
} else {
var country = request.httpParameterMap.get(Site.getCustomPreferenceValue('eswCountryUrlParam'));
eswHelper.setLocation(country);
}
File Path
int_eshopworld_sfra/cartridge/scripts/hooks/taxes.js
Description
Tax hook file (must be included in hooks.json).
// (PDF note) You must include this file in your hooks.json file.
// Example logic shown includes checks like:
// if (empty(taxrate || taxrate == null)) { ... }
File Path
int_eshopworld_sfra/cartridge/scripts/hooks/validateBasket.js
Description
Basket validation hook: maps ESW failure flags to user-facing errors and clears privacy flags.
} else if (!empty(session.privacy.eswfail) && session.privacy.eswfail) {
result.error = true;
result.message = Resource.msg('cart.eswerror', 'esw', null);
delete session.privacy.eswfail;
} else if (!empty(session.privacy.eswProductRestricted) && session.privacy.eswProductRestricted) {
result.error = true;
result.message = Resource.msg('cart.esw.product.notavailable', 'esw', null);
delete session.privacy.eswProductRestricted;
}
File Path
int_eshopworld_sfra/cartridge/scripts/hooks/cart/calculate.js
Description
Cart calculate hook (must be included in hooks.json); prevents applying platform promotions during ESW order calculation.
// (PDF note) You must include this file in your hooks.json file.
var eswHelper = require('*/cartridge/scripts/helper/eswHelper').getEswHelper();
exports.calculate = function (basket, isESWOrderCalculate) {
// ...
if (!eswHelper.getEShopWorldModuleEnabled() || !isESWOrderCalculate) {
PromotionMgr.applyDiscounts(basket);
}
// ...
};
Client scripts
File Path
int_eshopworld_sfra/cartridge/client/default/js/product/detail.js
Description
Product detail page client script listed as extended customization surface.
File Path
int_eshopworld_sfra/cartridge/client/default/js/product/quickView.js
Description
Quick view client script listed as extended customization surface.
Description
The PDF states customization to the following models is extended:
fullProduct.jsproductTile.jsproductSet.jsproductBundle.jsdetail.jsquickView.jsdefault.jstotal.js