Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DO NOT MERGE!!! All changes from last release for Nina #1042

Closed
wants to merge 31 commits into from

Conversation

jonsnyder
Copy link
Contributor

Description

DO NOT MERGE!!! This is all the changes for the new release.

Related Issue

Motivation and Context

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Improvement (non-breaking change which does not add functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA or I'm an Adobe employee.
  • I have made any necessary test changes and all tests pass.
  • I have run the Sandbox successfully.

jonsnyder and others added 30 commits February 6, 2023 12:52
* TNT-48367 Make SPA view names lowercase
Support for top and bottom of page events. Combine personalization display notifications together.
}) => {
return ({ decisionsDeferred, personalizationDetails, event, onResponse }) => {
return ({ cacheUpdate, personalizationDetails, event, onResponse }) => {
if (personalizationDetails.isRenderDecisions()) {
hideContainers(prehidingStyle);
Copy link
Contributor

@ninaceban ninaceban Sep 25, 2023

Choose a reason for hiding this comment

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

Add else clause here to call showContainers. Customers implementing async with pre-hiding snippet will have a hidden page till the timeout function from the snippet is called.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1058

@@ -35,10 +35,10 @@ export default ({
const xdm = { eventType: INTERACT };
const scope = decisionsMeta[0].scope;

if (scope !== PAGE_WIDE_SCOPE) {
if (isNonEmptyString(scope) && scope !== PAGE_WIDE_SCOPE) {
Copy link
Contributor

Choose a reason for hiding this comment

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

the scope would never be empty

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1056

xdm.web = {
webPageDetails: {
viewName: scope
viewName: scope.toLowerCase()
Copy link
Contributor

@ninaceban ninaceban Sep 25, 2023

Choose a reason for hiding this comment

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

scope is stored lowercase, no need to lowercase again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1056

}
},
items: [
{
Copy link
Contributor

@ninaceban ninaceban Sep 25, 2023

Choose a reason for hiding this comment

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

Default Content Item schema is used in Target to indicate that user has entered a "control" experience, using it liberally will cause confusion.

@@ -19,6 +19,11 @@ export const mergeDecisionsMeta = (
eventType,
eventLabel = ""
) => {
// Do not send a display notification with no decisions. Even empty view changes
// should include a proposition.
Copy link
Contributor

@ninaceban ninaceban Sep 25, 2023

Choose a reason for hiding this comment

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

let's move this logic where the event is triggered instead, this functions are calling event API, to merge to an existing event

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1061

}

if (!modules[type]) {
logger.warn("Invalid DOM action data: unknown type.", item.getData());
Copy link
Contributor

Choose a reason for hiding this comment

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

In such cases we should set renderAttempted: false, includeInNotifications:false

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1060

const errorMessage = `Failed to execute action ${item.toString()}. ${message} ${stack}`;
logger.error(errorMessage);
}
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

logger level should be warrning

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1058

let renderedItems = [];
let nonRenderedItems = [];
let itemRenderers = [];
let atLeastOneWithNotification = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

so many flags, a decision diagram would be very helpful for CE engineers debugging an issue.

[schema.HTML_CONTENT_ITEM]: createProcessHtmlContent({ modules, logger }),
[schema.REDIRECT_ITEM]: createProcessRedirect({
logger,
executeRedirect: url => window.location.replace(url),
Copy link
Contributor

Choose a reason for hiding this comment

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

extract this to a function

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1061


const render = () => {
return collect({ decisionsMeta: [item.getMeta()] }).then(() => {
executeRedirect(content);
Copy link
Contributor

Choose a reason for hiding this comment

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

Render would be called only when renderDecisions:true, otherwise it should be just part of the array of propositions returned.
Collect should be called here with documentMayUnload argument.
You should try/catch errors here and log the error and showContainers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If renderDecisions is false, processRedirect isn't even called, and the proposition is just returned as part of the returned propositions. See

if (personalizationDetails.isRenderDecisions()) {
.

Changing it to use collect is fixed in #1061

The try/catch is done in


The showContainers is in

return "page";
}
if (scopeType === "view") {
return "view";
Copy link
Contributor

@ninaceban ninaceban Sep 25, 2023

Choose a reason for hiding this comment

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

as this gets part of the proposition design, extract this into an enum of proposition types.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is fixed in #1056


export const EMPTY_PROPOSITIONS = { propositions: [] };

export default ({ logger, options }) => {
const applyPropositionsOptionsValidator = objectOf({
propositions: arrayOf(objectOf(anything())).nonEmpty(),
metadata: objectOf(anything())
propositions: arrayOf(objectOf(anything())),
Copy link
Contributor

Choose a reason for hiding this comment

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

this validator should be oneOf:

  • viewName
  • propositions && metadata

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you don't send in any propositions or a viewName, then this command does nothing. That's not an error. Additionally it is a valid use case to send in propositions without metadata. These could be page_wide_scope propositions that were not rendered automatically.

Copy link
Contributor

@ninaceban ninaceban left a comment

Choose a reason for hiding this comment

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

Generally, I would recommend breaking this into a few smaller PRs, it touches one of the most impactful and feature rich components, Personalization. Mixing the whole component refactoring and adding a big feature on top of that becomes pretty complicated for the PR reviewer to understand the changes and how it will impact the backward compatibility.
The src/components/Personalization/handlers/createProcessPropositions.js is pretty complex, would be good to break it into smaller descriptive pieces and comments. A design spec would also help CE rotation engineers that will potentially have to debug a related issue.

While testing Target use-cases, have found a few use-cases that needs to be fixed:

  • when renderDecisions: false the redirect offer should not be executed, the proposition should be returned in the result
  • the notification should be a collect instead of interact call
  • when renderDecisions:false the prehiding snippet should be removed(showContainers should be called)
  • when a click from a surface occurs the surface scope should not be sent in aviewName, viewName will be populated only when the proposition scopeType:view
  • when something fails, we log warnings, not errors

As improvements:

  • the functional tests for AJO should be improved to have the assertions for rendering, click notifications viewName I have mentioned above.
  • add test for renderDecisions:false and redirect offer being returned
  • add a functional test to validate that prehiding style is removed:
    -- when no personalization payload is returned
    -- when renderDecisions is false
    -- when an exception while executing

deduplicateArray
} from "../utils";

const getXdmPropositions = xdm => {
Copy link
Contributor

Choose a reason for hiding this comment

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

experience.decisioning is strictly Personalization related. Core should remain Personalization agnostic. Move this logic to Personalization component.

!userXdm.web ||
!userXdm.web.webPageDetails ||
!userXdm.web.webPageDetails.viewName
) {
Copy link
Contributor

Choose a reason for hiding this comment

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

in case viewName is undefined it will anyways be returned as undefined. No need for extra condition. Please revert this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1061

@@ -63,8 +81,23 @@ export default () => {
return;
}

const newPropositions = deduplicateArray(
Copy link
Contributor

Choose a reason for hiding this comment

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

this logic too should be moved to Personalization.

@@ -35,10 +35,10 @@ export default ({
const xdm = { eventType: INTERACT };
const scope = decisionsMeta[0].scope;

if (scope !== PAGE_WIDE_SCOPE) {
if (isNonEmptyString(scope) && scope !== PAGE_WIDE_SCOPE) {
Copy link
Contributor

Choose a reason for hiding this comment

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

the viewName would be populated only when the proposition was for an SPA view, add to this if clause another one that checks if scopeType: view.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #1056

@jonsnyder
Copy link
Contributor Author

jonsnyder commented Oct 18, 2023

I've addressed most of the comments here in these PRs:
#1056
#1057
#1058
#1060
#1061

Outstanding are still these comments:

  • Creating a decision diagram and making processPropositions easier to understand. Documenting how to create a new renderer.
  • Moving proposition deduplication out of core and into Personalization component.
  • Figuring out a better way to deal with empty view change notifications without having to reuse default content items.

@jonsnyder jonsnyder closed this Nov 9, 2023
@jonsnyder jonsnyder deleted the topAndBottom3 branch November 9, 2023 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants