-
Notifications
You must be signed in to change notification settings - Fork 43
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
FEATURE: Automatic proposition interaction tracking #1101
Conversation
src/components/Personalization/handlers/createProcessPropositions.js
Outdated
Show resolved
Hide resolved
src/components/Personalization/handlers/injectCreateProposition.js
Outdated
Show resolved
Hide resolved
Thank you @jasonwaters. 2 questions:
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Of course we'll need functional tests. I'm wondering what the use case is for changing the "always", "never" fields. It will be good to review all the configuration parameters.
src/components/Personalization/handlers/createProcessPropositions.js
Outdated
Show resolved
Hide resolved
src/components/Personalization/handlers/createProcessPropositions.js
Outdated
Show resolved
Hide resolved
# Conflicts: # src/components/Personalization/index.js
# Conflicts: # package-lock.json # package.json # src/components/Personalization/createApplyPropositions.js # src/components/Personalization/createClickStorage.js # src/components/Personalization/createOnClickHandler.js # src/components/Personalization/dom-actions/action.js # src/components/Personalization/dom-actions/appendHtml.js # src/components/Personalization/dom-actions/clicks/collectClicks.js # src/components/Personalization/dom-actions/initDomActionsModules.js # src/components/Personalization/dom-actions/insertHtmlAfter.js # src/components/Personalization/dom-actions/insertHtmlBefore.js # src/components/Personalization/dom-actions/prependHtml.js # src/components/Personalization/dom-actions/remapCustomCodeOffers.js # src/components/Personalization/dom-actions/remapHeadOffers.js # src/components/Personalization/dom-actions/setAttributes.js # src/components/Personalization/dom-actions/setStyles.js # src/components/Personalization/dom-actions/swapImage.js # src/components/Personalization/handlers/createProcessDomAction.js # src/components/Personalization/handlers/createProcessHtmlContent.js # src/components/Personalization/handlers/injectCreateProposition.js # src/components/Personalization/index.js # src/utils/dom/removeNode.js # test/functional/helpers/assertions/responseStatus.js # test/functional/specs/Config Overrides/C7437533.js # test/functional/specs/LibraryInfo/C2589.js # test/functional/specs/Migration/C8085775.js # test/functional/specs/Migration/C8085776.js # test/functional/specs/Migration/C8085779.js # test/functional/specs/Migration/C8085780.js # test/functional/specs/Privacy/C28754.js # test/unit/specs/components/Personalization/createApplyPropositions.spec.js # test/unit/specs/components/Personalization/createClickStorage.spec.js # test/unit/specs/components/Personalization/createComponent.spec.js # test/unit/specs/components/Personalization/createNotificationHandler.spec.js # test/unit/specs/components/Personalization/createOnClickHandler.spec.js # test/unit/specs/components/Personalization/dom-actions/appendHtml.spec.js # test/unit/specs/components/Personalization/dom-actions/clicks/collectClicks.spec.js # test/unit/specs/components/Personalization/dom-actions/createRedirect.spec.js # test/unit/specs/components/Personalization/dom-actions/customCode.spec.js # test/unit/specs/components/Personalization/dom-actions/initDomActionsModules.spec.js # test/unit/specs/components/Personalization/dom-actions/insertHtmlAfter.spec.js # test/unit/specs/components/Personalization/dom-actions/insertHtmlBefore.spec.js # test/unit/specs/components/Personalization/dom-actions/move.spec.js # test/unit/specs/components/Personalization/dom-actions/prependHtml.spec.js # test/unit/specs/components/Personalization/dom-actions/rearrangeChildren.spec.js # test/unit/specs/components/Personalization/dom-actions/remove.spec.js # test/unit/specs/components/Personalization/dom-actions/replaceHtml.spec.js # test/unit/specs/components/Personalization/dom-actions/resize.spec.js # test/unit/specs/components/Personalization/dom-actions/setAttributes.spec.js # test/unit/specs/components/Personalization/dom-actions/setHtml.spec.js # test/unit/specs/components/Personalization/dom-actions/setImageSource.spec.js # test/unit/specs/components/Personalization/dom-actions/setStyles.spec.js # test/unit/specs/components/Personalization/dom-actions/setText.spec.js # test/unit/specs/components/Personalization/handlers/createProcessDomAction.spec.js # test/unit/specs/components/Personalization/handlers/createProcessHtmlContent.spec.js # test/unit/specs/components/Personalization/handlers/createProcessPropositions.spec.js # test/unit/specs/components/Personalization/topLevel/buildAlloy.js # test/unit/specs/components/Personalization/topLevel/buildMocks.js # test/unit/specs/components/Personalization/topLevel/mixedPropositions.spec.js # test/unit/specs/components/Personalization/topLevel/pageWideDecisionsWithDomActionSchemaItems.spec.js # test/unit/specs/components/Personalization/topLevel/pageWideScopeDecisions.spec.js # test/unit/specs/components/Personalization/validateApplyPropositionsOptions.spec.js # test/unit/specs/utils/assignConcatArrayValues.spec.js # test/unit/specs/utils/createSubscription.spec.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Jason, the PR looks good!
The feature for automatically collecting clicks on personalized content, as per Erik's Wiki, is intended solely for HTML rendered content (either VEC or html-content-item). This feature is only supported by AJO, with Target only providing support for explicit click-tracking.
Upon reviewing the wiki, I found no requirement for automatic click tracking on json-content-item offers, leading to the introduction of a new action type, collectInteractions
. Unless there's a specific customer request or use-case, I would advise against adding a new capability to Alloy.
// .expect( | ||
// notification.events[0].xdm._experience.decisioning.propositions[0].id, | ||
// ) | ||
// .eql(propositionId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we still need these commented lines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest keeping them and un-commenting them when the TODO: Testcafe no longer captures the request body for sendBeacon requests.
is resolved.
After merging main
to my branch, I noticed testcafe was upgraded to the next major version. This upgrade broke the test. Version 3 of test cafe correctly captured request body for sendBeacon requests. I'm not sure if this is a regression on their part or an intentional change. But it definitely made it so we can't test as deeply as before.
// await t.expect(notification.events[0].xdm.eventType).eql(INTERACT); | ||
// | ||
// await t | ||
// .expect( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should check the request body for features like click-tracking
. If Testcafe doesn't capture the request body for sendBeacon
request then for testing purposes we should force interact
or find a way to validate we send the right payload.
cc: @jonsnyder @jfkhoury
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please let me know if there is a way to force fetch
instead of sendBeacon
for collect
calls. I tried to find a way but didn't see a clear path.
Thanks @ninaceban ! You're right, Erik's wiki doesn't mention tracking BTW, you're right about target services not fully benefiting from automatic interaction tracking yet. I'm not sure the product roadmap priorities for target, but I believe it is on the backlog. |
Given the uncertainty surrounding Target's plans to adopt the automatic click tracking feature, it would be advisable to avoid adding it now. The same applies to json-content-item items. It's always easier to add features later than to remove them. |
setAttribute(container, key, attributes[key]); | ||
}); | ||
return Promise.resolve(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was this left after sequential rendering revert? There are few other dom-actions files that return a Promise.resolve()
too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ninaceban i'll remove them if you want, but these actions should all return promises to be consistent with actions that require it such as appendHtml
, redirect
, insertHtmlBefore
, insertHtmlAfer
, prependHtml
, replaceHtml
and setHtml
. Is there a good reason to have inconsistent returns across all the dom-actions? Or should there be a strong contract/pattern for each dom action to follow?
src/components/Personalization/dom-actions/rearrangeChildren.js
Outdated
Show resolved
Hide resolved
@ninaceban I'm not sure if there is an action you want me to take here. can you please be specific? It would be advisable to avoid adding what? If you are asking to not add automatic proposition interaction tracking for target then no worries -- that's already done. It is disabled for target by default. As for the |
Description
This PR is to support automatic proposition click tracking as described here.
In depth technical details about this feature can be read here
This change does not modify the way element clicks are tracked. Any element designated for click tracking (whether from AJO or Target) is tracked by iterating all known click selectors and checking if the element clicked and it's ancestors match. This functionality remains untouched.
This PR adds new functionality that tracks interactions (clicks) for proposition item(s) rendered to the DOM.
It does so using data-attributes. When alloy renders proposition items, any time the DOM is modified (either by inserting elements or mutating an existing DOM element) alloy adds a data attribute,
data-aep-interact-id
to the element, which is then used for interaction tracking. Interact ids have a one to many relationship with propositions and proposition-items. Since there can be a plethora of campaigns targeting the same element. For this reason, the interact id is used as a key for alloy to look up an in-memory mapping to see which propositions and items are relevant.Additionally, a label and token may be added to an HTML proposition received from AJO using a data attribute.
Data attributes
HTML data attributes are used to store these details.
data-aep-click-label
data-aep-click-token
data-aep-interact-id
interact-id
maps to at least one proposition, but it can map to more than one if multiple propositions reference the same element.ℹ️ These 👆 names are tentative and subject to change. Please offer your feedback for naming if you have an opinion. ℹ️
Determining proposition, label & token when the user clicks within a proposition element
Beginning with the clicked element, each element's data attributes for
click-label
,click-token
andinteract-id
are read. If a value is found on the element, it is used for the interact event. If not, the parent element is inspected for the data attributes. If not found there, each parent element thereafter will be inspected until the root element has been reached. Note that there could exist nested labels and tokens within elements. In that case, only the first label and token values found while walking up the DOM tree will be used.New config option
A new optional configuration option has been added called
autoCollectPropositionInteractions
. The value is a map of decision providers, each with value that indicates how automatic proposition interactions should be handled.By default, automatic proposition interactions are always collected for AJO, and never collected for Target. The default value of
autoCollectPropositionInteractions
is:Possible configuration values for a decision provider are:
always
interact
events for any elements associated with a proposition.never
interact
events for DOM elements associated with a proposition.decoratedElementsOnly
interact
events for elements associated with a proposition but ONLY if the element has also have been "decorated" with data attributes specifying a label or token.enhanced
applyPropositions
command.The
applyPropositions
command now allows users to associate ajson-content-item
proposition item with a DOM element. This comes in handy for code based JSON content propositions.For example, imagine a customer has a
json-content-item
they used to generate a dom element or widget. They want to take advantage of automatic click tracking for that element. So they use theapplyPropositions
command to associate the proposition with the element selector. Sample code...Alloy adds an
interact-id
to the element, and associates it with the provided proposition. Now automatic click tracking will work the same way it does for other automatically rendered propositions.Types of changes
Checklist: