How to track Comparison Shopping behavior on a website using Salesforce Marketing Cloud Personalization (formerly known as Interaction Studio). Below is a breakdown of the key concepts and code to help you understand it more clearly.
Comparison Shopping refers to the action when a visitor copies a product name from your website, leaves the page, and presumably searches for the same product on other websites to compare prices. Tracking this behavior can provide insights into customer shopping habits and allow business users to trigger personalized campaigns (e.g., offering a discount if they detect that a customer is comparison shopping).
This feature allows businesses to:
Track visitors who might be comparing prices elsewhere.
Use this tracking for segmentation (grouping customers who comparison shop).
Trigger personalized campaigns when comparison shopping is detected (e.g., pop up an offer when they leave the page).
The implementation requires:
A Listener that detects when a visitor copies a product name.
Tracking when the user leaves the page after copying, signaling that they might be comparison shopping.
Sending an event to Marketing Cloud Personalization to track this behavior for future use in personalization.
// definition of SalesforceInteractions.ComparisonShopping
SalesforceInteractions.ComparisonShopping = (() => {
let productNameCopied = false;
const bindComparisonShoppingCopy = (event) => {
SalesforceInteractions.cashDom(event.currentTarget).on("copy.evgComparisonShopping", () => {
try {
productNameCopied = true;
} catch (e) {
SalesforceInteractions.sendException(e, "bindComparisonShopping: copy event");
}
});
};
const bindComparisonShoppingBlur = () => {
try {
SalesforceInteractions.cashDom(window).on("blur.evgComparisonShopping", () => {
if (productNameCopied) {
SalesforceInteractions.sendEvent({
interaction: {
name: "Comparison Shopping",
},
source: {
contentZones:
SalesforceInteractions.mcis.getSitemapResult().currentPage.source.contentZones,
},
});
productNameCopied = false;
}
});
} catch (e) {
SalesforceInteractions.sendException(e, "handleComparisonShopping");
}
};
return {
handleComparisonShopping: (event) => {
SalesforceInteractions.cashDom(window).off(".evgComparisonShopping");
bindComparisonShoppingCopy(event);
bindComparisonShoppingBlur();
},
};
})();
SalesforceInteractions.init().then(() => {
// sitemap
const config = {
pageTypes: [
{
// ...
listeners: [
SalesforceInteractions.listener(
"mouseup.initComparisonShopping touchend.initComparisonShopping",
".pdp-primary-info .product-name",
SalesforceInteractions.ComparisonShopping.handleComparisonShopping,
),
],
},
],
};
// ...
});
Here's a detailed explanation of the code, line by line:
SalesforceInteractions.ComparisonShopping = (() => {
Explanation: This line creates a self-contained immediately invoked function expression (IIFE). This pattern ensures that any variables and functions defined inside are private and can’t be accessed outside the module. It's creating the ComparisonShopping object inside the SalesforceInteractions namespace.
let productNameCopied = false;
Explanation: This variable keeps track of whether the user has copied a product name. It is initially set to false, and will be set to true when a copy action occurs.
const bindComparisonShoppingCopy = (event) => {
Explanation: This function binds a copy event listener to the target element, which will track when the user copies a product name. The event parameter refers to the event that triggered this function (likely a user action like clicking or copying).
SalesforceInteractions.cashDom(event.currentTarget).on("copy.evgComparisonShopping", () => {
try {
productNameCopied = true;
} catch (e) {
SalesforceInteractions.sendException(e, "bindComparisonShopping: copy event");
}
});
Explanation:
SalesforceInteractions.cashDom(event.currentTarget).on(...): This attaches a copy event listener to the element that triggered the event (e.g., the product name field). cashDom is a lightweight alternative to jQuery used for DOM manipulation.
When a copy event occurs, the function sets productNameCopied to true, meaning the user has copied a product name.
The try-catch block ensures any errors that occur during the copy event are caught and logged using SalesforceInteractions.sendException.
const bindComparisonShoppingBlur = () => {
Explanation: This function sets up an event listener that triggers when the user leaves the current window (usually by switching to another tab or window). This is important because the visitor may be leaving the page to compare prices elsewhere.
try {
SalesforceInteractions.cashDom(window).on("blur.evgComparisonShopping", () => {
if (productNameCopied) {
SalesforceInteractions.sendEvent({
interaction: {
name: "Comparison Shopping",
},
source: {
contentZones:
SalesforceInteractions.mcis.getSitemapResult().currentPage.source.contentZones,
},
});
productNameCopied = false;
}
});
} catch (e) {
SalesforceInteractions.sendException(e, "handleComparisonShopping");
}
};
Explanation:
The blur event is fired when the user switches focus away from the current window, implying they may be leaving the site.
If productNameCopied is true (i.e., the user copied a product name), it sends a "Comparison Shopping" event to Salesforce Marketing Cloud Personalization.
The source.contentZones property helps specify the page location where the comparison shopping event occurred.
After sending the event, productNameCopied is reset to false so that the system is ready to track the next instance of comparison shopping.
The try-catch block ensures that any errors in sending the event are caught and logged.
return {
handleComparisonShopping: (event) => {
SalesforceInteractions.cashDom(window).off(".evgComparisonShopping");
bindComparisonShoppingCopy(event);
bindComparisonShoppingBlur();
},
};
})();
Explanation: This returns an object with a single method handleComparisonShopping. When this method is called:
First, any existing event listeners with the .evgComparisonShopping namespace are removed from the window to prevent duplicate listeners.
Then, the bindComparisonShoppingCopy function is called to listen for the copy event.
Lastly, bindComparisonShoppingBlur is called to listen for the user leaving the page.
SalesforceInteractions.init().then(() => {
const config = {
pageTypes: [
{
listeners: [
SalesforceInteractions.listener(
"mouseup.initComparisonShopping touchend.initComparisonShopping",
".pdp-primary-info .product-name",
SalesforceInteractions.ComparisonShopping.handleComparisonShopping,
),
],
},
],
};
});
Explanation:
SalesforceInteractions.init() initializes the Salesforce Personalization (Interaction Studio) system. This ensures that the page is ready for interaction tracking.
Once initialized, the code defines a configuration for pageTypes that adds a listener to the product detail page (.pdp-primary-info .product-name).
It listens for mouseup (on desktop) and touchend (on mobile) events on the product name element. When triggered, the handleComparisonShopping function is called to track comparison shopping behavior.
The script tracks when a user copies a product name (using copy events) and monitors when they leave the page (using blur events).
If the user copies the product name and then navigates away, it sends an event called "Comparison Shopping" to Salesforce Marketing Cloud Personalization.
The system relies on event listeners (copy and blur) and sends data through the SalesforceInteractions.sendEvent function to track and respond to the user's actions.
Here's the step-by-step sequence of how the code executes in simple terms:
What happens?
When a user either clicks or taps on the product name on the page, the event listeners (for mouseup or touchend) trigger.
These listeners are attached to the product name element with the class .pdp-primary-info .product-name.
"mouseup.initComparisonShopping touchend.initComparisonShopping"
What happens?
When the mouseup or touchend event is detected on the product name, the handleComparisonShopping method from the ComparisonShopping object is called.
This function manages the comparison shopping tracking process.
SalesforceInteractions.ComparisonShopping.handleComparisonShopping
What happens?
Inside the handleComparisonShopping function, the first thing that happens is that any existing listeners for comparison shopping (with the namespace .evgComparisonShopping) are removed from the window. This prevents duplicate listeners from being attached every time the user interacts with the product name.
SalesforceInteractions.cashDom(window).off(".evgComparisonShopping");
What happens?
The function bindComparisonShoppingCopy(event) is called next.
This binds a listener to the element (product name) that tracks if the user copies the product name.
If the user copies the product name, the variable productNameCopied is set to true.
bindComparisonShoppingCopy(event);
What happens?
Next, the bindComparisonShoppingBlur() function is called.
This binds a blur event to the entire window, which triggers when the user leaves the page (e.g., switches tabs or browsers).
If the productNameCopied variable is true (meaning the user copied the product name), it sends a "Comparison Shopping" event to Salesforce Marketing Cloud.
After sending the event, productNameCopied is reset to false to prepare for the next comparison shopping interaction.
bindComparisonShoppingBlur();
What happens?
If the user copies the product name, the event listener that was set up in Step 4 detects this and sets productNameCopied = true.
productNameCopied = true;
What happens?
If the user then leaves the page (by switching to another tab, for example), the blur event is triggered.
If productNameCopied is true, it sends the "Comparison Shopping" event to Salesforce, tracking the user's intent to compare prices elsewhere.
The productNameCopied is reset to false afterward.
SalesforceInteractions.sendEvent({...});
productNameCopied = false;