@adobe/spacecat-shared-rum-api-client 2.40.11 → 2.40.12
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 +6 -0
- package/package.json +3 -3
- package/src/common/rum-bundler-client.js +9 -3
- package/src/common/traffic.js +36 -12
- package/src/functions/experiment.js +3 -1
- package/src/functions/opportunities/high-organic-low-ctr.js +3 -1
- package/src/functions/traffic-analysis.js +18 -6
- package/src/index.js +9 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [@adobe/spacecat-shared-rum-api-client-v2.40.12](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.40.11...@adobe/spacecat-shared-rum-api-client-v2.40.12) (2026-04-09)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **deps:** update adobe fixes ([#1503](https://github.com/adobe/spacecat-shared/issues/1503)) ([21d4d4b](https://github.com/adobe/spacecat-shared/commit/21d4d4b3cfa95ca7748ef4b65b04cace24768dfc))
|
|
6
|
+
|
|
1
7
|
## [@adobe/spacecat-shared-rum-api-client-v2.40.11](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.40.10...@adobe/spacecat-shared-rum-api-client-v2.40.11) (2026-04-06)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/spacecat-shared-rum-api-client",
|
|
3
|
-
"version": "2.40.
|
|
3
|
+
"version": "2.40.12",
|
|
4
4
|
"description": "Shared modules of the Spacecat Services - Rum API client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@adobe/fetch": "4.
|
|
38
|
+
"@adobe/fetch": "4.3.0",
|
|
39
39
|
"@adobe/helix-shared-wrap": "2.0.2",
|
|
40
|
-
"@adobe/helix-universal": "5.4.
|
|
40
|
+
"@adobe/helix-universal": "5.4.1",
|
|
41
41
|
"@adobe/rum-distiller": "1.23.0",
|
|
42
42
|
"@adobe/spacecat-shared-utils": "1.81.1",
|
|
43
43
|
"aws4": "1.13.2",
|
|
@@ -121,7 +121,9 @@ function generateUrlsForDateRange(startDate, endDate, domain, granularity, domai
|
|
|
121
121
|
* then data for the `/a1/` and `/a2` are counted towards `/`'s data
|
|
122
122
|
*/
|
|
123
123
|
async function mergeBundlesWithSameId(bundles) {
|
|
124
|
-
if (!bundles[0]?.url?.includes('bamboohr.com'))
|
|
124
|
+
if (!bundles[0]?.url?.includes('bamboohr.com')) {
|
|
125
|
+
return bundles;
|
|
126
|
+
}
|
|
125
127
|
const prodBaseUrl = 'https://www.bamboohr.com/experiments/';
|
|
126
128
|
const previewBaseUrl = 'https://main--bamboohr-website--bamboohr.hlx.page/experiments/archive/';
|
|
127
129
|
const manifestUrls = [
|
|
@@ -178,14 +180,18 @@ async function mergeBundlesWithSameId(bundles) {
|
|
|
178
180
|
|
|
179
181
|
const getControlPath = (url) => {
|
|
180
182
|
const path = new URL(url).pathname;
|
|
181
|
-
if (variantPaths.includes(path))
|
|
183
|
+
if (variantPaths.includes(path)) {
|
|
184
|
+
return mapping[path];
|
|
185
|
+
}
|
|
182
186
|
return path;
|
|
183
187
|
};
|
|
184
188
|
|
|
185
189
|
const byIdAndPath = bundles.reduce((acc, cur) => {
|
|
186
190
|
const controlPath = getControlPath(cur.url);
|
|
187
191
|
const key = `${cur.id}-${controlPath}`;
|
|
188
|
-
if (!acc[key])
|
|
192
|
+
if (!acc[key]) {
|
|
193
|
+
acc[key] = [];
|
|
194
|
+
}
|
|
189
195
|
if (variantPaths.includes(new URL(cur.url).pathname)) {
|
|
190
196
|
// eslint-disable-next-line no-param-reassign
|
|
191
197
|
cur.url = new URL(controlPath, cur.url).href;
|
package/src/common/traffic.js
CHANGED
|
@@ -25,8 +25,12 @@ import URI from 'urijs';
|
|
|
25
25
|
* URL if it does not contain any text.
|
|
26
26
|
*/
|
|
27
27
|
export function getSecondLevelDomain(url) {
|
|
28
|
-
if (!hasText(url))
|
|
29
|
-
|
|
28
|
+
if (!hasText(url)) {
|
|
29
|
+
return url;
|
|
30
|
+
}
|
|
31
|
+
if (url === '(direct)') {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
30
34
|
|
|
31
35
|
try {
|
|
32
36
|
const uri = new URI(prependSchema(url));
|
|
@@ -132,8 +136,12 @@ const emailTrackingParams = ['email'];
|
|
|
132
136
|
const any = () => true;
|
|
133
137
|
|
|
134
138
|
const anyOf = (truth) => (text) => {
|
|
135
|
-
if (Array.isArray(truth))
|
|
136
|
-
|
|
139
|
+
if (Array.isArray(truth)) {
|
|
140
|
+
return truth.includes(text);
|
|
141
|
+
}
|
|
142
|
+
if (truth instanceof RegExp) {
|
|
143
|
+
return truth.test(text);
|
|
144
|
+
}
|
|
137
145
|
return truth === text;
|
|
138
146
|
};
|
|
139
147
|
|
|
@@ -141,9 +149,15 @@ const anyOf = (truth) => (text) => {
|
|
|
141
149
|
const none = (input) => (Array.isArray(input) ? input.length === 0 : !hasText(input));
|
|
142
150
|
|
|
143
151
|
const not = (truth) => (text) => {
|
|
144
|
-
if (!hasText(text))
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
if (!hasText(text)) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
if (Array.isArray(truth)) {
|
|
156
|
+
return !truth.includes(text);
|
|
157
|
+
}
|
|
158
|
+
if (truth instanceof RegExp) {
|
|
159
|
+
return !truth.test(text);
|
|
160
|
+
}
|
|
147
161
|
return truth !== text;
|
|
148
162
|
};
|
|
149
163
|
|
|
@@ -199,12 +213,16 @@ const ALLOWED_VENDORS = {
|
|
|
199
213
|
* @returns {string} The vendor if allowed, empty string otherwise
|
|
200
214
|
*/
|
|
201
215
|
function validateVendor(type, category, vendor) {
|
|
202
|
-
if (!vendor)
|
|
216
|
+
if (!vendor) {
|
|
217
|
+
return '';
|
|
218
|
+
}
|
|
203
219
|
|
|
204
220
|
const allowedVendors = ALLOWED_VENDORS[type]?.[category];
|
|
205
221
|
|
|
206
222
|
// null/undefined means any vendor is allowed
|
|
207
|
-
if (!allowedVendors)
|
|
223
|
+
if (!allowedVendors) {
|
|
224
|
+
return vendor;
|
|
225
|
+
}
|
|
208
226
|
|
|
209
227
|
// Check if vendor is in the allowed list
|
|
210
228
|
return allowedVendors.includes(vendor) ? vendor : '';
|
|
@@ -308,9 +326,15 @@ export function extractTrafficHints(bundle) {
|
|
|
308
326
|
*/
|
|
309
327
|
export function classifyVendor(referrer, utmSource, utmMedium) {
|
|
310
328
|
const result = vendorClassifications.find(({ regex }) => {
|
|
311
|
-
if (regex.test(referrer))
|
|
312
|
-
|
|
313
|
-
|
|
329
|
+
if (regex.test(referrer)) {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
if (regex.test(utmSource)) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
if (regex.test(utmMedium)) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
314
338
|
return false;
|
|
315
339
|
});
|
|
316
340
|
return result ? result.result : '';
|
|
@@ -50,7 +50,9 @@ function handler(bundles) {
|
|
|
50
50
|
const result = {};
|
|
51
51
|
experiments.forEach((uev) => {
|
|
52
52
|
const [url, experiment] = uev.value.split(DELIMITER);
|
|
53
|
-
if (!result[url])
|
|
53
|
+
if (!result[url]) {
|
|
54
|
+
result[url] = [];
|
|
55
|
+
}
|
|
54
56
|
result[url].push({
|
|
55
57
|
experiment,
|
|
56
58
|
variants: [],
|
|
@@ -112,7 +112,9 @@ function convertToOpportunity(traffic) {
|
|
|
112
112
|
* @returns {Array} List of pages sorted by joint strength
|
|
113
113
|
*/
|
|
114
114
|
function sortPagesByEarnedAndOverallTraffic(pages) {
|
|
115
|
-
if (!Array.isArray(pages) || pages.length === 0)
|
|
115
|
+
if (!Array.isArray(pages) || pages.length === 0) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
116
118
|
|
|
117
119
|
const sortedOverall = [...pages].sort((a, b) => a.total - b.total);
|
|
118
120
|
const sortedEarned = [...pages].sort((a, b) => {
|
|
@@ -57,16 +57,24 @@ function getClicked(bundle) {
|
|
|
57
57
|
const latestClickEvent = bundle.events
|
|
58
58
|
.filter((e) => e.checkpoint === 'click')
|
|
59
59
|
.reduce((latest, current) => {
|
|
60
|
-
if (!latest || !latest.timeDelta)
|
|
61
|
-
|
|
60
|
+
if (!latest || !latest.timeDelta) {
|
|
61
|
+
return current;
|
|
62
|
+
}
|
|
63
|
+
if (current?.timeDelta > latest.timeDelta) {
|
|
64
|
+
return current;
|
|
65
|
+
}
|
|
62
66
|
return latest;
|
|
63
67
|
}, null);
|
|
64
68
|
|
|
65
|
-
if (!latestClickEvent)
|
|
69
|
+
if (!latestClickEvent) {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
66
72
|
|
|
67
73
|
const isConsentClick = !!utils.reclassifyConsent(latestClickEvent).vendor;
|
|
68
74
|
|
|
69
|
-
if (isConsentClick)
|
|
75
|
+
if (isConsentClick) {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
70
78
|
|
|
71
79
|
return 1;
|
|
72
80
|
}
|
|
@@ -78,14 +86,18 @@ function getConsent(bundle) {
|
|
|
78
86
|
|
|
79
87
|
const consentClick = bundle.events.find((e) => e.checkpoint === 'click' && utils.reclassifyConsent(e).vendor);
|
|
80
88
|
|
|
81
|
-
if (!consentClick)
|
|
89
|
+
if (!consentClick) {
|
|
90
|
+
return consentBannerStatus || null;
|
|
91
|
+
}
|
|
82
92
|
|
|
83
93
|
return utils.reclassifyConsent(consentClick).target;
|
|
84
94
|
}
|
|
85
95
|
|
|
86
96
|
function trafficType(bundle, memo) {
|
|
87
97
|
const key = `${bundle.id}${bundle.url}${bundle.time}`;
|
|
88
|
-
if (memo[key])
|
|
98
|
+
if (memo[key]) {
|
|
99
|
+
return memo[key];
|
|
100
|
+
}
|
|
89
101
|
|
|
90
102
|
const type = classifyTraffic(bundle);
|
|
91
103
|
// eslint-disable-next-line no-param-reassign
|
package/src/index.js
CHANGED
|
@@ -65,7 +65,9 @@ export default class RUMAPIClient {
|
|
|
65
65
|
const { env, log = console } = context;
|
|
66
66
|
const { RUM_ADMIN_KEY: rumAdminKey } = env;
|
|
67
67
|
|
|
68
|
-
if (context.rumApiClient)
|
|
68
|
+
if (context.rumApiClient) {
|
|
69
|
+
return context.rumApiClient;
|
|
70
|
+
}
|
|
69
71
|
|
|
70
72
|
const client = new RUMAPIClient({ rumAdminKey }, log);
|
|
71
73
|
context.rumApiClient = client;
|
|
@@ -126,7 +128,9 @@ export default class RUMAPIClient {
|
|
|
126
128
|
// eslint-disable-next-line class-methods-use-this
|
|
127
129
|
async query(query, opts) {
|
|
128
130
|
const { handler, checkpoints } = HANDLERS[query] || {};
|
|
129
|
-
if (!handler)
|
|
131
|
+
if (!handler) {
|
|
132
|
+
throw new Error(`Unknown query ${query}`);
|
|
133
|
+
}
|
|
130
134
|
|
|
131
135
|
try {
|
|
132
136
|
const domainkey = await this._getDomainkey(opts);
|
|
@@ -186,7 +190,9 @@ export default class RUMAPIClient {
|
|
|
186
190
|
|
|
187
191
|
async queryStream(query, opts) {
|
|
188
192
|
const { handler, checkpoints } = HANDLERS[query] || {};
|
|
189
|
-
if (!handler)
|
|
193
|
+
if (!handler) {
|
|
194
|
+
throw new Error(`Unknown query ${query}`);
|
|
195
|
+
}
|
|
190
196
|
|
|
191
197
|
try {
|
|
192
198
|
const domainkey = await this._getDomainkey(opts);
|