ISML Skill This skill guides you through creating and working with ISML (Isomorphic Markup Language) templates in Salesforce B2C Commerce. ISML templates combine HTML with dynamic server-side tags. Overview ISML templates are server-side templates that generate HTML. They use special tags prefixed with is and expressions in ${...} syntax to embed dynamic content. File Location Templates reside in the cartridge's templates directory: /my-cartridge /cartridge /templates /default # Default locale /product detail.isml tile.isml /home homepage.isml /util modules.isml # Custom tag definitions /fr_FR # French-specific templates /product detail.isml Essential Tags Conditional Logic < isif condition = " ${product.available} "
< span class = " in-stock "
In Stock </ span
< iselseif condition = " ${product.preorderable} "
< span class = " preorder "
Pre-order </ span
< iselse
< span class = " out-of-stock "
Out of Stock </ span
</ isif
Loops < isloop items = " ${products} " var = " product " status = " loopstate "
< div class = " product ${loopstate.odd ? 'odd' : 'even'} "
< span
${loopstate.count}. ${product.name} </ span
< isif condition = " ${loopstate.first} "
< span class = " badge "
Featured </ span
</ isif
</ div
</ isloop
Loop status properties: count - Iteration number (1-based) index - Current index (0-based) first - Boolean, true on first iteration last - Boolean, true on last iteration odd - Boolean, true on odd iterations even - Boolean, true on even iterations Variables
< isset name = " productName " value = " ${product.name} " scope = " page " />
< span
${productName} </ span
< isremove name = " productName " scope = " page " /> Scopes (required): page , request , session , pdict Output
< isprint value = " ${product.name} " />
< isprint value = " ${htmlContent} " encoding = " off " />
< isprint value = " ${price} " style = " CURRENCY " />
< isprint value = " ${order.creationDate} " style = " DATE_SHORT " /> Include Templates
< isinclude template = " product/components/price " />
< isinclude url = " ${URLUtils.url('Product-GetPrice', 'pid', product.ID)} " /> Decorator Pattern Base decorator (layouts/pagelayout.isml): <! DOCTYPE html
< html
< head
< title
${pdict.pageTitle} </ title
</ head
< body
< header
< isinclude template = " components/header " /> </ header
< main
< isreplace />
</ main
< footer
< isinclude template = " components/footer " /> </ footer
</ body
</ html
Page using decorator: < isdecorate template = " layouts/pagelayout "
< isslot id = " home-banner " context = " global " /> < div class = " homepage-content "
< h1
${pdict.welcomeMessage} </ h1
</ div
</ isdecorate
Expressions Expressions use ${...} syntax to embed dynamic values:
${product.name} ${product.price.sales.value}
${product.getAvailabilityModel().isInStock()}
${pdict.myVariable}
${session.customer.firstName}
${request.httpParameterMap.pid.stringValue}
${price > 100 ? 'expensive' : 'affordable'} ${firstName + ' ' + lastName} ${quantity * unitPrice} Built-in Utilities URLUtils
< a href = " ${URLUtils.url('Product-Show', 'pid', product.ID)} "
View </ a
< a href = " ${URLUtils.https('Account-Show')} "
My Account </ a
< img src = " ${URLUtils.staticURL('/images/logo.png')} " alt = " Logo " />
< a href = " ${URLUtils.abs('Home-Show')} "
Home </ a
Resource (Localization)
${Resource.msg('button.addtocart', 'product', null)}
${Resource.msgf('cart.items', 'cart', null, cartCount)} StringUtils
${StringUtils.truncate(description, 100, '...')}
${StringUtils.formatNumber(quantity, '###,###')} Custom Modules Define reusable custom tags in util/modules.isml :
< ismodule template = " components/productcard " name = " productcard " attribute = " product " attribute = " showPrice " attribute = " showRating " />
< isinclude template = " util/modules " /> < isproductcard product = " ${product} " showPrice = " ${true} " showRating = " ${true} " /> Component template (components/productcard.isml): < div class = " product-card "
< img src = " ${product.image.url} " alt = " ${product.name} " /> < h3
${product.name} </ h3
< isif condition = " ${pdict.showPrice} "
< span class = " price "
${product.price.sales.formatted} </ span
</ isif
< isif condition = " ${pdict.showRating && product.rating} "
< span class = " rating "
${product.rating} stars </ span
</ isif
</ div
Caching
< iscache type = " relative " hour = " 24 " />
< iscache type = " daily " hour = " 0 " minute = " 0 " />
<
iscache
type
=
"
relative
"
hour
=
"
1
"
varyby
=
"
price_promotion
"
/>
Place
< iscontent type = " text/html " charset = " UTF-8 " />
< iscontent type = " application/json " charset = " UTF-8 " />
< iscontent type = " application/xml " charset = " UTF-8 " /> Embedded Scripts < isscript
var ProductMgr = require('dw/catalog/ProductMgr'); var product = ProductMgr.getProduct(pdict.pid); var price = product.priceModel.price; </ isscript
< span
${price.toFormattedString()} </ span
Best Practice: Keep
blocks minimal. Move complex logic to controllers or helper scripts. Comments
< iscomment
<body>ISML comment - stripped from output. Use for documentation and hiding sensitive info. </ iscomment
Tag Location Constraints Not all ISML tags can be used anywhere. Important constraints: Tag Allowed Location
Must be before DOCTYPE declaration Must be before DOCTYPE declaration Only in