Scripting in ISML

Use full SFCC server-side scripting intelligence inside ISML expressions and isscript blocks, including dw.* types, pdict, loop variables, and importScript.

The headline capability of the ISML language server: templates are scripts too. Every ${ … } expression and every <isscript> block is analyzed by the same TypeScript-grade engine that powers .ds and .js files - so you get dw.* typing, completion, hover, and diagnostics inside your templates, not just tag highlighting.

How It Works

When the server analyzes a template it transpiles the ISML into an equivalent JavaScript view of the file: ${ … } expressions become expressions, <isset> and <isloop> become variable declarations, and <isscript> blocks are preserved verbatim. The offsets are kept aligned with the source, so completion and diagnostics land on the right characters in your actual .isml.

The transpiled view starts from a prelude that declares the variables SFCC makes ambient in every template, so they're always typed and in scope:

// Implicit prelude - present in every template's analysis
var Resource    = require('dw/web/Resource');
var URLUtils    = require('dw/web/URLUtils');
var StringUtils = require('dw/util/StringUtils');
var out         = new (require('dw/io/PrintWriter'))();
var L           = {};   // loop status (see <isloop> below)
var pdict       = new (require('dw/system/PipelineDictionary'))();

That means pdict, Resource, URLUtils, StringUtils, and out complete and type-check in any expression without you importing anything.

${ … } Expressions

Inside an expression you get full member completion, hover docs, and signature help - the same as in a script file.

<isprint value="${pdict.product.getName()}" />
<!--                ^ pdict typed, .product resolves, .getName() completes with dw.* docs -->

<a href="${URLUtils.url('Product-Show', 'pid', pdict.product.ID)}">
<!--        ^ URLUtils.url route + parameter completion -->

<isscript> Blocks

<isscript> blocks are preserved as real JavaScript and analyzed in place - write any cartridge logic and it behaves like a script file:

<isscript>
    var ProductMgr = require('dw/catalog/ProductMgr');
    var product = ProductMgr.getProduct(pdict.pid);   // typed dw.catalog.Product
    var price = product.getPriceModel().getPrice();
</isscript>
<isprint value="${price}" />

<isset> Variables

A <isset name="…"> becomes a variable declaration, so the name you define is tracked and completes in later expressions:

<isset name="displayPrice" value="${pdict.product.getPriceModel().getPrice()}" scope="page" />
<isprint value="${displayPrice}" />
<!--               ^ displayPrice is in scope and typed -->

<isloop> Variables and Status

The loop's var becomes a per-iteration variable, and the status object (first/last/count/index, etc.) is tracked through the loop-status model:

<isloop items="${pdict.products}" var="product" status="loopState">
    <div class="${loopState.first ? 'first' : ''}">
        <isprint value="${product.name}" />
        <!--             ^ product typed from the items collection -->
    </div>
</isloop>

importScript Inside ISML

Because <isscript> blocks are real script, importScript works in a template exactly as it does in a .ds file - it injects the imported script's top-level declarations into the global scope, so those symbols are then usable in the template's expressions.

<isscript>
    importScript('util/helpers.ds');   // injects formatMoney, TAX_RATE, … globally
</isscript>
<isprint value="${formatMoney(pdict.total)}" />
<!--               ^ formatMoney resolves, hovers, and navigates to helpers.ds -->

The injection and shadowing rules are identical to scripts - see Digital Script › importScript and Scope. Note that importScript lives inside an <isscript> block (it's a script statement), not in a bare ${ … } expression.

The Same dw API and Cartridge Model

Everything the script engine knows applies here too: the full dw.* API, your project's generated metadata types, and cartridge-aware require() resolution. See Types & the dw API and Module Resolution.

On this page