Using Template Resource Files For Labels in Commerce Cloud

It’s good practice to parameterize labels, rather than hard-coding them, so that they can localized easily. In SFCC, you define your labels in .properties files, and you can create separate files for each locale.

In this post, assume that your cartridge is called int_mycartridge. You would create your .properties file(s) in int_mycartridge/templates/resources:

/repo_root
+--int_mycartridge
   +--templates
      +--my_template_files.isml
      +--resources
         +--my_resource_file.properties

You can have more than one .properties file. The file naming convention for different locales is as follows:

  • my_resource_file.properties: Default locale file
  • my_resource_file_es.properties: Localization file for all Spanish (ES) locales
  • my_resource_file_es_ES.properties: Localization file for the es_ES (Spanish-Spain) locale

The file will look something like this, with one entry per line:

field.shipping.address.rut=Rol Unico Tributario

You can use your judgment as to the dot syntax – in the example above, which is for a checkout form, I followed the same pattern as other checkout fields.

Then, in either your ISML templates, you can reference the labels as follows:

<label>
${Resource.msg('field.shipping.address.rut', 'my_resource_file', 'Rol Unico Tributario')}:
</label>

Note that uses the Resource class. The second argument is the name of your .properties file (without the extension), and the third is the default text to show if the label couldn’t be found.

Forms
If you’re using SFRA’s declarative XML to define a form, complete with validation, then you will want to reference error messages in the definition XML, e.g.

<?xml version="1.0"?>
<form xmlns="http://www.demandware.com/xml/form/2008-04-19">
<field formid="regionCode" type="string" mandatory="true"
label="form.mycartridge.label.region"
missing-error="form.mycartridge.region.missing"
value-error="form.mycartridge.region.invalid"
parse-error="error.message.required"
regexp="(^[a-zA-Z0-9]+$)">
</field>

</form>

Note how this XML file references labels such as form.mycartridge.label.region. In this case, you simply need to define a resource file named forms.properties for the framework to locate your labels.

Using Custom Site Preferences in SFCC

This is a guide for creating custom site preferences for use with Salesforce Commerce Cloud. Site preferences let users of Business Manger (BM) define settings that are used in code. For information visit korucaredoula .

You can see available site preferences in Merchant Tools / Site Preferences / Custom Preferences. They are organized by groups (e.g. per cartridge).

Creating New Preferences
First create a group for your set of preferences in BM by going to Merchant Tools / Site Preferences / Custom Preferences and clicking New. If you simply need to add a new preference to an existing group, skip this step.

The next steps are a bit roundabout. Firstly, you have to go to Administration > Site Development > System Object Types, and select SitePreferences from the list. To add preference to your new group, for each one you’ll do the following:

  1. First create the attribute: Select the Attribute Definitions tab, click New, and define your new site preference (attribute), then click Apply. Use an ID that will be unique, since that will be the identifier you use for your preference in code.
  2. Then add it to your group: Go back to Site Preferences – Attribute Definitions, select the Attribute Grouping tab, find the group you created (it may be at the bottom of the list), and then click Edit. Search for your newly-created attribute, and click Add.

When you create the attribute, you can select the Value Type – boolean, string, date, enum, etc., and define options and select a default option, if applicable:

enum_options

Accessing Preferences in Code
Once you have defined your preference, you can access it in JavaScript like so:

var System = require('dw/system');
var site = System.Site.getCurrent();
var customPreferenceValue = site.getCustomPreferenceValue('myPreferenceID').getValue();

NOTE: If your preference has a simple type (e.g. string, boolean) just use site.getCustomPreferenceValue(‘myPreferenceID’) – you don’t need the getValue() method.

A tidy way to organize this is to have a helper file in your cartridge:

// FILE: int_mycartridge/cartridge/config/myCartridgePreferences.js
var System = require('dw/system');

function getPreferences() {
    var prefs = {};
    var site = System.Site.getCurrent();
    prefs.myPreferenceID = site.getCustomPreferenceValue('myPreferenceID').getValue();
    // ... other preferences
    return prefs;
}

module.exports = getPreferences();

… which you can then use in a JS file:

var prefs = require('~/cartridge/config/myCartridgePreferences');
// prefs.myPreferenceID is now available

… or an ISML template:

<isscript>
    var prefs = require('~/cartridge/config/myCartridgePreferences');
    // prefs.myPreferenceID is now available
</isscript>

Exporting Preferences
After manually setting-up your preferences in BM, export the XML files and store in your cartridge so that they are in source control. First you’ll need to export the meta data.

  1. Go to Administration > Site Development > Import & Export
  2. Click Export under Meta Data
  3. Choose System object type definitions and click Export
  4. Download the XML file locally

Next create the following file in your cartridge (assuming your cartridge’s folder is int_my_cartridge):

int_my_cartridge/metadata/meta/system-objecttype-extensions.xml

You’ll need to manually copy/paste just the content from the export that’s relevant to your file. It’ll look something like this, where “….” will have details about your attribute:

<?xml version="1.0" encoding="UTF-8"?>
<metadata xmlns="http://www.demandware.com/xml/impex/metadata/2006-10-31">
    <type-extension type-id="SitePreferences">
        <custom-attribute-definitions>
            <attribute-definition attribute-id="myPreferenceID">
                ....
            </attribute-definition>
            <attribute-group group-id="MyGroup">
                <display-name xml:lang="x-default">My Group</display-name>
                <attribute attribute-id="myPreferenceID"/>
            </attribute-group>
        </group-definitions>
    </type-extension>
</metadata>

Logging in Salesforce Commerce Cloud

I’ve been learning SFCC recently, and found that I was missing a simple guide for server logging, so I decided to write one.

Basic Usage
First you need to get a reference to a Log object, and then you issue log statements that are the level you want (debug, info, warn, error, fatal):

var Logger = require('dw/system/Logger');
var log = Logger.getLogger('my_category');
log.warn('createRequest call took {0}ms, which is more than the threshold of {1}ms', 999, 500);

By passing just one argument to getLogger(), you will be putting your log statements in the default location – more on that below.

Finding Log Entries
There are two ways to access logs, through Business Manager (BM), neither of which are immediately obvious:

  1. The log center
  2. The actual log files

The log center is accessed in Administration / Site Development / Development Setup, although it requires specific permissions:

logcenter

The other way is to access the log files directly – also via BM – in Administration / Site Development / Development Setup, then click on Folder Browser, and navigate to the Logs directory:

folder_browser

Log Files
If you initialize the log object with one argument (e.g. getLogger('my_category')), then you are specifying the category only, and the log entries will appear in a generic file. The file will be named something like customwarn-ecom-sandbox-SANDBOX-appserver-DATE.log where “warn” is the log level.

The category will appear in the log entry:

[2021-03-23 23:46:32.086 GMT] WARN PipelineCallServlet|212645572|SITE_NAME|CONTROLLER_NAME|PipelineCall|iEHTL3fGnn custom.my_category [] createRequest call took 999ms, which is more than the threshold of 500ms

You can add a second parameter when getting the log object, which will create a new log file. This may be useful if you are developing a cartridge and want all of that cartridge’s logging information stored in one place:

var log = Logger.getLogger('my_cartridge', 'my_category');

That will create a dedicated log file like so, in the same location as the other log files:

custom-my_cartridge-ecom-SANDBOX-ITENTIFIERS-DATE.log

Enabling Log Levels
The log level you want to use must be enabled in BM under Administration / Operations / Custom Log Settings, in the Custom Log Targets section:

enabled

If it’s not, then the log entries won’t appear.