DEV101 StudentGuide 2 8 2017
DEV101 StudentGuide 2 8 2017
for Digital I
Student Guide
Table of Contents
About the Course ....................................................................................................................................... 5
Module 1: Getting Started ......................................................................................................................... 6
Lesson 1.1: Platform Review ................................................................................................................ 6
Lesson 1.2: SiteGenesis Overview ........................................................................................................ 8
Lesson 1.3: Site Configuration .............................................................................................................. 9
Module 2: UX Studio ................................................................................................................................ 13
Lesson 2.1: Creating a Workspace ...................................................................................................... 13
Lesson 2.2: Creating a Server Connection .......................................................................................... 14
Lesson 2.3: Commerce Cloud Digital Views ........................................................................................ 16
Module 3: Cartridges ................................................................................................................................ 18
Lesson 3.1: Cartridge Path .................................................................................................................. 18
Lesson 3.2: Cartridge Types ................................................................................................................ 19
Lesson 3.3: Creating a SiteGenesis Storefront Cartridge .................................................................... 21
Module 4: JavaScript Controllers ............................................................................................................. 23
Lesson 4.1: Introduction to JavaScript Controllers ............................................................................. 23
Lesson: Displaying a Product Using Script API .................................................................................... 27
Module 5: ISML ........................................................................................................................................ 31
Lesson 5.1: ISML Tags and Expressions .............................................................................................. 32
Lesson 5.2: Creating and Accessing Variables .................................................................................... 35
Lesson 5.3: Reusing Code in Templates ............................................................................................. 38
Lesson 5.4: Conditional Statements and Loops .................................................................................. 45
Module 6: Content Slots ........................................................................................................................... 50
Lesson 6.1: Creating & Configuring Content Slots .............................................................................. 50
Lesson 6.2: Using Content Link Functions .......................................................................................... 54
Module 7: Commerce Cloud Digital Script ............................................................................................... 59
Lesson 7.1: Commerce Cloud Digital Script API .................................................................................. 59
This course covers how to modify and customize the Commerce Cloud Digital
Description reference application, SiteGenesis, using core Digital programming concepts,
files, and scripting language.
Course Objectives
After completing this course, you will be able to:
▪ Create cartridges to add reusable functionality to a site.
▪ Use JavaScript controllers to add business logic to a site.
▪ Create reusable code using ISML templates.
▪ Use Commerce Cloud Digital Script in ISML templates and script files.
▪ Use content slots to improve the appearance and flexibility of a site.
▪ Use the Forms Framework to control the validation, rendering, and storing of consumer-entered
values.
Note: The focus of the course is to use JavaScript controllers for new site development. If you need to
use pipelines to maintain an existing site, notify your instructor—Appendix A. covers pipeline concepts.
Learning Objectives
After completing this module, you will be able to:
▪ Create a new empty site.
▪ Import a copy of SiteGenesis into a site and configure its settings.
Every Realm includes a Primary Instance Group (PIG) which includes three Commerce Cloud Digital
instances:
▪ Production – this is the live instance used as the actual eCommerce storefront.
▪ Staging – use this instance for configuration, data enrichment, data import, and uploading of code
to prepare it for testing in the Development instance. Through data replication you can move data
from the staging instance to either the development or the production instance.
▪ Development – developers use this instance to test processes without impacting the production
storefront (i.e. Product import feed)
Every Realm also includes a Secondary Instance Group (SIG) that has five sandboxes (but can
accommodate more). Developers use sandboxes to develop and test code. They are not as powerful as
PIG instances in terms of performance, memory, and storage. However, they have a smaller footprint.
Platform Tools: Business Manager
Both merchants and developers use Business Manager to manage administrative tasks. Every Digital
instance has a Business Manager portal. For example, a merchandiser would log into Business Manager
in the Staging instance.
Merchandisers use Business Manager to manage… Developers use Business Manager to manage…
▪ Site URLs
▪ Site Preferences
Deploying a Storefront
When you first log into Business Manager for a given instance, by default no storefront has been
deployed. You must either:
▪ Create a new empty site (which contains no data).
▪ Import an existing site, such as SiteGenesis.
Import the current version of the SiteGenesis package (read-only) as a sample site into every
Sandbox instance. Caution: Never Import SiteGenesis into a Primary Instance Group (PIG)
Instance.
▪ It is recommended that you import SiteGenesis into an empty sandbox before importing your
custom sites. The prevents you from overwriting existing attributes and data for the custom site.
After importing SiteGenesis, you can validate its behavior by comparing it to the site running on the
demo instance.
Knowledge Check
Enter item number from Column B that matches the item in Column A
Column A Column B
Module 2: UX Studio
Learning Objectives
After completing this module, you will be able to:
§ Use UX Studio to create a new workspace.
§ Set up a server connection.
§ Navigate the user interface.
Introduction
UX Studio is an Integrated Development Environment (IDE) used for programming for Commerce Cloud
Digital. It is a plugin built on the Eclipse open-source development platform (www.eclipse.org), which
many developers use to build Java applications. It is not necessary to know Java to use UX Studio.
§ Kepler - http://updates.demandware.com/uxstudio/4.3
§ Luna - http://updates.demandware.com/uxstudio/4.4
§ Mars - http://updates.demandware.com/uxstudio/4.5
§ Neon - http://updates.demandware.com/uxstudio/4.6
7. Provide a name for the URL.
8. Select Salesforce Commerce Cloud from the list. Click Next. At this point, Eclipse compares UX
Studio’s requirements with what is available to ensure compatibility. The Install Details dialog
displays.
9. Click Next. The Review Licenses dialog displays.
10. Select the license agreement radio button. Click Finish. The Installing Software dialog displays,
indicating the installation’s progress.
11. In the Security Warning dialog, click OK.
12. Select Yes when prompted to restart Eclipse.
UX Studio is now installed. You can now use the Digital Development perspective in the upper right
corner.
If you already have a workspace and need to create a new one:
1. From the main menu in UX Studio, select File > Switch Workspace > Other.
2. The Workspace Launcher dialog displays.
3. In the Workspace field, enter a new workspace name and location. Click OK.
4. UX Studio closes and reopens.
Note: You might receive a dialog that asks if you want to delete projects on the server not
matching the ones in your workspace. If you are the only one working on that instance (e.g. it’s
your personal sandbox), you can make that decision. However, if you are working on a
collaborative instance consult first with your colleagues.
Note: If you import cartridges before you have an active server connection or have failed to link a
cartridge to the server, perform the following steps to ensure that cartridges upload correctly:
§ Right-click the server connection and select Properties.
§ In the Properties dialog, select Project References. Then select every cartridge that you want
uploaded to the server connection. Click OK.
Knowledge Check
Question Answer
Module 3: Cartridges
Learning Objectives
After completing this module, you will be able to
§ Describe what a cartridge is, its directory structure, and its path in Business Manager.
§ Create an empty cartridge.
§ Create a new storefront cartridge.
Introduction
A cartridge is a directory structure that provides a flexible deployment mechanism for customized
functionality. It can contain many different types of files including: static files (CSS, JavaScript, etc.),
image files, etc. It also contains folders for Commerce Cloud Digital specific files, such as: scripts,
templates, and form definitions.
A cartridge is fully contained in one directory. Every cartridge has specific sub-directories where certain
file-types must be stored. For instance, you must store all Digital Script files in a scripts folder.
Note: UX Studio generates the required storefront.properties file when you create a new
cartridge.
training:storefront_core:storefront_controllers
Note: All names are case-sensitive and must match your cartridge name if they exist in Eclipse.
There should be no spaces between each item.
5. Click Apply.
Cartridge Use to build site-specific, re-usable functionality when there are multiple
sites in a production instance.
You may want to add a new cartridge when functionality is:
§ Generic: reusable code used in multiple sites.
§ An integration to an external system.
§ Specific to a localized site: CSS, images and resource files for a language-
specific site.
Business Manager See your Commerce Cloud Digital documentation for more information.
Extension Cartridge
Best Practices
§ Keep an original SiteGenesis cartridge in your project for comparison or refer to your demo
instance.
§ Use a storefront cartridge for common code that you intend to reuse in multiple sites:
<client>_core
§ Create cartridges for site-specific functionality that might overwrite the core: app_<site>
§ Place any integration code in a int_<site> cartridge.
Knowledge Check
You should create a new cartridge when you need to build generic functionality that
can be reused in many sites.
You can view a list of all files in a cartridge located on a Digital server from Business
Manager.
Learning Objectives
After completing this module, you will be able to:
§ Describe JavaScript controller usage
§ Create, execute and troubleshoot JavaScript controllers
The require keyword imports a class from the API package to be used in the code.
The guard exposes the function with a new name. In this case, the function start is exposed to the
URL with the name Start. It can also enforce an http method (In this case, it is exposing the function
with a get method).
The ISML object gives the control to ISML, which can display the results. You can use response object
directly to display the results as shown below but it is not recommended.
response.setContentType('text/html');
response.getWriter().println('<h1>Hello World from Javascript controllers!</h1>');
Ideally the output should be rendered through ISML which is the view (Just like HTML or JSP). Also to
pass the results to the ISML. Here is an example code to output the results to an isml named
demo.isml and passing a string message to the parameter myParameter to the ISML.
ISML.renderTemplate(
'demo.isml',
{
myParameter:”Message from Controllers”
}
);
The parameter myParameter gets loaded on a hashmap named pdict and can can be retrieved from
the ISML (demo.isml ) using the syntax shown below.
${pdict.myParameter}
More details about the pdict are coming later in this course.
/**
* A hello world controller. This file is in cartridge/controllers folder
* @module controllers JHelloWorld
*/
var guard = require('storefront_controllers/cartridge/scripts/guard');
var ISML = require('dw/template/ISML');
function start() {
};
exports.Start = guard.ensure(['get'], start);
7. Inside the function start, add the following code to render the control to ISML:
ISML.renderTemplate(
'helloworld1.isml', {
myParameteronISML:
"Hello from Controllers"
}
);
8. In the templates/default folder, create an ISML file named helloworld1.isml with the
following code in it. Note: pdict will be discussed later.
${pdict.myParameteronISML}
9. Execute the controller.
10. Navigate to the storefront.
11. At the end of the URL add /default/JHelloWorld-Start
12. Press <enter> to execute the controller.
Pipeline Dictionary to Global Variables
pdict is a hashmap on which key, object pairs can be loaded. However, there are some built in pdict
keys (variables) that provide access to the most commonly used objects, such as session and request.
JavaScript controllers can use alternatives to pdict keys. Here are some of them. The strikethroughs indicate
implicit packages or classes in JavaScript controllers.
pdict keys Alternatives
CurrentSession TopLevel.global.session
CurrentRequest TopLevel.global.request
CurrentCustomer TopLevel.global.customer
CurrentHttpParameterMap TopLevel.global.request.httpParameterMap
CurrentPageMetaData TopLevel.global.request.pageMetaData
CurrentForms TopLevel.global.session.forms
In other words, controllers have access to request, response, session,
customer objects if you have used the valid import or require statements. They also have access to
CurrentHttpParameterMap variable using request.httpParameterMap and
pageMetaData.
The goal of this activity is to display query parameters using JavaScript controllers.
function start() {
}
exports.Start = guard.ensure(['get'], start);
3. Use the require syntax to import ProductMgr class from dw.catalog package after the guard.
4. Inside the start() function, paste the following code to get the parameter pid from the URL.
6. Copy and paste the following code to forward the control to ISML.
if (product===null) {
ISML.renderTemplate(
'productnotfound.isml',
{
message:'product with id '+parameterId+' not found'
}
);
}
else{
ISML.renderTemplate(
'productfound.isml',
{
myProduct:product
}
);
}
Knowledge Check
Module 5: ISML
Learning Objectives
After completing this module, you will be able to:
§ Use ISML tags in templates, including: <isset>, <isinclude>, <isdecorate>, and conditional
tags.
§ Use local and remote includes in ISML.
Introduction
Internet Store Markup Language (ISML) templates are files with a .isml extension. They define how
data, tags, and page markup are transformed into HTML that is sent to the browser, using Cascading
Style Sheets (CSS) for page layout and styling.
Commerce Cloud Digital uses templates to generate dynamic HTML-based web pages for responses
sent back to the client. Templates are created using ISML tags and expressions.
When describing a Digital application using the Model-View-Controller (MVC) pattern, the Digital Script
API represents the model, templates represent the view, and the JavaScript controllers are the
controller.
Create an ISML Template
1. In UX Studio, select a cartridge in Navigator View. Select File > New > ISML Template. The Create
Template dialog displays.
2. In the parent folder field, enter the name of the folder where you want to store your template. If
the folder does not exist, it will be created.
3. In the Template name box, enter a name for your template. You do not need to enter the .isml
extension.
4. Click Finish.
Your new template opens in the ISML editor in UX Studio. This editor supports HTML and ISML system
tag auto-completions as shown.
<isremove>
Variable- Removes a variable
related
<isinclude>
Includes the contents of one template on the current template
<ismodule>
Include Declares a custom tag
<iscomponent>
Includes the output of a controller or pipeline on the current
page
<isscript>
Allows Commerce Cloud Digital Script execution inside
Scripting
templates
<isselect>
Forms Enhances the HTML <select> tag
<isprint>
Formats and encodes strings for output
Output <isslot>
Creates a content slot
<iscache>
Caches a page
<iscomment>
Adds comments
Others <isdecorate>
Reuses a template for page layout
<isreplace>
Replaces content inside a decorator template
<isactivedatahead>
Allows collection of active data from pages with a <head> tag
Active <isactivecontenthead>
Collects category context from a page for active data
Data collection
<isobject>
Collects specific object impressions/views dynamically
ISML Expressions
ISML Expressions are based on the Digital Script language. Since Digital Script implements the
ECMAScript standard, access to variables, methods, and objects is the same as using JavaScript.
ISML expressions are embedded inside ${…} to enable the ISML processor to interpret the expression
prior to executing an ISML tag or the rest of the page. ISML expressions provide access to data by using
dot notation. This example accesses a property of the Product object in the pipeline dictionary:
${pdict.myProduct.UUID}
The difference between this ISML expression and one used inside a pipeline node property (i.e.
decision node) is that in ISML you must specify the ${pdict.object.property} if you want to
access a value in the pipeline dictionary, whereas inside pipeline node properties the access to the
pdict is implicit and the ${} not used: i.e. Product.UUID .
ISML expressions can also access Digital Script classes and methods. Two packages are available
implicitly in ISML, so classes do not need to be fully qualified:
§ TopLevel package: session.getCustomer()
§ dw.web package: URLUtils.url(), URLUtils.webRoot()
TopLevel package has a class named global which is implied so doesn’t need to be in the
prefix.
Other access to classes and methods must be fully qualified:
${dw.system.Site.getCurrent().getName()}
Examples of ISML expressions:
${TopLevel.global.session.getCustomer().getProfile().getLastName()}
Since TopLevel package and global class are implicit, the previous code is equivalent to the following
code:
${session.getCustomer().getProfile().getLastName()}
You can replace the get method with properties. So the previous code example is equivalent the
following code:
${session.customer.profile.lastName}
${pdict.CurrentSession.customer.profile.lastName}
${pdict.CurrentCustomer.profile.lastName}
${dw.system.Site.getCurrent().getName()}
${dw.system.Site.current.name}
ISML expressions allow complex arithmetical, boolean, and string operations:
${pdict.myProduct.getLongDescription() != null}
This course covers the most frequently used tags: <isset>, <isinclude>, <isdecorate>,
<isloop> and the conditional tags <isif>, <iselseif>, and <iselse>
Note: Although there are some ISML tags that do not need a corresponding closing </> tag (i.e.: the
<isslot> tag), it is best practice to always use a closing tag.
<isredirect> tag
This tag can redirect the control to another pipeline and redirect can be permanent or temporary.
<isredirect location="${URLUtils.https('Account-Show')}"
permanent="true"/>
<isredirect location="${URLUtils.url('LoginPanel')}">
<isredirect location="${URLUtils.url('LoginPanel-Start')}"
permanent="false">
<iscomment> tag
This tag is used to write comments in the ISML. For example.
<iscomment> ....This is a comment....</iscomment>
<isprint> tag
This tag can print formatted output of a variable or an expression to the browser. In order to do so, it
uses built in styles or formatters. You can see the documentation for formatters. Examples using
isprint with styles:
<isprint value="${myMoney}" style="MONEY_LONG"/>
<isprint value="${myMoney}" style="MONEY_SHORT"/>
<isprint value="${myNumber}" style="DECIMAL"/>
<isprint value="${myNumber}" style="INTEGER"/>
<isprint value="${myDate}" style="DATE_LONG"/>
<isprint value="${myDate}" style="DATE_SHORT"/>
<isprint value="${myString}" encoding="off"/>
MONEY_LONG prints money with currency symbol e.g. $3,333.00
MONEY_SHORT prints money without the symbol e.g. 3,333.00
DECIMAL prints the value with two decimal places e.g. 3,455.35
INTEGER rounds of and prints only the integer portion e.g. 3,455
DATE_LONG prints date in the long format like Jul 24, 2016
DATE_SHORT prints date in the long format like 07/24/2016
encoding="off" prints strings containing HTML, for example:
<h1> Welcome to Developing for Digital I Class</h1> prints as:
Welcome to Developing for Digital I Class
Lesson 5.2: Creating and Accessing Variables
You can create and access your own custom variables in an ISML template by using the <isset> tag.
When using the <isset> tag, name and value are required attributes that must be assigned. The
default scope is session, so you must be careful to qualify your variables accordingly if you do not
want them.
Example:
<isset
name = "<name>"
value = "<expression>"
scope = "session"|"request"|"page"
>
Here are some examples of using isset tag and retrieving the variables back from the scope
session Scope
Scope Attribute
A variable’s scope attribute refers to its accessibility level, such as session, request, and page. It
is important to understand the scopes of a variable and which objects can access that variable at each
level. Listed are the scopes from widest to narrowest access.
Scope Description
Session Available through the whole customer session, even across multiple requests. Any
variable added to the session scope becomes a custom attribute of the session object.
Since it is not a standard attribute it must be accessed with the session.custom
qualifier:
${session.custom.myVar}
pdict A hashmap, the scope of which is the JavaScript controller itself. It can span across
multiple requests if there is a form displayed and submitted as a part of the JavaScript
controller.
Request Available through a single browser request-response cycle; it does not persist in
memory for a subsequent request. Typically, it has the same scope as the JavaScript
controller execution.
They are available via the request scope. Similar to session variables, you must prefix
request variables with a qualifier request.custom when accessing them:
${request.custom.myRequestVar}
Page Available only for a specific ISML page, and its locally included pages. Their scope is
limited to the current template, and any locally included templates. They are accessed
without a prefix:
${pageVar}
Slotcontent Available only in the rendering template for a content slot.
<isloop> Available only inside the loop.
variable
7. Modify the examples using boolean and string values (i.e., “${false}” and “Hello”).
8. Test the JavaScript controller again to see the new variable values.
9. Increment the variables using the following syntax:
"${request.custom.requestVar + 1}"
Tag Description
<isinclude> Embed an ISML template inside an invoking template. There are two types:
12. Local Include – include the code of one ISML template inside of another while
generating the page. All variables from the including template are available in
the included template, including page variables. SiteGenesis uses local includes
extensively.
13. Remote Include – include the output of another controller or pipeline inside of
an ISML template. This is used primarily for partial page caching. Note: Pipeline
dictionary and page variables from invoking template are not available in the
included template. The only variables available to a remotely included
JavaScript controller are session variables.
Note: Includes from another server are not supported.
<isdecorate> Decorate the enclosed content with the contents of the specified (decorator)
template. A decorator is an ISML template that has HTML, CSS, and the overall
page design.
<ismodule> Define your own ISML tags which can be used like any standard tags.
<iscomponent> Invokes a remote include. You can pass as many attributes as you want without
having to use the URLUtils methods.
Template 2:
(calendar.isml)
<h1>Included template</h1>
When the browser renders the template, the user will see:
My Template
Included template
Locally include one template into another
1. Open any ISML template.
2. In the ISML code, determine where you want to embed the locally included template.
3. Add the <isinclude> tag to the template.
4. Save the template.
5. To test, use your template in a JavaScript controller.
Remote Includes
Using a remote include in a template will invoke another controller or pipeline which returns HTML at
runtime. This example calls a pipeline without passing URL parameters:
Syntax
<isinclude url=”pipeline_url”/>
Example
<isinclude url="${URLUtils.url('Product-IncludeLastVisited')}" />
In this example, the dw.web.URLUtils url() method builds a site-specific URL for the Product-
IncludeLastVisited controller. This is a best practice since you should never hardcode a controller
URL since it would contain a specific server in it. Use the URLUtils methods instead.
Here is an example of passing URL parameters:
<isinclude url="${URLUtils.https('Product-
GetLowATSThreshold','productid','ETOTE','typeOfTV','Wide-screen')}"/>
The page generated by the invoked controller can be dynamic or it may come from cache.
You can also implement a remote include, via the <iscomponent> tag. It supports passing multiple
attributes.
<iscomponent
pipeline = <string> | <expression>
[locale = <string> | <expression> ]
[any number of additional arbitrarily named parameters]
/>
Example
<iscomponent pipeline="Product-GetLowATSThreshold" productid="ETOTE"
typeOfTV="Wide-screen"/>
Typically, the decorator template only uses one tag, <isreplace/>. However, you can use multiple
tags. If the decorator template uses multiple <isreplace/> tags, the content to be decorated will be
included for each <isreplace/> tag.
A typical use case is to decorate the content body with a header and footer.
Example:
<isdecorate template="decoratorFolder/pt_myDecorator">
...My content...to be decorated
</isdecorate>
Decorator Template (templates/default/decoratorFolder/pt_myDecorator.isml)
<html>
<head>…</head>
<body>
This contains Header/Banner/Menus etc.
<isreplace/>
This contains footer/Copyright notice etc.
</body>
<html>
Final generated page
<html>
<head>…</head>
<body>
This contains Header/Banner/Menus etc.
...My content...to be decorated
This contains footer/Copyright notice etc.
</body>
<html>
Using the <isdecorate> Tag
1. Open the ISML template that has the code you want to replace in a decorator. Add the
<isdecorate> tag around the code to include in a decorator.
<isdecorate template="[directory/]decoratorname">
Your code goes here.
</isdecorate>
2. Save the template.
3. Open the decorator template. If you are using a SiteGenesis template, the decorator templates
names start with pt_.
4. Find the location in the code where you want to use the <isreplace/> tag. Add the tag to the
template.
5. Test the page by calling the controller that uses the decorator template. For example, if the
decorator template is used by the Account-Show controller, type in the URL that will execute the
Account-Show controller.
<ismodule template="components/breadcrumbs"
name="breadcrumbs"
attribute="bctext1"
attribute="bcurl1"
attribute="bctext2"
attribute="bcurl2"
attribute="bctext3"
attribute="bcurl3"
/>
§ The ISML file which specifies what happens when the attributes are passed. See the code snippet
from inside breadcrumbs.isml:
<isinclude template=”util/modules”/>
<head>
…
</head>
<body>
…
<isbreadcrumbs bctext1=”…” bcurl1=”…”/>
</body>
</html>
Here is how it would be organized.
<isproducttile product="${pdict.myProduct}"/>
§ Use <isnext> to jump forward within a loop to the next list element of an iterator. This tag affects
only the iterator of the inner loop. If an iterator has already reached its last element, or an iterator
is empty when an <isnext> is processed, the loop is terminated instantly.
The full syntax for using the <isloop> tag is:
<isloop
iterator|items = "<expression>"
[ alias|var = "<var name>" ]
[ status = "<var name>" ]
[ begin = "<expression>" ]
[ end = "<expression>" ]
[ step = "<expression>" ]>
…do something in the loop using <var_name>…
</isloop>
Attribute Description
items Expression returning an object to iterate over. Attributes iterator and items can be used
(iterator) interchangeably.
var (alias) Name of the variable referencing the object in the iterative collection referenced in the
current iteration.
Status Name of the variable name referencing loop status object. The loop status is used to
query information such as the counter or whether it is the first item.
Begin Expression specifying a begin index for the loop. If the begin is greater than 0, the
<isloop> skips the first x items and starts looping at the begin index. If begin is smaller
than 0, the <isloop> is skipped.
End Expression specifying an end index (inclusive). If end is smaller than begin, the <isloop>
is skipped.
Step Expression specifying the step used to increase the index. If step is smaller than 1, 1 is
used as the step value.
Attribute Description
Index The current index into the set of items, while iterating.
First True, if this is the first item while iterating (count == 1).
For example, if the <isloop> tag declares a status=”loopstate” variable, then it is possible to
determine the first time the loop executes by using: <isif condition=”loopstate.first”>.
Another example of <isloop> tag is:
<isloop items="${order.object.shipments}" var="Shipment" status="loopState">
<isif condition="${loopState.count >= (pdict.OrderPagingModel.pageSize +
1)}">
<isbreak/>
</isif>
<isif condition="${loopState.count==0}">
<isnext/>
</isif>
${loopState.count}
${loopState.index}
${loopState.first}
${loopState.last}
${loopState.even}
${loopState.odd}
</isloop>
function start() {
var basket=BasketMgr.currentBasket;
/*use ISML to display basket on Basket. The rendered ISML should be
showBasket.isml (Use the quickcard section “Giving control to ISML” for
help*/
}
exports.Start = guard.ensure(['get'], start);
Knowledge Check
Question Answer
Learning Objectives
After completing this module, you will be able to:
§ Create content slots for products and images.
§ Use rendering templates with content slots.
§ Configure content slots.
Introduction
A content slot is an area on the page where a merchant defines content to display based on certain
qualifiers or rules.
A content slot is used to show different types of content:
§ One or many products selected by the merchant
§ Category attributes (images or other visual)
§ Content assets from the content library
§ Static HTML and images from the static library
To view a content slot, use the Storefront Toolkit > Content Information tool. Hover the mouse
pointer around the page to reveal where content slots exist and to access a link to the slot’s
configuration page in Business Manager.
There are several types of content slots:
§ Global slots can appear on any page.
§ Category slots appear on category-specific pages since they depend on the category ID.
§ Folder Slots – appear in content library folders dependent on the folder ID.
There are many rules that drive the appearance of a slot: marketing campaigns, ranks, AB tests,
customer groups, etc. Campaigns and A/B testing are out of the scope of this course.
Content Slots vs. Content Assets
Slots are controlled by campaigns: start/end dates, customer groups, source codes, coupons and rank
are qualifiers that affect the appearance of a slot. Content Assets are reusable elements that do not
have qualifiers. Content slots and content assets are managed in different areas within Business
Manager. Slots are a marketing tool, therefore configuration information for content slots reside in
Site > Online Marketing > Content Slots; content assets are in the Content module.
§ The developer inserts a <isslot> tag in a template in the location where the slot will appear.
§ The developer creates a rendering template for the slot that defines how the slot data is to be
presented.
§ The merchant creates a configuration for the slot in Business Manager.
Creating Content Slots - Developer Tasks
You create a content slot inside a template using the <isslot> tag. The tag must be located exactly
where it should appear on the page. Here are some examples of tag usage:
Global slot example:
<isslot id=”header_banner” description=”…” context=”global”/>
Category slot example:
<isslot id=”category_top_featured” context=”category” description=”…”
context-object=”${pdict.ProductSearchResult.category}”/>
Folder slot example:
<isslot id="fldr-landing-slotbanner" context="folder" description="Large
Folder Landing Banner"
context-object="${pdict.ContentSearchResult.folder}"/>
Whenever the template is saved, the new content slot automatically displays in the list of slots under
Site > Online Marketing > Content Slots (this occurs because Commerce Cloud Digital scans any
template for the use of the <isslot> tag).
Creating the Slot Rendering Template
The slot displays the type of content out of four possible types. The developer creates a rendering
template that takes into account the type of content, how many objects to display, plus any CSS styling
required for the slot.
The header_banner slot uses the htmlslotcontainer template as the rendering template:
<iscache type="relative" hour="24"/>
<div class="htmlslotcontainer">
<isif condition="${slotcontent != null}">
<isloop items="${slotcontent.content}"
var="markupText">
<isprint value="${markupText.markup}"
encoding="off"/>
</isloop>
</isif>
</div>
Using slotcontent and <isprint> in Rendering Templates
Every slot is rendered by a system pipeline inside the core cartridge: _SYSTEM_Slot-Render. You do
not have access to this pipeline. It uses the slot configuration that the merchant creates and provides
all the configuration information to the rendering template by means of the
TopLevel.global.slotcontent constant. Only slot rendering templates get data via this constant.
The rendering template code checks that the slotcontent is not empty:
<isif condition="${slotcontent != null}">
Then it loops through the slotcontent.content (the content provided for
the slot):
<isloop items="${slotcontent.content}" var="markupText">
<isprint value="${markupText.markup}" encoding="off"/>
</isloop>
Inside the loop the code uses the <isprint> tag:
<isprint value="${markupText.markup}" encoding="off"/>
Note: For more information on the <isprint> tag in detail, there is extensive documentation and
usage examples for it in SiteGenesis.
Using the encoding="off" setting enables the HTML snippet to be generated without encoding, so
that the browser renders it correctly.
3. Copy the found template from the storefront cartridge to the exact same location into your
cartridge.
4. Before the no-hits-footer div, add a global slot:
<isslot id="search-no-hits-banner"
description="recommendations banner for search no results page"
context="global" />
5. Study the htmlslotcontainer.isml rendering template that is used to render HTML-type slots.
Creating Content Slot Configurations - Merchant Tasks
Merchants create content slot configurations by navigating to Site > Online Marketing > Content Slots
and locating the specific slot that the developer created, e.g. header-banner. The merchant can
select an existing configuration or click New to create a new one.
The merchant selects the type of content, for example, Product or HTML. Different fields display
depending on the content type selected, for example:
§ For a Product content slot, the Product field displays and the merchant enters the IDs of the
products to be displayed. The merchant then selects one of the templates designed to display
products from the Template drop-down menu.
§ For an HTML content slot, an HTML text area displays and the merchant enters the HTML content.
The merchant then selects one of the templates designed to display HTML from the Template
drop-down menu.
The Template menu contains all possible rendering templates that are available in all cartridges in the
cartridge path for this content type. The SiteGenesis storefront cartridge comes with default templates
for every type of content. The templates are located in specially named folders that Business Manager
discovers by default (for example, slots/html for the HTML type).
Here is the directory structure for the slot rendering templates in the SiteGenesis storefront cartridge:
The merchant can choose to reuse an existing rendering template or use a new one as instructed by
the developer. This is why the collaboration between merchant and developer is important—without a
rendering template, there is no way to visualize the slot.
The merchant also provides a schedule for the slot. This is either the default schedule or based on a
marketing campaign.
Here is an example of a function that creates a hyperlink to the Page-Show controller passing cid=2-
day-shipping-popup in the query string:
href="$url('Page-Show', 'cid', '2-day-shipping-popup')$"
Knowledge Check
Question Answer
Demo: Create a Slot with a Rendering Template for a Vertical Carousel of Products
Create a content slot in the nohits.isml that displays some products selected by a merchant. The
components involved will be: a rendering template, a style sheet, an ISML that has the content slot and
finally an ISML to link to the style sheet.
1. Open the nohits.isml template in your cartridge. This is the page which shows up when the
product that the customer searches is not found.
2. Below the search-no-hits-banner slot, add another global slot: <isslot id="merchant-products"
description="content for search no results page" context="global"/>
3. Create a directory structure so that you have slots/product folder as follows.
training/cartridge/templates/default/slots/product
4. Copy the verticalcarousel.isml from storefront to exactly the same location in the
training cartridge. This is the rendering template that you are going to modify.
5. Rename this verticalcarousel.isml in the training cartridge to
verticalcarouselx4.isml
6. Modify the carousel to match the following code:
<iscontent type="text/html" charset="UTF-8" compact="true"/>
<iscache type="relative" minute="30" varyby="price_promotion"/>
<isinclude template="util/modules"/>
<h2>${Resource.msg('global.carousel.featuredproducts','locale',null)}</h2
>
<div id="vertical-carousel">
<ul>
<li>
<div class="productcarousel">
<isloop items="${slotcontent.content}" var="product" status="status" >
12. In Business Manager, select Site > SiteGenesis > Online Marketing> Content Slots.
13. Search for the merchant-products slot. Create a new slot configuration for this slot so that it
displays multiple products using the new verticalcarouselx4.isml rendering template. The
rendering template will have to be chosen from the training cartridge. Make sure that you add
some products rather than the HTML (unlike you did in one of the previous exercise).
14. Go to the storefront from Business Manager in the browser. Search for some non-existent product
like MyBestPants.
15. Verify that the nohits.isml shows both the previous banner and multiple products in a vertical
carousel.
Learning Objectives
After completing this module, you will be able to:
§ Describe the Commerce Cloud Digital Script syntax.
§ Describe the Digital Script API packages.
§ Use Digital Script in ISML.
§ Debug Digital Script in UX Studio.
§ Use the Resource API and resource bundles.
Introduction
Commerce Cloud Digital Script (Digital Script) is the server-side language used for coding in Commerce
Cloud Digital.
§ It is based on JavaScript, which is standardized as ECMAScript. It implements ECMA-262 and the
ECMA-357 standard, also known as ECMA for XML or E4X.
§ It supports all JavaScript language extensions by Mozilla known as JavaScript 1.7 as well as optional
type specification (from JavaScript 2.0/ECMA 4th edition proposal and ActionScript).
Use Commerce Cloud Digital Script to access data about the system, such as: products, catalogs, prices,
etc. You write Digital Script in controllers and in ISML templates for expressions or inside
<isscript> tags.
ISML
Each new Digital update includes a well-documented API. The Script is available under the Studio Help
menus. The ISML documentation is available in the Digital documentation.
Salesforce continually updates clients to the latest version. Deployments happen globally on Tuesday
and Thursday between 2 and 7 am local POD time. The current version number displays at the bottom
of the Business Manager screen and it corresponds to Year.Deployment, for example, version 17.4
represents the fourth deployment in 2017.
Salesforce provides access to Preview releases by updating sandboxes prior to updating the PIG
instances. This gives your organization an opportunity to test any new API updates and other
customizations on your site prior to using that update in production. For more information, refer to the
Global Release Process FAQ https://xchange.demandware.com/docs/DOC-1815.
The Global Release Process ensures that all Salesforce clients stay on the same version of code and that
updates containing defect corrections as well as new functionality can be applied uniformly with
minimal down time.
API Packages
The Digital Script API is organized in packages, just like Java. Unlike Java, inheritance is not possible
from these classes or packages when you create a script. You can only use the properties and methods
of these classes in your scripts.
In Commerce Cloud Digital Script, the TopLevel package is the default package. It is similar to
java.lang in Java. It does not need to be imported in scripts. It provides standard ECMAScript
classes and extensions, such as: Error, Date, Function, String, Math, Number, XML.
The TopLevel.global class contains many of the common constants, and properties used in scripts.
Some properties are: customer, request and session.
Note: In the following packages there are many classes that end with Mgr
(e.g., dw.catalog.ProductMgr. These classes retrieve instances of business objects related to the
package they belong to. For example, use ProductMgr.getProduct(String id) to get a product
using a unique identifier. The method returns a Product instance which you can use to find
information about the product. This pattern is repeated for all Managers.
Inside of the <isscript> tag you can fully qualify every class you want to use or you can import any
packages at the top of the script:
<isscript>
var CatalogMgr=require('dw.catalog.CatalogMgr'); get smart quotes out.
var siteCatalog = CatalogMgr.getSiteCatalog();
…
</isscript>
~ indicates the current cartridge from where the script is being invoked. If the script is invoked from
some other cartridge then the cartridge still has to be in the cartridge path and it has to be mention in
in the require statement as well.
*/
function start() {
var parameterId = request.httpParameterMap.pid.stringValue;;
//var product = ProductMgr.getProduct(parameterId);
var product=/* Use the quickcard section “Invoking a Script” again to invoke the
method on ProductFinder */
if (product==null) {
ISML.renderTemplate(
'productnotfound.isml',
{
Log:'product with id '+parameterId+' not found'
}
);
}
else{
ISML.renderTemplate(
'productfound.isml',
{
myProduct:product
}
);
}
}
exports.Start = guard.ensure(['get'], start);
4. If not done already, modify your productnotfound.isml template so that it displays the
contents of the Log as follows:
${pdict.Log}
5. Test your controller. Verify that the product name appears as before and check the error path as
well.
When debugging, it is possible to run the script debugger along with the pipeline debugger.
Exercise: Create a Script/Controller Debug Configuration
1. In UX Studio, find the menu to create debug configurations.
2. Double-click UX Studio: Script Debugger to create a new configuration.
3. Complete the dialog as follows. Click Select to select your server and site.
7. Refresh the controller's invocation on the browser to hit the breakpoint (F5).
8. The debugger stops at the breakpoint.
9. Debug the script.
10. Check the Variables window to determine the args that are coming into the execute()
function.
11. Use F5 to execute the line.
12. Study the output variable which has the product: it should not be null.
13. Execute through the end of the controller (F8). The product name should display in the browser.
14. Fix any errors that you may have found, or just continue.
15. Debug the controller again, but this time use an invalid product ID in the URL.
16. Change the product URL parameter on the browser to a non-existing product.
17. After the breakpoint, verify the output variable holding the product: it should be null in this
case.
18. Execute through the end of the controller.
The resource bundles contain key=value pairs where the key might be compound (key.subkey) and
the value is a hard-coded string that uses Java MessageFormat syntax to implement parameter
replacement. Bundles are stored in each cartridge within the /templates/resources directory.
Strings from the bundles are accessible to all ISML templates via the dw.web.Resource.msg(key :
String , bundleName : String , defaultMessage : String ) method:
Notice that the second parameter points to the account.properties file, which may be overridden
by another cartridge in the cartridge path. The null in the third parameter means that the key itself will
be used whenever that key is not found in any resource bundle. Instead of the null you can also show
a string to display on the storefront in case the key could not be found.
Another useful method is the dw.web.Resource.msgf(key : String , bundleName :
String , defaultMessage : String , args : Object ...). Using this method, you can
specify a key with placeholders which can be dynamically replaced by the parameters specified in the
args argument of the method. For example, this usage of the method:
${Resource.msgf('singleshipping.wishlist', 'checkout', null,
owners.get(addressKey).profile.firstName )}
will be paired with the following Java MessageFormat definition in the resource bundle to allow the
first name of the wishlist’s owner to show up as Stefan’s Wishlist:
singleshipping.wishlist={0}\'\'s Wishlist
Knowledge Check
Exercise: Use a Resource Bundle in the Commerce Cloud Digital Script in JavaScript Controller
Goal: Modify the GetProduct script and ISML to use an externalized string instead of a hardcoded
string.
1. Open controllers/JShowProduct.ds. Inside this controller, after checking if the product
is null, add the following line of code to pick up a string productnotfoundMsg from the
resource bundle named myBundle.properties:
var errorMsg=dw.web.Resource.msgf('productnotfoundMsg', 'myBundle', null,
parameterId);
2. Using the quickcard as a guide (section “Giving control to ISML”), edit the next line to use the ISML
to render the template productnotfound.isml and pass the JSON
code {message:errorMsg}.
3. Create a file /templates/resources/myBundle.properties with the following content
(create the folder structure if not already there).
productnotfoundMsg=The product with the id {0} is not found
14. Notice that the name of the product in ‘default’ language is ‘Laptop Briefcase with wheels (37L)’.
Change Select Language dropdown to ‘French’. The name entry will be now blank. Paste ‘Laptop
Briefcase avec des roues (37L)’ without quotes in the name. Click Apply.
15. In your isml that displays your product (productfound.isml), enter the following to print the
product name (remove the earlier text):
${Resource.msgf('productfoundMessage', 'myBundle',null, pdict.myProduct.name)}
18. Run the ShowProduct pipeline or JShowProduct controller with the parameter pid=P0048.
Your URL will be similar to:
https://studentXX.training-na02.dw.demandware.net/on/demandware.store/Sites-
SiteGenesis-Site/default/JShowProduct-Start?pid=P0048
Learning Objectives
After completing this module, you will be able to:
§ Describe the concepts and usage of the Commerce Cloud Digital Forms framework.
§ Create a new form and implement it in a pipeline.
Introduction
Commerce Cloud Digital provides tools to simplify form display and processing. Use the Digital Forms
framework to control how consumer-entered values are validated by the application, rendered in a
browser, and possibly stored on a server.
To use the DigitalForms framework, you need the following files:
§ An xml form to define and store the metadata
§ A pipeline or JS Controller that will validate and process the form
§ A properties file that contains externalized form labels and possible error messages
§ An ISML template that will display the form to the user
There are three objects that interact when working with Digital forms:
§ XML metadata file: located in the cartridge/forms/default directory. It describes the fields,
labels, validation rules and actions that apply when the field is used in an ISML template.
§ ISML template: it uses the form metadata fields and actions to show an HTML form to the user.
§ Object (optional): this object represents a single system or custom object in the pdict, and it can
be used to pre-fill the metadata file as well as to store submitted form data to the database.
Example
Given this form metadata XML file:
You can create this ISML template whose fields depend on the data from the form metadata.
Optionally, a pdict object containing data from the database can be bound to the form metadata file,
allowing it to be prefilled with data. This data would appear in the ISML template since it references
the form fields.
Element Description
form Required: top level tag that contains all other elements inside <form>…</form>
field Required: Defines data field with many attributes (see table below)
options Use as a child element inside a field to pre-fill multiple options like months, days, etc.
Option Use as a child element inside an options element to specify a single option
action Required: Defines a possible action the user might take on the form
Include Allows inclusion of one form metadata definition into another
List Allows inclusion of several items (i.e. collection of addresses) as a single field
Group Allows grouping of elements to be invalidated together
Attributes Description
formid Required: unique ID to identify the field for ISML templates and controllers.
Type Required: data type for field (see table below).
label Usually a key to an externalized string in the forms.properties resource
bundle.
description Description for field, might be used in tooltips.
min-length, Restricts the field length for data entry.
max-length
min, max Valid range for integer, number and dates.
range-error Message shown if value provided does not fall within the specified range.
regexp Regular expression for string fields: email, phone, zip code, etc.
parse-error Message shown when the data entered does not match the regex. Usually a
key to an externalized string.
mandatory Field is required via server-side validation when true.
missing-error Message shown if the primary key validation error is generated in a pipeline.
value-error Shown if an element is invalidated in a pipeline.
Binding Used to match field to a persistent object attribute.
Masked Specify # of characters to mask.
Format Format for display of dates, numbers, etc.
whitespace Specify whitespace handling (none or remove).
timezoned Optional flag for date objects (true or false).
default-value Pre-defines a value for a field.
checked-value Value when field is checked in a form.
unchecked- Value when field is unchecked in form.
value
You can modify the behavior of the <isinputfield> tag since it is a custom tag implemented in the
SiteGenesis cartridge.
The final requirement in the ISML template is to implement the button that matches the action in the
form metadata. For this, create a standard HTML button with a name attribute that points to a specific
action in the form metadata:
<input type="submit"
value="${Resource.msg('global.submit','locale',null)}"
name="${pdict.CurrentForms.newsletter.subscribe.htmlName}"/>
Knowledge Check
4.
Learning Objectives
After completing this module, you will be able to:
§ Define custom objects and create instances programmatically.
§ Use transactions to save the custom object in the database.
§ Implement custom logging to allow debugging and error messages to be written to logs.
Introduction
Previously, you created a simple form using an Interaction Continue Node. You validated the data
being submitted, but did not store the data permanently. Custom Objects (CO) enable the data to be
persistent.
Custom Objects extend the Commerce Cloud Digital data model. They are basically a new table in the
database where you specify the primary key and storage attributes (columns) that suit your business
needs.
Note: Always first consider if you can use a Digital System object (Product, Catalog, etc.) instead of
creating a custom object. Although you can create custom objects, they are best used to store static
data (like configuration parameters), not for uncontrolled amounts of data (like analytics). Custom
objects searches can be slow if the data is large. You should consider data growth and cleanup in your
Custom Objects. Commerce Cloud Digital Governance has quotas around custom object API usage and
data size which will be enforced in the future.
Custom Object Creation
You create custom objects at the organization level; therefore, they are available for use in all
storefronts within the organization. You use two Business Manager modules to define and manage
your custom objects:
§ Custom Object Definitions: facilitates naming, primary key and column specification. It is located in
Administration > Site Development.
§ Custom Object Editor: facilitates instance creation and editing. It is located in Site - <site> > Custom
Objects > Custom Object Editor.
When defining the Custom Object, specify the storage scope of the instances: site or organization.
§ Organization Custom Objects can be used by any site.
§ Site Custom Objects are created by one site and cannot be read by another.
The Custom Object type itself is always available to the entire organization. Also, you can specify if you
want Custom Object instances to be replicable. This means you can copy them from Staging to
Production during the replication process.
An example of Custom Object usage is a newsletter. Customers can sign up for it, but the platform
does not have a system table to support. These subscriptions are intended for export since the
platform should not be used for mass mailing campaigns. It is tempting to add the subscription data to
the Profile system object, but this would imply that only registered users would be able to sign up. To
enable anyone to get a newsletter, you need to define a Custom Object. This Custom Object should not
be replicable, since subscriptions created in staging should not be copied to Production.
You also need to consider how to clean up Custom Objects once they have been exported or after a
certain expiration period. This means the creation of a cleanup batch job that should run on a
schedule.
Custom Objects can also store configuration parameters to integrate with external systems, avoiding
the need to create multiple Site Preferences. These Custom Objects need to be replicable if the
settings made in Staging are suitable for Production.
You can either create custom objects using Business Manager or programmatically. Before you can
create a custom object instance you must first define the custom object data type in Business
Manager.
Creating a New Custom Object Type Using Business Manager
1. Log into Business Manager.
2. Select Administration > Site Development > Custom Object Definitions.
3. Click New to create a new Custom Object type.
4. Fill in the required fields for the Custom Object type:
ID: the unique ID of the object type. It cannot contain spaces.
§ Key Attribute: This is the unique key for the custom object type.
§ Data Replication: Specify whether the custom object type data will be replicable to other
instances.
§ Storage Scope: Specify whether the custom object type will be available for a site or for the
entire organization.
5. Click Apply. The Attribute Definitions and Attribute Grouping tabs become available.
6. Click the Attribute Definitions tab. Notice the default values created with your Custom Object type.
These values cannot be changed once they are created.
7. To create the attributes (values you wish to capture in the table), click New.
8. In the ID field, specify a unique name. In the Value Type drop-down, select the type of data being
entered for the attribute.
9. Click Apply.
10. Click the Back button to add another attribute.
11. When you are finished adding attribute definitions, create an Attribute Group. Click the Attribute
Grouping tab.
12. In the ID field, enter a name for your grouping. In the Name field, enter a name. Click Add.
13. Add field attributes to the group. Click the Edit link.
14. To the right of the ID field, click the ellipses to select field attributes.
15. Select the attributes you wish to add from the list by clicking in the checkbox next to each one.
Click Select.
You can now view, add, and edit new instances of the custom object type you just created in the
Custom Object Editor section.
Creating a New Custom Object Instance Manually Using Business Manager
1. In Business Manager, select the site for which you want to manage custom objects.
2. Select Custom Objects > Custom Object Editor. The Manage Custom Objects page display.
3. From the drop-down list, select the custom object type that you wish to manage.
4. To create a new custom object, click New.
5. Enter data in each of the required fields. Click Apply.
6. You have now created a custom object. Click the Back button to exit the custom object editor.
This creates an instance with a system-generated, unique PK. You could also use:
CustomObjectMgr.createCustomObject("NewsletterSubscription", args.email);
This assumes that the args.email value is a unique string every time a Custom Object is created.
Otherwise, a duplicate PK error occurs.
Database Transaction Handling
There are two approaches to database transaction handling in Commerce Cloud Digital:
§ Implicit – The script automatically starts the transaction and then commits or rolls back if
Commerce Cloud Digital determines it to be appropriate.
§ Explicit – the transaction is controlled in the script. The developer explicitly indicates in the code
when the transaction should begin, rollback, or commit.
To write to a custom log, you need to use the dw.system.Logger.getLogger() factory method.
This method creates a Logger object for a specified category:
var logger = Logger.getLogger("logFilePrefix","category" );
logger.debug("Input params received in pipelet
firstName: {0}\n lastName: {1}\n email: {2}",
args.firstName, args.lastName, args.email);
try
{
… do something…
}
catch (e)
{
logger.warn(“error description: {0}", e.causeMessage );
}
Use the Logger object to write a message for a specific severity level: Logger.error(String msg).
The message uses the Java MessageFormat API, so you can specify placeholders. Typically, these
messages are not localized since they are read internally by site administrators, but they can be.
Enabling Custom Logging
In order to write to log files, you need to enable Custom Log Settings:
1. In Business Manager, select Administration > Operations > Custom Log Settings.
2. Create a log category. Enter it in the field under a given severity. Click Add.
3. Enable the checkbox next to the log category where you want to write. Click Apply.
4. Click Log Debug to File to enable debug messages to be written to a log up to 10 megabytes.
Usually Debug and Info messages are written to memory only, and visible via the Request Log tool.
5. Run the pipeline you wish to debug.
6. In Business Manager, review the custom log file. Select Administration > Site Development >
Development Setup > Log Files.
7. Open the log file that was just created. Search for the file by date. The custom log file name is
similar to: customdebug-177.aaaq.demandware.net-appserverxxxx.log. However, if
you gave a prefix while creating the log, the file name starts with custom-<prefix name>
Knowledge Check
Custom objects are the only way to store custom data in Commerce Cloud Digital.
Learning Objectives
After completing this module, you will be able to:
§ Use data binding to pre-fill forms and update persistent data from the form.
§ Use an explicit transaction to commit changes to the database.
Because NewsletterSubscription is a Custom Object, you want to bind this form to have
firstName, lastName and email fields which are all custom attributes. Notice that the fields do
not have a lock icon (you added them as custom attributes of the Custom Object):
When the information is stored in a custom object in the code, you can manage that transaction
explicitly in the code using dw.system.Transaction. The following methods can then handle
the transaction.
Transaction.begin(..)
Transaction.commit(..)
Transaction.rollback(..)
Transactions can also be implicit. This means that the transactions will not have to be explicitly begun
or committed. They will be handled by the Commerce Cloud Digital. The following is an example code
for implicit transaction.
var txn = require('dw/system/Transaction');
txn.wrap(function(){
// work with business objects here
});
4. Just below these lines, use the require syntax to get CustomerObjectMgr form dw.object
package.s
5. Add the next line as:
var co=CustomObjectMgr./*invoke a method to create object from
NewsletterSubscription custom object type with the
newsletterForm.email.value as the primary key. */
Note: Follow the instruction in the comment to make the line fully executable and working (use
Script API as the guide if needed).
6. Use the copyTo method (use the quickcard section “Handling Forms”) to store newsletterForm
to the object created above.
7. Adjust newslettersuccessV2.isml to point to the controller JNewsletterV3.js.
8. Execute the JavaScript controller.
9. In Business Manager, select Merchant Tools > Custom Objects > Custom Object Editor. Determine
if the object was created.
Knowledge Check
Exercise: Store and Retrieve the Preferences using the JavaScript Controller JEditPreferences.js
Create a new JEditPreferences.js controller to pre-fill the form with the logged-in customer
preferences. Once the customer changes his/her preferences, save the data to the database.
Note: Perform Step 1-3 only if you have not so in the previous exercise.
1. Extend the Profile System Object.
1. In Business Manager, extend the Profile system object with the following custom attributes:
(Administration > Site Development > System Object Definitions)
2. interestApparel : Boolean
3. interestElectronics : Boolean
4. newsletter : Boolean
a. None of the attributes are mandatory.
b. Add them to an Attribute Group Preferences to view the settings later in the Customer area.
5. Modify the Content Asset that shows the Account Overview.
6. Login to your Storefront account (register as a new customer if you haven’t already).
a. On the account overview page, use the Storefront Toolkit > Content Information to locate the
account-landing content asset which is located in the middle of the page (or locate it
Business Manager).
b. In the account-landing asset, add a new list item that calls the JEditPreferences
pipeline. Use the $httpsUrl(JEditPreferences-Start)$ content link function to invoke
your pipeline (this syntax was covered in the Content Slot module):
<li>
<a title="View and modify items on your list or invite friends"
href="$httpsUrl(JEditPreferences-Start)$">
<i class="fa fa-bookmark"></i>
<h2>Preferences</h2>
<p>View and modify your preferences</p>
</a>
</li>
7. Edit the Form Metadata to add bindings and externalization of strings.
8. Open the preferences.xml form metadata file.
9. Externalize the keys in preferences.xml in templates/resources/forms.properties file for example:
forms.preferences.apparel=Are you interested in Apparel ?
Learning Objectives
After completing this module, you will be able to:
§ Learn about page caching
§ Use the JavaScript Controller Profiler
§ Replicate code and data in the Primary Instance Group (PIG).
Note: In the Business Manager, the JavaScript Controller Profiler is referred to as the Pipeline Profiler.
Introduction
Commerce Cloud Digital provides tools that you can use to improve site performance as well as
replicate code and data.
Note: The Developing for Digital II course provides additional information on this topic.
Parameter Description
type = Relative enables you to specify a certain period of time, in minutes and
"relative | daily" hours, after which the page will be deleted from the cache. Daily enables
you to specify an exact time when the page will be deleted from the cache.
hour = integer Indicates either the caching duration or the time of day. If the type
attribute is set to daily, the hour value must be an integer, ranging from
0 to 23. If type is set to relative, all integer values greater than 0 are
valid (the default value is 0, meaning either the page is never cleared from
the cache or only the minute attribute is relevant).
minute = integer Indicates either the caching duration or the time of day. If the type
attribute is set to daily, the minute value must be an integer ranging
from 0 to 59. If type is set to relative, all integer values greater than 0
are valid (the default value is 0, meaning either the page is never cleared
from the cache or only the hour attribute is relevant).
varyby= Enables you to mark a page as personalized: this does not mean that the
"price_promotion" page is unique for a person but rather that different versions of the same
page showing different prices, promotions, sorting rules or AB test
segments will be cached by Commerce Cloud Digital. For example, this
parameter is necessary for product pages since a customer belonging to a
customer group might get special promotions that other customer groups
don’t get. While the ISML template is the same, the generated pages vary,
and therefore caching every version of the page benefits performance. For
performance reasons, a page should only be marked with the varyby
property if the page is really personalized; otherwise, the performance
can unnecessarily degrade.
Frequently changing pages benefit from a shorter caching period. Stored pages are only invalidated
and a new one pulled from the application server if any of the following occur:
§ The defined caching time is exceeded.
§ A replication has been performed (with the exception of coupons and geolocation data).
§ An explicit page cache invalidation is triggered by a merchant in Business Manager.
As a best practice, disable page caching on sandboxes, development and staging environments in order
to see changes immediately. In Production caching is always on by default.
Portions of pages can be cached separately. You can assemble a page from snippets with different
caching attributes using remote includes. Each part:
§ Must be a result of a pipeline request to the application server.
§ Is included using the <isinclude url=""> or the <iscomponent pipeline=….> syntax.
§ Can have different cache times or no caching at all.
In general, do not cache pages that show buyer or session information.
These types of analytics are only collection on Production instances, not Sandboxes. In this example, it
reveals that the Home-Show controller (which generates the homepage) is not cached: the Caching
column shows red for all hits. If you see this trend in your analytic data, you may decide to alter the
caching settings or the caching interval.
Across Digital customers, the two critical metrics to focus on from a performance perspective are the
average response times of Search-Show and Product-Show controllers. These controllers are used
across all customers and are the main components of most pages on Digital installations.
§ For Search-Show the average response is 400ms. Customers should be <= to this value to be in a
good performance range.
§ For Product-Show the average response is 320ms-400ms. Customers should be <= to this value to
be in a good performance range.
Salesforce strongly recommends that you check analytics reports each week and after you make code
changes to track these metrics.
Page Level Caching
Once the <iscache> tag is added to an ISML template, the entire ISML page will be cached for the
time specified in the tag.
For example, the page shown will be cached for 1 hour and 30 minutes:
3. Create a new pipeline named Caching or a javaScript controller named JCaching to display
the above template.
4. Test the template in your SiteGenesis storefront. Refresh your page. Does the time change on
refresh?
5. Enable caching on your SiteGenesis site. Retest the template. You may need to wait a minute
before you see the page has been cached.
Partial Page Caching
Generally, a single page should not be cached completely. Some parts of the page should be cached,
while other parts should not be cached. In this case you need to use remote includes for every part
that has unique caching characteristics. Every remote include calls a different pipeline which generates
an ISML template, each template having (possibly) different page caching.
The syntax for a remote includes uses the URLUtils class to call a remote pipeline with optional
parameters appended:
<isinclude url="${URLUtils.url('Page-Include', 'cid',
'COOKIE_TEST')}">
You can also use the newer <iscomponent> tag to implement a remote include.]
Exercise: Use the Cache Information Tool
1. Browse the SiteGenesis home page.
2. Turn on Storefront Toolkit > Cache Information.
3. Study the cache information for the whole page.
4. Study the cache information for a content slot and open the template to see the cache settings.
5. Study the cache information for the Cart remote include. Why is this page not cached?
5. Click the link for that site where you want to capture data:
a. The pipeline profiler displays a high-level view of response times per script or pipeline, such as
hits, total time for a page to be generated, average time, etc.
b. Look for scripts with high average run times and high hits. These are the first areas to focus on
performance improve.
c. To view more detailed data for a specific script, click the script name.
6. Test the script or a different one again.
7. While the pipeline profiler runs you have access also to captured script data.
8. Turn off the profiler and analyze the results.
9. If you make modifications to the script, retest to verify if performance has improved.
UX Studio integrates with SVN for source management. To learn more about using SVN in UX Studio,
view our online webinar in XChange: http://xchange.demandware.com/docs/DOC-2667.
When a developer has tagged a new code version and is ready to upload the new code to staging,
he/she creates a new code version on Staging in Business Manager from Administration > Site
Development > Code Deployment page.
Next, the developer uploads custom cartridges with UX Studio or WebDAV client using 2-factor
authentication and tests the storefront in Staging. A rollback to a previous version is available.
For major code changes, it is recommended to use a sandbox for testing:
To test in a sandbox, export the site data to the global directory from staging and import it into your
sandbox using the Site Import/Export module in Business Manager.
When you need to test code metadata (site preferences, new attributes, etc.), the build engineer
replicates from Staging to Development:
This is also good practice for testing processes without impacting the production storefront (i.e.
Product import feed).
The last step in code replication is moving code from Staging to Production using Business Manager.
To replicate code from Staging to Development or Staging to Production:
1. Log into the Staging Business Manager with an account that has code replication permissions.
1. Select Administration > Replication > Code Replication.
2. Click New to create a new replication process.
3. From the Target drop-down menu, specify whether the replication process is to Development or
Production.
4. Select whether you want to process to run manually or automatically. Click Next.
5. Specify what type of replication you want:
1. Code Transfer & Activation: immediately activates the new code version.
d. Code Transfer: Only transfers the code.
2. Click Next.
3. Click Start to start the replication process. Click Create to add the replication process to the list.
4. If you selected the process to run manually, click Start to start the job from the list.
Data Replication has two phases:
§ Transfer – long running processes where data is copied from Staging into shadow tables and folders
on Production. No changes are shown in storefront.
§ Publishing – Very fast process. Changes in shadow tables and folders become active, the page
cache is purged, and the new version is shown in storefront.
After data has been replicated, a one-time rollback (undo) is possible. This reverses the data to the
state of the last successful replication.
To view the progress of a replication, monitor the staging logs on the staging and production instance.
Like code replication, you set up data replication in Business Manager. The process similar, except you
select the data that you want to replicate.
Just as code replication can only occur between Staging and Development or Staging and Production,
data replication is a one-way process from Staging to the other primary instances.
To replicate data from Staging to Development or Staging to Production:
1. Log into the Staging Business Manager with an account that has code replication permissions.
2. Select Administration > Replication > Data Replication.
3. Click New to create a new data replication process.
4. Specify the target for the data replication process: Development or Production.
5. Select whether you want to process to run manually or automatically. If automatically, specify the
date and time the process should run.
6. Specify when you want an email notification and who should receive it. Click Next.
7. At the next screen, specify what type of replication you want: Data Transfer & Publishing or Data
Transfer.
8. Expand the sites to select the site data you wish to replicate. Click Next.
9. Click Start to create and trigger the process immediately. Click Create to add the replication
process to the list. Click Cancel to go back to the list of replication processes without saving
anything.
10. If you clicked Create, to start the process, click Start from the list of processes.
Knowledge Check
Question Answer
2. What two caching types can be used when using the <iscache> tag?
Appendix A: Pipelines
Learning Objectives
After completing this module, you will be able to:
§ Describe what a pipeline is, the pipeline dictionary, and the elements in a pipeline.
§ Create a pipeline that includes: start, interaction, call, and jump.
§ Use pipelets within pipelines.
§ Execute and troubleshoot pipelines.
Note: In general, JavaScript controllers replace pipelines throughout Commerce Cloud Digital. If you
are creating a new site, Salesforce strongly recommends the use of JavaScript controllers. However, if
you are working with an existing site that has pipelines, it is important to understand how pipelines
work so that you can maintain and extend them if needed.
Cartridge Folder Structure
Cartridges can contain either controllers and pipelines or controllers alone. If you have
controllers and pipelines in the same cartridge, and they have the same name, the platform uses the
controller and not the pipeline. Even if they are in different cartridges and have the same name, the
platform uses the controller in the path and not the pipeline.
Pipeline Overview
A pipeline is a logical model of a particular business process, similar to a flow chart. UX Studio provides
a visual representation of the process within the Eclipse IDE. This example shows the Product-Show
pipeline that renders the product detail page on the SiteGenesis site.
Pipelines are stored in XML files in the file system, both locally and on the server. You define and store
pipelines within the context of a cartridge.
When the storefront application references a pipeline in a cartridge, it searches for the pipeline in the
cartridge path and uses the first one it finds. When a pipeline with the same name exists on two
cartridges, the first one found in the path is used. Therefore, use unique pipeline names to ensure that
the framework locates the correct pipeline.
There are many pipeline elements available.
Call Node Invoke a specified sub-pipeline. After the sub-pipeline execution, the
workflow returns to the calling pipeline.
Assign Node Assign values to new or existing Pipeline Dictionary entries, using up to 10
configured pairs of dictionary-input and dictionary-output values
Stop Node Terminate a sub-pipeline and calling pipelines; stops execution immediately.
Use in pipelines that execute a batch job.
Decision Node Evaluate a condition and navigate to a different branch in the pipeline.
Creating a Pipeline
A new pipeline needs at least one Start node and one Interaction Node. In UX Studio, when creating a
new pipeline, access the pipeline palette from the Pipeline Editor. Note: If the palette is not visible,
click the button on the upper-right corner of the editor.
Start Nodes
A pipeline may have multiple Start nodes, but each node must have a unique name. Every Start node is
the beginning of a specific logical branch within the pipeline. Configuration properties include:
§ Name: Used in pipeline calls.
§ Call mode: Specifies the accessibility of the pipeline from a browser.
§ Public: Can be called from the browser or from another pipeline.
§ Private: Can be called from another pipeline via Call or Jump Nodes.
§ Secure Connection Required:
§ False: Pipeline can be invoked with HTTP and HTTPS protocols.
§ True: Start node can only be accessed via secure (HTTPS) protocol.
Interaction Node
This node specifies the template to display in the browser. If the Dynamic Template is:
§ true: Template Expression must be a variable containing a template name. The template to be
called by an Interaction node is not always hard-coded in the node. Instead, the name can be
determined dynamically during runtime from the Pipeline Dictionary.
§ false: The template expression contains a path to the template under the templates/default
folder.
Transition Node
The transition node creates a transition between two nodes. To create a transition between two nodes
click and drag your mouse between two nodes in a pipeline.
To create a simple pipeline using a Start node and an Interaction node:
1. From UX Studio, click File > New > Pipeline. The Create Pipeline dialog displays.
2. Provide a name that describes its business purpose.
3. Click Finish.
4. From the palette, click and drag a Start node to the work area.
5. Click and drag an Interaction Node to the work area.
6. Hold your mouse pointer down over the white dot at the bottom of the Start Node. Drag-and-drop
your mouse pointer over to the white dot at the top of the Interaction Node. Release your mouse.
A Transition Node connects the two elements.
7. Click the Interaction Node twice (not double-click). This displays an ellipsis button next to the node.
8. Click the ellipsis button to select the template you wish to display with the Interaction node.
9. Select the template. Click OK.
10. Save the pipeline: CTRL+S.
3. Use the palette to drag a start node onto the pipeline editor. The name defaults to Start.
4. Drag an Interaction Node below the start node, and connect them with a Transition.
5. Create a template hello.isml that renders a simple HTML page with a “Hello World!” greeting:
<html>
<head>
<title>Hello</title>
</head>
<body>
Hello World!
</body>
</html>
6. In the pipeline’s Interaction node, specify the template name hello.isml in its properties.
7. Double-click the Interaction node to verify that it opens the hello.isml template.
8. Save both the pipeline and the template.
Executing a Pipeline
Execute pipelines from the browser via an HTTP(S) request or via Call or Jump Nodes. Note: If the
pipeline Start node is set as Private it can only be called via a Call or Jump node.
Calling a pipeline via a HTTP request requires the pipeline name and start node at the end of the
storefront URL: http://instance.realm.client.demandware.net/on/
demandware.store/Sites-YourSite-Site/default
You can also pass parameters via HTTP requests using this syntax:
To execute a public pipeline from the storefront:
1. Open your storefront in a browser window.
2. At the end of the URL add the default/ directory, then enter your pipeline name and start node
using the following syntax:
/Sites-SiteGenesis-Site/default/Hello-Start
3. To pass parameters, add a query string after the pipeline invocation:
Sites-SiteGenesis-Site/Default/Product-Show?pid=ETOTE
Call nodes and End nodes work together to process specific functionality in a pipeline.
Call Nodes
A Call node invokes a specified sub-pipeline. A sub-pipeline is a pipeline that is designed for reusability
and typically is defined as private, meaning that it cannot be invoked from a URL.
After the sub-pipeline executes, the workflow returns to the calling pipeline by means of an End node.
It behaves like a function call where the function might return one or multiple values.
A Call node requires only a Pipeline-Start node to invoke. You can provide this information as a fixed
configuration value or from a pipeline dictionary key.
End Nodes
An End node finishes the execution of the called sub-pipeline and returns a value equal to the End
node name. This name must be unique within the sub-pipeline and it may be used by the calling
pipeline to control flow after the call.
After the call, a transition from the Call node with the same name as the returned value is followed. In
the following example, if the CheckValue sub-pipeline returns a notEmpty value, then that transition is
followed on the Start pipeline. Additionally, a Call node is used to invoke another pipeline. At the end
of the execution of the called pipeline is a Decision node that checks whether a value called param has
been passed in a URL string. The End nodes return control back to the Call node.
To use a Call node with a Transition node:
1. In UX Studio, open the pipeline where you want to add the Call node.
2. Select the Call node from the palette and drag it over the transition node where you want it. Note:
Be sure the transition node turns red before you release the mouse.
3. Click the ellipsis next to the Call node.
4. Select the pipeline and start node you want to call using the Call node.
5. From the Called Pipeline dialog, select Show Pipelines from the drop-down. In the first field, enter
the name of the pipeline that you want to find. The lower boxes will populate with available
pipelines and Start nodes.
6. Click OK.
7. Add Interaction nodes that will display the proper isml template, depending on which value is
returned by the called pipeline.
8. Name the Transition nodes from the Call node according to the values returned by the End nodes in
the called pipeline.
Jump Nodes
A Jump node invokes a specified sub-pipeline. After the sub-pipeline’s execution, the workflow does
not return to the calling pipeline. It is the responsibility of the sub-pipeline to complete the task.
A Jump node requires:
§ The name of the pipeline to be jumped to
§ The name of the pipeline start node to be used
This information can be provided either:
§ As a fixed configuration value
Passing Parameters
You can pass parameters to the pipeline dictionary using a URL query string:
The parameters will be added to the CurrentHttpParameterMap object inside the pdict. You can
see the values stored in the pipeline dictionary when you run the pipeline debugger.
In this example, the CurrentHttpParameterMap is an object of type HttpParameterMap. It
contains (on this invocation) a single key called param, which in turn contains multiple values. One of
them is the stringValue, which contains the string ‘1234’. You could also use the intValue if you
wanted to use the integer value 1234 on a calculation.
Note: For more information on the different classes mentioned here, consult the Digital Script and
Pipeline APIs in the Help menu.
Pipeline Debugger
The Pipeline Debugger operates at the pipeline level, not at source code level. It provides step-by-step
tracking for pipeline execution and for examining the pipeline dictionary at runtime.
The Debugger requires a running Commerce Cloud Digital system and a properly configured Remote
Server connection. You also need to create a debug configuration before running the Debugger.
To execute the pipeline debugger properly, you need a pipeline with breakpoints set on at least one
node. When you launch a pipeline debugger, the breakpoint color changes from a semi-transparent
green to solid green:
5. In UX Studio, the execution stops at the breakpoint, as indicated by the vertical bars:
The Debug Perspective toolbar enables you to step through the pipeline. Or use the corresponding
keyboard shortcuts:
Exercise: Use the Debugger for a Pipeline
1. Create a pipeline debug configuration called Pipeline Debug.
2. Add a breakpoint on the Call-Start pipeline.
3. From the storefront, invoke the pipeline.
4. View the variables window when the debugger stops at the breakpoint.
5. Using the F5 key, step through the debugger. What are the values stored in the pdict?Rerun the
Call-Start pipeline but this time add a parameter at the end of the string:
/Call-Start?param=1234
6. Check the values of the CurrentHttpParameterMap after the Start Node.
7. Continue stepping thru the pipeline and observe changes in the pdict.
Pipelets
In this section, you will use the pipeline dictionary to print information to a page using Pipelets. A
pipelet executes an individual business function within a Digital pipeline. Pipelets are pre-coded pieces
of functionality provided by Salesforce, but you can also use other types of pipelets from the palette
such as:
§ Script: invoke a custom Digital script file
§ Eval: evaluate data in the Pipeline Dictionary
§ Assign: assign values to specific keys in the pdict
Commerce Cloud Digital Pipelets are available in UX Studio via the Pipelets view. They belong to the
bc_api cartridge, which downloada as part of the Digital API the first time you connect to a server.
There is a published API available under UX Studio Help menus or in the Commerce Cloud Digital
documentation.
Each Digital pipelet has documentation on its functionality, input and output parameters. You can see
this information in the Properties view when the pipelet is selected on the pipeline.
To access and use a Digital API pipelet:
1. In UX Studio, open or create the pipeline where you wish to add a pipelet.
2. Open the Pipelet view tab.
3. Drag and drop the pipelet onto the Transition node between the two nodes where you want the
pipelet to execute. Be sure the Transition node turns red when you hover your mouse pointer over
it. Otherwise, the pipelet will not be connected to the node.
4. Depending on the pipelet you are using, you will need to configure the pipelet for execution in the
Properties tab of the pipelet. In the example shown, a GetProduct pipelet creates a product object
by using a ProductID value. The value for the input comes from a stored variable in the pipeline
dictionary. The product object output will need a name value.
Undeclared Values
Declared Values
5. Save your pipeline.
Introduction
Simple Feed Integration loosely couples Commerce Cloud Digital and external systems by exchanging
files on a File Transfer Server. Simple Feed Integration supports the protocols WebDAV (HTTP and
HTTPS) and SFTP for the transfer with the File Transfer Server. WebDAV HTTP (no network layer
encryption) is meant for development/testing purposes only. When considering WebDAV HTTPS, note
that an SSL-certificate from a Digital accepted Certificate Authority (CA) needs to be installed at the File
Transfer Server. The list of accepted CAs is available at Commerce Cloud Digital’s Customer Central.
The File Transfer Server needs to be hosted by the customer or another 3rd party. Commerce Cloud
Digital does not offer hosting File Transfer Servers. The WebDAV access to certain folders on a Digital
instance cannot be used for that purpose.
The simple feed cartridges support the following integration flow:
File Format
The file format for the incoming and outgoing feeds is the standard Commerce Cloud Digital
import/export format. For XML files the schema definitions (XSD files) can be downloaded from
Customer Central. A good approach to create a sample file to set up the data as desired in Business
Manager, run an export from the Business Manager user interface, and use the exported file as a
template.
All import files can alternatively be provided in gzip format (not to be confused with zip). In that case
provide the file with extensions .xml.gz or .csv.gz at the File Transfer Server and adjust the file
matching rule. The validation and import processes automatically unzip the files during processing.
Simple Feed Cartridges
The two cartridges included in the Simple Feed integration are:
§ int_simplefeeds: Implementation of generic logic. Needs to be assigned to the storefront site
and the Business Manager site. Modification of the Custom_FeedJobs pipeline is necessary to
use the feed configuration custom object. Do not modify other code.
1. Technically an arbitrary number of schedules and feed configurations can be set up on a Commerce
Cloud Digital instance. Currently, however, it is not possible to tell the schedule what configuration
to use. Therefore, the only way to tie a schedule to a configuration is to use a unique pipeline start
node. The cartridge int_simplefeeds comes with a pipeline Custom_FeedJobs. There is a start
node StartDefault that reads the feed configuration with the ID Default. In this course, we
only cover start node and feed configuration. To set up additional configurations, add additional
parameters and reference those when setting up the schedules.
h. In most cases, the feed jobs are triggered by a pre-defined schedule (e.g. hourly, daily). It is also
possible to keep the schedule disabled and trigger it manually in Business Manager, or to
provide code that triggers the job with the RunJobNow pipelet.
i. To set up a new job schedule, in Business Manager select Administration > Operations > Job
Schedules. Create a new job, name it (e.g. CatalogUpdate), make sure the execution scope is
Sites, Pipeline is Custom_FeedJobs, Start node StartDefault.
j. On the Sites tab, select all storefront sites for which you want to execute the job. Note: You can
provide site specific feed job configurations.
k. On the Resources tab, specify all object types that your feed job will modify. The job framework
tries to acquire locks for these resources before the job starts, effectively avoiding parallel
execution with other import processes or data replication.
l. On the Notification tab, configure email addresses to receive job execution status emails.
Additionally, you can send more granular success and error emails by feed tasks. Configure
them with the task. Feed tasks can report temporary errors such as communication errors with
external systems as job failures to the job framework (on-temporary-error: FAIL). Here you can
define how to handle them: Continue as Scheduled, Retry, or Stop on Error.
m. In the Parameters tab, you can define a parameter for any resource you want to import into a
site.
n. Create Feed Job Configuration
o. A feed job configuration is stored in a site specific custom object and may contain multiple tasks
(e.g. DownloadAndImportCatalog and DownloadAndImportPriceBooks).
p. To create a feed job configuration, in Business Manager select Custom Objects > Custom
Object Editor. Create a new instance of Feed Job Configuration.
q. As ID provide the ID you previously used when creating a new instance of the
FeedJobConfiguration custom object (the identifier used in pipeline
Custom_FeedJobs-StartDefault > check the properties of the Script Node),
r. The file documentation/TasksXMLCatalogOnly.xml provides an example for TasksXML. It
lists all supported tasks and contains inline documentation. Derive project specific
configurations from that file by removing unneeded tasks and updating the information. It may
be sensible to have the same task (e.g. DownloadAndImportCatalog) multiple times in a
feed configuration if feeds from different sources or with different content are processed.
2. Testing
1. The structure of the XML for the custom object FeedJobConfiguration can be found in the
sample file TasksXML.xml in the documentation folder.
s. There are sample import files in the sampledata folder.
t. In most cases, the feed jobs are triggered by a pre-defined schedule (e.g. hourly, daily). It is also
possible to keep the schedule disabled and trigger it manually in Business Manager, or to
provide code that triggers the job with the RunJobNow pipelet.
Note: It is not advisable to expose the RunJobNow pipelet in a public pipeline as this could be
exploited to flood your job queue. If you must use this pipelet in the storefront, implement a custom
security mechanism so that only authorized requests can execute the pipelet.
cc. Check it. Select Administration > Site Development > Custom Object Definitions. Do you see a
Custom Object Type FeedJobConfiguration?
dd. Edit TasksXMLCatalogOnly.xml. The contents of this file becomes an attribute value of our
custom object, which the pipeline uses to determine the logic for importing our data.
ee. Open
C:\projects\training\cartridges\simplefeeds\documentation\ TasksXMLCatalogOnly.xml using
your favorite editor.
2. Refer to your specific student## instance.
<remote-folder-url>
https://mydisk.se/training/studentXX/
</remote-folder-url>
Note: This file is a simplified version of the TasksXML.xml file. It points to a specific, non-
DigitalWebDAV server, and performs only a catalog download and import.
4. Select SiteGenesis > Custom Object > Custom Object Editor. Create a new
FeedJobConfiguration object (not definition) with the following values for its attributes:
1. ID – catalogTest
2. From Email – your email
3. Tasks XML – copy the contents of
C:\projects\training\cartrides\simplefeeds\documentation\TasksXMLCat
alogOnly.xml to this field.
5. Create a job to test the catalog import.
1. In Business Manager, select Administration > Operations > Job Schedules.
1. Create a new schedule and name it CatalogUpdate.
2. Check Enabled.
3. Change the Execution Scope to Sites.
4. Set the pipeline to Custom_FeedJobs.
5. Start node to StartDefault.
6. Click Apply.
2. On the Sites tab, select the SiteGenesis site. Click Apply.
3. On the Resources tab, specify the catalog and product object types that your feed job will modify.
4. On the Notification tab:
1. Configure your email address to receive job execution status emails.
2. Check Enabled.
3. Click Apply.
4. On the Parameters tab, use the same ID as the parameter in the Script Node of the
Custom_FeedJobs-StartDefault pipeline (Check it, it is Jobid?). For Value, use the ID of the
instance of your FeedJobConfiguration (catalogTest) custom object.
5. Run the job:
1. Go to https://mydisk.se/training/student##/ to see the contents of the WebDAV server.
2. Verify that the remote WebDAV server directory referenced in the TasksXML is already populated
with test files from the C:\projects\simplefeeds\sampledata directory.
3. Test the job by running the feed job from Business Manager.
4. Verify if the job worked (your catalog imported).
1. Select Site > SiteGenesis > Products and Catalogs > Catalogs > Catalog > Cat1.
2. Check if Prod1 is assigned to it. Do you know where it came from?
From the WebDAV server … from Catalog_2008-03-11_20-49-12.xml perhaps.
Congratulations
This concludes Developing for Digital I. At this point, you should apply what you have learned to the
Digital platform in preparation for DEV101: Developing in Commerce Cloud Digital exam. Additionally,
you should further your knowledge and skills by taking the DEV201: Developing for Digital II course and
its associated certification.
Cartridges when Controllers are Used in Conjunction with Pipelines
Cartridges can contain either controllers and pipelines or controllers alone. Controllers must be
located in a controllers folder in the cartridge, at the same level as the Pipelines folder. If you have
controllers and pipelines in the same cartridge, and they have the same name, the platform uses the
controller and not the pipeline. Even if they are in different cartridges and have the same name, the
platform uses the controller in the path and not the pipeline.
Note: If your sub-pipeline is not named using JavaScript method naming conventions,
you must rename it to selectively override it. For example, if your subpipeline start node is named
1start, you must rename it before overriding it with a controller method, because the controller
method cannot have the same name and be a valid JavaScript method.
To create and deploy a new site using Business Manager in Salesforce Commerce Cloud, first log into Business Manager and navigate to Administration > Sites > Manage Sites. Click 'New' to create a new site, enter a site ID and name, select a default currency, and click 'Apply'. Once the site is created, import existing data or a reference site such as SiteGenesis for initial setup. SiteGenesis can be imported via Administration > Site Development > Site Import & Export. Then set up the site for specific needs, managing catalogs, products, preferences, and code through Business Manager . For deployment, data and code need to be replicated from the Staging to Production instance. For data replication, log into Staging, select Administration > Replication > Data Replication, set up the replication target to Production or Development, and initiate the process. For code, go to Administration > Replication > Code Replication in Staging, and specify the replication target. Start the replication process to move the site configuration live . Finally, configure site-specific settings like caching and indexing to ensure the site functions correctly ."}
Importing SiteGenesis into a Primary Instance Group (PIG) Instance is not recommended because it can overwrite existing attributes and data for custom sites. Instead, it should be imported into an empty sandbox first before importing custom sites to prevent such overwriting and ensure a clean installation that does not affect existing configurations .
A merchandiser using Business Manager can manage Products & Catalogs, Content, Marketing campaigns, Search settings, Customers, Site Analytics, Site URLs, Site Preferences, Code & Data Replication, Code Versioning, Site Development, Data Import/Export, and Global Preferences for all sites within an organization .
ISML expressions are structured using the Digital Script language syntax, based on ECMAScript standards, which allows access to objects, methods, and variables similar to JavaScript. These expressions are embedded inside `${}` to access properties of an object using dot notation, such as `${pdict.myProduct.UUID}`, where `pdict` is the pipeline dictionary that stores data . The purpose of ISML expressions in Commerce Cloud Digital applications is to dynamically retrieve and display data, such as product details, on web pages generated on the server-side, integrating seamlessly with HTML and other ISML tags to form the view in the Model-View-Controller (MVC) architecture used by Salesforce Commerce Cloud Digital . This allows for the dynamic rendering of web content based on application logic and business rules.
Developers can utilize ISML templates in Commerce Cloud Digital to dynamically create web pages by incorporating a variety of ISML tags and expressions within the templates. Key ISML tags include those for HTTP-related tasks such as <iscookie>, flow control like <isif> and <isloop>, and inclusion of template contents using <isinclude> and <iscomponent>. ISML expressions, embedded in ${...}, allow access to data and objects similar to JavaScript . The <isset> tag is used to create variables, and <isprint> formats strings for output, while <isdecorate> and <isreplace> manage content reuse and replacement within templates . JavaScript controllers complement ISML templates by handling business logic and interaction with data, which can then render results through ISML to maintain MVC architecture principles ."}
Creating a content slot within Commerce Cloud is significant because it facilitates site customization by allowing merchants to display specific content based on rules such as marketing campaigns, customer groups, and AB tests. Content slots enable the dynamic display of various content types, including products, category attributes, and static images, depending on predefined qualifiers like start/end dates and customer groups . The collaboration between developers and merchants in creating and configuring these slots enables a flexible and reusable content presentation . This setup enhances the site's customization and responsiveness to different user interactions and marketing strategies .
The JavaScript Controller JShowProduct in Commerce Cloud's model-view-controller architecture serves as the controller logic to handle requests for displaying a product. It accepts a product ID as a parameter from the URL, retrieves the product information using the ProductMgr class, and then forwards the control to the appropriate ISML template for rendering. If the product exists, it renders the 'productfound.isml' template with the product details; if not, it renders 'productnotfound.isml' with an error message .
Viewing cartridge contents via the WebDAV Cartridge Directory allows developers to verify the structure and content of uploaded cartridges, ensuring that they match the expected setup for site functionality. This is crucial during development to confirm that all necessary files are available and correctly organized before activation on the server . Additionally, developers can troubleshoot and validate cartridge configurations by comparing them against the active code version, facilitating precise debugging and adjustments .
A storefront cartridge in Salesforce Commerce Cloud serves as a directory structure to organize and deploy custom functionality in a flexible manner. It typically contains static files like CSS and JavaScript, as well as Commerce Cloud-specific items such as scripts and templates . Common reusable code intended for multiple sites is placed in a core storefront cartridge (e.g., <client>_core), while site-specific functionalities that may override the core are stored in separate cartridges for each site (e.g., app_<site>). Integration-specific code is housed in integration cartridges (e.g., int_<site>). The structure includes sub-directories for specific file types, ensuring organized deployment . Storefront cartridges can be added to the cartridge path in Business Manager to facilitate their use and deployment across sites .
Using a custom security mechanism is important when exposing the RunJobNow pipelet in a public pipeline because the pipelet can execute code arbitrarily if exposed, potentially allowing unauthorized users to run jobs, leading to security vulnerabilities. Only authorized users should be able to trigger jobs to prevent malicious use or accidental misuse that could disrupt business processes or reveal sensitive data . Providing code that triggers the job should therefore be accompanied by appropriate access controls and security checks to ensure that only legitimate requests are executed .