You are on page 1of 259

Student Guide

B2C Commerce Developer


with SFRA
SFCCD-102W22v1-SG
Agenda for CCD102

Day 1:

Introductions

Access Training Files

Overview of B2C Commerce

§ Salesforce B2C Commerce

§ Storefront Reference Architecture (SFRA)

§ Business Manager

Getting Started

§ Access SFRA in Business Manager

§ Setup a Workspace in Visual Studio Code

§ Navigate Directories and Files in Visual Studio Code

Cartridges & Plugins

§ Explain SFRA Cartridges

§ Work with Plugin Cartridges

§ Use a Custom Cartridge

§ Update the Cartridge Path in Business Manager

§ Create a New Code Version to Upload Cartridges to the Sandbox

Controllers, Routes, & Debugging

§ Explain Controllers & Routes

§ Troubleshoot & Debug Code

Create a Controller

Perform Script Debugging

Extend a Controller

Changing or adding Data Using Prepend & Append

Day 2:

Controllers, Routes, & Debugging

§ Use Middleware Scripts & Chaining

§ Call a Script in a Controller

Models

§ Explore Models in SFRA

§ Extend a Model Using base.call

§ Extend a Model Using a New Decorator

ISML

§ Create an ISML Template

§ Use a Decorator Template


§ Use a Remote and Local Include
§ Use a Loop in ISML
§ Use Resource Bundles in Templates

Content Slots & Page Designer


§ Create a Content Slot
§ Create a Content Slot Configuration
§ Create a Page Using Page Designer

Day 3:

Content Slots & Page Designer

§ Develop a Component for Page Designer


§ Display a Page Designer Page

Objects & Forms


§ Explain the Forms Framework
§ Modify a Form (Server-Side Validation)
§ Modify a Custom Object Type
§ Retrieve Customer Information
§ Enable Custom Logging
§ Modify and Capture a System Object
§ Locate Client-Side Form Validation

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

Performance & SFRA Tools


§ Implement Page Caching
§ Implement Partial Page Caching
§ Track Performance Metrics
§ Explain SFRA Tools
§ Explore GitHub
§ Install SFRA with NPM Tools
§ Perform Unit & Integration Tests
SFCCD-102W22v1-SG

B2C Commerce Developer with SFRA

CCD102
Copyright

© Copyright 2000-2019 salesforce.com, inc. All rights reserved. Various trademarks held
by their respective owners.

Rights of ALBERT EINSTEIN are used with permission of The Hebrew University of


Jerusalem. Represented exclusively by Greenlight.

This document contains proprietary information of salesforce.com, inc., it is provided


under a license agreement containing restrictions on use, duplication and disclosure
and is also protected by copyright law. Permission is granted to customers of
salesforce.com, inc. to use and modify this document for their internal business
purposes only. Resale of this document or its contents is prohibited.

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.

Forward Looking Statements

Statement under the Private Securities Litigation Reform Act of 1995:


This document and other items we publish, including through social media other matters, and any related claims, negotiations and settlements;
outlets, may contain forward-looking statements, the achievement or unanticipated changes in our effective tax rate; factors affecting our
success of which involves risks, uncertainties, and assumptions. If any such outstanding convertible notes and credit facility; fluctuations in the number
risks or uncertainties materialize or if any of the assumptions proves of shares we have outstanding and the price of such shares; foreign
incorrect, the results of salesforce.com, inc. could differ materially from the currency exchange rates; collection of receivables; interest rates; factors
results expressed or implied by the forward-looking statements we make. affecting our deferred tax assets and ability to value and utilize them,
The risks and uncertainties referred to above include – but are not limited including the timing of achieving profitability on a pre-tax basis; the
to – risks associated with possible fluctuations in our financial and potential negative impact of indirect tax exposure; the risks and expenses
operating results; our rate of growth and anticipated revenue run rate, associated with our real estate and office facilities space; and general
including our ability to convert deferred revenue and unbilled deferred developments in the economy, financial markets, and credit markets.
revenue into revenue and, as appropriate, cash flow, and our ability to grow Further information on these and other factors that could affect the
deferred revenue and unbilled deferred revenue; errors, interruptions or financial results of salesforce.com, inc. is included in the reports on Forms
delays in our service or Web hosting; breaches of our security measures; the 10-K, 10-Q and 8-K and in other filings we make with the Securities and
financial impact of any previous and future acquisitions; the nature of our Exchange Commission from time to time, including our most recent Form
business model; our ability to continue to release, and gain customer 10-K. These documents are available on the SEC Filings section of the
acceptance of, new and improved versions of our service; successful Investor Information section of our website at www.salesforce.com/
customer deployment and utilization of our existing and future services; investor.
changes in our sales cycle; competition; various financial aspects of our Any unreleased services or features referenced in this or other
subscription model; unexpected increases in attrition or decreases in new presentations, press releases or public statements are not currently
business; our ability to realize benefits from strategic partnerships; reliance available and may not be delivered on time or at all. Customers who
on third-party computer hardware and software; the emerging markets in purchase our services should make their purchase decisions based upon
which we operate; unique aspects of entering or expanding in international features that are currently available.
markets; our ability to hire, retain and motivate employees and manage our
growth; changes in our customer base; technological developments;
regulatory developments; litigation related to intellectual property and

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

Logistics Courseware and Your Fellow


Agenda Students
• Class etiquette • Agenda for this class • Your name
and participation • Layout of the manual • Goals for your time
• Breaks and exercises in this class
• Download Files

B2C Commerce Developer with SFRA (CCD-102)

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)

Developing for Salesforce B2C Commerce Cloud Using


Storefront Reference Architecture (CCD-102)
LESSON 1:
Overview of B2C Commerce
LESSON 2:
Getting Started
LESSON 3:
Cartridges & Plugins
LESSON 4:
Controller, Routes, & Debugging
LESSON 5:
Models
LESSON 6:
ISML, Content Slots, & Page Designer
LESSON 7:
Objects & Forms
LESSON 8:
Hooks, OCAPI, & Jobs
LESSON 9:
Performance & SFRA Tools

Join Me 1-1: Access Sandbox and Training Files

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

Lesson 1: B2C Commerce & Storefront Reference Architecture


Overview

We’ll begin this class with a foundation in Salesforce B2C


