@adobe/spacecat-shared-rum-api-client 2.23.4 → 2.24.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 +7 -0
- package/package.json +1 -1
- package/src/functions/form-vitals.js +94 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-rum-api-client-v2.24.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.23.4...@adobe/spacecat-shared-rum-api-client-v2.24.0) (2025-05-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* identify iframe forms ([#715](https://github.com/adobe/spacecat-shared/issues/715)) ([d2e0a47](https://github.com/adobe/spacecat-shared/commit/d2e0a47f1020471a6f22f9d713e6bf9c03df2279))
|
|
7
|
+
|
|
1
8
|
# [@adobe/spacecat-shared-rum-api-client-v2.23.4](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.23.3...@adobe/spacecat-shared-rum-api-client-v2.23.4) (2025-04-30)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@ import { DataChunks } from '@adobe/rum-distiller';
|
|
|
14
14
|
import { generateKey, DELIMITER, loadBundles } from '../utils.js';
|
|
15
15
|
|
|
16
16
|
const METRICS = ['formview', 'formengagement', 'formsubmit'];
|
|
17
|
-
const CHECKPOINTS = ['viewblock', 'click', 'fill', 'formsubmit', 'navigate'];
|
|
17
|
+
const CHECKPOINTS = ['viewblock', 'click', 'fill', 'formsubmit', 'navigate', 'viewmedia'];
|
|
18
18
|
const KEYWORDS_TO_FILTER = ['search'];
|
|
19
19
|
|
|
20
20
|
function initializeResult(url) {
|
|
@@ -41,7 +41,7 @@ function filterEvents(bundles) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const isFormRelatedEvent = ['fill', 'formsubmit'].includes(event.checkpoint)
|
|
44
|
-
|| /\bform\b
|
|
44
|
+
|| /\bform\b|aemform\w*/i.test(event.source);
|
|
45
45
|
return isFormRelatedEvent && !KEYWORDS_TO_FILTER.some((keyword) => event.source
|
|
46
46
|
&& event.source.toLowerCase().includes(keyword));
|
|
47
47
|
}),
|
|
@@ -82,6 +82,7 @@ function populateFormsInternalNavigation(bundles, formVitals) {
|
|
|
82
82
|
dataChunks.filter = { checkpoint: ['navigate'] };
|
|
83
83
|
dataChunks.filtered.forEach((bundle) => {
|
|
84
84
|
const formInternalNav = bundle.events.find((e) => e.checkpoint === 'navigate');
|
|
85
|
+
|
|
85
86
|
const formVital = findByUrl(formVitals, bundle.url);
|
|
86
87
|
if (formInternalNav && formVital
|
|
87
88
|
&& !formVital.forminternalnavigation
|
|
@@ -133,8 +134,58 @@ function containsFormVitals(row) {
|
|
|
133
134
|
return METRICS.some((metric) => Object.keys(row[metric]).length > 0);
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
function getParentPageVitalsGroupedByIFrame(bundles, dataChunks, iframeParentMap) {
|
|
138
|
+
const iframeVitals = {};
|
|
139
|
+
if (dataChunks.facets.urlUserAgents) {
|
|
140
|
+
dataChunks.facets.urlUserAgents.reduce((acc, { value, weight }) => {
|
|
141
|
+
const [url, userAgent] = value.split(DELIMITER);
|
|
142
|
+
|
|
143
|
+
let iframeSrc = null;
|
|
144
|
+
for (const iframeUrl of Object.keys(iframeParentMap)) {
|
|
145
|
+
for (const parentUrl of iframeParentMap[iframeUrl]) {
|
|
146
|
+
if (parentUrl === url) {
|
|
147
|
+
iframeSrc = iframeUrl;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (iframeSrc) {
|
|
153
|
+
acc[url] = acc[url] || { url, pageview: {}, forminternalnavigation: [] };
|
|
154
|
+
acc[url].pageview[userAgent] = acc[url].pageview[userAgent] || weight;
|
|
155
|
+
acc[url].iframeSrc = iframeSrc;
|
|
156
|
+
}
|
|
157
|
+
return acc;
|
|
158
|
+
}, iframeVitals);
|
|
159
|
+
}
|
|
160
|
+
const groupedByIframeSrc = {};
|
|
161
|
+
const parentWebVitals = {};
|
|
162
|
+
|
|
163
|
+
// select the parent page with the most views
|
|
164
|
+
for (const [url, obj] of Object.entries(iframeVitals)) {
|
|
165
|
+
const { iframeSrc } = obj;
|
|
166
|
+
const totalViews = (obj.pageview.mobile || 0) + (obj.pageview.desktop || 0);
|
|
167
|
+
if (!groupedByIframeSrc[iframeSrc] || totalViews > groupedByIframeSrc[iframeSrc].totalViews) {
|
|
168
|
+
groupedByIframeSrc[iframeSrc] = { url, totalViews };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
for (const { url } of Object.values(groupedByIframeSrc)) {
|
|
173
|
+
parentWebVitals[url] = iframeVitals[url];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
populateFormsInternalNavigation(bundles, parentWebVitals);
|
|
177
|
+
findFormCTAForInternalNavigation(bundles, Object.values(parentWebVitals));
|
|
178
|
+
|
|
179
|
+
const iframeParentVitalsMap = {};
|
|
180
|
+
for (const vitals of Object.values(parentWebVitals)) {
|
|
181
|
+
iframeParentVitalsMap[vitals.iframeSrc] = vitals;
|
|
182
|
+
}
|
|
183
|
+
return iframeParentVitalsMap;
|
|
184
|
+
}
|
|
185
|
+
|
|
136
186
|
function handler(bundles) {
|
|
137
187
|
// Filter out search related events
|
|
188
|
+
|
|
138
189
|
const bundlesWithFilteredEvents = filterEvents(bundles);
|
|
139
190
|
|
|
140
191
|
const dataChunks = new DataChunks();
|
|
@@ -143,17 +194,26 @@ function handler(bundles) {
|
|
|
143
194
|
const formViewdataChunks = new DataChunks();
|
|
144
195
|
loadBundles(bundlesWithFilteredEvents, formViewdataChunks);
|
|
145
196
|
const formSourceMap = {};
|
|
197
|
+
const iframeParentMap = {};
|
|
146
198
|
const globalFormSourceSet = new Set();
|
|
147
|
-
formViewdataChunks.filter = { checkpoint: ['viewblock'] };
|
|
199
|
+
formViewdataChunks.filter = { checkpoint: ['viewblock', 'viewmedia'] };
|
|
148
200
|
formViewdataChunks.filtered.forEach(({ url, events }) => {
|
|
149
201
|
formSourceMap[url] = formSourceMap[url] || new Set();
|
|
150
|
-
events.forEach(({ checkpoint, source }) => {
|
|
202
|
+
events.forEach(({ checkpoint, source, target }) => {
|
|
151
203
|
if (checkpoint === 'viewblock' && source) {
|
|
152
204
|
formSourceMap[url].add(source);
|
|
153
205
|
globalFormSourceSet.add(source);
|
|
154
206
|
}
|
|
207
|
+
if (checkpoint === 'viewmedia' && target) {
|
|
208
|
+
const regex = /aemform[\w.]*\.iframe[\w.]*/;
|
|
209
|
+
if (regex.test(target)) {
|
|
210
|
+
iframeParentMap[target] = iframeParentMap[target] || new Set();
|
|
211
|
+
iframeParentMap[target].add(url);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
155
214
|
});
|
|
156
215
|
});
|
|
216
|
+
|
|
157
217
|
// traffic acquisition data per url - uncomment this when required
|
|
158
218
|
// const trafficByUrl = trafficAcquisition.handler(bundles);
|
|
159
219
|
// const trafficByUrlMap = Object.fromEntries(
|
|
@@ -192,12 +252,41 @@ function handler(bundles) {
|
|
|
192
252
|
return acc;
|
|
193
253
|
}, formVitals);
|
|
194
254
|
});
|
|
255
|
+
|
|
256
|
+
const iframeParentVitalsMap = getParentPageVitalsGroupedByIFrame(
|
|
257
|
+
bundles,
|
|
258
|
+
dataChunks,
|
|
259
|
+
iframeParentMap,
|
|
260
|
+
);
|
|
261
|
+
|
|
195
262
|
// populate internal navigation data
|
|
196
263
|
populateFormsInternalNavigation(bundles, formVitals);
|
|
197
264
|
// filter out pages with no form vitals
|
|
198
265
|
const filteredFormVitals = Object.values(formVitals).filter(containsFormVitals);
|
|
199
266
|
findFormCTAForInternalNavigation(bundles, filteredFormVitals);
|
|
200
|
-
|
|
267
|
+
|
|
268
|
+
const updatedFormVitals = filteredFormVitals.map((formVital) => {
|
|
269
|
+
const formVitalCopy = { ...formVital };
|
|
270
|
+
const parentFormVital = iframeParentVitalsMap[formVital.url];
|
|
271
|
+
if (parentFormVital) {
|
|
272
|
+
const {
|
|
273
|
+
url,
|
|
274
|
+
pageview,
|
|
275
|
+
forminternalnavigation,
|
|
276
|
+
iframeSrc,
|
|
277
|
+
} = parentFormVital;
|
|
278
|
+
Object.assign(formVitalCopy, {
|
|
279
|
+
url,
|
|
280
|
+
pageview: { ...pageview },
|
|
281
|
+
forminternalnavigation,
|
|
282
|
+
|
|
283
|
+
iframeSrc,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
return formVitalCopy;
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
return [...updatedFormVitals];
|
|
201
290
|
}
|
|
202
291
|
|
|
203
292
|
export default {
|