On this page: Set up and run the sample that fetches and renders content cards with the Adobe Experience Platform Web SDK so you can deliver client-side personalized content on your web pages.
This sample showcases how to retrieve Content Cards from Adobe Journey Optimizer (AJO) using Adobe Experience Platform. By leveraging the Adobe Experience Platform Web SDK, the personalization content is fetched and rendered entirely on the client side.
Upon the initial page load, the page displays its default state. However, if you interact with the Deposit Funds or Share on social media buttons, additional content cards will appear. These cards are triggered by client-side conditions, ensuring they are displayed only when specific actions are taken.
Running the sample run-sample
-
Set up local SSL certificates for HTTPS. These samples require locally signed SSL certificates to serve content over HTTPS:
-
Install
mkcerton your computer. -
After installation, run
mkcert -installto install themkcert rootcertificate.
-
-
Clone the repository to your local machine.
-
Open a terminal and navigate to the sample’s folder.
-
Install the required dependencies by running
npm install. -
Start the application by running
npm start. -
Open your web browser and go to
https://localhost.
How it works setup
-
Include and configure the Web SDK on the page using settings from the
.envfile in the sample folder.code language-none <script src="https://cdn1.adoberesources.net/alloy/2.18.0/alloy.min.js" async></script> alloy("configure", { defaultConsent: "in", edgeDomain: "{{edgeDomain}}", edgeConfigId: "{{edgeConfigId}}", orgId:"{{orgId}}", debugEnabled: false, personalizationStorageEnabled: true, thirdPartyCookiesEnabled: false }); -
Use the
sendEventcommand to fetch personalized content.code language-none alloy("sendEvent", { renderDecisions: true, personalization: { surfaces: ["web://alloy-samples.adobe.com/#content-cards-sample"], }, }); -
Subscribe to content cards for a specific surface using the
subscribeRulesetItemscommand. Each time rulesets are evaluated, handle the result object in the callback, which will containpropositionswith content card data.code language-none const contentCardManager = createContentCardManager("content-cards"); alloy("subscribeRulesetItems", { surfaces: ["web://alloy-samples.adobe.com/#content-cards-sample"], schemas: ["https://ns.adobe.com/personalization/message/content-card"], callback: (result, collectEvent) => { const { propositions = [] } = result; contentCardManager.refresh(propositions, collectEvent); }, }); -
Manage rendering of content cards and send
interactanddisplayevents using thecontentCardsManagerobject found inscript.js. Extract, sort, and process content cards from the received propositions.code language-none const createContentCard = (proposition, item) => { const { data = {}, id } = item; const { content = {}, meta = {}, publishedDate, qualifiedDate, displayedDate, } = data; return { id, ...content, meta, qualifiedDate, displayedDate, publishedDate, getProposition: () => proposition, }; }; const extractContentCards = (propositions) => propositions .reduce((allItems, proposition) => { const { items = [] } = proposition; return [ ...allItems, ...items.map((item) => createContentCard(proposition, item)), ]; }, []) .sort( (a, b) => b.qualifiedDate - a.qualifiedDate || b.publishedDate - a.publishedDate ); const contentCards = extractContentCards(propositions); -
Render the content cards based on the details defined for each campaign. Each card includes a
title,body,imageUrl, and other custom data values.code language-none const renderContentCards = () => { const contentCardsContainer = document.getElementById(containerElementId); contentCardsContainer.addEventListener("click", handleContentCardClick); let contents = ""; contentCards.forEach((card) => { const { id, title, body, imageUrl, meta = {} } = card; const { buttonLabel = "" } = meta; contents += ` <div class="col"> <div data-id="${id}" class="card h-100"> <img src="${imageUrl}" class="card-img-top" alt="..."> <div class="card-body d-flex flex-column"> <h5 class="card-title">${title}</h5> <p class="card-text">${body}</p> <a href="#" class="mt-auto btn btn-primary">${buttonLabel}</a> </div> </div> </div> `; }); contentCardsContainer.innerHTML = contents; collectEvent( "display", contentCards.map((card) => card.getProposition()) ); }; -
When the
subscribeRulesetItemscallback is invoked, a convenience function calledcollectEventis also provided. This function is used to send Experience Edge events to track interactions, displays, and other user actions. In this sample, collectEvent tracks when a content card is clicked. Additionally, if the button on the content card is clicked, the browser is directed to theactionUrlspecified by the campaign.code language-none const handleContentCardClick = (evt) => { const cardEl = evt.target.closest(".card"); if (!cardEl) { return; } const isAnchor = evt.target.nodeName === "A"; const card = contentCards.find((card) => card.id === cardEl.dataset.id); if (!card) { return; } collectEvent("interact", [card.getProposition()]); if (isAnchor) { evt.preventDefault(); evt.stopImmediatePropagation(); const { actionUrl } = card; if (actionUrl && actionUrl.length > 0) { window.location.href = actionUrl; } } };
Key Observations key-observations
personalizationStorageEnabled
The personalizationStorageEnabled option is set to true in the configure command. This ensures that previously qualified content cards are stored and continue to be displayed across user sessions.
Triggers
Content cards support custom triggers evaluated on the client side. When a trigger rule is met, additional content cards are displayed. This sample uses four different campaigns, one for each content card, all sharing the same surface: web://alloy-samples.adobe.com/#content-cards-sample. The table below outlines the trigger rules for each campaign and how to satisfy them.
The evaluateRulesets command is triggered when clicking the “Deposit Funds” and “Share on social media” buttons. Each button specifies the relevant decisionContext to fulfill the rules defined for the respective campaigns.
document.getElementById("action-button-1").addEventListener("click", () => {
alloy("evaluateRulesets", {
renderDecisions: true,
personalization: {
decisionContext: {
action: "deposit-funds",
},
},
});
});
document.getElementById("action-button-2").addEventListener("click", () => {
alloy("evaluateRulesets", {
renderDecisions: true,
personalization: {
decisionContext: {
action: "social-media",
},
},
});
});
This section contains structured knowledge intended to support interpretation, retrieval, and question answering related to this topic.
For complete understanding, this information should be combined with the documentation on this page. Neither source is intended to stand alone; the page describes the feature, while this section provides additional context that helps disambiguate terminology, intent, applicability, and constraints.
- TL;DR: This page walks through a sample that uses the Adobe Experience Platform Web SDK to fetch and render Adobe Journey Optimizer content cards entirely on the client side of a web page.
Intents:
- Set up and run the Web SDK content card sample locally over HTTPS
- Configure the Web SDK (alloy) on a page and fetch personalized content with the sendEvent command
- Subscribe to content cards for a surface using the subscribeRulesetItems command
- Render content cards and send display and interact events
- Trigger additional content cards client side using evaluateRulesets and a decisionContext
- Persist qualified content cards across user sessions with personalizationStorageEnabled
Glossary:
- Surface: The identifier a content card subscription and events are scoped to, for example
web://alloy-samples.adobe.com/#content-cards-sample(product-specific) - subscribeRulesetItems: The Web SDK command used to subscribe to content cards for a surface; its callback returns propositions containing content card data (product-specific)
- evaluateRulesets: The Web SDK command triggered on client-side actions to evaluate rulesets using a decisionContext (product-specific)
- decisionContext: The context passed with evaluateRulesets that supplies the values needed to satisfy a campaign’s client-side trigger rules (product-specific)
- collectEvent: A convenience function provided in the subscribeRulesetItems callback used to send Experience Edge events to track displays, interactions, and other user actions (product-specific)
- personalizationStorageEnabled: A configure option that, when set to true, stores previously qualified content cards so they continue to be displayed across user sessions (product-specific)
- Trigger rule: A client-side condition that, when met, causes additional content cards to be displayed (product-specific)
Guardrails:
- To use disqualification rules with content cards, Web SDK version 2.28.0 or later is required.
- You need to install node and npm to run the sample.
- The samples require locally signed SSL certificates to serve content over HTTPS.
- In this sample, four campaigns are used, one per content card, all sharing the same surface
web://alloy-samples.adobe.com/#content-cards-sample.
Terminology:
- Canonical name: Configure content cards support in Web SDK — Acronym: SDK — variants: Web SDK content card sample, Content cards configuration Web SDK
- Synonyms: “Web SDK” = “alloy”
- Do not confuse: “sendEvent” (fetch personalized content) ≠ “subscribeRulesetItems” (subscribe to content cards for a surface) ≠ “evaluateRulesets” (evaluate rulesets on a client-side action)
- Do not confuse: “display” event (content card shown) ≠ “interact” event (content card clicked)
FAQ:
- Q: What Web SDK version is needed for disqualification rules? — Web SDK version 2.28.0 or later is required to use disqualification rules with content cards.
- Q: Why do the samples require SSL certificates? — The samples serve content over HTTPS, so they require locally signed SSL certificates; the page uses
mkcertto create and install them. - Q: How are qualified content cards kept across sessions? — Setting
personalizationStorageEnabledto true in the configure command stores previously qualified content cards so they continue to be displayed across user sessions. - Q: How are additional content cards triggered? — Content cards support custom triggers evaluated on the client side; the sample calls
evaluateRulesetswith adecisionContextwhen the Deposit Funds or Share on social media buttons are clicked. - Q: What happens when a content card button is clicked? — The
collectEventfunction tracks the interaction, and if the button is an anchor, the browser is directed to theactionUrlspecified by the campaign.