Commerce & Storefront Reference Architecture.

1. B2C Commerce Overview


2. Storefront Reference Architecture
3. Business Manager

Salesforce B2C Commerce Integrations


Instances

A B2C Commerce Instance Type Purpose


instance is an application Sandbox Used by developers to create and update storefront
infrastructure that code. One per developer. You usually have five or
includes the following more (POD based) / infinite (on-demand).
components: Development User acceptance testing. CDN-enabled on a pass-
through level. Not scalable.
• Web servers Staging Shared by many merchants to import and maintain
storefront data. Used to preview storefront data as it
• Application servers has been scheduled for the future.
• Database servers
System administrators import data and upload code
to prepare it for testing.

Only instance that can have both data and code


replicated both to development and production.
Production A live, scalable storefront that is CDN-enabled.

B2C Commerce Architecture 13

ODS
Realm
Realm
Sandboxes

Data Center POD

Development Staging Production


Primary
Instance
Group (P.I.G.)

Secondary Sandboxes
Instance
Group (S.I.G.)
....
Storefront Reference Architecture (SFRA)

• Out-of-the box blueprint for


site design, with fully
functioning cart, checkout,
homepage, detail page.
• Leverages JavaScript
controllers development
model, User Experience best
practices, data driven design,
and the popular Bootstrap
mobile UI.
• Easily customized by
retailers, system integrators,
and developers.

SFRA Cartridge Stack

Site
Storefront Branding
PLUGIN

Wishlist Payment Integrations Gift Registry

LINK
Apple Pay Other In Store Pick-Up

PWA Cross-Cloud Integrations Sitemap

SFRA Core Codebase

Storefront Reference Architecture

Commerce Cloud API Layer

Features and Functionality


Global Release Process on the Commerce Cloud Platform

Model View Controller (MVC) Architectural Pattern

storeLocator.isml
Shopper
stores.js
Sees View
Model
Updates
Uses

ViewModel
Binds
ViewModel Controller Manipulates
Stores.js
Stores-Find

Benefit: Enforces the Development of Modular and Maintainable Code


Business Manager

Merchants use the Business Developers use the Business


Manager to manage: Manager to:
• Products and catalogs • Deploy code
• Content • Define objects
• Marketing campaigns • Add cartridges
• Search settings • Adjust OCAPI settings
• Customers • Manage:
• code and data replication
• Site analytics
• code versioning
• Site URLs • site development
• Site preferences • data import and export
• global preferences

Demo: Business Manager Organization

I’ll demonstrate the main


features of the Business
Manager.

Lesson 1: Knowledge Check

Name the architectural pattern used in SFRA.

Name two features of the 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

As a developer building your company’s To get started, you’ll use Storefront


digital storefront, you’ve been tasked Reference Architecture (SFRA) as a
with creating a fully functioning site. foundation for a customized site.

Make sure to…

✓Access SFRA
✓Set your workspace
✓Navigate cartridges

Ways to Access SFRA

From Business Manager… From GitHub…

SFRA Core Codebase SFRA Core Codebase


or
All-in-One Codebase Plugin Cartridge Clone or
download the
and/or
plugin and link
Code is compiled. Extra Link Cartridge cartridges you
steps needed to use and/or need. Use NPM
command line tools for scripts to compile
Customization Cartridge
front end development code.
and testing in the future.

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.

Storefront & Master Catalog Structure

Each site may consist of:


• One or more master catalogs which contain the actual products
• A single storefront catalog (site catalog) which provides search and
navigation with categories

Products

Storefront
Catalog
Master Catalogs
Products Storefront
Site

Exercise 2-2: Share Catalog Data Between Sites

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

NOTE: Sites can share catalogs.


Exercise 2-3: Set Up Your Workspace

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.

Join Me 2-4: Navigate Directories & Files in VSC

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

5 minutes 4. Open a New Window


Lesson 2: Knowledge Check

True or False
You can access SFRA through GitHub.

You do not need to rebuild search indexes for a site.


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…

✓Explain SFRA cartridges


✓View the modules folder and explain
purpose
✓Work with plugin cartridges
✓Use a custom cartridge for changes
✓Update the cartridge path in the
Business Manager
✓Create a new code version

Cartridge

DEFINITION

1 Folder containing a set of resources.

2 Provides specific storefront features or an external integration.

3 Has specific subfolders for different types of resources – templates,


scripts, forms, and static content.
Typical Cartridge Stack

Description Development Guidance

Project customizations Customize as Necessary

LINK plugins with


Ideally Never Change
additional functionality
at your own risk
built by a third-party

Plugins with additional Ideally Never Change


functionality at your own risk

Base cartridges Never Change

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

Example: product.isml is in both the plugin and base


cartridges. The template is not found in the custom cartridge. B2C
Commerce uses the first one it finds in the path from left to right.

Cartridge path:
app_custom_cartridge:plugin_cartridge:app_storefront_base

Not found Executed (Not searched)


Cartridge Path Considerations

Plugin cartridges are…


• Developed against the base cartridge, but not
against each other.
• May contain conflicting code, for example
using the same template or controller name.

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

• Use CommonJS modules to share


reusable functionality
• Modules folder is a peer of cartridge
folders
• SFRA provides a server module

CommonJS is a specification (not


a library) that defines the
behavior of the exports variable
as well as the require function.

NOTE: Never edit the contents of the server module, as it voids any promise of backward compatibility
or support from Commerce Cloud.

Exercise 3-1: Work with Plugin Cartridges

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

Exercise 3-2: Use a Custom Cartridge

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.

Exercise 3-3: Create a New Code Version

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.

Best Practices for Cartridges

• Never directly modify anything in the


base cartridges (app_storefront_base or
modules).
• Use custom cartridges to separate
functionality specific to a brand or locale,
so you can reuse most of your cartridge
stack for other sites.

Lesson 3: Knowledge Check

What are the two main directories you’ll find in the


Storefront Reference Architecture?

Why is the order of the cartridges on the cartridge path


important?

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

1 Server-side scripts that handle storefront requests.

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.

3 Written in JavaScript and B2C Commerce Script, and must


conform to the CommonJS module standard.
B2C Commerce Script

• Server-side language based on JavaScript


• Access storefront site data, such as products, catalogs, and prices
• Used in controllers and ISML templates

