A sitemap is a JavaScript configuration file that instructs the Data 360 SDK which pages to track, what events to capture, and how to extract data from the page.
[ACTION REQUIRED: Review Note] - NOTE: You can use the Sitemap Generator (Coming Soon) tool to build your sitemap configuration without writing code.
Sitemap Basics
- The sitemap is wrapped inside
SalesforceInteractions.init(), which handles SDK initialisation and consent before the sitemap runs. - Consent is passed as a Promise that resolves when a user opts in or out. Each consent object requires
purpose,provider, andstatus. SalesforceInteractions.initSitemap()accepts three keys:global(cross-site listeners),pageTypeDefault(fallback for unmatched pages), andpageTypes(page-specific interactions and listeners).- Each page type uses an
isMatchfunction or regex to identify the current URL. Define one page type per distinct page template on your site. - Resolvers extract values from the page at event-fire time. Use
resolvers.fromSelector(),resolvers.fromSelectorAttribute(), andresolvers.fromHref()to pull data from DOM elements. - Every event must include an
eventTypeproperty — without it, the SDK fires the event but Data 360 will not translate or ingest it.
[ACTION REQUIRED: Review Note] - WARNING: If an event does not have
eventTypemapped, it will not appear in Data 360. Always verifyeventTypeis present on every event, especially custom events, before uploading your schema.
Basic Sitemap Example
The following example demonstrates a complete sitemap covering consent management, a global email capture listener, and page types for a product page, cart page, and order confirmation page.
SalesforceInteractions.init({
consents: new Promise((resolve) => {
const { OptIn, OptOut } = SalesforceInteractions.ConsentStatus;
const purpose = SalesforceInteractions.ConsentPurpose.Tracking;
const provider = "Test Provider";
// user clicks button that grants consent
document
.getElementById("opt-in")
.addEventListener(
"click",
() => resolve([{ purpose, provider, status: OptIn }]),
{
once: true,
},
);
// user clicks button that revokes consent
document
.getElementById("opt-out")
.addEventListener(
"click",
() => resolve([{ purpose, provider, status: OptOut }]),
{
once: true,
},
);
}),
}).then(() => {
// set the log level during sitemap development to see potential problems
SalesforceInteractions.log.level = "debug";
const {
cashDom,
listener,
resolvers,
sendEvent,
util,
CartInteractionName,
CatalogObjectInteractionName,
OrderInteractionName,
} = SalesforceInteractions;
const global = {
listeners: [
// capture email address when a user signs up
listener("submit", ".user-signup-form", (actionEvent) => {
const emailAddress = cashDom("#user_email").val();
if (emailAddress) {
sendEvent({
interaction: {
name: "Email Sign Up",
},
user: {
attributes: {
email: emailAddress,
eventType: "contactPointEmail",
},
},
});
}
}),
],
// attach optional data to every actionEvent that is sent out
onActionEvent: (actionEvent) => {
const email = window && window._userInfo && window._userInfo.email;
if (email) {
actionEvent.user = actionEvent.user || {};
actionEvent.user.attributes = actionEvent.user.attributes || {};
actionEvent.user.attributes.emailAddress = email;
}
return actionEvent;
},
};
const productIdResolver = resolvers.fromSelectorAttribute(
".product",
"data-id",
);
const productPage = {
name: "product",
isMatch: () => /products/.test(window.location.pathname),
// capture the product being viewed when the page is opened
interaction: {
name: CatalogObjectInteractionName.ViewCatalogObject,
catalogObject: {
type: "Product",
id: productIdResolver,
attributes: {
name: resolvers.fromSelector(".product-title"),
url: resolvers.fromHref(),
imageUrl: resolvers.fromSelectorAttribute(".product img", "src"),
},
relatedCatalogObjects: {
Color: resolvers.fromSelectorAttributeMultiple(
".color-value",
"data-attr-value",
),
},
},
},
listeners: [
// capture when the user adds this product to their cart
listener("click", ".add-to-cart", () => {
sendEvent({
interaction: {
name: CartInteractionName.AddToCart,
lineItem: {
catalogObjectType: "Product",
catalogObjectId: productIdResolver(),
quantity: parseInt(cashDom(".product .quantity input").val(), 10),
price: parseFloat(cashDom(".product .price").text().trim()),
},
},
});
}),
// capture when the user shares the product to social media
listener("click", ".share", () => {
sendEvent({
interaction: {
name: CatalogObjectInteractionName.ShareCatalogObject,
catalogObject: {
type: "Product",
id: productIdResolver(),
},
},
});
}),
],
};
const cartPage = {
name: "Cart",
isMatch: () => /^\/cart/.test(window.location.href),
listeners: [
// capture when a user removes an item from their cart
listener("click", ".remove-from-cart", (event) => {
const $cartItem = cashDom(event.target).parents(".cart-item").first();
sendEvent({
interaction: {
name: CartInteractionName.RemoveFromCart,
lineItem: {
catalogObjectType: "Product",
catalogObjectId: $cartItem.attr("data-id"),
quantity: parseInt($cartItem.find(".quantity").text().trim(), 10),
},
},
});
}),
],
};
const orderConfirmationPage = {
name: "Order Configuration",
isMatch: /\/confirmation/.test(window.location.href),
// capture when a user completes an order
interaction: {
name: OrderInteractionName.Purchase,
order: {
id: resolvers.fromSelectorAttribute(".order", "data-id"),
totalValue: parseFloat(resolvers.fromSelector(".order .total").trim()),
lineItems: () =>
cashDom(".order .line-items").map((index, el) => {
const $lineItem = cashDom(el);
return {
catalogObjectType: "Product",
catalogObjectId: $lineItem.attr("data-id"),
quantity: parseInt($lineItem.find(".quantity").text().trim(), 10),
};
}),
},
},
};
const pageTypeDefault = {
name: "default",
};
SalesforceInteractions.initSitemap({
global,
pageTypeDefault,
pageTypes: [cartPage, orderConfirmationPage, productPage],
});
});
Uploading the Sitemap to Data 360
Once your sitemap code is ready, upload it to your web connector in Data 360 Setup.
- Create a JavaScript file named
sitemap.jsand paste your sitemap code into it. - Go to Data 360 Setup and click Web & Mobile Apps.
- Click on the connector you created in the previous step.
- Navigate to the Sitemap section of the connector setup page.
- Click Upload and select your
sitemap.jsfile. - Review the sitemap for errors and click Save.
[ACTION REQUIRED: Update Image Here] - Original Context/URL: Screenshot of the Sitemap section on the connector setup page showing the Upload button and error review panel.
Summary
A complete sitemap covers consent management, global listeners, and page-specific interactions. Every event must include an eventType property to be translated and ingested by Data 360. Once your sitemap is in place, validate that events are firing correctly in the browser console before uploading your schema and creating a Data Stream.