Salesforce Commerce Cloud (Demandware)
Salesforce Commerce Cloud (Demandware)
This is for:
DeveloperIn this article, we’ll cover the steps involved in implementing the Qubit cartridge on your Salesforce Commerce Cloud site.
Intro
What is a cartridge?
A cartridge is a mechanism for packaging and deploying program code and data. Our cartridge contains all the necessary elements to integrate your Salesforce ecommerce solution with Qubit, including smartserve.js and our QProtocol data layer, with all the data points you need to better understand your visitors, uncover relevant insights, and discover opportunities for personalization.
From a technical perspective, the setup can be divided into 2 steps:
-
Installing the cartridge and then configuring it in the Business Manager
-
Emitting events based on visitor browsing behavior
Before getting started, we will briefly provide some context around the events collected by our data layer, QProtocol, looking in particular at the events typically emitted on the different page types found on an ecommerce platform. We will also look at the types of pages you can track by installing the Qubit cartridge.
QProtocol events
In the following table we identify the QProtocol events typically emitted by page type:
Page | Available events |
---|---|
All |
ecView, ecUser, ecBasketItem, ecBasketSummary |
Home |
ecView, ecUser, ecBasketItem, ecBasketSummary |
Product |
ecView, ecUser, ecProduct, ecBasketItem, ecBasketSummary |
Listing |
ecView, ecUser, ecBasketItem, ecBasketSummary |
Basket |
ecView, ecUser, ecBasketItem, ecBasketSummary |
Checkout |
ecView, ecUser, ecBasketItem, ecBasketSummary |
Confirmation |
ecView, ecUser, ecBasketItemTransaction, ecBasketTransactionSummary |
The Qubit cartridge includes a set of methods that we can add to the ISML templates for tracking.
In the following table, we identify a list of pages that you can track in Site Genesis with Qubit:
Page type | Description |
---|---|
home |
a home page |
content |
all other pages, not from the list |
product |
a product detail page |
category |
a page listing multiple products |
search |
a search results page |
basket |
a cart view page |
checkout |
a page summarizing order details and the last page before an order is submitted |
confirmation |
the post-purchase confirmation page |
Installing the cartridge on a sandbox
Step 1
Open Studio and select File > Import > General > Existing Project into Workspace:
Step 2
Navigate to the directory containing intqubit_, and select it. Then select Finish. Finally, select OK to link the cartridge to the sandbox
Step 3
Select your sandbox connection and select Properties. Select Project References and check-in intqubit_
Business Manager setup
Step 1
Open Business Manager and select Administration > Sites > Manage Sites and then select the Salesforce Commerce Cloud site you want to install the cartridge on
Step 2
In the Settings tab add the following to the Cartridges path at the beginning of the line:
int_qubit:
Select Apply to save the change
Step 3
in Import & Export, select Import and select the file system-objecttype-extensions.xml
Configuring the cartridge
Step 1
Open your site in the Business Manager and select Merchant Tools > Custom Preferences > Qubit
Step 2
Add or edit the configuration as required. When done, select Save to commit.
Refer to the following table for details of the options available to configure the cartridge:
Name | Type | Description | Default |
---|---|---|---|
Qubit Enabled__ |
Boolean |
Whether the Qubit integration is enabled |
Yes |
Tracking ID__ |
String |
The tracking Id for your site, as provided by Qubit |
n/a |
Emit Events__ |
Boolean |
Whether Qubit events are emitted |
Yes |
UV API Script |
String |
The UV API script |
n/a |
Enable ecEvents for your store |
Array of Strings |
Defines which events will be emitted on your site, and therefore what data will be passed to Qubit |
|
Package__ |
Enumeration |
Defines which Qubit package has been selected by the client |
Pro |
Smartserve URL__ |
String |
The URL of the smartserve.js provided by Qubit, e.g. |
n/a |
Smartserve Location__ |
Enumeration |
The page location where the Smartserve script will be injected |
Start of HEAD |
Smartserve Asynchronous__ |
Boolean |
Whether the Smartserve file should be loaded asynchronously |
Yes |
Namespace |
String |
The custom namespace value, provided by Qubit during onboarding and only required for those client emitting custom events or fields |
n/a |
Send Product Listing Events__ |
Boolean |
Whether to enable the sending of product events from listing pages |
No |
Product Listing Event Limit |
Number |
Limit the number of product events sent on a product listing page |
20 |
Product Stock Data |
Boolean |
Whether to include the product stock level in product events |
Yes |
Always Send Basket Events* |
Boolean |
Whether to send basket events on every page or only in the checkout funnel |
Yes |
Checkout Pages |
String |
Comma separated controller names in the checkout funnel (for example, |
n/a |
Product’s custom SKU attribute |
String |
Name of the product’s custom attribute containing the SKU |
n/a |
Note
|
Editing app.js
The following changes must be done in the storefront cartridge.
Step 1
In appstorefront_core/cartridge/js/app.js_ edit the Qubit module path to match the cartridge location:
Step 2
Add the following line to appstorefront_core/cartridge/js/app.js_:
qubit.init();
Editing Resource.ds
You’ll need to modify Resources.ds to get the controller URL and preferences.
Step 1
Add the following lines to appstorefront_core/cartridge/scripts/util/Resource.ds_:
//Qubit Integration
ecBasketItemAction: URLUtils.url('Qubit-BasketItemAction').toString()
//Qubit Integration
Step 2
Add the following lines to ResouceHelper.getPreferences
in appstorefront_core/cartridge/scripts/util/Resource.ds_:
//Qubit Integration
QUBIT_NAMESPACE: Site.getCurrent().getCustomPreferenceValue('qubitNamespace'),
SEND_PRODUCT_LISTING_EVENTS:Site.getCurrent().getCustomPreferenceValue('sendProductListingEvents'),
PRODUCT_LISTING_EVENTS_LIMIT:Site.getCurrent().getCustomPreferenceValue('productListingEventLimit'),
ALWAYS_SEND_BASKET_EVENTS:Site.getCurrent().getCustomPreferenceValue('alwaysSendBasketEvents'),
QUBIT_PACKAGE: Site.getCurrent().getCustomPreferenceValue('qubitPackage').getValue(),
EMIT_EVENTS: Site.getCurrent().getCustomPreferenceValue('emitEvents'),
QUBIT_ENABLE: Site.getCurrent().getCustomPreferenceValue('qubitEnable')
//Qubit Integration
Editing modules.isml
Step 1
Add the following lines to util/modules.isml:
<iscomment>
Render Qubit scripts information
</iscomment>
<ismodule template="qubit/qubittrackscript"
name="qubittrackscript"
/>
<iscomment>
Render Qubit events information
</iscomment>
<ismodule template="qubit/qubittrackeventdata"
name="qubittrackeventdata"
attribute="event_type"
attribute="page_name"
attribute="page_data"
attribute="is_call_event"
/>
Step 2
To ensure the best possible data accuracy and experience delivery, it is important to call the module as early as possible on the page.
You can call the Qubit module from a number of different page locations.
htmlhead.isml
Add the following lines, to components/header/htmlhead.isml in the desired position
Top header:
<isinclude template="qubit/uvapiscript" />
<isinclude template="qubit/smartservestartofhead" />
Bottom header:
<isinclude template="qubit/smartserveendofhead" />
footer_UI.isml
Add the following lines to components/header/footerUI.isml_ in the desired position
<isinclude template="qubit/smartserveendofbody" />
Step 3
To add the module for events, add the following lines to util/modules.isml:
<iscomment>
Render Qubit scripts information
</iscomment>
<ismodule template="qubit/qubittrackscript"
name="qubittrackscript"
/>
<iscomment>
Render Qubit events information
</iscomment>
<ismodule template="qubit/qubittrackeventdata"
name="qubittrackeventdata"
attribute="event_type"
attribute="page_name"
attribute="page_data"
attribute="is_call_event"
/>
Emitting Qubit Events
ecView
Emitted on every page before any other event and with the type field populated.
Add the following lines after the </isscript>
tag in components/footer/footer.isml:
<iscomment> Qubit Integration </iscomment>
<isqubittrackeventdata event_type="ecView"/>
<iscomment> Qubit Integration </iscomment>
ecUser
Emitted once per view to report visitor metadata. The event should be emitted on every page as long as there is data available for the user.
Add the following lines in the components/header/headercustomerinfo.isml template file:
<iscomment> Qubit Integration </iscomment>
<isinclude template="util/modules"/>
<isqubittrackeventdata event_type="ecUser"/>
<iscomment> Qubit Integration </iscomment>
ecProduct
Emitted on product detail pages.
Step 1
Add the following lines at the bottom of product/producttile.isml:
<iscomment> Qubit Integration </iscomment>
<isinclude template="util/modules"/>
<isqubittrackeventdata event_type="ecProduct" page_name="search" page_data="${Product}" />
<iscomment> Qubit Integration </iscomment>
Step 2
Add the following lines at the bottom of product/components/variations.isml:
<iscomment> Qubit Integration </iscomment>
<isinclude template="util/modules" />
<isqubittrackeventdata event_type="ecProduct" page_name="${!empty(pdict.isSet) && pdict.isSet ? 'linkedproduct' : 'product'}" page_data="${pdict.Product}" />
<iscomment> Qubit Integration </iscomment>
Step 3
Add the following lines to product/producttopcontentPS.isml:
<iscomment> Qubit Integration </iscomment>
<isinclude template="util/modules" />
<isqubittrackeventdata event_type="ecProduct" page_name="linkedproduct" page_data="${pdict.Product}" />
<iscomment> Qubit Integration </iscomment>
Step 4
It is also necessary to make changes to the storefront Javascript files to emit events when the quickview popup opens.
Add the following lines to the load
function in appstorefront_core/cartridge/js/ajax.js_:
"var loadAjax = " (assign ajax call in variable call loadAjax)
"return loadAjax;" (return loadAjax at the end of ajax call)
Step 5
Add the following lines to the replace
section in appstorefront_core/cartridge/js/dialog.js_:
"var replaceDialog = " (assign ajax load call in replaceDialog variable)
"return replaceDialog;" (return replaceDialog at the end of the ajax load call)
Step 6
Add the following lines in the navigateQuickview
function in appstorefront_core/cartridge/js/quickview.js_:
"var navigateQV = " (assign dialog.replace call in navigateQV variable)
Add the following lines after the dialog.replace
in the same file:
if (navigateQV) {
navigateQV.then(function() {
$( "body" ).trigger( "productQuickView");
});
}
ecBasketItem
Emitted on every page, as long as there are one or more items in the user’s basket.
Add the following lines before the pliList
loop in checkout/components/minilineitems.isml:
<iscomment> Qubit Integration </iscomment>
<isinclude template="util/modules" />
<isqubittrackeventdata is_call_event="${pdict.p_showreverse}" event_type="ecBasketItem" page_data="${productLineItem}" />
<iscomment> Qubit Integration </iscomment>
ecBasketItemAction
Emitted for every interaction with the basket, using the action field to specify whether a line item was added or removed. The event should also contain the summary for the full basket.
For line item additions, add the following lines to appstorefront_core/cartridge/js/pages/product/addToCart.js_:
$( "body" ).trigger( "ecBasketItemAction", [$form, 'add']);
For line item removals, replace the code sample inside the deleteProduct
click event in appstorefront_core/cartridge/js/pages/cart.js_:
if (removeItemEvent) {e.preventDefault();
}
else {
removeItemEvent = true;
}
With:
var data = {
'pid': $(this).closest('.cart-row').find('.sku .value').text(),
'Quantity': $(this).closest('.cart-row').find('.item-quantity input[name$="quantity"]').val(),
'action': 'remove'
};
$( "body" ).trigger( "ecBasketItemAction", [data, 'remove'], function () {
if (removeItemEvent) {
e.preventDefault();
} else {
removeItemEvent = true;
}
});
ecBasketItemTransaction
Emitted only on order summary pages with transaction.id
.
Step 1
Add the following lines after the Order
variable at top of components/order/orderdetails.isml:
<iscomment> Qubit Integration </iscomment>
<isinclude template="util/modules" />
<isqubittrackeventdata page_name="transactionId" page_data="${Order.orderNo}" />
<iscomment> Qubit Integration </iscomment>
Step 2
Add the following lines inside the productLineItem
loop in components/order/orderdetails.isml:
<iscomment> Qubit Integration </iscomment>
<isqubittrackeventdata event_type="ecBasketItemTransaction" page_data="${productLineItem}" />
<iscomment> Qubit Integration </iscomment>
ecBasketSummary
Emitted on all pages when the visitor has one or more basket items.
Add the following lines inside the mini-cart-content
class div in checkout/cart/minicart.isml:
<iscomment> Qubit Integration </iscomment>
<isqubittrackeventdata event_type="ecBasketSummary" page_data="${pdict.Basket}" />
<iscomment> Qubit Integration </iscomment>
ecBasketTransactionSummary
Emitted on the order summary page after ecBasketItemTransaction
events.
Add the following lines before the order-totals-table
class div in components/order/ordertotals.isml:
<iscomment> Qubit Integration </iscomment>
<isinclude template="util/modules" />
<isqubittrackeventdata event_type="ecBasketTransactionSummary" page_data="${LineItemCtnr}" />
<iscomment> Qubit Integration </iscomment>