SiteGenesis JavaScript Controllers (SGJC) Standards Compliance
This topic covers the following standards and supported browser versions.
Cookies Notification/Opt-in for European Cookie Law
European Cookie Law requires websites to notify
customers that cookies are being used and how. The SiteGenesis application
uses an optional content asset, called cookie_hint,
to
contain this notice.
If this asset is... | Then... |
---|---|
Missing or offline | No notice is given. The cookies are set as they always have been. This approach is used in the USA, for example. |
Present and online* | The cookie_hint content appears. Clicking I
ACCEPT sets the cookies and causes the popup to not
appear again. |
Browsers
SGJC officially supports the following browsers, and one version earlier.
Desktop
- Chrome 53+
- Firefox 49+ (including the latest Extended Support Release (ESR) that is, 45)
- Microsoft Edge 38+
- Microsoft Internet Explorer 11
- Safari 10+
Mobile
- iOS 10+: Chrome (most recent)
- Safari (most recent)
See Business Manager User Interface.
Supported Browsers Desktop (supporting the latest browser version):
Commerce Cloud Store supports the latest version of the browsers listed above, as well as one version earlier. Refer to documentation for more details. The plus(+) sign signifies support of both major and minor browser releases following the listed browser version. End of Support for Opera As of January 1, 2017, Commerce Cloud will no longer support Opera due to infrequent client use. We continue to evaluate browser usage throughout 2018, and if we see changes with browser adoption, we consider supporting it. Implications of These Changes To ensure optimal performance, we encourage all clients to upgrade to a supported browser prior to January 1, 2017. Commerce Cloud continues to test and fix bugs in all supported browsers. Customers are welcome to use any browser they want, but there can be noticeable performance issues with unsupported browsers. If you encounter any issues with a supported browser, open a ticket with Commerce Cloud Support.
CSS Input Field Types
- color
- date
- datetime
- datetime-local
- month
- number
- range
- search
- tel
- time
- url
- week
For more information, see http://www.w3schools.com/html/html5_form_input_types.asp.
SiteGenesis and Web Content Accessibility Guidelines (WCAG)
The Web Content Accessibility Guidelines (WCAG) provide a single shared standard for web content accessibility that meets the needs of individuals, organizations, and governments internationally. WCAG documents explain how to make web content more accessible to people with disabilities. See http://www.w3.org/WAI/intro/wcag.
The SGJC application was changed to better conform to the WCAG guidelines. The list of changes shown here is intended to provide examples of how you can make your storefront application more accessible:
- Added context in the titles of category refinements, folder refinements, and price refinements.
- Added prefixes in the set/bundle products titles for added context.
- Mini cart button has the title Go to Cart and not the same text as the button.
- The compare checkboxes on the category landing page product tiles now have unique label text. The unique text appends the product name to the text and visually hides it. Then, a span was added with just the text "Compare".
- Removed the title from the image and added it to the link. The image only requires alt, not a title.
- Made the title different and more contextual from the text.
- Removed invalid hypertext reference and added visually hidden text.
- Added visually hidden label to email form element in demo data.
- Removed unnecessary titles from images, added alt where missing, and ensured that previous changes were not affected.
- The user-links in headercustomerinfo.isml now include a title that adds more context to the links.
- Added visually hidden text to buttons.
- Changed titles of color refinement swatches to add more context.
- The password reset link now has a title that adds context.
- Changed demo data in library.xml for the footer content assets and added (or modified) footer titles.
- Store locator and user icons now have titles that add more context.
- Product item names in the cart have more contextual titles.
- Added visually hidden text to the link of category landing page's slot banner.
- Changed the size chart link title to add more context.
- Made product action titles are different from text and add context.
- Changed the title of color and size to add more context.
- Added prefixes to titles.
- Added visually hidden text to the social sharing links.
- Added address and add credit card pages titles have more context.
- Added titles to paging.
- Product tile titles now contain prefixes for more context.
- Removed the invalid hypertext reference error by removing the href attribute.
- Breadcrumb titles have a prefix for added context.
The WCAG guidelines followed were:
- Level A: 2.4.4 Link Purpose (In Context)
- Level AAA: 2.4.9 Link Purpose (Link Only)
The title-related corrections to SiteGenesis use technique H33 (http://www.w3.org/TR/2014/NOTE-WCAG20-TECHS-20140916/H33). The link text is supplemented with the title attribute to add more context, making it easier for people with disabilities to determine the purpose of the link.
Consent Tracking in SGJC
Commerce Cloud enables merchants to track personal information about their shoppers, and use this information to improve their shoppersβ overall shopping experience. Some merchants can decide to provide their shoppers a way to deny or grant their consent to such tracking.
This topic describes a sample implementation for consent tracking in SGJC. The purpose of this sample implementation is to suggest how you can implement this capability on a storefront adapted from SGJC. This sample implementation is meant to be informative, but not prescriptive.
This sample implementation uses:
- A content asset for displaying a consent request message to the shopper
- A site-specific preference, Tracking, to disable tracking by default
- A session-specific flag to allow tracking if the shopper grants consent
More details about the sample implementation are provided later in this document.
Content Asset for the Consent Request Message
To display a consent message to the shopper, the sample implementation
uses a content asset whose internal ID is consent_tracking_hint
.
This content asset contains meaningless text, which you can replace with your own
message.
Site-Specific Preference (Tracking)
The Tracking site preference determines the default tracking behavior for a site. If set to Opt-in, personal information is not tracked by default for all shoppers visiting the site; otherwise, personal information is tracked.
To set this preference, select Merchant Tools > site > Site Preferences > Privacy.
The sample implementation assumes that the Tracking preference is set to Opt-In.
Session Tracking Flag
The sample implementation presents a consent request message to the shopper, who can choose to allow tracking. If the shopper allows tracking, the sample implementation enables tracking during the shopperβs session.
You can enable tracking on a session by calling the following method:-
dw.system.Session.setTrackingAllowed(boolean)
-- If you call this method with a value oftrue
, the method enables tracking for the current session;false
, disables tracking.
You can determine the current value of the tracking flag by calling the following method:
-
dw.system.Session.isTrackingAllowed()
-- This method returns the current state of the sessionβs tracking flag (true
indicates that tracking is enabled;false
, disabled).
Extra Implementation Details
The sample implementation uses a server-side endpoint to set the session tracking flag based on the value of a URL parameter. The shopperβs choice to grant or deny consent determines the value of this parameter.
The server-side endpoint is named
Account-consentTracking
:
function consentTracking() {
var consent = request.httpParameterMap.consentTracking.value == 'true';
session.custom.consentTracking = consent;
session.setTrackingAllowed(consent);
}
The
result of the shopperβs decision is stored in the server-side variable
session.custom.consentTracking
. It is important to communicate
the state of this variable with the client-side code running on your storefront, so
the sample implementation places this information in a global location that is
accessible to all SGJC-based storefront pages
(footer_UI.isml
).
The client-side implementation can check
the state of this variable and store it in a client-side variable
(consent
). The client-side implementation can then use the
value of the variable to determine whether to display the consent request message to
the shopper.
Several other changes to the client side complete the sample implementation.
The following properties are added to the
βresources
β object in the Resource.ds
file:
TRACKING_CONSENT: Resource.msg('global.tracking_consent', 'locale', null),
TRACKING_NO_CONSENT: Resource.msg('global.tracking_no_consent', 'locale', null),
The
following properties are added to the βurls
β object in the
Resource.ds
file:
consentTracking: URLUtils.url('Page-Show', 'cid', 'consent_tracking_hint').toString(),
consentTrackingSetSession: URLUtils.url('Account-ConsentTracking').toString(),
The
client-side variable (consent
) is set before
is included in the
app.js
footer_UI.isml
template:
<script>var consent = ${session.custom.consentUser};</script>
<script src="${URLUtils.staticURL('/js/app.js')}"></script>
A
consentTracking
module is required in app.js
:
consentTracking = require('./consentTracking);
...
consentTracking.init();
...
$('.consent-tracking-policy').on('click', function (e) {
e.preventDefault();
consentTracking.show();
});
Lastly,
the consentTracking
module is
implemented:
function getConsent() {
dialog.open({
url: Urls.consentTracking,
options: {
closeOnEscape: false,
dialogClass: 'no-close',
buttons: [{
text: Resources.TRACKING_CONSENT,
click: function () {
$(this).dialog('close');
$.ajax({
type: 'GET',
url: util.appendParamToURL(Urls.consentTrackingSetSession, 'consentTracking', true),
success: function () {
showPrivacyDialog();
},
error: function () {
showPrivacyDialog();
}
})
}
}, {
text: Resources.TRACKING_NO_CONSENT,
click: function () {
$(this).dialog('close');
$.ajax({
type: 'GET',
url: util.appendParamToURL(Urls.consentTrackingSetSession, 'consentTracking', false),
success: function () {
showPrivacyDialog();
},
error: function () {
showPrivacyDialog();
}
})
}
}]
}
});
}
function enablePrivacyCookies() {
if (document.cookie.indexOf('dw=1') < 0) {
document.cookie = 'dw=1; path=/';
}
if (document.cookie.indexOf('dw_cookies_accepted') < 0) {
document.cookie = 'dw_cookies_accepted=1; path=/';
}
}
function showPrivacyDialog(){
if (SitePreferences.COOKIE_HINT === true && document.cookie.indexOf('dw_cookies_accepted') < 0) {
// check for privacy policy page
if ($('.privacy-policy').length === 0) {
dialog.open({
url: Urls.cookieHint,
options: {
closeOnEscape: false,
dialogClass: 'no-close',
buttons: [{
text: Resources.I_AGREE,
click: function () {
$(this).dialog('close');
enablePrivacyCookies();
}
}]
}
});
}
} else {
// Otherwise, we don't need to show the asset, just enable the cookies
enablePrivacyCookies();
}
}
var consentTracking = {
init: function () {
if (consent == null && SitePreferences.CONSENT_TRACKING_HINT) { // eslint-disable-line no-undef
getConsent();
}
if (consent != null && SitePreferences.CONSENT_TRACKING_HINT){ // eslint-disable-line no-undef
showPrivacyDialog();
}
},
show: function () {
getConsent();
}
};
module.exports = consentTracking;
Downloading a Shopper's Information in SGJC
When you implement your SGJC-based storefront, consider providing your shoppers with a mechanism to download their data.
Registered users see a Download my data button on the My Account page. When a shopper clicks this button, SGJC downloads a JSON file to the shopper's browser with the following information:
- Profile
- Address
- Payment instruments
- Orders
- Wish lists
- Gift registries
- Shopping lists
The JSON file illustrates the type of information to provide to your shoppers. Your business can provide different data in a different format.
Sample JSON file
This sample file shows the type of information you can provide to the shopper.
{
"profile": {
"birthday": "1988-10-21T00:00:00.000Z",
"companyName": "",
"customerNo": "D00000001",
"email": "[email protected]",
"fax": "",
"firstName": "Test1",
"gender": "Female",
"jobTitle": "",
"lastLoginTime": "2018-02-14T20:07:31.074Z",
"lastName": "Doe",
"lastVisitTime": "2018-02-14T20:07:31.074Z",
"phoneBusiness": "",
"phoneHome": "",
"phoneMobile": "",
"preferredLocale": "",
"previousLoginTime": "2015-05-18T20:43:17.000Z",
"previousVisitTime": "2015-05-18T20:43:17.000Z",
"salutation": "",
"secondName": "",
"suffix": "",
"taxID": null,
"taxIDMasked": null,
"taxIDType": null,
"title": "",
"male": false,
"female": true,
"nextBirthday": "2018-10-21T00:00:00.000Z"
},
"addressbook": [
{
"address1": "104 Presidential Way",
"address2": null,
"city": "Woburn",
"companyName": null,
"countryCode": "us",
"firstName": "Test1",
"fullName": "Test1 User1",
"id": "Home",
"jobTitle": null,
"lastName": "User1",
"phone": "781-555-1212",
"postalCode": "01801",
"postBox": null,
"salutation": null,
"secondName": null,
"stateCode": "MA",
"suffix": null,
"suite": null,
"title": null
},
{
"address1": "91 Middlesex Tpke",
"address2": null,
"city": "Burlington",
"companyName": null,
"countryCode": "us",
"firstName": "Jane",
"fullName": "Jane Doe",
"id": "Work",
"jobTitle": null,
"lastName": "Doe",
"phone": "781-555-1212",
"postalCode": "01803",
"postBox": null,
"salutation": null,
"secondName": null,
"stateCode": "MA",
"suffix": null,
"suite": null,
"title": null
}
],
"wallet": [],
"orders": [],
"productList": {
"whishlists": [],
"giftregistries": [],
"shoppinglists": []
},
"thirdpartydata": {}
}
Implementation Details
This example conditionally provides a Download my
data button in the accountoverview.isml
template.
<isif condition="${pdict.downloadAvailable}">
<a class="profile-data-download button"
href="${URLUtils.url('Account-DataDownload')}"> ${Resource.msg('account.landing.databutton','account',null)}</a>
</isif>
When the user clicks the button, the
Account-DataDownload
controller is called. The
Account.js
controller file applies the following guard to
the datadownload()
function, exporting it as
DataDownload
.
/** returns customer data in json format.
* @see {@link module:controllers/Account~datadownload} */
exports.DataDownload = guard.ensure(['get', 'https', 'loggedIn'], datadownload);
The body of the datadownload()
function is implemented in
Account.js
as follows.
/**
* Allows a logged in user to download the data from their profile in a json file.
*/
function datadownload() {
var profile = customer.profile;
var profileDataHelper = require('~/cartridge/scripts/profileDataHelper');
let response = require('~/cartridge/scripts/util/Response');
var site = require('dw/system/Site');
var fileName = site.current.name + '_' + profile.firstName + '_' + profile.lastName + '.json';
response.renderData(profileDataHelper.getProfileData(profile), fileName);
return;
}
This function relies on the helper script
profileDataHelper.js
, which provides several helper
functions, such as getWallet(profile)
,
getWishlists(ProductListMgr)
, and so on. The helper
script exports
, which
calls the helper functions, constructs the JSON string, and returns the
result to the shopper's browser.
getProfileData
exports.getProfileData = function (profile) {
var ProductListMgr = require('dw/customer/ProductListMgr');
var downloadJSONObj = {};
downloadJSONObj.profile = getProfile(profile);
downloadJSONObj.addressbook = getAddressBook(profile);
downloadJSONObj.wallet = getWallet(profile);
downloadJSONObj.orders = getOrders(profile);
downloadJSONObj.productList = {
whishlists: getWishLists(ProductListMgr),
giftregistries: getGiftregistries(ProductListMgr),
shoppinglists: getShoppingLists(ProductListMgr)
};
downloadJSONObj.thirdpartydata = {};
return JSON.stringify(downloadJSONObj, null, 2);
};