Secure 2024: Forrester Wave™ Q2 2022 Showcases Leading Bot Management Solutions
Tech & Engineering Blog

11 Days of Salesforce Storefront Reference Architecture (SFRA) — Day 6: Using Services Framework

A common use case for cartridges is to retrieve data from outside sources, and our cartridge is no different. Today, we are going to add a random dad joke below our magic gif because, well, nothing captures the essence of magic like a good dad joke, does it?

Creating a Service

The Services Framework helps us manage calls to external web services and analyze their performance. It is a site-wide setting and is accessible from the Administration section of the Business Manager. A service definition, which is how we describe and set a service within the Services framework, usually consists of 3 parts: Credentials, Profile, and Service, however in some use cases, the credentials and/or profile parts can be omitted (we will see such a scenario on day 7).

Let’s go ahead and create our dad joke service:

  1. Open your Business Manager and navigate to Administration > Operations >Services.
  2. Click on the Credentials tab and then New.
  3. Credentials enable us to set the URL (and, if needed, authentication details) for our service. Set the URL to and name our credentials MagicCatridge.Dad.Credentials. Click Apply__ to save.**

New Service Credentials Screenshot icanhazdadjoke FTW!

Next, we will create a profile for our service. The profile enables us to configure connection related settings to our service, such as timeout and rate-limiting.

  1. Click on the Profiles tab and then New.
  2. Name the new profile MagicCartridge.Dad.Profile and set its connection timeout to 500. This will ensure that if we cannot connect to the service within 500ms, the connection will be dropped. Click Apply.

Finally, let’s create the service itself. Service is where we combine all of the settings for a service, such as its type, status (live/disabled), mode, etc.

  1. Click on the Services tab and then New.
  2. Set the following:
  3. Name the service MagicCartridge.Dad.Service.
  4. Check the Enabled checkbox.
  5. Set the profile to MagicCartridge.Dad.Profile .
  6. Set the credentials to MagicCartridge.Dad.Credentials .

Click Apply to save.

New Service Screenshot

Our new Dad service! ❤️

This concludes our dad joke service configuration. But since nothing uses it yet, it’s sitting all alone in the dark waiting for a purpose in life. We will fix this issue next.

Initializing the Dad Joke Service

Just like many things in life, before we can use our new dad joke service in the cartridge, we have to initialize it. All of our initialization logic will be handled in a single file, dadjokeservice.js, created under a services folder within our cartridge:

  1. cd to the root of the MagicCartridge folder (cd cartridges/magicCartridge/cartridge), and create a new folder named services.
  2. Inside the new services folder, create a new file called dadjokeservice.js and add the following content:
var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry');

var dadJokeAPIService = LocalServiceRegistry.createService('MagicCartridge.Dad.Service', {
    createRequest: function (svc, params) {
        svc.addHeader('Accept', 'application/json');
        return params;
    parseResponse: function (svc, httpClient) {
        var result;

        try {
            result = JSON.parse(httpClient.text);
        } catch (e) {
            result = httpClient.text;
        return result;

module.exports = {
    dadJokeAPIService: dadJokeAPIService

So what are we seeing here?

Line 1: Imports the LocalServiceRegistery module, which is the base class for creating services.

Line 3: Creates an instance of the MagicCartridge.Dad.Service we previously defined and saves it to the dadJokeAPIService variable.

Lines 4–8: Defines a createRequest method, which allows you to set different properties related to the service. In our example, we set the service method always to be GET (line 5) and to always have an Accept header of application/json (line 6). We end the method by returning the params object (line 7).

🐘 There are plenty of properties we can set on the svc object other then headers and method. Refer to Salesforce Commerce Cloud docs for more information.

Lines 9–18: Defines a parseResponse method, which allows you to get the raw response of the service call, and parse or manipulate it to your needs. In our example, we try to parse the service call response (httpClient.text) to JSON (line 13) and save that to the result variable. If we fail (for example, we got a bad response, etc.) we will save the raw service call response to the result variable (line 15). We end the method by returning the result variable (line 17).

Lines 21–23: Exports the dadJokeAPIService object.

Using the Dad Joke Service

To display the result of our service call using the Magic template, we have to call the service on the Magic controller and pass the result to the Magic template on the pipeline dictionary (pdict).

First, let’s modify our Magic.js controller to use the dad joke service:

var server = require('server');
var service = require('magicCartridge/cartridge/services/dadjokeservice');

server.get('Show', function (req, res, next) {
    var properties = {};
    var template = 'magic';

    var svcResult =;
    if (svcResult.status === 'OK') {
        properties.joke = svcResult.object.joke;

    res.render(template, properties);

module.exports = server.exports();

Can you spot the changes from yesterday’s version?

Line 2: Imports the Dad joke service and sets the service variable to reference it.

Line 5: Defines an empty properties object.

Line 8: Uses the service object’s call method to make the actual call to the service and store its result with the svcResult variable.

Lines 9–11: If the service call was successful, the svcResult’s object property will hold the JSON response from the service. This JSON response contains a joke property that holds the actual joke. We will save that property to a new property on our properties object called joke.

Line 13: Calls the render method of the res object, passing it the properties object we created on line 5. This object can later be used in an ISML template when it renders. To call this object in an ISML template we will use the pdict global object. We will see how to use pdict next.

Updating the Template

With all the backend stuff behind us, its time to update the Magic cartridge’s ISML template to actually display the joke.

  1. cd to the templates/default folder of our cartridge and open the magic.isml file.
  2. Change the code as follows:
<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">
    	.mainDiv {
    		margin:0 auto;
 		body {
 			background-color: <isprint value="${dw.system.Site.current.preferences.custom.MagicBackground}" encoding="htmlcontent"/>;
 		.jokeContainer {
 		.jokeContainer .emoji {
 			font-size: 50px;
 			margin-bottom: 2px;
 		.jokeContainer .joke {
	<div class="mainDiv">
		<div style="width:100%;height:0;padding-bottom:92%;position:relative;"><iframe src="" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe></div><p><a href="">via GIPHY</a></p>
		<div class="jokeContainer">
			<p class="emoji">🤓</p>
			<p class="joke">${pdict.joke}</p>

So what's changed from yesterday?

Lines 16–25: Adds 3 new CSS classes to be used for the dad joke display.

Lines 31–34: Adds the container and content of the joke. Notice the use of pdict at line 33 - it is the equivalent to the properties object we set on the render method above. That object had a joke key and, as such, so does pdict.

Go Wild 🌈

So now we have all the pieces in place let’s see how it renders:


ROTFL 🤣🤣🤣🤣

Every time you refresh the page, a call will be made to the dad joke service, grabbing a fresh (and hilarious) joke. That joke will then be stored in an object we pass to the render function, which is then used by the ISML template (via the pdict object) to render the joke!

With this, we can wrap up the Services framework for today. Tomorrow we will continue to tinker with Services framework and see how we can make it more dynamic.

As always, looking forward to your comments either here or on Twitter 😎