Set up Qubit on Salesforce Commerce Cloud

In 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:

  1. Installing the cartridge and then configuring it in the Business Manager
  2. 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:

image2

Step 2

▸ Navigate to the directory containing int_qubit, 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 int_qubit

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

ecView

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.https://static.goqubit.com/smartserve-2001.js

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, e.g. Cart-Show

n/a

Product’s custom SKU attribute

String

Name of the product's custom attribute containing the SKU

n/a

INFO: * denotes a mandatory configuration.

Editing app.js

The following changes must be done in the storefront cartridge.

Step 1

▸ In app_storefront_core/cartridge/js/app.js edit the Qubit module path to match the cartridge location:

image7

Step 2

▸ Add the following line to app_storefront_core/cartridge/js/app.js:

qubit.init();

image8

Editing Resource.ds

You will need to modify Resources.ds to get the controller URL and preferences.

Step 1

▸ Add the following lines to app_storefront_core/cartridge/scripts/util/Resource.ds:

//Qubit Integration
ecBasketItemAction: URLUtils.url('Qubit-BasketItemAction').toString()
//Qubit Integration

image9

Step 2

▸ Add the following lines to ResouceHelper.getPreferences in app_storefront_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

image10

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

image11

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

image12

Bottom header:

<isinclude template="qubit/smartserveendofhead"  />

image13

footer_UI.isml

▸ Add the following lines to components/header/footer_UI.isml in the desired position

<isinclude template="qubit/smartserveendofbody"  />

image14

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

image15

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>

image16

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>

image17

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>

image18

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>

image19

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>

image20

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 app_storefront_core/cartridge/js/ajax.js:

"var loadAjax = " (assign ajax call in variable call loadAjax)
“return loadAjax;” (return loadAjax at the end of ajax call)

image21

Step 5

▸ Add the following lines to the replace section in app_storefront_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)

image22

Step 6

▸ Add the following lines in the navigateQuickview function in app_storefront_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");
	 });
}

image23

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>

image24

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 app_storefront_core/cartridge/js/pages/product/addToCart.js:

$( "body" ).trigger( "ecBasketItemAction", [$form, 'add']);

image25

▸ For line item removals, replace the code sample inside the deleteProduct click event in app_storefront_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;
}
});

image26

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>

image27

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>

image28

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>

image29

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>

image30

Last updated: March 2021
Did you find this article useful?