Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/every-ravens-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@adobe/alloy": patch
---

Passes inbox item after user subscribes to ruleset items
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
REDIRECT_ITEM,
RULESET_ITEM,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
} from "../../constants/schema.js";
import {
buildPageSurface,
Expand Down Expand Up @@ -102,6 +103,7 @@ export default ({
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
];

if (scopes.includes(PAGE_WIDE_SCOPE)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

import { INBOX_ITEM } from "../../constants/schema.js";
import { PERSONALIZATION_DECISIONS_HANDLE } from "../../constants/decisionProvider.js";
import flattenObject from "../../utils/flattenObject.js";

const extractInboxPropositions = (payloads) =>
payloads.filter(
(payload) =>
Array.isArray(payload.items) &&
payload.items.length > 0 &&
payload.items.every((item) => item.schema === INBOX_ITEM),
);

export default ({
renderDecisions,
decisionProvider,
Expand All @@ -27,16 +36,20 @@ export default ({
};

return ({ response }) => {
decisionProvider.addPayloads(
response.getPayloadsByType(PERSONALIZATION_DECISIONS_HANDLE),
const personalizationPayloads = response.getPayloadsByType(
PERSONALIZATION_DECISIONS_HANDLE,
);
decisionProvider.addPayloads(personalizationPayloads);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to extract the inbox propositions here. This code is run inside the onResponse lifecycle event inside the RulesEngine component so it only needs to return the matching propositions. The regular personalization process with include the inbox proposition in the response already.

So there should be no changes to this file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are not ruleset payloads, though, so they don't get evaluated/extracted in the RulesEngine. That was one approach we considered (and in fact originally implemented), but there was a desire to move away from it.

Copy link
Collaborator Author

@Spencer-Smith Spencer-Smith Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait I forgot that Serban had mentioned this strategy the other day. In that case, I'm not sure any code changes are necessary to the SDK at all? We can just close this MR, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can close it. Sorry for making you work for nothing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually still got paid for working on this, so it wasn't for nothing


// only evaluate events that include a personalization query
if (!event.hasQuery()) {
return { propositions: [] };
}

const propositions = decisionProvider.evaluate(context);
const inboxPropositions = extractInboxPropositions(personalizationPayloads);

const evaluatedPropositions = decisionProvider.evaluate(context);
const propositions = [...evaluatedPropositions, ...inboxPropositions];

return applyResponse({
renderDecisions,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/constants/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const HTML_CONTENT_ITEM =
export const JSON_CONTENT_ITEM =
"https://ns.adobe.com/personalization/json-content-item";
export const RULESET_ITEM = "https://ns.adobe.com/personalization/ruleset-item";
export const INBOX_ITEM = "https://ns.adobe.com/personalization/inbox-item";
export const REDIRECT_ITEM =
"https://ns.adobe.com/personalization/redirect-item";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
REDIRECT_ITEM,
RULESET_ITEM,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
} from "../../../../../src/constants/schema.js";

describe("Personalization::createPersonalizationDetails", () => {
Expand Down Expand Up @@ -162,6 +163,7 @@ describe("Personalization::createPersonalizationDetails", () => {
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
DOM_ACTION,
],
decisionScopes: expectedDecisionScopes,
Expand Down Expand Up @@ -201,6 +203,7 @@ describe("Personalization::createPersonalizationDetails", () => {
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
DOM_ACTION,
],
decisionScopes: expectedDecisionScopes,
Expand Down Expand Up @@ -240,6 +243,7 @@ describe("Personalization::createPersonalizationDetails", () => {
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
DOM_ACTION,
],
decisionScopes: expectedDecisionScopes,
Expand Down Expand Up @@ -279,6 +283,7 @@ describe("Personalization::createPersonalizationDetails", () => {
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
],
decisionScopes: expectedDecisionScopes,
surfaces: [],
Expand Down Expand Up @@ -319,6 +324,7 @@ describe("Personalization::createPersonalizationDetails", () => {
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
],
decisionScopes: expectedDecisionScopes,
surfaces: ["web://test1.com/"],
Expand Down Expand Up @@ -360,6 +366,7 @@ describe("Personalization::createPersonalizationDetails", () => {
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
],
decisionScopes: expectedDecisionScopes,
surfaces: ["web://test1.com/"],
Expand Down Expand Up @@ -487,6 +494,7 @@ describe("Personalization::createPersonalizationDetails", () => {
RULESET_ITEM,
MESSAGE_IN_APP,
MESSAGE_CONTENT_CARD,
INBOX_ITEM,
DOM_ACTION,
],
decisionScopes: expectedDecisionScopes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down Expand Up @@ -172,6 +173,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe("PersonalizationComponent", () => {
"https://ns.adobe.com/personalization/ruleset-item",
"https://ns.adobe.com/personalization/message/in-app",
"https://ns.adobe.com/personalization/message/content-card",
"https://ns.adobe.com/personalization/inbox-item",
"https://ns.adobe.com/personalization/dom-action",
],
decisionScopes: ["__view__"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,27 +444,42 @@ describe("RulesEngine:createDecisionProvider", () => {
},
]);
});
it("ignores payloads that aren't json-ruleset type", () => {
decisionProvider.addPayload({
it("does not add payloads that contain only inbox items (handled in response handler)", () => {
const inboxPayload = {
id: "66e05490-5e91-45c4-8eee-339784032940",
scope: "mobileapp://com.app/trendingnow",
scopeDetails: {
decisionProvider: "AJO",
activity: { id: "99db8aff4-82af-460e-8524-73e1441afdfa#id" },
},
items: [
{
id: "569d1166-d3e0-4aea-b9a7-6de8ebdf3aec",
schema: "https://ns.adobe.com/personalization/inbox-item",
data: {
content: {
heading: { content: "Trending Now Inbox" },
layout: { orientation: "horizontal" },
capacity: 10,
},
},
},
],
};
decisionProvider.addPayload(inboxPayload);
expect(decisionProvider.evaluate()).toEqual([]);
});

it("does not add payloads that have items but no inbox or ruleset items (e.g. TGT dom-action only)", () => {
const tgtPayload = {
id: "AT:eyJhY3Rpdml0eUlkIjoiMTQxMDY0IiwiZXhwZXJpZW5jZUlkIjoiMCJ9",
scope: "__view__",
scopeDetails: {
decisionProvider: "TGT",
activity: {
id: "141064",
},
experience: {
id: "0",
},
strategies: [
{
algorithmID: "0",
trafficType: "0",
},
],
characteristics: {
eventToken: "abc",
},
activity: { id: "141064" },
experience: { id: "0" },
strategies: [{ algorithmID: "0", trafficType: "0" }],
characteristics: { eventToken: "abc" },
correlationID: "141064:0:0:0",
},
items: [
Expand All @@ -480,7 +495,8 @@ describe("RulesEngine:createDecisionProvider", () => {
},
},
],
});
};
decisionProvider.addPayload(tgtPayload);
expect(decisionProvider.evaluate()).toEqual([]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -396,4 +396,65 @@ describe("RulesEngine:createOnResponseHandler", () => {
identityMap: undefined,
});
});

it("converts inbox-only payloads to propositions and passes them to applyResponse with evaluated propositions", () => {
const event = {
getViewName: () => undefined,
getUserIdentityMap: () => undefined,
hasQuery: () => true,
getContent: () => ({ query: {}, xdm: {}, data: {} }),
};
const responseHandler = createOnResponseHandler({
renderDecisions: true,
decisionProvider,
applyResponse,
event,
personalization: {},
decisionContext: {},
});
const inboxPayload = {
id: "66e05490-5e91-45c4-8eee-339784032940",
scope: "mobileapp://com.app/trendingnow",
scopeDetails: {
decisionProvider: "AJO",
activity: { id: "99db8aff4-82af-460e-8524-73e1441afdfa#id" },
},
items: [
{
id: "569d1166-d3e0-4aea-b9a7-6de8ebdf3aec",
schema: "https://ns.adobe.com/personalization/inbox-item",
data: {
content: {
heading: { content: "Trending Now Inbox" },
capacity: 10,
},
},
},
],
};
const response = {
getPayloadsByType: () => [inboxPayload],
};
responseHandler({ response });
expect(lifecycle.onDecision).toHaveBeenCalledWith(
expect.objectContaining({
propositions: [
expect.objectContaining({
id: inboxPayload.id,
items: [
expect.objectContaining({
schema: "https://ns.adobe.com/personalization/inbox-item",
data: expect.objectContaining({
content: {
heading: { content: "Trending Now Inbox" },
capacity: 10,
},
}),
}),
],
}),
],
}),
);
});
});
5 changes: 5 additions & 0 deletions sandboxes/browser/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import AlloyVersion from "./components/AlloyVersion";
import ConfigOverrides from "./ConfigOverrides";
import InAppMessages from "./components/InAppMessagesDemo/InAppMessages";
import ContentCards from "./components/ContentCardsDemo/ContentCards";
import MessageInbox from "./components/MessageInboxDemo/MessageInbox";
import PushNotifications from "./PushNotifications";
import ReferrerTest from "./ReferrerTest";
import Advertising from "./Advertising";
Expand Down Expand Up @@ -108,6 +109,9 @@ const BasicExample = () => {
<li>
<Link to="contentCards">Content Cards</Link>
</li>
<li>
<Link to="messageInbox">Message Inbox</Link>
</li>
<li>
<Link to="pushNotifications">Push Notifications</Link>
</li>
Expand Down Expand Up @@ -149,6 +153,7 @@ const BasicExample = () => {
<Route path="configOverrides" element={<ConfigOverrides />} />
<Route path="inAppMessages" element={<InAppMessages />} />
<Route path="contentCards" element={<ContentCards />} />
<Route path="messageInbox" element={<MessageInbox />} />
<Route path="pushNotifications" element={<PushNotifications />} />
<Route path="referrerTest" element={<ReferrerTest />} />
<Route path="concierge" element={<Concierge />} />
Expand Down
Loading