@adobe/spacecat-shared-rum-api-client 2.22.5 → 2.23.0
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/CHANGELOG.md +14 -0
- package/package.json +2 -2
- package/src/functions/form-vitals.js +67 -45
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-rum-api-client-v2.23.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.22.6...@adobe/spacecat-shared-rum-api-client-v2.23.0) (2025-04-16)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* formsource wise segregation of audit result ([#692](https://github.com/adobe/spacecat-shared/issues/692)) ([0f4f503](https://github.com/adobe/spacecat-shared/commit/0f4f503facbd81538a0d445a462735766e7bfffa))
|
|
7
|
+
|
|
8
|
+
# [@adobe/spacecat-shared-rum-api-client-v2.22.6](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.22.5...@adobe/spacecat-shared-rum-api-client-v2.22.6) (2025-04-15)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **deps:** update dependency @adobe/helix-universal to v5.2.0 ([#694](https://github.com/adobe/spacecat-shared/issues/694)) ([55883c5](https://github.com/adobe/spacecat-shared/commit/55883c597c61c891fc17ed39d0aab1c33af5b90c))
|
|
14
|
+
|
|
1
15
|
# [@adobe/spacecat-shared-rum-api-client-v2.22.5](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.22.4...@adobe/spacecat-shared-rum-api-client-v2.22.5) (2025-04-15)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/spacecat-shared-rum-api-client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.23.0",
|
|
4
4
|
"description": "Shared modules of the Spacecat Services - Rum API client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@adobe/fetch": "4.2.0",
|
|
39
39
|
"@adobe/helix-shared-wrap": "2.0.2",
|
|
40
|
-
"@adobe/helix-universal": "5.
|
|
40
|
+
"@adobe/helix-universal": "5.2.0",
|
|
41
41
|
"@adobe/spacecat-shared-utils": "1.26.4",
|
|
42
42
|
"@adobe/rum-distiller": "1.16.3",
|
|
43
43
|
"aws4": "1.13.2",
|
|
@@ -14,8 +14,7 @@ import { DataChunks } from '@adobe/rum-distiller';
|
|
|
14
14
|
import trafficAcquisition from './traffic-acquisition.js';
|
|
15
15
|
import { generateKey, DELIMITER, loadBundles } from '../utils.js';
|
|
16
16
|
|
|
17
|
-
const
|
|
18
|
-
const METRICS = ['formview', 'formengagement', 'formsubmit', 'formbuttonclick'];
|
|
17
|
+
const METRICS = ['formview', 'formengagement', 'formsubmit'];
|
|
19
18
|
const CHECKPOINTS = ['viewblock', 'click', 'fill', 'formsubmit', 'navigate'];
|
|
20
19
|
const KEYWORDS_TO_FILTER = ['search'];
|
|
21
20
|
|
|
@@ -25,7 +24,6 @@ function initializeResult(url) {
|
|
|
25
24
|
formsubmit: {},
|
|
26
25
|
formview: {},
|
|
27
26
|
formengagement: {},
|
|
28
|
-
formbuttonclick: {},
|
|
29
27
|
pageview: {},
|
|
30
28
|
forminternalnavigation: [],
|
|
31
29
|
};
|
|
@@ -51,39 +49,48 @@ function filterEvents(bundles) {
|
|
|
51
49
|
}));
|
|
52
50
|
}
|
|
53
51
|
|
|
52
|
+
function isFormSource(source, eventSource) {
|
|
53
|
+
const excludeSrc = ['form.', 'form#'];
|
|
54
|
+
if (source === 'unknown') {
|
|
55
|
+
return /\bform\b/.test(eventSource?.toLowerCase()) && !excludeSrc.some((exclude) => eventSource?.includes(exclude));
|
|
56
|
+
} else {
|
|
57
|
+
return eventSource?.includes(source);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
const metricFns = {
|
|
55
|
-
formview: (bundle) => {
|
|
56
|
-
const formView = bundle.events.find((e) => e.checkpoint === 'viewblock' &&
|
|
62
|
+
formview: (source) => (bundle) => {
|
|
63
|
+
const formView = bundle.events.find((e) => e.checkpoint === 'viewblock' && isFormSource(source, e.source));
|
|
57
64
|
return formView ? bundle.weight : 0;
|
|
58
65
|
},
|
|
59
|
-
formengagement: (bundle) => {
|
|
60
|
-
const formClick = bundle.events.find((e) => e.checkpoint === 'click'
|
|
66
|
+
formengagement: (source) => (bundle) => {
|
|
67
|
+
const formClick = bundle.events.find((e) => (e.checkpoint === 'click' || e.checkpoint === 'fill') && isFormSource(source, e.source));
|
|
61
68
|
return formClick ? bundle.weight : 0;
|
|
62
69
|
},
|
|
63
|
-
formsubmit: (bundle) => {
|
|
64
|
-
const formSubmit = bundle.events.find((e) => e.checkpoint === 'formsubmit');
|
|
70
|
+
formsubmit: (source) => (bundle) => {
|
|
71
|
+
const formSubmit = bundle.events.find((e) => e.checkpoint === 'formsubmit' && isFormSource(source, e.source));
|
|
65
72
|
return formSubmit ? bundle.weight : 0;
|
|
66
73
|
},
|
|
67
|
-
formbuttonclick: (bundle) => {
|
|
68
|
-
const formButtonClick = bundle.events.find((e) => e.checkpoint === 'click' && e.source
|
|
69
|
-
&& /\bform\b/.test(e.source.toLowerCase())
|
|
70
|
-
&& /\bbutton\b/.test(e.source.toLowerCase()));
|
|
71
|
-
return formButtonClick ? bundle.weight : 0;
|
|
72
|
-
},
|
|
73
74
|
};
|
|
74
75
|
|
|
76
|
+
function findByUrl(formVitals, url) {
|
|
77
|
+
return Object.values(formVitals).find((item) => item.url === url);
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
function populateFormsInternalNavigation(bundles, formVitals) {
|
|
76
81
|
const dataChunks = new DataChunks();
|
|
77
82
|
loadBundles(bundles, dataChunks);
|
|
78
83
|
dataChunks.filter = { checkpoint: ['navigate'] };
|
|
79
84
|
dataChunks.filtered.forEach((bundle) => {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
const formInternalNav = bundle.events.find((e) => e.checkpoint === 'navigate');
|
|
86
|
+
const formVital = findByUrl(formVitals, bundle.url);
|
|
87
|
+
if (formInternalNav && formVital
|
|
88
|
+
&& !formVital.forminternalnavigation
|
|
89
|
+
.some((e) => e.url === formInternalNav.source)) {
|
|
90
|
+
const fv = findByUrl(formVitals, formInternalNav.source);
|
|
91
|
+
formVital.forminternalnavigation.push({
|
|
92
|
+
url: formInternalNav.source,
|
|
93
|
+
pageview: fv?.pageview,
|
|
87
94
|
});
|
|
88
95
|
}
|
|
89
96
|
});
|
|
@@ -134,34 +141,49 @@ function handler(bundles) {
|
|
|
134
141
|
const dataChunks = new DataChunks();
|
|
135
142
|
loadBundles(bundlesWithFilteredEvents, dataChunks);
|
|
136
143
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
const formViewdataChunks = new DataChunks();
|
|
145
|
+
loadBundles(bundlesWithFilteredEvents, formViewdataChunks);
|
|
146
|
+
const formSourceMap = {};
|
|
147
|
+
const globalFormSourceSet = new Set();
|
|
148
|
+
formViewdataChunks.filter = { checkpoint: ['viewblock'] };
|
|
149
|
+
formViewdataChunks.filtered.forEach(({ url, events }) => {
|
|
150
|
+
formSourceMap[url] = formSourceMap[url] || new Set();
|
|
151
|
+
events.forEach(({ checkpoint, source }) => {
|
|
152
|
+
if (checkpoint === 'viewblock' && source) {
|
|
153
|
+
formSourceMap[url].add(source);
|
|
154
|
+
globalFormSourceSet.add(source);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
143
158
|
// traffic acquisition data per url
|
|
144
159
|
const trafficByUrl = trafficAcquisition.handler(bundles);
|
|
145
160
|
const trafficByUrlMap = Object.fromEntries(
|
|
146
161
|
trafficByUrl.map(({ url, ...item }) => [url, item]),
|
|
147
162
|
);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
const formVitals = {};
|
|
164
|
+
|
|
165
|
+
globalFormSourceSet.forEach((source) => {
|
|
166
|
+
// counts metrics per each group
|
|
167
|
+
const match = source.match(/form[#.](\w+)/);
|
|
168
|
+
const formsource = match ? match[1] : 'unknown';
|
|
169
|
+
// groups by url and user agent
|
|
170
|
+
dataChunks.addFacet('urlUserAgents', (bundle) => generateKey(bundle.url, bundle.userAgent));
|
|
171
|
+
METRICS.forEach((metric) => dataChunks.addSeries(metric, metricFns[metric](formsource)));
|
|
172
|
+
// aggregates metrics per group (url and user agent)
|
|
173
|
+
dataChunks.facets.urlUserAgents.reduce((acc, { value, metrics, weight }) => {
|
|
174
|
+
const [url, userAgent] = value.split(DELIMITER);
|
|
175
|
+
const key = formSourceMap[url].has(source) ? generateKey(url, source) : url;
|
|
176
|
+
acc[key] = acc[key] || initializeResult(url);
|
|
177
|
+
acc[key].pageview[userAgent] = acc[key].pageview[userAgent] || weight;
|
|
178
|
+
acc[key].trafficacquisition = trafficByUrlMap[url];
|
|
179
|
+
acc[key].formsource = source;
|
|
180
|
+
METRICS.filter((metric) => metrics[metric].sum) // filter out user-agents with no form vitals
|
|
181
|
+
.forEach((metric) => {
|
|
182
|
+
acc[key][metric][userAgent] = metrics[metric].sum;
|
|
183
|
+
});
|
|
184
|
+
return acc;
|
|
185
|
+
}, formVitals);
|
|
186
|
+
});
|
|
165
187
|
// populate internal navigation data
|
|
166
188
|
populateFormsInternalNavigation(bundles, formVitals);
|
|
167
189
|
// filter out pages with no form vitals
|