Example from SFRA


server.get('MiniCart', server.middleware.include, function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');

var currentBasket = BasketMgr.getCurrentOrNewBasket();


var quantityTotal;

res.render('/components/header/miniCart', { quantityTotal: quantityTotal });


next();
});


Controller Code Example

Use require to load the


server module
'use strict';

var server = require('server');


server.get('Show', function (req, res, next)
{
res.render('/home/homepage');
next();
});

module.exports = server.exports();

Registers all functions in the controller that use server.get, server.post,


or server.use functions as routes


Server Module
DEFINITION: Located in the SFRA global modules folder, it provides the routing functionality for
controllers. EVERY controller requires this module.

//server.js is in modules cartridge


var server = require('server’);
First parameter:
always the server.get('Show', function(req, res, next) {
name of the res.json({ value: 'Hello World'});
route (URL
next();
endpoint)
}); Last parameter: usually the main
function for the endpoint.
module.exports = server.exports();

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

server.get('Show', function (req, res, next){


res.render('/home/homepage');
next();
});

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.


Add Middleware Functions


MIDDLEWARE CHAINING DEFINITION: The process of adding functions between the first and last
parameter, with functions taking 3 arguments: req, res, and next.

req Stands for request module, which references the req.getPageMetaData


Request class. Use when you are looking for input req.getFormData
information. req.querystring

res Stands for response module which references the res.json


Response class. Use for outputting data back to the res.setViewData
client. res.render(templateName.data)
res.getViewData

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.

Get Ready to Code

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

I’ll demonstrate how to


test a controller in the
storefront.
Anatomy of a Controller URL

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).

NOTE: This assumes that Rule-Based Storefront URLs are disabled.


Exercise 4-1: Create a Controller, Version 1

Scenario: To illustrate the basic syntax of a controller, use an old


favorite, “Hello World”. You’ll create two versions. In the first one,
print content directly to the response.

Goal: Task:

Show how a basic 1. Create a Controller to Write a Response


controller works.

NOTE: Writing directly to the response is not recommended, especially in a production instance.
However, it is useful from troubleshooting.

Passing Parameters

Renders the hello.isml template and passes a string message called


param1:
res.render('hello', {param1:"Hello from ISML"});

param1 is loaded on the pdict hashmap in the hello.isml template:


${pdict.param1}

Exercise 4-2: Create a Controller, Version 2

Scenario:
Now, create a controller that renders an ISML template with a
dynamic property that accesses the declared value “Hello World”.

Goal: Tasks:

Render an ISML template 1. View the ISML Template


and pass a parameter. 2. Create a Controller to Render an ISML
Template

General Troubleshooting

Use this checklist to for general troubleshooting:

❑ All cartridges are in a cartridges folder.


❑ dw.json is located in the root folder and has accurate
information.
❑ Cartridges are being uploaded to the server.
❑ Target and Active version directory match.
❑ Cartridge path names are correct.
❑ Time to live is 0 and Enable Page Caching is disabled.
❑ Site has been indexed.
❑ Save before executing and type the URL correctly.

Join Me 4-3: Troubleshoot with the Request Log Tool

Tasks:
1. Select RefArch (if not selected) storefront.
2. Click Toolkit.
3. Click the Request Log icon.
4. View the Request Log.

10 minutes

Debug Scripts and Controllers

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.

Inherits functionality from the next


'use strict'; controller with the same name found
to the right on the cartridge path.
var server = require('server');
var page = module.superModule;
server.extend(page);

Extends existing server object with a list of new routes from


the controller with the same name found by
module.superModule.

Ways to Extend a Route

Use server.extend, then…


Purpose Considerations
server.append Modifies the route by inserting Do not use when you’re
functionality after the original interacting with a web service or
middleware. third-party system.
server.prepend Modifies the route by inserting
functionality before the original
middleware.

server.replace Modifies the route by replacing the Replace a route to change


original middleware. individual steps in a middleware
chain.

Prepend and Append

Example: Prepend and append are used in plugin_wishlists


to modify the Login route in the Account.js controller. Additional
viewData is inserted before and after the route. Navigate to
training/plugin_cartridges/plugin_wishlists/
controllers/Account.js to see the full solution.
var server = require('server');
server.extend(module.superModule);

server.prepend('Login', function (req, res, next) {



next();
});

server.append('Login', function (req, res, next) {



next();






Exercise 4-5: Extend a Controller

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

Creating a Custom Home Page

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.

Middleware Scripts & Chaining

• 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
);
}






Exercise 4-7: Use Middleware Scripts & Chaining

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

B2C Commerce Script API

Salesforce updates B2C Commerce several times per year:


• Sandboxes are updated before PIG instances
• Updates include a well-documented API
• Version number is at the bottom of the Business Manager: Year.Number

B2C Commerce API Packages

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

• Model that uses the B2C Commerce API


• Provides reusable functionality
• Use these scripts first before creating your own

BEST PRACTICE: Include B2C Commerce API in scripts or models, instead of directly in a controller, to
follow the MVC pattern.

Exercise 4-8: Call a Script from a Controller

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

Lesson 4: Knowledge Check

True or False
Controllers must conform to B2C Commerce module
standard.

Middleware chaining allows you to extend routes


without having to rewrite them.

Introductions
1 | Overview of 3 | Cartridges
& Housekeeping B2C Commerce 2 | Getting
Started 4 | Controllers,
Routes, &
Debugging

5 | Models 7 | Objects &


8 | Hooks,
Forms
6 | ISML, Content OCAPI, & Jobs
Slots, & Page 9 | Performance
Designer & SFRA Tooling

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…

✓Locate Models in the base cartridge


✓Extend a Model by using
superModule functionality with the
call() method
✓Extend a Model by creating a new
decorator
Total number in
stock

Model

DEFINITION

1 Takes API objects and converts them to serializable JSON.

Applies business logic while it’s doing the conversion, to represent


2
information in a usable format.
Join Me 5-1: Models in the Base

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

10 minutes 3. View the Product Model


• app_storefront_base/cartridge/models/product
• Complex model
QUESTION: Since you should never directly modify code in the base cartridge,
how would you override or extend a model?

Extend a Model

Example: To customize a model, you call the original model in


app_storefront_base and add properties to the JSON using
superModule functionality with the call() method.

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);
}






