@adobe/spacecat-shared-rum-api-client 2.9.10 → 2.10.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/README.md +42 -0
- package/package.json +1 -1
- package/src/functions/form-vitals.js +94 -0
- package/src/index.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-rum-api-client-v2.10.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.9.10...@adobe/spacecat-shared-rum-api-client-v2.10.0) (2024-11-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* form vitals ([#429](https://github.com/adobe/spacecat-shared/issues/429)) ([1b0f92f](https://github.com/adobe/spacecat-shared/commit/1b0f92f682070ffc7db379602d94fa04cb442b10))
|
|
7
|
+
|
|
1
8
|
# [@adobe/spacecat-shared-rum-api-client-v2.9.10](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.9.9...@adobe/spacecat-shared-rum-api-client-v2.9.10) (2024-11-11)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -298,6 +298,48 @@ Calculates the amount of non-inorganic (earned and owned) traffic and the click-
|
|
|
298
298
|
|
|
299
299
|
```
|
|
300
300
|
|
|
301
|
+
### form-vitals
|
|
302
|
+
|
|
303
|
+
Collects form vitals for a specified domain within a given time interval. Identifies whether each URL has embedded forms and counts form views/submission/engagement. This data can infer opportunities, such as URLs with low CTR and limited form engagement, URLs with high page views but fewer form submissions etc.
|
|
304
|
+
An example response:
|
|
305
|
+
|
|
306
|
+
```json
|
|
307
|
+
[
|
|
308
|
+
{
|
|
309
|
+
"url": "https://business.adobe.com/",
|
|
310
|
+
"formsubmit": {},
|
|
311
|
+
"formview": {
|
|
312
|
+
"desktop:mac": 800,
|
|
313
|
+
"desktop:windows": 1900,
|
|
314
|
+
"mobile:ios": 100,
|
|
315
|
+
"mobile:android": 300
|
|
316
|
+
},
|
|
317
|
+
"formengagement": {
|
|
318
|
+
"desktop:windows": 100
|
|
319
|
+
},
|
|
320
|
+
"pageview": {
|
|
321
|
+
"desktop:mac": 800,
|
|
322
|
+
"desktop:windows": 1900,
|
|
323
|
+
"mobile:ios": 100,
|
|
324
|
+
"mobile:android": 300
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"url": "https://business.adobe.com/se/resources/main.html",
|
|
329
|
+
"formsubmit": {
|
|
330
|
+
"desktop:windows": 100
|
|
331
|
+
},
|
|
332
|
+
"formview": {},
|
|
333
|
+
"formengagement": {
|
|
334
|
+
"desktop:windows": 100
|
|
335
|
+
},
|
|
336
|
+
"pageview": {
|
|
337
|
+
"desktop:windows": 100
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
```
|
|
342
|
+
|
|
301
343
|
## Linting
|
|
302
344
|
Lint the codebase using:
|
|
303
345
|
```
|
package/package.json
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const FORM_SOURCE = ['.form', '.marketo', '.marketo-form'];
|
|
14
|
+
const BOT = 'bot';
|
|
15
|
+
const CHECKPOINT_MAPPING = { formsubmit: 'formsubmit', viewblock: 'formview', click: 'formengagement' };
|
|
16
|
+
|
|
17
|
+
function initializeResult(url, pageViews) {
|
|
18
|
+
return {
|
|
19
|
+
url,
|
|
20
|
+
formsubmit: {},
|
|
21
|
+
formview: {},
|
|
22
|
+
formengagement: {},
|
|
23
|
+
pageview: pageViews[url],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function collectFormVitals(bundles, pageViews) {
|
|
28
|
+
const results = {};
|
|
29
|
+
|
|
30
|
+
// Helper functions to identify event types
|
|
31
|
+
const isFormViewEvent = ({ checkpoint, source }) => checkpoint === 'viewblock' && FORM_SOURCE.includes(source);
|
|
32
|
+
const isFormClickEvent = ({ checkpoint, source }) => checkpoint === 'click' && source && /\bform\b/.test(source.toLowerCase());
|
|
33
|
+
const isFormSubmitEvent = ({ checkpoint }) => checkpoint === 'formsubmit';
|
|
34
|
+
|
|
35
|
+
for (const bundle of bundles) {
|
|
36
|
+
const {
|
|
37
|
+
url, userAgent, weight, events,
|
|
38
|
+
} = bundle;
|
|
39
|
+
|
|
40
|
+
if (userAgent && !userAgent.startsWith(BOT)) {
|
|
41
|
+
// Track if each condition has been processed for this event
|
|
42
|
+
const processedCheckpoints = {
|
|
43
|
+
formsubmit: false,
|
|
44
|
+
click: false,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Process each event within the bundle
|
|
48
|
+
for (const event of events) {
|
|
49
|
+
const { checkpoint, source } = event;
|
|
50
|
+
|
|
51
|
+
// Only process the checkpoint once per event
|
|
52
|
+
if (!processedCheckpoints[checkpoint]) {
|
|
53
|
+
if (isFormViewEvent({ checkpoint, source })
|
|
54
|
+
|| isFormSubmitEvent({ checkpoint })
|
|
55
|
+
|| isFormClickEvent({ checkpoint, source })) {
|
|
56
|
+
results[url] = results[url] || initializeResult(url, pageViews);
|
|
57
|
+
const key = CHECKPOINT_MAPPING[checkpoint];
|
|
58
|
+
const res = results[url];
|
|
59
|
+
res[key] = {
|
|
60
|
+
...res[key],
|
|
61
|
+
[userAgent]: (res[key][userAgent] || 0) + weight,
|
|
62
|
+
};
|
|
63
|
+
// Mark this checkpoint as processed - click and formsubmit as processed
|
|
64
|
+
if (checkpoint === 'click' || checkpoint === 'formsubmit') {
|
|
65
|
+
processedCheckpoints[checkpoint] = true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return results;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function pageviewsByUrlAndUserAgent(bundles) {
|
|
76
|
+
return bundles.reduce((acc, cur) => {
|
|
77
|
+
const { userAgent } = cur;
|
|
78
|
+
if (!userAgent || userAgent.startsWith(BOT)) return acc;
|
|
79
|
+
acc[cur.url] = acc[cur.url] || {};
|
|
80
|
+
acc[cur.url][userAgent] = (acc[cur.url][userAgent] || 0) + cur.weight;
|
|
81
|
+
return acc;
|
|
82
|
+
}, {});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function handler(bundles) {
|
|
86
|
+
const pageViews = pageviewsByUrlAndUserAgent(bundles);
|
|
87
|
+
const formVitals = collectFormVitals(bundles, pageViews);
|
|
88
|
+
return Object.values(formVitals);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default {
|
|
92
|
+
handler,
|
|
93
|
+
checkpoints: ['viewblock', 'formsubmit', 'click'],
|
|
94
|
+
};
|
package/src/index.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { fetchBundles } from './common/rum-bundler-client.js';
|
|
13
13
|
import notfound from './functions/404.js';
|
|
14
14
|
import cwv from './functions/cwv.js';
|
|
15
|
+
import formVitals from './functions/form-vitals.js';
|
|
15
16
|
import experiment from './functions/experiment.js';
|
|
16
17
|
import trafficAcquisition from './functions/traffic-acquisition.js';
|
|
17
18
|
import variant from './functions/variant.js';
|
|
@@ -22,6 +23,7 @@ import highOrganicLowCtr from './functions/opportunities/high-organic-low-ctr.js
|
|
|
22
23
|
const HANDLERS = {
|
|
23
24
|
404: notfound,
|
|
24
25
|
cwv,
|
|
26
|
+
'form-vitals': formVitals,
|
|
25
27
|
experiment,
|
|
26
28
|
'traffic-acquisition': trafficAcquisition,
|
|
27
29
|
variant,
|