@adobe/alloy 2.14.0 → 2.15.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/libEs5/components/ActivityCollector/attachClickActivityCollector.js +1 -1
- package/libEs5/components/ActivityCollector/configValidators.js +2 -1
- package/libEs5/components/ActivityCollector/createGetLinkDetails.js +79 -0
- package/libEs5/components/ActivityCollector/createLinkClick.js +22 -64
- package/libEs5/components/ActivityCollector/getLinkName.js +158 -0
- package/libEs5/components/ActivityCollector/getLinkRegion.js +76 -0
- package/libEs5/components/ActivityCollector/index.js +43 -4
- package/libEs5/components/ActivityCollector/utils.js +52 -2
- package/libEs5/components/Audiences/injectProcessDestinations.js +1 -3
- package/libEs5/components/Personalization/createClickStorage.js +4 -2
- package/libEs5/components/Personalization/createExecuteDecisions.js +8 -2
- package/libEs5/components/Personalization/createOnClickHandler.js +4 -2
- package/libEs5/components/Personalization/dom-actions/clicks/collectClicks.js +57 -6
- package/libEs5/components/Personalization/event.js +12 -2
- package/libEs5/constants/libraryVersion.js +1 -1
- package/libEs5/core/buildAndValidateConfig.js +33 -21
- package/libEs5/core/componentCreators.js +4 -0
- package/libEs6/components/ActivityCollector/attachClickActivityCollector.js +1 -1
- package/libEs6/components/ActivityCollector/configValidators.js +3 -2
- package/libEs6/components/ActivityCollector/createGetLinkDetails.js +77 -0
- package/libEs6/components/ActivityCollector/createLinkClick.js +24 -64
- package/libEs6/components/ActivityCollector/getLinkName.js +151 -0
- package/libEs6/components/ActivityCollector/getLinkRegion.js +68 -0
- package/libEs6/components/ActivityCollector/index.js +39 -4
- package/libEs6/components/ActivityCollector/utils.js +43 -1
- package/libEs6/components/Audiences/injectProcessDestinations.js +1 -3
- package/libEs6/components/Personalization/createClickStorage.js +4 -2
- package/libEs6/components/Personalization/createExecuteDecisions.js +6 -2
- package/libEs6/components/Personalization/createOnClickHandler.js +5 -2
- package/libEs6/components/Personalization/dom-actions/clicks/collectClicks.js +50 -6
- package/libEs6/components/Personalization/event.js +13 -3
- package/libEs6/constants/libraryVersion.js +1 -1
- package/libEs6/core/buildAndValidateConfig.js +19 -2
- package/libEs6/core/componentCreators.js +4 -0
- package/package.json +3 -3
|
@@ -12,13 +12,30 @@ governing permissions and limitations under the License.
|
|
|
12
12
|
import attachClickActivityCollector from "./attachClickActivityCollector";
|
|
13
13
|
import configValidators from "./configValidators";
|
|
14
14
|
import createLinkClick from "./createLinkClick";
|
|
15
|
+
import createGetLinkDetails from "./createGetLinkDetails";
|
|
16
|
+
import getLinkName from "./getLinkName";
|
|
17
|
+
import getLinkRegion from "./getLinkRegion";
|
|
18
|
+
import { determineLinkType, findSupportedAnchorElement, getAbsoluteUrlFromAnchorElement } from "./utils";
|
|
19
|
+
const getLinkDetails = createGetLinkDetails({
|
|
20
|
+
window,
|
|
21
|
+
getLinkName,
|
|
22
|
+
getLinkRegion,
|
|
23
|
+
getAbsoluteUrlFromAnchorElement,
|
|
24
|
+
findSupportedAnchorElement,
|
|
25
|
+
determineLinkType
|
|
26
|
+
});
|
|
15
27
|
|
|
16
28
|
const createActivityCollector = ({
|
|
17
29
|
config,
|
|
18
30
|
eventManager,
|
|
19
|
-
handleError
|
|
31
|
+
handleError,
|
|
32
|
+
logger
|
|
20
33
|
}) => {
|
|
21
|
-
const linkClick = createLinkClick(
|
|
34
|
+
const linkClick = createLinkClick({
|
|
35
|
+
getLinkDetails,
|
|
36
|
+
config,
|
|
37
|
+
logger
|
|
38
|
+
});
|
|
22
39
|
return {
|
|
23
40
|
lifecycle: {
|
|
24
41
|
onComponentsRegistered(tools) {
|
|
@@ -26,7 +43,6 @@ const createActivityCollector = ({
|
|
|
26
43
|
lifecycle
|
|
27
44
|
} = tools;
|
|
28
45
|
attachClickActivityCollector({
|
|
29
|
-
config,
|
|
30
46
|
eventManager,
|
|
31
47
|
lifecycle,
|
|
32
48
|
handleError
|
|
@@ -37,7 +53,10 @@ const createActivityCollector = ({
|
|
|
37
53
|
event,
|
|
38
54
|
clickedElement
|
|
39
55
|
}) {
|
|
40
|
-
linkClick(
|
|
56
|
+
linkClick({
|
|
57
|
+
targetElement: clickedElement,
|
|
58
|
+
event
|
|
59
|
+
});
|
|
41
60
|
}
|
|
42
61
|
|
|
43
62
|
}
|
|
@@ -46,4 +65,20 @@ const createActivityCollector = ({
|
|
|
46
65
|
|
|
47
66
|
createActivityCollector.namespace = "ActivityCollector";
|
|
48
67
|
createActivityCollector.configValidators = configValidators;
|
|
68
|
+
|
|
69
|
+
createActivityCollector.buildOnInstanceConfiguredExtraParams = ({
|
|
70
|
+
config,
|
|
71
|
+
logger
|
|
72
|
+
}) => {
|
|
73
|
+
return {
|
|
74
|
+
getLinkDetails: targetElement => {
|
|
75
|
+
return getLinkDetails({
|
|
76
|
+
targetElement,
|
|
77
|
+
config,
|
|
78
|
+
logger
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
49
84
|
export default createActivityCollector;
|
|
@@ -68,5 +68,47 @@ const isExitLink = (window, linkUrl) => {
|
|
|
68
68
|
|
|
69
69
|
return true;
|
|
70
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Reduces repeated whitespace within a string. Whitespace surrounding the string
|
|
73
|
+
* is trimmed and any occurrence of whitespace within the string is replaced with
|
|
74
|
+
* a single space.
|
|
75
|
+
* @param {string} str String to be formatted.
|
|
76
|
+
* @returns {string} Formatted string.
|
|
77
|
+
*/
|
|
71
78
|
|
|
72
|
-
|
|
79
|
+
|
|
80
|
+
const truncateWhiteSpace = str => {
|
|
81
|
+
return str && str.replace(/\s+/g, " ").trim();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const isEmptyString = str => {
|
|
85
|
+
return !str || str.length === 0;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const determineLinkType = (window, config, linkUrl, clickedObj) => {
|
|
89
|
+
let linkType = "other";
|
|
90
|
+
|
|
91
|
+
if (isDownloadLink(config.downloadLinkQualifier, linkUrl, clickedObj)) {
|
|
92
|
+
linkType = "download";
|
|
93
|
+
} else if (isExitLink(window, linkUrl)) {
|
|
94
|
+
linkType = "exit";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return linkType;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const findSupportedAnchorElement = targetElement => {
|
|
101
|
+
let node = targetElement;
|
|
102
|
+
|
|
103
|
+
while (node) {
|
|
104
|
+
if (isSupportedAnchorElement(node)) {
|
|
105
|
+
return node;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
node = node.parentNode;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export { urlStartsWithScheme, getAbsoluteUrlFromAnchorElement, isSupportedAnchorElement, isDownloadLink, isEmptyString, isExitLink, truncateWhiteSpace, findSupportedAnchorElement, determineLinkType };
|
|
@@ -49,11 +49,9 @@ export default (({
|
|
|
49
49
|
return Promise.all(urlDestinations.map(urlDestination => {
|
|
50
50
|
return fireReferrerHideableImage(urlDestination.spec).then(() => {
|
|
51
51
|
logger.info(createResultLogMessage(urlDestination, true));
|
|
52
|
-
}).catch(() => {
|
|
53
|
-
// We intentionally do not throw an error if destinations fail. We
|
|
52
|
+
}).catch(() => {// We intentionally do not throw an error if destinations fail. We
|
|
54
53
|
// consider it a non-critical failure and therefore do not want it to
|
|
55
54
|
// reject the promise handed back to the customer.
|
|
56
|
-
logger.error(createResultLogMessage(urlDestination, false));
|
|
57
55
|
});
|
|
58
56
|
})).then(noop);
|
|
59
57
|
};
|
|
@@ -14,7 +14,8 @@ const metasToArray = metas => {
|
|
|
14
14
|
return {
|
|
15
15
|
id: key,
|
|
16
16
|
scope: metas[key].scope,
|
|
17
|
-
scopeDetails: metas[key].scopeDetails
|
|
17
|
+
scopeDetails: metas[key].scopeDetails,
|
|
18
|
+
trackingLabel: metas[key].trackingLabel
|
|
18
19
|
};
|
|
19
20
|
});
|
|
20
21
|
};
|
|
@@ -29,7 +30,8 @@ export default (() => {
|
|
|
29
30
|
|
|
30
31
|
clickStorage[value.selector][value.meta.id] = {
|
|
31
32
|
scope: value.meta.scope,
|
|
32
|
-
scopeDetails: value.meta.scopeDetails
|
|
33
|
+
scopeDetails: value.meta.scopeDetails,
|
|
34
|
+
trackingLabel: value.meta.trackingLabel
|
|
33
35
|
};
|
|
34
36
|
};
|
|
35
37
|
|
|
@@ -14,8 +14,12 @@ const DEFAULT_ACTION_TYPE = "defaultContent";
|
|
|
14
14
|
|
|
15
15
|
const identity = item => item;
|
|
16
16
|
|
|
17
|
+
const getItemMeta = (item, decisionMeta) => item.characteristics && item.characteristics.trackingLabel ? assign({
|
|
18
|
+
trackingLabel: item.characteristics.trackingLabel
|
|
19
|
+
}, decisionMeta) : decisionMeta;
|
|
20
|
+
|
|
17
21
|
const buildActions = decision => {
|
|
18
|
-
const
|
|
22
|
+
const decisionMeta = {
|
|
19
23
|
id: decision.id,
|
|
20
24
|
scope: decision.scope,
|
|
21
25
|
scopeDetails: decision.scopeDetails
|
|
@@ -23,7 +27,7 @@ const buildActions = decision => {
|
|
|
23
27
|
return decision.items.map(item => assign({
|
|
24
28
|
type: DEFAULT_ACTION_TYPE
|
|
25
29
|
}, item.data, {
|
|
26
|
-
meta
|
|
30
|
+
meta: getItemMeta(item, decisionMeta)
|
|
27
31
|
}));
|
|
28
32
|
};
|
|
29
33
|
|
|
@@ -27,7 +27,10 @@ export default (({
|
|
|
27
27
|
const selectors = getClickSelectors();
|
|
28
28
|
|
|
29
29
|
if (isNonEmptyArray(selectors)) {
|
|
30
|
-
const
|
|
30
|
+
const {
|
|
31
|
+
decisionsMeta,
|
|
32
|
+
eventLabel
|
|
33
|
+
} = collectClicks(clickedElement, selectors, getClickMetasBySelector);
|
|
31
34
|
|
|
32
35
|
if (isNonEmptyArray(decisionsMeta)) {
|
|
33
36
|
const xdm = {
|
|
@@ -44,7 +47,7 @@ export default (({
|
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
event.mergeXdm(xdm);
|
|
47
|
-
mergeDecisionsMeta(event, decisionsMeta, PropositionEventType.INTERACT);
|
|
50
|
+
mergeDecisionsMeta(event, decisionsMeta, PropositionEventType.INTERACT, eventLabel);
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
};
|
|
@@ -16,28 +16,72 @@ const getMetasIfMatches = (clickedElement, selector, getClickMetasBySelector) =>
|
|
|
16
16
|
documentElement
|
|
17
17
|
} = document;
|
|
18
18
|
let element = clickedElement;
|
|
19
|
+
let i = 0;
|
|
19
20
|
|
|
20
21
|
while (element && element !== documentElement) {
|
|
21
22
|
if (matchesSelectorWithEq(selector, element)) {
|
|
22
|
-
|
|
23
|
+
const matchedMetas = getClickMetasBySelector(selector);
|
|
24
|
+
const foundMetaWithLabel = matchedMetas.find(meta => meta.trackingLabel);
|
|
25
|
+
|
|
26
|
+
if (foundMetaWithLabel) {
|
|
27
|
+
return {
|
|
28
|
+
metas: matchedMetas,
|
|
29
|
+
label: foundMetaWithLabel.trackingLabel,
|
|
30
|
+
weight: i
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
metas: matchedMetas
|
|
36
|
+
};
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
element = element.parentNode;
|
|
40
|
+
i += 1;
|
|
26
41
|
}
|
|
27
42
|
|
|
28
|
-
return
|
|
43
|
+
return {
|
|
44
|
+
metas: null
|
|
45
|
+
};
|
|
29
46
|
};
|
|
30
47
|
|
|
48
|
+
const cleanMetas = metas => metas.map(meta => {
|
|
49
|
+
delete meta.trackingLabel;
|
|
50
|
+
return meta;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const dedupMetas = metas => metas.filter((meta, index) => {
|
|
54
|
+
const stringifiedMeta = JSON.stringify(meta);
|
|
55
|
+
return index === metas.findIndex(innerMeta => JSON.stringify(innerMeta) === stringifiedMeta);
|
|
56
|
+
});
|
|
57
|
+
|
|
31
58
|
export default ((clickedElement, selectors, getClickMetasBySelector) => {
|
|
32
59
|
const result = [];
|
|
60
|
+
let resultLabel = "";
|
|
61
|
+
let resultLabelWeight = Number.MAX_SAFE_INTEGER;
|
|
62
|
+
/* eslint-disable no-continue */
|
|
33
63
|
|
|
34
64
|
for (let i = 0; i < selectors.length; i += 1) {
|
|
35
|
-
const
|
|
65
|
+
const {
|
|
66
|
+
metas,
|
|
67
|
+
label,
|
|
68
|
+
weight
|
|
69
|
+
} = getMetasIfMatches(clickedElement, selectors[i], getClickMetasBySelector);
|
|
36
70
|
|
|
37
|
-
if (metas) {
|
|
38
|
-
|
|
71
|
+
if (!metas) {
|
|
72
|
+
continue;
|
|
39
73
|
}
|
|
74
|
+
|
|
75
|
+
if (label && weight <= resultLabelWeight) {
|
|
76
|
+
resultLabel = label;
|
|
77
|
+
resultLabelWeight = weight;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
result.push(...cleanMetas(metas));
|
|
40
81
|
}
|
|
41
82
|
|
|
42
|
-
return
|
|
83
|
+
return {
|
|
84
|
+
decisionsMeta: dedupMetas(result),
|
|
85
|
+
eventLabel: resultLabel
|
|
86
|
+
};
|
|
43
87
|
});
|
|
@@ -10,8 +10,10 @@ OF ANY KIND, either express or implied. See the License for the specific languag
|
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
const EVENT_TYPE_TRUE = 1;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
/* eslint-disable no-underscore-dangle */
|
|
14
|
+
|
|
15
|
+
export const mergeDecisionsMeta = (event, decisionsMeta, eventType, eventLabel = "") => {
|
|
16
|
+
const xdm = {
|
|
15
17
|
_experience: {
|
|
16
18
|
decisioning: {
|
|
17
19
|
propositions: decisionsMeta,
|
|
@@ -20,7 +22,15 @@ export const mergeDecisionsMeta = (event, decisionsMeta, eventType) => {
|
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
|
-
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
if (eventLabel) {
|
|
28
|
+
xdm._experience.decisioning.propositionAction = {
|
|
29
|
+
label: eventLabel
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
event.mergeXdm(xdm);
|
|
24
34
|
};
|
|
25
35
|
export const mergeQuery = (event, details) => {
|
|
26
36
|
event.mergeQuery({
|
|
@@ -34,6 +34,21 @@ const transformOptions = (schema, options) => {
|
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
const buildAllOnInstanceConfiguredExtraParams = (config, logger, componentCreators) => {
|
|
38
|
+
return componentCreators.reduce((memo, {
|
|
39
|
+
buildOnInstanceConfiguredExtraParams
|
|
40
|
+
}) => {
|
|
41
|
+
if (buildOnInstanceConfiguredExtraParams) {
|
|
42
|
+
assign(memo, buildOnInstanceConfiguredExtraParams({
|
|
43
|
+
config,
|
|
44
|
+
logger
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return memo;
|
|
49
|
+
}, {});
|
|
50
|
+
};
|
|
51
|
+
|
|
37
52
|
export default (({
|
|
38
53
|
options,
|
|
39
54
|
componentCreators,
|
|
@@ -46,8 +61,10 @@ export default (({
|
|
|
46
61
|
const config = createConfig(transformOptions(schema, options));
|
|
47
62
|
setDebugEnabled(config.debugEnabled, {
|
|
48
63
|
fromConfig: true
|
|
49
|
-
});
|
|
50
|
-
|
|
64
|
+
}); // eslint-disable-next-line no-underscore-dangle
|
|
65
|
+
|
|
66
|
+
const extraParams = buildAllOnInstanceConfiguredExtraParams(config, logger, componentCreators);
|
|
67
|
+
logger.logOnInstanceConfigured({ ...extraParams,
|
|
51
68
|
config
|
|
52
69
|
});
|
|
53
70
|
return config;
|
|
@@ -9,6 +9,10 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
|
|
|
9
9
|
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
+
// This is the only place where core is allowed to import from components.
|
|
13
|
+
// This makes sure that each component could be removed without breaking the library
|
|
14
|
+
|
|
15
|
+
/* eslint-disable import/no-restricted-paths */
|
|
12
16
|
import createDataCollector from "../components/DataCollector";
|
|
13
17
|
import createActivityCollector from "../components/ActivityCollector";
|
|
14
18
|
import createIdentity from "../components/Identity";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/alloy",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0-alpha.1",
|
|
4
4
|
"description": "Adobe Experience Platform Web SDK",
|
|
5
5
|
"main": "libEs5/index.js",
|
|
6
6
|
"module": "libEs6/index.js",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"uuid": "^3.3.2"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@adobe/alloy": "^2.
|
|
67
|
+
"@adobe/alloy": "^2.15.0-alpha.0",
|
|
68
68
|
"@babel/cli": "^7.12.8",
|
|
69
69
|
"@babel/core": "^7.2.2",
|
|
70
70
|
"@babel/plugin-proposal-object-rest-spread": "^7.3.2",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"rollup-plugin-terser": "^7.0.2",
|
|
119
119
|
"semver": "^7.3.7",
|
|
120
120
|
"start-server-and-test": "^1.10.6",
|
|
121
|
-
"testcafe": "^2.
|
|
121
|
+
"testcafe": "^2.3.1",
|
|
122
122
|
"testcafe-browser-provider-saucelabs": "^1.9.0",
|
|
123
123
|
"testcafe-reporter-junit": "^3.0.2",
|
|
124
124
|
"url-exists-nodejs": "^0.1.0",
|