Exercise 5-2: Extend a Model

Scenario: You’d like to customize the store model to include an email


address for each store location. To do this, you call the original model in
app_storefront_base and add properties to the JSON using
superModule functionality with the call() method.

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

Extend a Model with a New Decorator

*New Decorator: *Included Template: productAvailability.isml


stockinformation.js Main Template: productDetails.isml
Decorator: availability.js
Shopper
*Model: fullProduct.js Sees View
Model
Updates
Uses

ViewModel
Binds
ViewModel Controller Manipulates
Product.js
* In the next exercise, we will be Product-Show?pid=
updating these files.

Exercise 5-3: Extend a Model with a New Decorator

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:

Create a new decorator 1. View Current Functionality in the Storefront


for the product model. 2. View Current Functionality in the Code
3. Create a New Decorator
4. Extend the Model
5. Update the View
QUESTIONS: Can you explain what’s happening in this solution?

Lesson 5: Knowledge Check

How can you extend a model when no decorator


pattern is used?

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

5 | Models 6 | ISML, 7 | Objects &


Content Slots, Forms 8 | Hooks,
OCAPI, & Jobs
& Page 9 | Performance
& SFRA Tooling
Designer

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

• Internet Store Markup Language


• Transform data, tags, and markup into HTML
• Generate dynamic HTML responses
• .isml files
• Include ISML tags
• Contains expressions View

Join Me 6-1: Prophet Debugger & ISML

Tasks:
Advanced support of ISML syntax
1. Select an ISML template. includes hover information,
2. Open Prophet Debugger. autocomplete tags, and more.

3. Hover over ISML tags.

5 minutes

ISML Tags

ISML tags can be grouped by function. ISML Tag Groups


<isif> <isreplace/> • HTTP-related
<isloop> <isselect> • Flow control
• Variable-related
<isinclude> • Include
<iscomponent> • Scripting
<isslot>
• Forms
<isdecorate> • Output
<ismodule> <isset> • Others
• Active Data

Common Examples of ISML Tags in SFRA

<iscomment>
Use this server-side comment tag instead of an HTML <!-- --> tag.
Example

<iscomment>This code is not executed by the server.</iscomment>

<isscript>
Use this to create scripts within templates.
Example
<isscript>
var assets = require('*/cartridge/scripts/assets.js');
assets.addCss('/css/account/dashboard.css');
</isscript>

Common Examples of ISML Tags in SFRA

<isprint>
Prints formatted output from a variable or expression, using regional settings that you can configure in Business Manager.
Examples

<isprint value="${myNumber}" style="DECIMAL"/>

<isprint value="${myNumber}" style=”MONEY_SHORT"/>

<isprint value="${myNumber}" style="DATE_LONG"/>

Template Decorator

Decorator area

<isreplace/> area

Decorator area
Types of Template Decorators

Syntax for Page Decorator Template: Navigation


<isdecorate template = "common/layout/page">
...
</isdecorate>

Syntax for Checkout Decorator Template: No Navigation


<isdecorate template = "common/layout/checkout">
...
</isdecorate>

Using a Template Decorator

1 Template that uses a decorator:


<isdecorate template="common/layout/page">
...My content...
</isdecorate>

2 The decorator template: 3 Final generated page:


page.isml
<html> <html>
<head>…</head> <head>…</head>
<body> <body>
Header, Navigation Header, Navigation
<isreplace/> ...My content...
Footer, Copyright Footer, Copyright
</body> </body>
</html> </html>




























Building a Promotional Landing Page

promo.isml 6-2
Template
6-6 decorator
Resource Bundle

6-7 & 6-8


Slot creation & config

6-4 & 6-5


6-3
Loops, remote
Local include
include

Exercise 6-2: Use a Template Decorator

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

Best Practices for Other ISML Tags in SFRA

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

The TopLevel package and its global class are implicit in ISML. Do not
include them explicitly in ISML templates.

This code causes a runtime error:


${TopLevel.global.slotcontent.content}

You must omit TopLevel.global:


${slotcontent.content}

The dw.web Package

Like the TopLevel package, the dw.web package is


implicit in ISML. You need not include it explicitly in your
ISML, but unlike TopLevel.global, it will not cause an
error if you do.

${dw.web.URLUtils.url()}
This
code:
${URLUtils.url()}
Is equivalent to this
code:


Examples of Complex ISML Expressions

ISML expressions allow complex arithmetical, boolean,


and string operations.

Examples
${lineItem.productType === 'bundle' && ((pdict.order && !
pdict.order.orderStatus) || miniCart)}

${'slotBannerImage' in category.custom &&


category.custom.slotBannerImage}

${pdict.valid.error && pdict.items.length !== 0}


Local Includes

A local include embeds one ISML template in another ISML template.


Syntax
<isinclude template="[directory/]templatename"/>

The .isml extension


Example
is not required.
Template 1:
<h1>My Template</h1> <br/> Browser Output
<isinclude template=" My Template
extras/calendar"/>
Included template
 
Template 2 (calendar.isml):
<h1>Included template</h1>

Exercise 6-3: Use a Local Include

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.

Creating and Accessing Variables

Use the isset element to create and access custom variables in an ISML template.

<isset name = "x" value =


<isset "12343" scope= "page"/>
name = "<name>"
value = "<expression>"
scope = "page"
>

The scope is session by <isset name = "x" value =


default. Only “page” is "${12343}" scope= "page" />
recommended.

Retrieval Syntax by Scope

Use the isset element to create


and access custom variables in
an ISML template.

<isset name="order" value="${pdict.account.orderHistory}"


scope="page"/>
<isinclude template="account/order/orderHistoryCard"/>

Retrieval syntax: ${order}


Variable Attributes

Value Attribute Scope Attribute


A hardcoded string or number, or an The accessibility level of the
variable.
ISML expression that accesses another
Scopes from widest to narrowest
variable or object access:
Value Type Example • Global Preferences
String value="hardcoded text" • Site Preferences
value="$ • session
Expression {pdict.myProduct.name}" • pdict
• request
• page
• slotcontent
• <isloop> variable

Conditional Statements and Loops

<isif condition="${ ISML expression evaluated}">


Do something here if the condition is true.

<iselseif condition="${ check another condition}">


Do something if this condition is true.

<iselse>
If none of these conditions is true, do this.

</isif>







Using Conditional Statements

1. Decide where you want to write your ISML conditional statement.


2. Begin your conditional statement with the <isif condition="…"> tag.

Example
<isif condition="${pdict.myProduct.online}">
Product is online

<iselse>
Product is offline

</isif>




Loops

• Use the <isloop> tag to loop through elements in a collection or array.


• List data such as categories, products, shipping methods, or payment
methods.
• Use the <isbreak> and <isnext> tags to control the loop.
Syntax
<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>







<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

For the status variable, the following properties are accessible:

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>





















Exercise 6-4: Use a Loop in ISML

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

A remote include invokes a controller that returns HTML at runtime.


Syntax
<isinclude url="controller_url"/>

Examples
Build a site-specific URL dynamically (to avoid a hardcoded server name):
<isinclude url="${URLUtils.url('Cart-MiniCart')}" />

Pass URL parameters to the invoked controller:


<isinclude url="${URLUtils.url('Tile-Show', 'pid',
product.id, 'swatches', true, 'ratings', true,
'showQuickView', false)}" />

Exercise 6-5: Use a Remote Include

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.

Resource API and Resource Bundles


Using a Resource Bundle

Syntax
dw.web.Resource.msg(key:String, bundleName:String, defaultMessage:String)

Examples
Localized string value default text

Resource.msg('page.heading.payments', 'payment', null)

Name of properties file (refers to all,


Use to display parameters payment, payment_fr, etc.)
Resource.msgf('page.heading.payments', 'payment', null,
parameter1)
Value of first parameter

Exercise 6-6: Resource Bundles in a Template

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

To see content slots on the storefront:


1. Click Toolkit in Business Manager.
2. Click on the Content Info icon in the 3
storefront Toolkit.
3. Move your mouse pointer over sections
of the page to reveal slots.

Content Slots and Content Assets

Content Slot Content Asset

UP TO 75% OFF

• Configured within campaigns • Non-configurable, reusable elements


• Business Manager: Merchant Tools>Online • Business Manager: Merchant
Marketing>Content Slots Tools>Content>Content Assets

Creating and Configuring Content Slots

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

Developer Creates a Content Slot

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}"
/>

Developer Creates a Slot Rendering Template

The header_banner slot uses the htmlslotcontainer template as the


rendering template.
1. slotcontent is not empty

<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









Exercise 6-7: Create a Content Slot

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.

Merchant Creates a Content Slot Configuration

Enter HTML

Enter product IDs

Add a schedule (optional)


Structure for Slot Rendering Templates in SFRA

• Merchant can choose to reuse an


existing rendering template or use a
new one as instructed by the
developer.
• Collaboration between merchant
and developer is important—without
a rendering template, there is no way
to visualize the slot.

Using Content Link Functions

href="$url('Page-Show', 'cid', '2-day-shipping-popup')$"


Exercise 6-8: Create a Content Slot Configuration

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

Allows business users to build commerce experiences faster


Create and manage pages
Business users can design, schedule and publish
pages quickly

Drag and drop content


A powerful visual editor makes content and layout
changes easy

Preview across all touchpoints


Ensure beautiful experiences with preview by device
type, customer group, schedule and locale

Build with reusable components


Developers leverage open web standards and
provided solution kit to easily create reusable
components

Let’s Dig into 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

The Structure: Pages, Regions, and Components

● 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.

Page, Region, and Component Examples

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

Developer Tasks: What can developers create?

Developers create page types and component Promo Page Type


types based on project requirements:
Banner

● Page Types Banner


○ Can be considered “templates” (promo
page, landing page, content page). Product
Tile Banner
○ Contains set regions with specified
components available for use in that
Product
Tile
Category
region. Product
Tile
Tile
● Component Types
○ Type of content available for use in a
specific region (banners, product tiles, Banner
category tiles, layout, etc).



Page and Component Storage

● A Page and Component:


○ Are part of the dw.experience package.
○ Contains regions, which can contain components.
○ Has a property type that defines use - PageType or
ComponentType.

● All the above are stored as content assets:


○ Not visible under Merchant Tools > Content
Assets.
○ Part of the content library, which can be exported.

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

● If any of these is not the case, then false is returned.

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
}
...

Cartridge Files and Folder Structure


Directory Path Contains
├── experience (.js and .json) /experience Server side logic and definitions of types
├── components
├── commerce_assets .../components/ Asset components that will have
├── commerce_layouts commerce_assets configurable attributes and render visible
├── einstein content
├── pages
├── utilities .../components/ Layout components that can contain child
├── static commerce_layout components and will render no or only
├── templates (isml) limited visible content by themselves
├── default
├── experience .../components/ Einstein components
├── components einstein
├── pages .../pages Page types

.../utilities dwscript files for server side logic not related


to a single page or component type
/static css for the experience
/templates isml used to render the pages
.../default/experience the isml used by the page and component
types








How are Types Defined?

Meta Definition Behavior Front End


region definitions Business logic Markup generation
Specifying the drop zones Gathering and preparing Producing the actual HTML
into which the merchant can merchant defined attributes by laying out the regions and
place components. for presentation, e.g. search rendering the merchant
queries. defined attributes.
attribute definitions
Specifying what content is to
be provided by the
merchants.

JSON JavaScript ISML, CSS and resource


Exercise 6-10: View Cartridge Structure & File Types

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

A NEW Frequently Asked Question Component

Convey Business Independent FAQ item


Requirements with styling for a question
starting with a and answer. Multiple items
description and can be used together to
Ecommerce Developer then defining the make a list of frequently
Director
attributes. asked questions.

Requirements

faq_item_content

Internal Attribute ID = text_faq_title


Attribute Type = string

Internal Attribute ID = text_faq_question


Attribute Type = string

Internal Attribute ID = text_faq_answer


Attribute Type = markup

Internal Attribute ID = disable_faq_title


Attribute Type = boolean
Internal Attribute ID = disable_faq_item
Attribute Type = boolean

Component Attribute Types

Component Attribute Attribute Semantics Page Designer UI DWScript API Type


Type Control

string string input field string

text string text area string

boolean boolean checkbox boolean

integer integer input field number

enum enumeration of string or select box (single select) string/number


integers

product product SKU product picker dw.catalog.Product

category category ID category picker dw.catalog.Category

markup html string rich text editor string

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

Scenario: A developer can deliver new components that are required by


business users. Once the business requirements have been collected,
the developer will create the component and view it in Page Designer.

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.

Render the Page: SFRA Code Example

'use strict';

var server = require('server');


var PageMgr = require('dw/experience/PageMgr');

server.get('Show', function (req, res, next) {


var page = PageMgr.getPage('page.ID');

res.print(PageMgr.renderPage(page.ID, "page.ID"));
next();

});

module.exports = server.exports();





Exercise 6-12: Render the Page

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

Lesson 6: Knowledge Check

When should you use the <isscript> tag?

What contexts of content slots can you create?

Can a slot be created in Business Manager?

How are types defined in Page Designer?

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

What do we ✓ Modify a Form


want to ✓ Retrieve Customer Information
capture?
✓ Compare Client-Side Forms
✓ Enable Custom Logging
✓ Modify and Capture a System Object

System & Custom Objects


About Custom Objects

Suppose you want to collect some specific customer information.


You can use a form to solicit and display user input, but how do you save that
information?

You can store information in objects:


1. First choice is to use a system object.
2. If no system object suits your needs, create a custom object type.

Considerations for Using Custom Objects

• Used to extend the B2C Commerce data model.


• Facilitate data storage when no system objects are suitable.
• Are implemented like a new table in the database. You specify the key attribute and storage
attributes.

Custom Object Type Custom Object


Company Contact City Phone Company Contact City Phone

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.

Defining a Custom Object Type

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

I’ll demonstrate how to


create a custom object
type.
Exercise 7-1: Define 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

Commonly-Used Classes in the dw.object Package


Class Description
User-defined attributes that extend a system object or
CustomAttributes custom object
Syntax: co_instance.custom.attribute
CustomObject An instance of a custom object and its attributes
Provides methods for creating, retrieving, deleting, and
CustomObjectMgr
searching for custom objects
PersistentObject Represents an object that can be stored and retrieved
Represents an object that can be extended with
ExtensibleObject
custom attributes

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

dw.object.CustomObject System Objects


Creating Custom Objects Programmatically

Create an instance of a custom object with a system-generated unique key


attribute:
CustomObjectMgr.createCustomObject("MyConfigurationObject",
UUIDUtils.createUUID());

Create an instance of a custom object with the specified email address:


CustomObjectMgr.createCustomObject("NewsletterSubscription",
args.email);

Must be unique or a unique


constraint violation occurs


Creating Custom Objects Manually

Use the Custom Object Editor in the Business Manager

Newsletter
example:
• No system object (the Profile system
object is limited to registered users)
• Exported for mass mailing
• Not replicable

Form Components

Include these basics…


• Form Definition (Metadata) in XML
File
• Controller to Render & Handle
Form
• Script to Create Custom Object
• ISML Template to View Form

Optional
• Client-side JavaScript

Sample Code to Process Forms

Form functions
var newsletterForm = server.forms.getForm('newsletter');
newsletterForm.clear();

In-memory form object persists


data during session until cleared
Render form
res.render('newsletter/newslettersignup', {
newsletterForm: newsletterForm,
… any additional parameters …
});


Database Transaction Handling

Implicit Explicit

The script automatically starts The transaction is controlled in


the transaction and then the script. The developer
commits or rolls back if B2C explicitly indicates in the code
Commerce determines it to be when the transaction should
appropriate. begin, roll back, or commit.
Implicit Transaction Control

Syntax
var Transaction = require('dw/system/Transaction');
Transaction.wrap(function()
{
//Your code
});

Example
Transaction.wrap(function()
{
couponStatus = cart.addCoupon(couponCode);
});


Explicit Transaction Control

