Professional Documents
Culture Documents
Day 1:
Introductions
§ Business Manager
Getting Started
Create a Controller
Extend a Controller
Day 2:
Models
ISML
Day 3:
Day 4:
Hooks, OCAPI, & Jobs
§ Explain Hooks
§ Create a Custom Hooks
§ Describe OCAPI
OCAPI settings and configuration
Testing OCAPI using API explorer
Execute to Invoke OCAPI call
Testing OCAPI using postman
§ Create Jobs
CCD102
Copyright
© Copyright 2000-2019 salesforce.com, inc. All rights reserved. Various trademarks held
by their respective owners.
The information in this document is subject to change without notice. Should you find
any problems or errors, please log a case from the Support link on the Salesforce home
page. Salesforce.com, inc. does not warrant that this document is error-free.
Introductions
3 | Cartridges
1 | Overview of
& Housekeeping B2C Commerce 2 | Getting & Plug-ins
Started 4 | Controllers,
Routes, &
Debugging
7 | Objects &
5 | Models Forms 8 | Hooks,
6 | ISML, Content OCAPI, & Jobs
Slots, & Page 9 | Performance
Designer & SFRA Tooling
Introductions
Target Audience
▪ Application Developers, Solution Architects, System Integrators
Recommended Background
▪ Development experience with JavaScript, HTML, CSS, jQuery
▪ Experience working with e-commerce applications
▪ Completion CCM-101: Managing the Storefront
▪ B2C Commerce Developer Trail
Software Requirements
▪ Visual Studio Code (required)
▪ Node.js (recommended)
Tasks:
1. Log into Sandbox
2. Download Files
10 minutes
TIP: Make sure you don’t have any spaces in the names of folders and files in
the directory path. This will be important in future exercises.
1 | Overview
Introductions
of B2C 3 | Cartridges
& Housekeeping 2 | Getting
Commerce Started 4 | Controllers,
Routes, &
Debugging
7 | Objects &
5 | Models Forms 8 | Hooks,
6 | ISML, Content OCAPI, & Jobs
Slots, & Page 9 | Performance
Designer & SFRA Tooling
ODS
Realm
Realm
Sandboxes
Secondary Sandboxes
Instance
Group (S.I.G.)
....
Storefront Reference Architecture (SFRA)
Site
Storefront Branding
PLUGIN
LINK
Apple Pay Other In Store Pick-Up
storeLocator.isml
Shopper
stores.js
Sees View
Model
Updates
Uses
ViewModel
Binds
ViewModel Controller Manipulates
Stores.js
Stores-Find
Business Manager
Introductions 1 | Overview of
& Housekeeping B2C Commerce 2 | Getting Started 3 | Cartridges
4 | Controllers,
Routes, &
Debugging
7 | Objects &
5 | Models Forms 8 | Hooks,
6 | ISML, Content OCAPI, & Jobs
Slots, & Page 9 | Performance
Designer & SFRA Tooling
Story
✓Access SFRA
✓Set your workspace
✓Navigate cartridges
TIPS: We will access SFRA from Business Manager. This is the quickest and easiest way to start
working. However, getting familiar with everything out on GitHub is a must!
Exercise 2-1: Access SFRA
Scenario:
To set up SFRA and install a functioning site, you’ll need to import a demo site
in Business Manager and configure site settings. From here, see how to
download the cartridges to your local machine.
Tasks:
Goal:
1. Import a Demo Site
Access SFRA from
2. Configure Site Settings
Business Manager.
3. Optional: Download Cartridges
NOTE: Import the All-in-One Feature Cartridge, which contains plugin cartridges. We’ll learn more
about how to use this option in a later exercise.
Products
Storefront
Catalog
Master Catalogs
Products Storefront
Site
Scenario: The SFRA import contains both site-specific data and data
shared among all sites in the organization. The SFRA catalogs are available
to new sites you create. Let’s take a closer look by creating a new site.
Goal: Tasks:
Use Catalogs to Share 1. Create a New Site
Data Between Sites. 2. Disable Caching
3. Share Existing Catalog
4. Rebuild Search Indexes
Scenario: To edit and write source code, you’ll need an IDE. Any IDE
will work, Visual Studio Code has Prophet Debugger for B2C Commerce
Cloud, which can be used to easily upload cartridges and debug.
Goal: Tasks:
Set up your workspace 1. Install Visual Studio Code
with SFRA Cartridges. 2. Install or Update Prophet Debugger
3. Add sfra-training-site
4. Create a New Workspace
NOTE: Directions for installing and navigating Eclipse/UX Studio are in the Appendix 3 and 4.
Tasks:
1. Open Prophet View & Documentation
2. Find a File
• Ctrl + p on Windows or Cmd + p on Mac
3. Find Text Within All Files
• Edit>Find in Files
• Ctrl + Shift + F on Windows or Cmd + Shift + F on Mac
True or False
You can access SFRA through GitHub.
Introductions 3 | Cartridges
1 | Overview of
& Housekeeping B2C Commerce 2 | Getting
Started 4 | Controllers,
Routes, &
Debugging
7 | Objects &
5 | Models Forms 8 | Hooks,
6 | ISML, Content OCAPI, & Jobs
Slots, & Page 9 | Performance
Designer & SFRA Tooling
Story
Once you have the default features Explore SFRA cartridges, and use your
from the SFRA Demo Site Import, you’d own custom cartridge.
like to enhance site functionality.
To do this…
Cartridge
DEFINITION
NOTE: Use an overlay cartridge to modify the base to ensure seamless upgrades. Never directly
customize the server module because you will void any guarantees for backward compatability.
Cartridge Directory Structure
Cartridge Name
dw.json //used to upload code
package.json
cartridges
├── app_custom_name
├── cartridge
├── client //client-side JavaScript and CSS
├── controllers // business logic for the application
├── experience // business logic & metadata for Page Designer
├── forms // form metadata files
├── models //gets data from server and provides it as JSON
├── scripts //reusable functionality
├── static //static resources (compiled) unlikely to change
├── templates //ISML templates
└── default //common template location
└── resources //properties files for localization
...
Cartridge Path
Cartridge Execution
Cartridge path:
app_custom_cartridge:plugin_cartridge:app_storefront_base
You can…
• Use plugin_cartridge_merge from
GitHub.
• Or, use the all-in-one code base from Business
Manager.
TIPS: Similar conflicts can occur with link and custom cartridges. Keep this in mind as you build out
your site.
SFRA Modules
NOTE: Never edit the contents of the server module, as it voids any promise of backward compatibility
or support from Commerce Cloud.
Scenario: When you accessed SFRA from Business Manager, you imported
the all-in-one feature cartridge. This is a quick way to get all the features at
once. However, you may not need every feature. Learn how to modify this
option to reduce the number of plugins and code you need to manage.
Goal: Tasks:
Modify the all-in-one 1. View Current Functionality
feature cartridge. 2. Set Site Preferences
3. Update Cartridge Path
Scenario:
To introduce new functionality to a storefront, you’ll use a new cartridge. It’s
important that you store each type of resource in its corresponding folder.
Goal: Tasks:
1. View Custom Cartridge in Workspace
Use a custom cartridge to
modify the base cartridge. 2. Update Cartridge Path
NOTE: All exercise files will be located or created in this new custom cartridge. You can create your
own custom cartridges using Prophet or NPM Scripts. Directions are in your exercise guide.
Scenario: You’ve updated the cartridge path with your custom cartridge,
but there’s no code in your sandbox for that cartridge. You’re about to
make customizations to the site, so you’ll create a new code version and
upload the cartridges in your workspace to your sandbox.
Tasks:
Goal:
1. Add a New Code Version
Upload code to a new
2. Create a Server Connection
code version.
3. Enable Auto Upload
4. Enable Auto Save
5. Check Upload
NOTE: A code version is a folder in Business Manager that contains custom cartridges. An instance
uses the currently active code version.
Introductions
1 | Overview of 3 | Cartridges
& Housekeeping B2C Commerce 2 | Getting
Started 4 | Controllers,
Routes, &
Debugging
7 | Objects &
5 | Models Forms 8 | Hooks,
6 | ISML, Content OCAPI, & Jobs
Slots, & Page 9 | Performance
Designer & SFRA Tooling
Story
You’re ready to customize your site to Use controllers and routes to extend
include a few new features. Before you scripts that handle requests on the
product page.
get started, you get acquainted with
using controllers, which manage the
flow of data throughout the storefront. It’s time to…
✓Create a Controller
✓Troubleshoot & debug code
✓Change data in a template
✓Change template styles
✓Use middleware scripts
✓Customize the home page
✓Call a script in a controller
Controller
DEFINITION
Manage the flow of data in your application, and calls models that create
2
ViewModels to process each request as a route and generate a response.
module.exports = server.exports();
Server Module
DEFINITION: Located in the SFRA global modules folder, it provides the routing functionality for
controllers. EVERY controller requires this module.
NOTE: You can add as many parameters in between the first and last parameter. Each parameter
specifies a function to be executed in order. Use next() or next (new Error()).
Types of Routes
Type Purpose
server.get GET requests are typically used to retrieve information. Parameters
are included in the request's query string.
server.post POST requests are intended for saving information. The data to save
is sent in the request's body.
server.use Responds to both GET and POST requests, as well as the other http
methods. (Rarely used).
NOTE: GET and POST are HTTP verbs and the routes define functions that respond to the verbs.
next Use to notify the server that you are done with this
middleware step and it can execute the next step in
the chain.
NOTE: Existing routes can be extended or replaced, without having to rewrite the entire controller.
1
Open the starter file in
app_custom_exercises.
Read the comments. 2
Code a solution.
Use the Documentation or
Quick Card for support.
View Functionality in the
base or plugin.
3
Check the solution file in
app_custom_solutions
or ask for help.
Demo: Testing Controllers
Sample URL
https://zztr-035.sandbox.us02.dx.commercecloud.salesforce.com/
on/demandware.store/Sites-RefArch-Site/en_US/Search-Show?q=TV&lang=en_us
Legend
035 The number of your sandbox.
The ID of the site you're currently viewing.
Sites-RefArch-Site
For Business Manager, it will be Sites-Site.
en_US Locale you're browsing.
Search The Controller you're executing.
Show The route that you're executing in the current controller.
q=TV&lang=en_US Query string (covered in detail later in course).
Goal: Task:
NOTE: Writing directly to the response is not recommended, especially in a production instance.
However, it is useful from troubleshooting.
Passing Parameters
Scenario:
Now, create a controller that renders an ISML template with a
dynamic property that accesses the declared value “Hello World”.
Goal: Tasks:
General Troubleshooting
Tasks:
1. Select RefArch (if not selected) storefront.
2. Click Toolkit.
3. Click the Request Log icon.
4. View the Request Log.
10 minutes
NOTE: Use Visual Studio Code to debug scripts and controllers by creating a debug configuration.
Exercise 4-4: Script Debugger
Scenario:
When things don’t work, you’ll want to debug your code. You can
use the Prophet Debugger in Visual Studio Code to do this.
Tasks:
Goal:
1. Debug Configuration
Create a Script Debug
2. Start Working
Configuration.
3. Debug
superModule
DEFINITION: API that imports functionality from the first controller with the same name and location
found to the right of the current cartridge on the cartridge path.
Scenario:
You can override or extend a controller. Overriding is simply creating a new controller with the
same name in your custom cartridge. You use superModule to extend, which executes the
original middleware, along with the additional steps included in your extension. Try it out.
Goal: Tasks:
1. Add Middle Cartridge to Cartridge Path
Use superModule to
inherit functionality. Use 2. View the Original Controller Routes
server.prepend, 3. Extend the Show Route (Prepend and Append)
server.append, and 4. Replace the Start Route (Replace)
server.replace extend
the original middleware.
Query String
Example:
A query string is the portion of a URL where data is passed to a web
application and/or back-end database. In Storefront Reference
Architecture query strings are parsed on the req argument.
Navigate to the app_storefront_base/cartridge/
controllers/
Checkout.js to see this in action.
req argument parses query string parameters and assigns them to the
req.querystring object.
req.querystring.object
server.append server.prepend
Home-Show Home-Show?promo=1
req.querystring.promo == 1
Exercise 4-6: Custom Home Page
Scenario: You’d like to create a custom home page that displays data in one of two ways
based on the presence of query string parameters. You need to inherit functionality of
the original Home.js controller and extend it to include the two sets of viewData.
Then, you need to update the view by overriding the original ISML template.
Goal: Tasks:
Use superModule to inherit 1. View Current Functionality
functionality. Use 2. Inherit & Extend Functionality
server.prepend and 3. Override ISML Template
server.append to include
additional viewData.
Update the view.
• Located in app_storefront_base/cartridge/scripts
• Used in controllers to reuse functions
• Use the require() function to load a script
Example from SFRA
var server = require('server');
var userLoggedIn = require('*/cartridge/scripts/middleware/
userLoggedIn');
server.get(
'Show',
userLoggedIn.validateLoggedIn,
function (req, res, next) {
//Code to execute here
);
}
Scenario:
You’d like to make a page visible only to users that are logged into the
site. Use a middleware script from the base to reuse functionality.
Tasks:
Goal:
1. View Middleware Scripts
Invoke a step from the 2. Code a Solution
userLoggedIn script to • Require a Middleware Script
limit visibility to logged in • Invoke a Step to Validate Login
users. 3. View Functionality – Not Logged In
4. View Functionality – Logged In
A class that ends with Mgr retrieves instances of business objects related to its
package.
Name Description Example Classes
dw.campaign For campaign and promotions PromotionMgr, Campaign,
Promotion, SourceCodeGroup
dw.catalog For catalog, product, and price book CatalogMgr, Category, Product,
Recommendation, PriceBook
dw.content For non-product content management ContentMgr, Content, Folder,
Library
dw.customer For customer profile and account CustomerMgr, Customer, Profile,
ProductList, OrderHistory
dw.order For orders, including: basket, coupons, Basket, Order, ProductLineItem,
line items, payment, shipment ShippingMgr, TaxMgr
ProductMgr.getProduct(String id)
Example
Product Factories
Script Directory
app_storefront_base/cartridge/scripts/factories/product.js
BEST PRACTICE: Include B2C Commerce API in scripts or models, instead of directly in a controller, to
follow the MVC pattern.
Scenario:
Create a controller that accesses storefront data and displays product
information or an error message. Do this by calling the product factories
script, which uses the B2C Commerce API.
Goal: Tasks:
Use B2C Commerce Script 1. Study the Script
API by calling a script. 2. View ISML Templates
3. Create a Controller
True or False
Controllers must conform to B2C Commerce module
standard.
Introductions
1 | Overview of 3 | Cartridges
& Housekeeping B2C Commerce 2 | Getting
Started 4 | Controllers,
Routes, &
Debugging
Story
You’d like add data to appear on your Extend a Model to store data in JSON
storefront. The data is represented in two format prior to passing it to a
models, store and product. You’ll need to template.
extend these models to make the
customizations.
Explore it, and…
Model
DEFINITION
Tasks:
1. View Models
• app_storefront_base/cartridge/models
• Models convert object returned by the Salesforce B2C Script APIs
into pure JSON objects designed for the Storefront.
2. View the Payment Model
• app_storefront_base/cartridge/models/payment.js
• Simple model
Extend a Model
Directory: app_storefront_base/cartridge/models/stores.js
function stores(storesResultsObject) {
this.stores = createStoresObject(storesResultsObject);
Directory: plugin_cartridges/plugin_instorepickup/cartridge/models/stores.js
var base = module.superModule;
function stores(storesResultsObject) {
base.call(this, storesResultsObject);
this.stores = addInventroyList(this.stores, storesResultsObject);
}
…
Goal: Tasks:
Extend the store model to 1. View Current Functionality in the Storefront
include an email address. 2. View Current Functionality in the Code
3. Extend the Model
4. Update the View
ViewModel
Binds
ViewModel Controller Manipulates
Product.js
* In the next exercise, we will be Product-Show?pid=
updating these files.
Scenario: Now, let’s add specific stock information to the product details.
To do this, create a new decorator for the product model that will define
the stock information. Then extend the product model to include the new
decorator.
Goal: Tasks:
Can you give another example for when you may want
to extend or create a new model?
Introductions 3 | Cartridges
1 | Overview of
& Housekeeping B2C Commerce 2 | Getting & Plug-ins
Started 4 | Controllers,
Routes, &
Debugging
Story
New and customized pages are a must for Generate dynamic storefront pages using
your storefront. You’d like to create a new ISML templates and storefront pages.
page for an upcoming promotion. You can
render this view using ISML templates and
Dig in, and…
tags. In situations where you’d like to give
some control to the merchant, you can
create a content slot. ✓Create an ISML Template
✓Use a Decorator Template
✓Use a Remote and Local Include
✓Use a Loop in ISML
✓Create a Content Slot
✓Create a Content Slot Configuration
✓Use Resource Bundles in Templates
ISML
ISML
Tasks:
Advanced support of ISML syntax
1. Select an ISML template. includes hover information,
2. Open Prophet Debugger. autocomplete tags, and more.
5 minutes
ISML Tags
<iscomment>
Use this server-side comment tag instead of an HTML <!-- --> tag.
Example
<isscript>
Use this to create scripts within templates.
Example
<isscript>
var assets = require('*/cartridge/scripts/assets.js');
assets.addCss('/css/account/dashboard.css');
</isscript>
<isprint>
Prints formatted output from a variable or expression, using regional settings that you can configure in Business Manager.
Examples
Template Decorator
Decorator area
<isreplace/> area
Decorator area
Types of Template Decorators
promo.isml 6-2
Template
6-6 decorator
Resource Bundle
Scenario:
You’re tasked with building a promotional landing page that can be used to
showcase products that are on sale. You’d like to have the navigational
decorator at the top of the page.
Goal: Tasks:
1. View Decorator Templates
Wrap the content of a
template in a decorator 2. Create a Controller
template. 3. Add Decorator to ISML Template
isset Only use to set a variable used by isinclude. Don’t use complex expressions in
this tag.
isscript Only use to add static content to the assets object.
ismodule Only used for content assets.
isobject Used to wrap products for analytic and the Storefront Toolkit.
iscache Set by default to 24 hours. Recommend to change this value in the controller.
iscontent
iscookie
CHANGE THESE VALUES in the CONTROLLER.
isredirect
isstatus
ISML Expressions
ISML expressions:
• Are based on B2C Commerce Script, which implements
the ECMAScript standard
• Use dot notation to access classes and methods
• Are enclosed in ${ }
Syntax
${pdict.object.property}
Example
${pdict.product.productName}
The TopLevel package and its global class are implicit in ISML. Do not
include them explicitly in ISML templates.
${dw.web.URLUtils.url()}
This
code:
${URLUtils.url()}
Is equivalent to this
code:
Examples
${lineItem.productType === 'bundle' && ((pdict.order && !
pdict.order.orderStatus) || miniCart)}
Local Includes
Scenario:
You’d like to include details on the promo page that will be used across
multiple promotional landing pages. Compartmentalize your code using a
local include, so you can use it over again.
Tasks:
Goal:
1. View Templates
Reuse code in ISML 2. Create an ISML Template
templates.
3. Include Template
NOTE: SFRA uses Bootstrap 4 because of its wide adoption in the technical community.
Use the isset element to create and access custom variables in an ISML template.
Variable Attributes
<iselse>
If none of these conditions is true, do this.
</isif>
Example
<isif condition="${pdict.myProduct.online}">
Product is online
<iselse>
Product is offline
</isif>
Loops
<isloop> Attributes
Attribute Description
items Expression returning an object to iterate over. Attributes iterator and
(iterator) items can be used interchangeably.
Name of the variable referencing the object in the iterative collection
var (alias)
referenced in the current iteration.
Name of the variable referencing loop status object. The loop status is
status used to query information such as the counter or whether it is the first
item.
Expression specifying a begin index for the loop. If the begin is greater
begin 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.
Expression specifying an end index (inclusive). If end is smaller than
end
begin, the <isloop> is skipped.
Expression specifying the step used to increase the index. If step is
step
smaller than 1, 1 is used as the step value.
Status Variable Properties
Attribute Description
count The number of iterations, starting with 1.
index The current index into the set of items, while iterating.
first True, if this is the first item while iterating (count == 1).
last True, if this is the last item while iterating.
odd True, if count is an odd value.
even True, if count is an even value.
Status Attribute Example
<isif condition="${lineItem.bonusProductLineItemUUID==='bonus'}">
<isloop items="${lineItem.bonusProducts}"
var="bonusProduct" status="loopstate">
<isif condition="${loopstate.first}">
<br/>
${Resource.msg('text.lineitem.bonus.msg','cart',null)}
</isif>
… etc. …
<isif condition="${loopstate.last}">
<br/>
</isif>
</isloop>
</isif>
Scenario:
On the promotion landing page, you’d like to create a list of promotional items
a customer has in their cart. Since everything’s on sale, this should be easy!
Tasks:
Goal:
1. View B2C Script API
Loop through elements of
2. Create a Controller
a specified iterator.
3. Create an ISML Template
4. Test Loop
Remote Includes
Examples
Build a site-specific URL dynamically (to avoid a hardcoded server name):
<isinclude url="${URLUtils.url('Cart-MiniCart')}" />
Scenario:
Now, you’ll display the list on your promo page by using a remote include. This
option is best when you need sections of your page to have different cache
times.
Tasks:
Goal:
1. View B2C Commerce Script API
Invoke a controller in a 2. Add a Remote Include
template.
Syntax
dw.web.Resource.msg(key:String, bundleName:String, defaultMessage:String)
Examples
Localized string value default text
Scenario:
Use resource bundles rather than hard coded strings for the title on
your promotional landing page.
Tasks:
Goal:
1. Create Properties Files
Localize content for
2. Internationalize ISML
English and French.
3. Change Locales
4. Test the Page
Content Slots
Content Slots
Products
Categories
Content Assets
Static HTML
Recommendations
Content Slot Contexts
Global Slot
Category Slot
Identifying Slots on the Storefront
UP TO 75% OFF
1 Developer
(using VSC)
Create a Slot in ISML A slot can have one or
more configurations
3
Create a Slot Merchant (using
the Business
Rendering
Manager)
Template
2
Configure
Examples
Global slot:
<isslot id="header-banner-m" description="..." context="global" />
Category slot:
<isslot id="cat-landing-slotbanner-m" context="category"
description="Banner at the top of Category Landing Pages"
context-object="${pdict.category}"
/>
<div class="htmlslotcontainer">
<isif condition="${slotcontent != null}">
<isloop items="${slotcontent.content}" var="markupText">
<isprint value="${markupText.markup}" encoding="off"/>
</isloop>
</isif>
</div>
3. generate HTML
2. loop through content
Scenario:
You’d like to display a banner on your promotional page that
merchants can change whenever they’d like.
Tasks:
Goal:
1. View Functionality
Create a slot for 2. Add a Content Slot
merchants to use.
Enter HTML
Scenario:
Time to test your content slot by configuring it. You’ll complete the
steps a merchant would take to create slot configuration.
Tasks:
Goal:
1. Find the Content Slot
Configure a content slot 2. Create a New Configuration
in Business Manager.
3. Use the HTML Editor
4. Finish Configuration & Test
Page Designer
Page Designer
Topics
- Understand the Structure
- Create a Page as a Business User
- Identify Developer Tasks
- View Cartridge Structure & File Types
- Create a Component
- Render the Page
● Pages
○ Outermost container that contains regions
● Regions
○ Hierarchical structuring of components
○ Contains components
● Components
○ Attributes that specify the actual content
○ Layouts that contain regions that contain
other components
NOTE: Pages and Components are constrained by customer group and/or date range.
REGION
COMPONENT
PAGE
Exercise 6-9: Create a Page as a Business User
Scenario:
The Page Designer feature is available for business users to create and manage
pages. They can drag and drop content with a powerful visual editor, making
content and layout changes easy.
Goal: Tasks:
Build a commerce 1. Launch Page Designer
experience faster. 2. Navigate Page Designer
3. Add a Banner
4. Add a Layout
5. Add Category Tile
6. Preview Page
TIP: Use a shared library if you intend to reuse Pages and Components in multiple site.
Page Visibility
● The Page class has a visible() method that returns true if the page is
currently visible. This happens when
○ Page is published
○ Page is set to visible in current locale
○ All visibility rules apply, requiring that
○ Schedule matches
○ Customer group matches
○ Associated Campaign or Promotion is active and qualified
TIP: Use a shared library if you intend to reuse Pages and Components in multiple site.
Page Visibility
...
var page = PageMgr.getPage(pageID);
if(page.hasVisibilityRules()) {
{
// pagecaching is NOT ok here
if (page.isVisible())
{
response.writer.print(PageMgr.renderPage(pageID, {});
}
}
else
{
// pagecaching is ok here, but requires a pagecache refresh
if merchants start adding visibility rules to the page
}
...
Scenario:
Let’s dig in to understand all the pieces. View the directory
structure and file types required for pages and components.
Goal: Tasks:
Understand how a 1. View Cartridge Structure
cartridge is structured and 2. Understand the File Types
the file types required for 3. View Page Files
Page Designer.
4. View Component Files
Requirements
faq_item_content
TIP: Full list of component attribute types can be found in the Appendix 5 in your Exercise Guide.
Exercise 6-11: Create a New Component
Tasks:
Goal:
1. Edit & Add the Meta Definition File
Edit and add the files and
2. Edit & Add the Rendering Script
scripts for a new
component. Then view 3. Edit & Add the Rendering Template
the component in Page 4. Add the Component to the Page
Designer. 5. Publish Page
NOTE: Be careful to place your files in the right directory, naming each file the same.
'use strict';
res.print(PageMgr.renderPage(page.ID, "page.ID"));
next();
});
module.exports = server.exports();
Scenario:
Let’s display our new sales page. Use the dw.experience.PageMgr
to render the salespage in a simple controller.
Goal: Tasks:
Render the Page Designer 1. Create a Controller
page. 2. Render the Page
Introductions 3 | Cartridges
1 | Overview of
& Housekeeping B2C Commerce 2 | Getting & Plug-ins
Started 4 | Controllers,
Routes, &
Debugging
7 | Objects &
5 | Models 8 | Hooks,
6 | ISML, Content Forms OCAPI, & Jobs
Slots, & Page 9 | Performance
Designer & SFRA Tooling
Story
Capture information from your users by
You'd like to offer unregistered creating a form. Use objects to capture
and retrieve customer information.
customers the option to sign up for a
company newsletter. You’ll create a
Work through it…
custom object to store the information
and modify a form to do this.
✓ Explain System & Custom Objects
✓ Create a Custom Object
✓ Explain the Forms Framework
String String String String Alfreds Futterkiste Maria Anders Berlin 030-0074321
Antonio Moreno
Antonio Moreno México D.F. (5) 555-3932
Taquería
(171)
Around the Horn Thomas Hardy London
555-7788
• Can have local (site-specific) or global (organization-wide) storage scope.
• Are best used for small amounts of static data.
• Require planning for data growth and cleanup.
• Are limited by governance quotas on custom object API usage and data volume.
To create a custom object, you must first define the custom object type:
• Organization level
• Key attribute and data
type
• Replicability
• Scope
• Retention (if not
replicable)
• Attributes (fields
and data types)
Replicate from Staging? Scope of instances of
the custom object
Demo: Create a Custom Object Type
Scenario:
You’d like to capture whether a unregistered customer wants to receive
promotions while signing up for a company newsletter. First, define a custom
object type in Business Manager.
Goal: Tasks:
Use Business Manager to 1. Define the Custom Object Type
Define a Custom Object 2. Create the Field Attributes
Type 3. Create an Attribute Group
Commonly-Used Classes
Inheritance Tree
Inheritance Tree for the Custom Object Type and System Object Type
TopLevel.Object
Many other commonly-used
Extends
classes share this inheritance
tree, including: dw.object.PersistentObject
dw.catalog.Product
dw.system.SitePreferences Extends
dw.object.ExtensibleObject
Extends
Newsletter
example:
• No system object (the Profile system
object is limited to registered users)
• Exported for mass mailing
• Not replicable
Form Components
Optional
• Client-side JavaScript
Form functions
var newsletterForm = server.forms.getForm('newsletter');
newsletterForm.clear();
Implicit Explicit
Syntax
var Transaction = require('dw/system/Transaction');
Transaction.wrap(function()
{
//Your code
});
Example
Transaction.wrap(function()
{
couponStatus = cart.addCoupon(couponCode);
});
try {
more code
Transaction.commit();
}
catch (ex) {
Transaction.rollback();
optional error handling code
}
Object Interaction
• Boolean
• Date
• Integer
• Number
• string
NOTE: For more about field element attributes, see the documentation.
<?xml version="1.0"?>
<form xmlns="http://www.demandware.com/xml/form/2008-04-19"
secure="false">
<field
formid="fname"
label="label.input.firstname.profile"
mandatory="true"
max-length="50"
type="string" />
<action formid="submit" valid-form="true"/>
</form>
Exercise 7-2: Use the Forms Framework
Scenario:
You’ll test the components of the forms framework by working with pre-built
templates and controllers that provide the functionality to capture customer
information.
Goal: Tasks:
Inspect and test a 1. View Files & Code
functioning form. 2. Update Controller
3. Edit Script
4. Test the Form
Controller
Exercise 7-3: Modify the Metadata
Scenario:
First, you’ll add to the form definition in the XML file and update
the relevant resource bundle.
Tasks:
Goal:
1. Edit XML File
Reference the custom
2. Add Label to forms.properties
object in the form
definition.
Scenario:
Now, it’s time to modify the view by updating the ISML template
used for signing up.
Tasks:
Goal:
1. Edit ISML
Display the label and
2. Test the Page
checkbox for the
promotion opt-in on the
form.
Scenario:
To capture an additional piece of information in the custom object, you must
add an attribute to the custom object type and include it in the attribute
group.
Tasks:
Goal:
1. Create Attribute Definition
Create a place to store 2. Add to Attribute Group
information.
3. Create an Instance of New Custom Object
Scenario: To finish up, you’ll need to edit the utility script that creates the
custom object. You’ll add to the script, to create the promo opt-in
attribute. This is necessary to ensure the information is saved and visible in
Business manager.
Tasks:
Goal:
1. Edit Script
Update the script to
2. Test the Form
create a new attribute on
the custom object. 3. Check the Custom Object
NOTE: This code can also be written directly in the controller. However, following the MVC pattern
best practice, you should keep this code separate.
Highest Fatal
Severity
Error
Warn
Info
Lowest
Debug
Severity
Writing a Custom Log
Example
var logger = Logger.getLogger("logFilePrefix","category");
logger.debug("Input params received firstName: {0}\n
lastName: {1}\n email: {2}", args.firstName,
args.lastName, args.email);
try { your code }
catch (e)
{ logger.warn("error description: {0}", e.causeMessage); }
Custom Logging Considerations
+++ Maximum log file size per day reached, logging suspended.
Tasks:
Goal:
1. Create a Log Category
Use custom logging to 2. View Code in the Controller
capture error messages.
3. Test the Controller
4. View the Log File
Goal: Tasks:
Use Business Manager to 1. Modify a System Object Type
Modify a System Object & 2. Update Controller
Create a Form that 3. Add Link in Content Asset
Captures User 4. Test the Form
Information
NOTE: Most of the files for the form are created for you. You’ll make some updates to the controller
after you’ve modified the system object.
Client-Side JavaScript
NOTE: Search the Salesforce Commerce Cloud GitHub community for the plugin_newsletter
repository to view a client-side example.
True or False
The Form Definition describes the data you need from
the form and the system objects you want to use.
Introductions 3 | Cartridges
1 | Overview of
& Housekeeping B2C Commerce 2 | Getting & Plug-ins
Started 4 | Controllers,
Routes, &
Debugging
Story
Hooks
Hooks
You’d like to send a welcome email to customers that have signed up for
the newsletter. You can use a hook that sends an email to customers when
they submit the form.
✓Explain Hooks
✓Create a Custom Hook
✓Identify Aspects of Running Multiple Hooks
Hook
DEFINITION
{
"hooks": "./cartridge/scripts/hooks.json"
}
NOTE: A hook doesn’t have access to ‘req’ and ‘res’ objects like a controller does.
Goal: Tasks:
1. View the Email Script
Send an email with a
hook. 2. Create package.json
3. Create hooks.json
4. Update Controller
5. Test the Hook
Example:
You have two cartridges, the base and a custom cartridge for gift
cards. You have two unique calculations for tax, one for the regular
products that include a tax and one for gift cards that aren’t taxed.
When it comes time to calculate the tax for the entire cart, you can
use the hooks manager to call an event. That event calls it from all
registered points, one on the gift card cartridge and one on the
base. Each executes and they are totaled.
plugin_giftcards:app_storefront_base
dw.order.calculateTax dw.order.calculateTax
OCAPI
OCAPI
DEFINITION: Open Commerce API enables access to resources using HTTP requests and HTTP
responses. Consists of three component APIs: Shop API, Data API, Meta API
Examples:
• Endless Aisle • Business Manager • API Explorer
• Customer Service Center • ERP/CRM/CMS Integrations
• Pinterest Buyable Pins • Continuous Integration
• Mobile Shopping Apps
Shop API
How It Works
Invoke Shop API to allow for product search based on
availability information.
Data API
ERP Integration
An integration with the enterprise resource planning platform to
sync inventory data across business processes in the supply
chain.
How It Works
Invoke Data API to get all product inventory records for an
inventory list.
Meta API
API Explorer
A tool that allows developers to browse and test OCAPI
APIs.
How It Works
Invoke Meta API to retrieve a list of all documents available
for an API and version.
HEAD (s) returns headers only (same as GET request), but not resource data
Production Instance
http(s)://public_domain/dw/api_type/
Version ID
base_url/version_id/resource_type/identifier
base_url/v20_3/resource_type/identifier
Resource Type
base_url/version_id/resource_type/identifier
base_url/v20_3/products/identifier
Identifier
base_url/version_id/resource_type/identifier
base_url/v20_3/products/123FOO456bar
OCAPI URL Syntax - Extended URL, continued
Multiple Identifiers
base_url/version_id/resource_type/identifier
base_url/v20_3/products/(123,456,789)
base_url/v20_3/customers/auth
base_url/v20_3/baskets/12345/items
Resource Types
Use Case
A customer service application that allows an agent to view a customer’s past
purchases.
How It Works
Invoke Shop API to return a list of all purchases of an item from a customer’s
product list.
Operation
GET /customers/{customer_id}/product_lists/{list_id}/items/{item_id}/purchases
Request URL
https://demo-ocapi.demandware.net/s/-/dw/shop/v20_4/customers/4562/
product_lists/5965/items/6314/purchases?client_id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Use Case
Integration with a marketing application is required to
ensure an up-to-date customer list is available for email
campaigns.
Application
Invoke Data API to initiate an action to read an existing
customer list.
Operation
GET /customer_lists/{list_id}
Request URL
https://demo-ocapi.demandware.net/s/-/dw/data/v20_4/
customer_lists/2345?client_id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Use Case
A tool for developers that allows them to browse all
existing versions of an API.
Application
Invoke Meta API to retrieves all existing versions and their
statuses for a given API.
Operation
GET /rest/{api_name}
Request URL
https://demo-ocapi.demandware.net/s/-/dw/meta/v99_9/rest/shop?
client_id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Query String
REQUEST:
POST /dw/shop/v20_3/products/123?method=DELETE HTTP/1.1
HTTP Header
REQUEST:
POST /dw/shop/v20_4/products/123 HTTP/1.1
Host: example.com
Accept: application/json
x-dw-http-method-override: DELETE
Client ID
NOTE: OCAPI requires that all client applications identify themselves using a client ID. You can obtain
a client ID in Account manager. You’ll include the client ID in every API request.
Bearer Token
GET https://.../shop/v20_3/baskets
Authorization:Bearer token
Query String
GET https://example.com/dw/shop/v20_3/products/123456?client_id=aaaaaaaaaaaaaaa
aaaaaaaaaaaaaaa
HTTP Header
GET https://example.com/dw/shop/v20_3/products/123456 x-dw-client-
id:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OCAPI Settings
NOTE: To use OCAPI, you must first configure client permissions that control read and write access to
specified resources.
• Define for for a single site (site-specific) or for all sites (global).
CLICK PATH:
Business manager | Administration | Site Development | Open Commerce API Settings
{
"_v":"20.4",
"clients":
[
{
"client_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"allowed_origins":["http://www.sitegenesis.com"],
"resources":
[
{
"resource_id":"/customers",
"methods":["post"],
"read_attributes":"(**)",
"write_attributes":"(**)",
"version_range":{"from":"18.2"}
},
OCAPI Hooks
Server-side script functions, typically called before and after the HTTP method
execution.
RESOURCE:
Search for OCAPI Hooks in the B2C Commerce Infocenter.
Scenario:
To use OCAPI, you must first configure client permissions. You’ll do
this in Business Manager by modifying a JSON document.
Goal: Tasks:
1. Access OCAPI Settings in Business Manager
Configure client
permissions. 2. Add Configuration Settings for Shop API
3. Add Configuration Settings for Data API
HINT: Use the code review slide or the solution code for help.
API Explorer
RESOURCE:
Search for API Explorer in the B2C Commerce Infocenter.
Scenario:
API Explorer can be very useful, especially when you connect it with an
environment. Practice using the API Explorer with Shop API to get
product details from your sandbox.
Tasks:
Goal:
1. Connect API Explorer to Sandbox
Get product details from 2. Use Shop API to Get Product
a sandbox using API
Explorer.
Scenario:
A development team in your organization is working on a project that
requires setting up an OCAPI call. You’ll help them create a URL and test
it with their Java App.
Tasks:
Goal: 1. Install JDK
2. Add App to Workspace
Make an OCAPI call. 3. Install Java Extension Pack
4. Create the URL
5. Run the App
6. Enter the Required Fields
7. View Results
Scenario:
Postman allows you to send a post request, which changes something on the
server. We’d like to use OCAPI to create a new customer in Business Manager.
Let’s practice making an OCAPI call with this third-party application.
Tasks:
Goal: 1. Register a New Customer
2. Download and Install Postman
Use OCAPI with a third-
3. Import a Postman Collection
party application.
4. Update the Host Server
5. Get Customer Authorization
6. Get Customer
7. Get Client Authorization
8. Post New Customer
9. Verify New Customer
Jobs
Jobs
DEFINITION: Jobs automate routine tasks or long-running processes. Jobs can use out-of-the-box
system steps or developers can create custom job steps. Jobs can run manually or on a schedule.
Job
Flow A Flow B
Step Step
Step Step
Step
Job Flows
NOTE: In the Business Manager UI, sequential flows take up the width of the screen (1) and execute
in the order shown, from top to bottom. Sibling flows appear next to each other and run
simultaneously as long as system resources are available (2).
2
Job Flow Scope
When you create a job flow, you must select one of the following scope
options:
All Storefront Sites On all storefront sites available at the time the job executes
Site Parameter On the sites you pass to it using the OCAPI Data API
Job Steps
The job framework includes out-of-the-box system job steps that require no coding
for common processes. A developer can create custom job steps if required.
Name Description
ExportCatalog Exports catalog data.
RESOURCE: For a full list of all job steps included with B2C Commerce, search for All Job Steps in the
B2C Commerce Infocenter.
Job Parameters
NOTE: Use only for step parameters that have the same type as the parameter for which you originally
set the job parameter.
Managing Jobs
Job History
CLICK PATH:
Administration | Operations | Job History
CLICK PATH:
Administration | Operations | Job Statistics
Scenario:
The product team is introducing new shirts in the store. The data has
been exported from the PIM and is provided to in an XML file. Create a
job that imports the file.
Goal: Tasks:
1. Upload XML File
Create an import job.
2. Create a Job to Import the Catalog
3. View Job History
4. Verify Success
NOTE: In reality, you could schedule this as a nightly batch job that will pick up a routine PIM export.
Introductions 3 | Cartridges
1 | Overview of
& Housekeeping B2C Commerce 2 | Getting & Plug-ins
Started 4 | Controllers,
Routes, &
Debugging
7 | Objects &
5 | Models Forms 8 | Hooks,
6 | ISML, Content OCAPI, & Jobs 9 | Performance
Slots, & Page & SFRA Tooling
Designer
Story
Discussion
Caching Recommendations
Scenario: You can control the cache time of individual pages. For
this example, you’d like to set the cache time of the promo
description page to 2 minutes. You’ll use middleware chaining to set
cache time through the controller.
Tasks:
Goal:
1. Update Cache Script
Cache the
promodesciption.isml 2. Create a Controller
template. 3. Test Controller
NOTE: You’ll verify the cache time of the page in the next exercise.
<isinclude url="${URLUtils.url(‘Pdescription-Show','cid',
'COOKIE_TEST')}">
Exercise 9-2: Implement Partial Page Caching
Scenario:
Let’s return to our promo landing page. You don’t want this entire page to be
cached, only the promo description. Because the cache time is set through the
controller and not the page itself, use a remote include instead of a local include.
Goal: Tasks:
1. Update ISML
Cache a portion of
storefront page. 2. Test Page
The Pipeline Profiler provides insight into pipeline and script performance.
Site Performance: Code Profiler
We’ll review…
GitHub Repositories
• Create Cartridges
• Lint Code
• Compile Code
• Upload Cartridges
• Run Unit Tests
• Run Integration Testing
NOTE: package.json is a file at the root of each project (folder/cartridges) that contains
metadata information which the package requires.
Scenario: In order to use SFRA Tooling with NPM scripts, you’ll need to in
install SFRA from GitHub. For this exercise, we’ll provide a downloaded,
zipped version for you. You can read more about the available scripts in
the README file of the SGMF Scripts repository.
Tasks:
Goal: 1. Unpack Repository
Install SFRA & Tools from 2. Create a New Workspace
the Command Line. 3. Check Node Version
4. Create a dw.json File
5. Install SFRA Command-Line Tools
6. Run Basic Scripts
Scenario: There are two types of testing provided with SFRA Tooling, unit
and integration. Integration testing checks to see if different pieces of the
code are working together. Unit testing checks a single component of an
application. Let’s test these powerful tools.
Goal: Tasks:
1. Run Unit Tests
Use command line tool to
perform tests. 2. Run Integration Tests
What’s Next?
LEARN ALL THE SKILLS YOU NEED
Build on your skills with self-paced learning or another expert-led class.
https://sfdc.co/learnsalesforce