Tech & Engineering Blog

11 Days of Salesforce Storefront Reference Architecture (SFRA) — Day 11: Playing With Templates

Time flies when you’re having fun. Today is our last stop on the SFRA development train, and its an exciting one for sure! In today’s post, we will play around with ISML templates, or in other words, the visual representation layer of our storefront.

Let’s Talk About Cache, Baby

Templates are used a lot, but by default, they are not cached. That being said, there may be times where we want to cache the template for better performance. For cases like these, ISML comes to our aid with the iscache element. The iscache element should be placed at the top of the page and enables us to set cache on a template and configure it, using a number of properties, to suit our needs:

  • Status: A boolean flag that enables/disables page caching. Since caching is disabled by default, just the presence of the iscache tag implicitly enables page caching.
  • Type: A required property that sets the type of cache being used. The values for type can be either relative or daily, the former allows us to specify a period of time (in hours and minutes) for the page to be deleted from the cache, and the later allows us to specify a specific time in the day when the page will be deleted from the cache (eg. 3 am).
  • Hour: When the cache type is set to relative, the hour property represents the duration in hours before the page is cleared from the cache. When the cache type is set to daily, the property represents the hour of the day (in 24h format) when the cache will expire.
  • Minute: When the cache type is set to relative, the minute property represents the duration in minutes before the page is cleared from the cache. When the cache type is set to daily, the property represents the minute of the hour in the day when the cache will expire.

🐘 The iscache element has two additional properties which are beyond the scope of this post: varyby and if. If you like to learn more about them, head over to the official SFCC documentation.

Go Wild 🌈

Consider the following tag:

<iscache status="on" type="relative" minute="15"/>

This will cache the page for a period of 15 minutes (notice the use of relative and minute here).

Another example would be:

<iscache status="on" type="daily" hour="21" minute="30"/>

This tag uses the daily type, which means that the hour and minute properties represent an hour in the day (9:30pm in this case).

A JSON Response

Not all templates have to be visual. There may come a time when you would like to return a JSON object as your response (for example, an API route). Up until now we only used res.render to render our responses to the client, however res has another card up its sleeve: res.json. Using res.json allows us to render a JSON object directly, without the need to add any ISML templates or set the content type of the response.

On the Magic controller (located in our Magic cartridge controllers folder) add the following route:

server.get('Json',  function (req, res, next) {
	var svcResult =;
    if (svcResult.status === 'OK') {
    } else {


The code looks similar to our Show method, but instead of rendering it on the page, we render the response from the icanhazdadjoke service directly on the page using res.json!

Go Wild 🌈

If you navigate to the /Magic-Json route (don't remember the full URL? head back to Day 4 to refresh your memory) and you should see something like this:

Magic Json

Our joke JSON in all its glory! 🎉

Overcoming the Language Barrier

Internationalization is another important concept for our storefront, as it allows us to provide content to visitors in more than one language. ISML templates support this concept using a feature called properties files. So what are these magical files? Well, nothing more than a dictionary of key/value of text really. Let’s create a new template on our Magic cartridge called hello.isml that initially have the following content:

<iscontent type="text/html" charset="UTF-8" compact="true"/>
<!doctype html>
	<meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<h1>Welcome to Our Storefront!</h1>
	<p>Please have a look around and contact us with any question.</p>

As you can see, it’s a pretty basic (and ugly) template that shows a header and some text. Now, this text only caters to an English speaking audience, but what if we want to show a visitor whose browser language is Spanish the same text in his native language?

If you look closely at the templates folder of our cartridge, you’ll notice a folder called resources. As the name suggests, this folder holds the resources (or language) files for our template. Let’s create a default language (a.k.a properties) file in the folder that will hold the English text. Create a new file called inside the resources folder with the following content:

hello.template.header=Welcome to Our Storefront!
hello.template.text=Please have a look around and contact us with any question.

This is the same text as we had hardcoded on the hello.isml template just a moment ago. Let’s update our template to actually use the properties file:

<iscontent type="text/html" charset="UTF-8" compact="true"/>
<!doctype html>
	<meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

So what do we have here?

Line 9: We replaced the hardcoded text with the msg method of the Resources object in order to display the text from a resource file. The method takes three arguments:

  1. The key to the text we wish to display.
  2. The name of the properties file to use.
  3. The default value to display. In this example, I left it as null.

Go Wild 🌈

If you browse to a route that uses this template you will see it just like before:

Storefront Now, let’s add another file named in the resources folder:

Thank you, Google Translate!

And that's it! if a Spanish speaking visitor comes to our site, he will see the translated text:


You can have as many properties files as you wish to support different languages. There is virtually no limit to the internalization you can have on your storefront.


This brings our journey with SFRA to its final destination. I hope I managed to show you at least one cool aspect of the SFCC platform you didn't know before, and as always please contact me with any comments or suggestions either here or on Twitter. I look forward to hearing which day was your favorite 😎