Example var Transaction = require('dw/system/


Transaction');
Transaction.begin();
your code

try {
more code
Transaction.commit();
}
catch (ex) {
Transaction.rollback();
optional error handling code
}




Object Interaction

The fields in the ISML template form are defined by the


values in the form metadata XML.

ISML Template Form Metadata Object (optional)


XML Metadata File

XML Elements in the Form Metadata File


Element Description
form Required: top level tag that contains all other elements inside <form>…</form>
field Required: Defines data field with many attributes
Use as a child element inside a field to pre-fill multiple options such as months,
options
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 within another
list Allows inclusion of several items (such as collection of addresses) as a single field
group Allows grouping of elements to be invalidated together
Field Element May Use the Following Attributes

The only data types supported by the field element are:

• Boolean
• Date
• Integer
• Number
• string

NOTE: For more about field element attributes, see the documentation.

Form Metadata File Example

<?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

Modifying this Form…

ISML Form Custom


Template Metadata Object

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.

Exercise 7-4: Modify the View

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.

Exercise 7-5: Modify the Custom Object Type

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

Exercise 7-6: Modify the Utility Script (Model)

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.

Enable Custom Logging

Highest Fatal
Severity
Error
Warn
Info
Lowest
Debug
Severity
Writing a Custom Log

To write to a custom log, use the


dw.system.Logger.getLogger() factory method.

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

• getLogger()method throws an exception if maximum number of log files per day


has already been obtained.
• Log files are captured daily, stored for 30 days and then automatically deleted.
• After 5 days, log files are moved into a Log/Archive directory & compressed into
qzip files
• To retain log files longer than 30 days, download the files and store them locally.
• Allowing files to grow indefinitely can cause performance and storage issues, so you
can restrict files by time or size. For example, a file can be allowed to collect data for
10 minutes or to save up to 10 MB.
• You can write up to 10 MB per day into the customdebug, custominfo,
customfatal, customerror and customwarn log files. The same limit applies to
the number of fatal, error, warn, debug and info messages that can be stored in
custom named log files.

Custom Logging Considerations – An Example

• A day is 00:00 to 24:00 (12:00 AM to midnight next day) in a site time


zone. Logging is suspended until the next day (00:00) once the 10 MB
limit has been reached.
• If the maximum possible log size is almost reached, for example, the log
file size is 9.9 MB, and the next log message will exceed the limit, the log
message is still written, but only up to an additional 100 KB beyond the
100 MB. This lets you use the log content's full permitted amount.
• When the log file has reached its maximum size for the day, the
following info message is written to the log file:

+++ Maximum log file size per day reached, logging suspended.


Exercise 7-7: Enable Custom Logging

Scenario: If you’d like to capture debug and error messages in a log


file, you can enable custom logging. Use the custom log settings in
Business manager, view the necessary code in the controller, and
view via the Request Log tool.

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

Using System Objects


Exercise 7-8: Modify and Capture a System Object

Scenario: To capture registered users’ preferences, you can modify an


existing system object type. Let’s modify the profile system object, then
create a simple form that captures a registered user’s information.

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

Client-Side JavaScript Directory


cartridge/client/default/js

Form Validation Helper Class Directory


app_storefront_base/cartridge/client/default/js/components

• Invoke formValidation($form, data) to validate the form based on


the meta-data and throw an error message if necessary.
• Does not need to be sequential, we can do this via an AJAX call.

NOTE: Search the Salesforce Commerce Cloud GitHub community for the plugin_newsletter
repository to view a client-side example.

Lesson 7: Knowledge Check

True or False
The Form Definition describes the data you need from
the form and the system objects you want to use.

Extending an existing system object by adding new


attributes is preferable to creating a new custom object.

Introductions 3 | Cartridges
1 | Overview of
& Housekeeping B2C Commerce 2 | Getting & Plug-ins
Started 4 | Controllers,
Routes, &
Debugging

7 | Objects & 8 | Hooks,


5 | Models Forms
6 | ISML, Content
Slots, & Page
OCAPI, & Jobs 9 | Performance
Designer & SFRA Tooling

Story

Go deeper with advanced developer


It’s time to go further with advanced concepts, Hooks, OCAPI, & Jobs.
coding and B2C Commerce
functionality. You need to apply
Learn more, then…
concepts around Hooks, OCAPI, and
Jobs to complete a few items on your
to-do list. ✓Explain Hooks
✓Create a Custom Hook
✓Identify Aspects of Running Multiple
Hooks
✓Define OCAPI
✓Use OCAPI
✓Explain Jobs
✓Create a Job

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.

Think it through, then…

✓Explain Hooks
✓Create a Custom Hook
✓Identify Aspects of Running Multiple Hooks

Hook

DEFINITION

1 Configure functionality to be called at a specific point

2 Extension points to call scripts

3 Uses OCAPI or Custom in storefront application


Hook Definition

• Hooks definition is located in the package.json file


• package.json is located under the root folder, for example
app_storefront_base

{
"hooks": "./cartridge/scripts/hooks.json"
}

package.json file points to the hook file for a cartridge,


using the hooks keyword.

NOTE: A hook doesn’t have access to ‘req’ and ‘res’ objects like a controller does.

Sample Code for hooks.json

hooks.json location is mentioned in package.json


{
app.payment.processor.defaul
"hooks": [
t is the extension point
{
"name": "app.payment.processor.default",
"script": "./hooks/cart/calculate.js"
},
]
}

Call to the Hook from a Script


return dw.system.HookMgr.callHook('app.payment.processor.default', 'Handle',
cart
);
The function to be invoked on the hook.







Exercise 8-1: Create a Custom Hook

Scenario: Create a custom hook that sends an email when the


customer submits the newsletter subscription form. The email script
has been created for you. You’ll take it from there, creating a
hooks.json and package.json, then updating the controller.

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

Hooks: A Real World Example

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

Shop API Data API Meta API


• Access public shop information. • Access or update merchant • Access details about
• Access customer-specific data resources the resources and
• Create and submit a basket • Server-to-server integrations documents
• Interact with the system as an provided by OCAPI
agent on behalf of a customer

Examples:
• Endless Aisle • Business Manager • API Explorer
• Customer Service Center • ERP/CRM/CMS Integrations
• Pinterest Buyable Pins • Continuous Integration
• Mobile Shopping Apps

Shop API

Allows a client to interact with the system as a shop


customer or as an agent shopping on behalf of a customer.

Endless Aisle Example


A mobile application used by in-store sales professionals to
order items for a customer that are not currently in stock at
the current store location.

How It Works
Invoke Shop API to allow for product search based on
availability information.

Data API

Gives create/read/update/delete access to system resources.

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

Used to retrieve a formal description of the Open


Commerce API, including custom attributes.

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.

OCAPI HTTP Methods

GET (s) retrieves resources on the server

HEAD (s) returns headers only (same as GET request), but not resource data

DELETE (i) removes one or more resources on the server

PUT (i) create or replace a resource

PATCH allows partial resource modification by sending a delta document.

POST for action request or for Http method overriding

OPTION (s) return list of available operations for a resource


OCAPI URL Syntax - Base URL

Production Instance
http(s)://public_domain/dw/api_type/

Non-production Instance (includes staging, development, and sandboxes)


http(s)://sub_domain.demandware.net/s/site_id/dw/api_type/

*api_type = shop, data, or meta


OCAPI URL Syntax - Extended URL

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)

Action (Authenticated customer)


base_url/version_id/resource_type/action

base_url/v20_3/customers/auth

Relationship Type (Item in a Basket)


base_url/version_id/resource_type/relationship_type

base_url/v20_3/baskets/12345/items
Resource Types

Shop API Data API


• Baskets • Campaigns
• Content • Catalogs
• CustomObjects • Coupons
• Customers • CustomerGroups
• GiftCertificate • CustomerLists
• OrderSearch • GiftCertificates
• Orders • GlobalPreferences
• ProductSearch • Libraries
• Products • LocaleInfo
• Promotions • Permissions
• Sessions • Promotions
• Site • Stores
• Stores • Users
RESOURCE: Search for Shop API resources or Data Api resources in the B2C Commerce Infocenter for
a complete list of resource types.

Shop API Example

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

Shop API Example, continued

Request URL
https://demo-ocapi.demandware.net/s/-/dw/shop/v20_4/customers/4562/
product_lists/5965/items/6314/purchases?client_id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Response Class (application/json)


{
"count": 0,
"data": [
{
"id": "string",
"order_no": "string",
"product_list_item_id": "string",
"purchaser_name": "string",
"quantity": 0
}
],
"total": 0
}

Endless Aisle Example


url = scheme + '://' + storefront_host + site_url + base_url + url;

url = eaUtils.appendURL(url, 'client_id', client_id);



