"Write ISML templates for B2C Commerce — <isprint>, <isif>, <isloop>, <isset>, <isinclude>, <isdecorate>, expression syntax ${pdict.*}, Resource.msg() localization, content slots, and template inheritance. Use when building B2C storefront templates."
Scanned 5/29/2026
Install to Claude Code
npx -y skills add OrcaQubits/agentic-commerce-skills-plugins --skill sf-b2c-isml --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Sf B2c Isml?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/orcaqubits-sf-b2c-isml)More formats (shields.io, HTML) on the badges page.
---
name: sf-b2c-isml
description: >
"Write ISML templates for B2C Commerce — <isprint>, <isif>, <isloop>,
<isset>, <isinclude>, <isdecorate>, expression syntax ${pdict.*},
Resource.msg() localization, content slots, and template inheritance. Use when
building B2C storefront templates."
---
# sf-b2c-isml
Build ISML (Internet Store Markup Language) templates for Salesforce B2C Commerce storefronts.
## Before Writing Code
**Fetch live documentation FIRST:**
- Search: "Salesforce B2C Commerce ISML reference 2026"
- Search: "B2C Commerce template best practices encoding modes"
- WebFetch: Official ISML tag reference from Salesforce docs
- WebFetch: Template best practices and encoding guidelines
**Why:** ISML syntax, tag attributes, encoding modes, and localization patterns evolve with each B2C Commerce release. Always verify current specs before generating template code.
## Conceptual Architecture
### ISML Key Tags
| Tag | Purpose | Key Attributes |
|-----|---------|----------------|
| `<isprint>` | Output with encoding | `value`, `encoding` (required for XSS safety) |
| `<isif>` / `<iselseif>` / `<iselse>` | Conditional rendering | `condition` |
| `<isloop>` | Iteration | `items`, `var`, `status`, `begin`, `end`, `step` |
| `<isset>` | Variable assignment | `name`, `value`, `scope` (page/request/session) |
| `<isinclude>` | Include partial template | `template` (path) or `url` (controller action) |
| `<isdecorate>` | Decorator/layout wrapper | `template` (decorator path) |
| `<isreplace>` | Insertion point in decorator | (no attributes) |
| `<isslot>` | Content slot | `id`, `context` (category/folder/global), `description` |
| `<iscache>` | Template-level caching | `type`, `hour`, `varyby` |
| `<isscript>` | Inline server-side JS | (use sparingly -- prefer controllers) |
| `<iscontent>` | Set content type/charset | `type`, `charset` |
| `<isstatus>` | Set HTTP status code | `code` |
| `<isredirect>` | Server-side redirect | `location` |
| `<iscomment>` | Server-side comment | (not rendered to client) |
### Encoding Modes for `<isprint>`
| Mode | Context | When to Use |
|------|---------|-------------|
| `htmlcontent` | HTML body text | Default for most output (de facto SFRA standard) |
| `htmlsinglequote` | Single-quoted HTML attributes | `<div title='...'>` |
| `htmldoublequote` | Double-quoted HTML attributes | `<div title="...">` |
| `htmlunquote` | Unquoted HTML attributes | Rarely needed; prefer quoted attributes |
| `jshtml` | JavaScript strings in HTML | `<script>var x = '...';</script>` |
| `jsattribute` | JS in HTML event attributes | `onclick="..."` |
| `jsonvalue` | JSON values | JSON data output |
| `uricomponent` | URL query parameters | Query string values |
| `uristrict` | Full URI encoding | Path segments |
| `xmlcontent` | XML body content | XML/RSS feeds |
| `off` | No encoding | Trusted content ONLY -- avoid in production |
Always specify encoding. Choose based on output context. Never use raw `${variable}` for user-controlled data without encoding.
### Expression Syntax
**Pipeline Dictionary (pdict):**
- `${pdict.variableName}` -- access controller-passed data (SFRA: from `res.render()`)
- In SFRA, `pdict` contains only what the controller explicitly passed
- Legacy SiteGenesis globals (CurrentSession, CurrentRequest, etc.) are NOT available in SFRA controllers
**Object Navigation:**
- `${pdict.product.name}` -- dot notation for nested properties
- `${pdict.basket.totalGrossPrice.value}` -- deep property access
- Null-safe: always check for null/undefined before accessing nested properties
**Operators:** Arithmetic (`+`, `-`, `*`, `/`, `%`), comparison (`==`, `!=`, `<`, `>`), logical (`&&`, `||`, `!`), ternary (`${cond ? a : b}`).
### `<isloop>` Status Object
| Property | Type | Description |
|----------|------|-------------|
| `first` | Boolean | True on first iteration |
| `last` | Boolean | True on last iteration |
| `count` | Number | Current iteration (1-based) |
| `index` | Number | Current iteration (0-based) |
Access via the `status` attribute: `<isloop items="${list}" var="item" status="loopstate">`, then use `${loopstate.first}`, `${loopstate.index}`, etc.
### `<isset>` Scope Rules
| Scope | Lifetime | Use Case |
|-------|----------|----------|
| `page` | Current template render | Temporary computation within a template |
| `request` | Current HTTP request | Share data across included templates |
| `session` | Current user session | Persist across requests (use sparingly) |
Default scope is `session` -- always specify scope explicitly to avoid unintended session pollution.
### Localization (Resource Bundles)
```isml
${Resource.msg('key', 'bundleName', 'Default')}
${Resource.msgf('key', 'bundle', 'Default {0}', param)}
```
Common bundles: `forms`, `common`, `error`, `product`. Always provide meaningful default values. Resource bundles are `.properties` files in `templates/resources/`.
### Decorator Pattern (Template Inheritance)
Decorators wrap child content via `<isdecorate>` and `<isreplace>`:
```isml
<!-- Child template -->
<isdecorate template="common/layout/page">
<h1>Page Content</h1>
<!-- replaces <isreplace /> in decorator -->
</isdecorate>
```
The decorator template defines shared layout (header, footer, `<head>`) and uses `<isreplace />` to mark where child content is inserted. Nested decorators are supported.
### Common Patterns
```isml
<!-- Pattern: product loop skeleton -->
<!-- Fetch live docs for loopstate properties -->
<isloop items="${pdict.products}" var="product" status="loopstate">
<isprint value="${product.name}" encoding="htmlcontent" />
</isloop>
```
```isml
<!-- Pattern: URL generation -->
<a href="${URLUtils.url('Product-Show', 'pid', product.ID)}">
<isprint value="${product.name}" encoding="htmlcontent" />
</a>
```
### URL Generation Helpers
| Method | Purpose |
|--------|---------|
| `URLUtils.url()` | Generate absolute URL for controller action |
| `URLUtils.https()` | Force HTTPS URL |
| `URLUtils.staticURL()` | URL to static asset in cartridge |
| `URLUtils.absURL()` | Absolute URL with full domain |
| `URLUtils.home()` | Homepage URL |
| `URLUtils.continueURL()` | Current request URL for form returns |
### Content Slots
Configured in Business Manager. Slots support HTML, products, categories, or content assets. Use descriptive IDs (`home-banner-top`, `category-promo-sidebar`) and set appropriate context (global, category, folder). Slot rendering can be cached separately from template caching.
### Platform Warnings
- `<isscript>` executes on the server and can access the full SFCC API -- keep logic minimal and move heavy processing to controllers or scripts.
- `<isset scope="session">` persists across requests -- avoid session bloat by defaulting to `page` scope.
- SFRA templates do NOT support SiteGenesis pipeline dictionary globals; only data from `res.render()` is available.
- Template-level `<iscache>` is separate from CDN caching; both must be configured correctly.
## Best Practices
### Security
- Always encode output with the correct mode for context.
- Never use `encoding="off"` unless input is fully trusted.
- Use CSRF tokens on all state-changing forms.
- Validate user input in controllers before passing to templates.
### Performance
- Minimize `<isscript>` blocks -- move logic to controllers or scripts.
- Use `<isset>` to compute expensive values once and reuse.
- Avoid deeply nested loops and conditionals.
- Use `<iscache>` for templates that do not change per request.
### Maintainability
- Use decorators for consistent page layout across templates.
- Extract reusable components into separate templates with `<isinclude>`.
- Externalize all user-facing strings to resource bundles for i18n.
- Follow naming convention: lowercase-hyphenated template names.
### Template Organization
| Directory | Contents |
|-----------|----------|
| `common/layout/` | Decorators (page, checkout, account) |
| `components/` | Shared partials (header, footer, navigation) |
| `product/` | Product display templates |
| `search/` | Search results templates |
| `account/` | Customer account templates |
| `cart/` | Cart and mini-cart templates |
| `checkout/` | Checkout flow templates |
---
Fetch the ISML tag reference, encoding mode documentation, and resource bundle guide for exact tag attributes, encoding behaviors, and localization APIs before implementing.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!