Manage display events in the Web SDK
Display events tell personalization or analytics services that a specific piece of personalized content was displayed to the user. Sending display events improves reporting accuracy by helping downstream systems distinguish between content that was requested and content that was actually shown.
Send display events automatically
Automatic display events are typically the simplest option. They are sent immediately after Web SDK finishes rendering eligible content from the sendEvent response, which can improve reporting accuracy.
To send display events automatically, use a sendEvent call that sets renderDecisions to true and set personalization.sendDisplayEvent to true (or omit it, since true is the default):
alloy("sendEvent", {
renderDecisions: true,
personalization: { }, // sendDisplayEvent defaults to true
xdm: {
web: {
webPageDetails: {
name: "home"
}
}
}
});
applyPropositions), you must send display events explicitly using sendEvent.Send display events in subsequent sendEvent calls
Including display events in a later sendEvent call is useful when you want to attach additional page load data that isn’t available when requesting personalization. It is commonly used when implementing Top and bottom page events. Correctly implementing display events in this manner helps avoid issues with Bounce rate in Adobe Analytics.
-
On the initial
sendEventcall (often at the top of the page), request and render content, but suppress automatic display events by settingrenderDecisionstotrueandpersonalization.sendDisplayEventtofalse:code language-js alloy("sendEvent", { renderDecisions: true, personalization: { sendDisplayEvent: false }, xdm: { web: { webPageDetails: { name: "home" } } } }); -
Later (often at the bottom of the page), call
sendEventwith an XDM payload that includes display events for propositions that were rendered since the previous request by settingpersonalization.includeRenderedPropositionstotrue:code language-js alloy("sendEvent", { personalization: { includeRenderedPropositions: true }, xdm: { // Add any additional page load telemetry you want to send here web: { webPageDetails: { name: "home" } } } });
includeRenderedPropositions.Send display events for manually rendered propositions
If you render content yourself (either fully manual rendering or using applyPropositions), you must send display events explicitly using the sendEvent command. Call sendEvent with an XDM payload that includes the following properties:
_experience.decisioning.propositionscontaining the rendered propositions’id,scope, andscopeDetails_experience.decisioning.propositionEventType.displayset to1
The following two examples use this helper function to build the display event XDM payload:
function buildDisplayEventXdm(renderedPropositions) {
return {
eventType: "decisioning.propositionDisplay",
_experience: {
decisioning: {
propositions: renderedPropositions.map(({ id, scope, scopeDetails }) => ({
id,
scope,
scopeDetails
})),
propositionEventType: { display: 1 }
}
}
};
}
The following example uses manual rendering with display events:
function renderExample(propositions) {
// Your custom logic here. Return ONLY the propositions that were actually rendered.
// For example: return [propositions[0]];
return [];
}
alloy("sendEvent", {
personalization: { decisionScopes: ["discount"] },
xdm: { }
}).then(({ propositions = [] }) => {
const renderedPropositions = renderExample(propositions);
if (!renderedPropositions.length) { return; }
return alloy("sendEvent", { xdm: buildDisplayEventXdm(renderedPropositions) });
});
The following example uses the applyPropositions command with display events. It chains sendEvent, applyPropositions, then another sendEvent together:
alloy("sendEvent", {
personalization: { decisionScopes: ["discount", "salutation"] },
xdm: { }
}).then(({ propositions = [] }) => {
return alloy("applyPropositions", {
propositions,
metadata: {
salutation: { selector: "#salutation", actionType: "setHtml" },
discount: { selector: "#daily-special", actionType: "replaceHtml" }
}
});
}).then(({ propositions: renderedPropositions = [] }) => {
if (!renderedPropositions.length) { return; }
return alloy("sendEvent", { xdm: buildDisplayEventXdm(renderedPropositions) });
});
Common mistakes to avoid
- Send display events before rendering finishes: Send display events after auto-rendering completes, after
applyPropositionsresolves, or after your manual rendering logic completes. - Send display events for propositions that you didn’t render: Only include propositions that were actually displayed to the user.
- Dropping
scopeDetails: IncludescopeDetailsfrom the proposition object when sending display events.