url = eaUtils.appendURL(url, 'locale', default_locale);
url = eaUtils.appendURL(url, 'currency', options.currency);
url = eaUtils.appendURL(url, 'country', options.country);
url = eaUtils.appendURL(url, 'c_endlessaisle', true);

if (type === 'PUT' || type === 'DELETE' || type === 'PATCH') {
params.type = 'POST’;
params.headers['x-dw-http-method-override'] = type;
}

var xhr = Ti.Network.createHTTPClient({

});

xhr.open(params.type, url);
xhr.onload = function(eResp) {










Data API Example

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}

Data API Example, continued

Request URL
https://demo-ocapi.demandware.net/s/-/dw/data/v20_4/
customer_lists/2345?client_id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Response Class (application/json)


{
"id": "string"
}

Meta API Example

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}

Meta API Example, continued

Request URL
https://demo-ocapi.demandware.net/s/-/dw/meta/v99_9/rest/shop?
client_id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Response Class (application/json)


{
"versions": [
{
"link": "string",
"name": "string",
"status": "string"
}
]
}

Override HTTP Method

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

Both examples delete a product with the ID 123.


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.

• Manage various features, including OCAPI client permission and


OCAPI caching.

• Define for for a single site (site-specific) or for all sites (global).

• Specify OCAPI setting by editing one or more JSON documents.

CLICK PATH:
Business manager | Administration | Site Development | Open Commerce API Settings

Code Review: JSON Document

{
"_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.

Example (SHOP API)

Request Method Request Path Extension Points


POST /baskets • dw.ocapi.shop.basket.beforePOST
• dw.ocapi.shop.basket.afterPOST
• dw.ocapi.shop.basket.modifyPOSTResponse
• dw.ocapi.shop.basket.validateBasket

RESOURCE:
Search for OCAPI Hooks in the B2C Commerce Infocenter.

Exercise 8-2: Configure OCAPI Settings

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

Allows application developers to interactively explore the


Open Commerce APIs. You can:

• Browse and review APIs


• Test APIs by launching requests

Built using Swagger-UI with information delivered by the


Meta APIs.

RESOURCE:
Search for API Explorer in the B2C Commerce Infocenter.

API Explorer Demo


Exercise 8-3: Use API Explorer

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.

Exercise 8-4: Making an OCAPI Call

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

Exercise 8-5: Postman

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:

Scope Flow Execution


Organization For the instance

All Storefront Sites On all storefront sites available at the time the job executes

Specific Sites Only on the storefront sites you select

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.

ExportContent Exports the folder in the specified content Library.

ExportCustomerList Exports a customer list, it's preferences as well as the


customers assigned to the customer list.
ImportCatalog Imports 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.

• Create job parameters to use in different


job steps.
• Allows you to change the value of the
parameter once, updating all steps that
include that parameter.

Managing Jobs

After jobs are created, use Business Manager to manage them.

Job History

CLICK PATH:
Administration | Operations | Job History

Monitor Job Statistics

CLICK PATH:
Administration | Operations | Job Statistics

Exercise 8-6: Create a Job

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.

Lesson 8: Knowledge Check

Where is the location of the hooks.json mentioned?

What is the difference between a hook and controller?

Which OCAPI HTTP method creates or replaces a


resource?

Where do you go to monitor the duration and number


of executions for jobs?

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

Measure the performance of each


Once your storefront is complete, you’ll function so your customers have a great
want to ensure it performs well. You’ll experience. Compile and test your code
using Node.js.
also make sure your code has been
compiled and tested.
Tackle the last steps…

✓Implement Page Caching


✓Implement Partial Page Caching
✓Track Performance Metrics
✓Explain SFRA Tooling
✓Explore GitHub
✓Install SFRA with Tools
✓Perform Tests

Discussion

Q. What is the single most critical factor in keeping


visitors on your storefront and increasing sales?
A. Page download time

Q. What impacts page download time?


A. Many objects and complex calculations, 3rd party
integrations, and slow webservices.

Q. How can you reduce page download time?


A. Cache appropriate storefront pages and smart
coding to avoid overuse of objects and complex
calculators.





Site and Page Caching

In the controller, set the cache on the set of response object.


Example
function setCacheSettings(req, res, next) {
res.cachePeriod = 24;
res.cachePeriodUnit = 'hours’;
res.personalized = true;
next();
}




Caching Recommendations

• Disable caching on sandbox, development, and


staging instances.
• Cache portions of pages that contain a mixture of
relatively-static and frequently-changing content.
• Frequently changing pages benefit from a shorter
caching period.
• As a general rule, do not cache pages that display
buyer information or session information.

Exercise 9-1: Implement Page Caching

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.

Partial Page Caching Example

<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

Site Performance: Pipeline Profiler

The Pipeline Profiler provides insight into pipeline and script performance.
Site Performance: Code Profiler

The Code Profiler provides insight into run time performance.


Demo 9-3: Track Performance Metrics

I’ll show you how to…

Track the performance metrics in


the Pipeline Profiler and the Code
Profiler.

Demo 9-4: GitHub

We’ll review…

GitHub Repositories

package.json file contents


Searching the GitHub Repo


storefront-reference-architecture
README
package.json
plugin_wishlists
sgmf-scripts
SFRA Tooling

SFRA provides an NPM repository of JavaScript


modules that run in Node.js to:

• 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.

Exercise 9-5: Install SFRA with Tools

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

Exercise 9-6: Perform Tests

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

Lesson 9: Knowledge Check

What is the default cache setting?

Where do you change the value for cache?

Are SFRA Tools available when you access the code


from Business Manager?

Thanks for Attending!


Your opinion matters, and we want to hear from you. Navigate to our
Class Survey to give us your feedback.
http://bit.do/classroomsurvey
http://bit.do/virtualsurvey

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

EARN SKILL-BASED CREDENTIALS


Get rewarded for the skills you learn and get industry-wide recognition
for your expertise.
https://trailhead.salesforce.com/credentials/

CONNECT WITH FELLOW TRAILBLAZERS


© Copyright 2021 salesforce.com, inc.
All rights reserved. Various trademarks
Community: https://sfdc.co/TrailheadCommunity
held by their respective owners.
Twitter: @Trailhead
Facebook: /SalesforceTrailhead










You might also like