Web Components · PDP
PDPPlaceholderEngine
A small templating engine exposed as window.PDPPlaceholderEngine. Renders {{path.to.value}} placeholders inside arbitrary strings — with array indexing, conditionals, defaults, and built-in filters. Used by <mmm-pdp-placeholder-integration> and any data-pdp-render elements on the page.
Overview
Unlike every other entry in the PDP family, this is not a custom element. It is a JavaScript class registered as a global. Use it to evaluate template strings against product data — useful for SEO descriptions, social-share captions, schema.org JSON-LD, dynamic alt-text.
Features:
- Nested property access —
{{product.productInfo.name}} - Array indexing —
{{product.productInfo.media[0].src.full}} - Array helpers —
.length,first,last,join - Conditional rendering —
{{product.available ? "In Stock" : "Out of Stock"}} - Default values —
{{product.description || "No description"}} - Filters / formatters —
{{price | currency}} - Custom filters via
registerFilter() - Safe property access — undefined paths return
""in default mode
When to use
- For dynamic alt-text, meta-descriptions, share captions on the PDP.
- To build dynamic JSON-LD schema.org product blocks.
- For ad-hoc string templates against any product-shaped object.
Quick start
<script src="https://v2-api-production.commmerce.com/api/v1/web-component/commmerce-sdk.js?store=sample-store"></script>
<script>
const engine = new window.PDPPlaceholderEngine({
product: { name: 'Classic Tee', price: 29 }
});
console.log(engine.render('Buy {{product.name}} for {{product.price | currency}}'));
/* → "Buy Classic Tee for ₹29" */
</script>Constructor
OptionTypeDefaultDescription
dataobject—Required. The data object to resolve {{paths}} against.options.prefixstring{{Opening delimiter for placeholders.options.suffixstring}}Closing delimiter for placeholders.options.filtersobject{}Map of name → fn custom filters. Merged with the built-ins.options.strictModebooleanfalseWhen true, throws on undefined paths. When false, returns empty string.Built-in filters
FilterSignatureExampleResult
currencycurrency(value, symbol = '₹'){{1234.5 | currency}}₹1,234.50uppercaseuppercase(value){{name | uppercase}}CLASSIC TEElowercaselowercase(value){{name | lowercase}}classic teetruncatetruncate(value, length=100, suffix='...'){{desc | truncate:20}}First 20 chars + "..."stripHtmlstripHtml(value){{html | stripHtml}}Plain text with tags removed.datedate(value, format='default'){{publishedAt | date}}Locale-formatted (en-IN) date string.jsonjson(value){{product | json}}Pretty-printed JSON.firstfirst(value){{media | first}}First array element.lastlast(value){{media | last}}Last array element.joinjoin(value, sep=', '){{tags | join}}Array joined with separator.defaultdefault(value, fallback=''){{description | default}}Pass-through with fallback.Methods
MethodReturnsDescriptionNotes
render(template)string—Replace every {{path}} in the template with its resolved value.renderDeep(obj)object—Recursively render every string value inside the object.getNestedValue(path)any—Read a value by dot-notation path. Used internally by render().registerFilter(name, fn)void—Register a custom filter. Filter function receives the value plus any arguments passed in the template.PDPPlaceholderEngine.getAvailablePlaceholders(data, root, maxDepth)string[]staticWalk the data and return all valid {{paths}} up to maxDepth — useful in editor UIs.Examples
1. Simple substitution
const engine = new window.PDPPlaceholderEngine({
product: { name: 'Classic Tee', price: 29 }
});
engine.render('{{product.name}} — ₹{{product.price}}');
/* → "Classic Tee — ₹29" */2. Conditional + default chain
engine.render(
'{{product.available ? "In stock" : "Sold out"}} — '
+ 'ships {{product.shippingNote || "in 3–5 days"}}'
);3. Custom filter
engine.registerFilter('rupees', (v) => '₹' + Number(v).toLocaleString('en-IN'));
engine.render('Pay {{product.price | rupees}}');
/* → "Pay ₹1,29,000" */