@adobe/spacecat-shared-utils 1.29.0 → 1.30.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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [@adobe/spacecat-shared-utils-v1.30.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.30.0...@adobe/spacecat-shared-utils-v1.30.1) (2025-02-06)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * composeAuditURL user agent failing for some sites ([#583](https://github.com/adobe/spacecat-shared/issues/583)) ([81bd136](https://github.com/adobe/spacecat-shared/commit/81bd136693ded29130b73b1c0258b6727104f5e1))
7
+
8
+ # [@adobe/spacecat-shared-utils-v1.30.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.29.0...@adobe/spacecat-shared-utils-v1.30.0) (2025-02-06)
9
+
10
+
11
+ ### Features
12
+
13
+ * adding more opportunities utils for forms ([#580](https://github.com/adobe/spacecat-shared/issues/580)) ([4cb7d5d](https://github.com/adobe/spacecat-shared/commit/4cb7d5d94ff887932809416b3cf918fc3b56a58d))
14
+
1
15
  # [@adobe/spacecat-shared-utils-v1.29.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.28.4...@adobe/spacecat-shared-utils-v1.29.0) (2025-02-03)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-utils",
3
- "version": "1.29.0",
3
+ "version": "1.30.1",
4
4
  "description": "Shared modules of the Spacecat Services - utils",
5
5
  "type": "module",
6
6
  "engines": {
@@ -39,7 +39,7 @@
39
39
  "chai": "5.1.2",
40
40
  "chai-as-promised": "8.0.1",
41
41
  "husky": "9.1.7",
42
- "nock": "13.5.6",
42
+ "nock": "14.0.0",
43
43
  "sinon": "19.0.2",
44
44
  "sinon-chai": "4.0.0"
45
45
  },
package/src/formcalc.js CHANGED
@@ -68,6 +68,16 @@ function hasLowerConversionRate(formSubmit, formViews) {
68
68
  return formSubmit / formViews < CR_THRESHOLD_RATIO;
69
69
  }
70
70
 
71
+ function hasLowFormViews(pageViews, formViews) {
72
+ return formViews > 0 && (formViews / pageViews) < 0.7;
73
+ }
74
+
75
+ function hasHighPageViewLowFormCtr(ctaPageViews, ctaClicks, ctaPageTotalClicks, formPageViews) {
76
+ return ctaPageTotalClicks > 0
77
+ && (ctaClicks / ctaPageTotalClicks) < 0.4
78
+ && (formPageViews / ctaPageViews) < 0.1;
79
+ }
80
+
71
81
  /**
72
82
  * Returns the form urls with high form views and low conversion rate
73
83
  *
@@ -96,3 +106,91 @@ export function getHighFormViewsLowConversionMetrics(formVitalsCollection, inter
96
106
  });
97
107
  return urls;
98
108
  }
109
+
110
+ /**
111
+ * Returns the form urls with high page views and low form views
112
+ *
113
+ * @param resultMap
114
+ * @returns {*[]}
115
+ */
116
+ export function getHighPageViewsLowFormViewsMetrics(formVitalsCollection, interval) {
117
+ const urls = [];
118
+ const resultMap = aggregateFormVitalsByDevice(formVitalsCollection);
119
+ resultMap.forEach((metrics, url) => {
120
+ const { total: pageViews } = metrics.pageview;
121
+ const { total: formViews } = metrics.formview;
122
+ const { total: formEngagement } = metrics.formengagement;
123
+
124
+ if (hasHighPageViews(interval, pageViews) && hasLowFormViews(pageViews, formViews)) {
125
+ urls.push({
126
+ url,
127
+ pageViews,
128
+ formViews,
129
+ formEngagement,
130
+ });
131
+ }
132
+ });
133
+ return urls;
134
+ }
135
+
136
+ /**
137
+ * Returns the form urls with high page views containing ctr and low form views
138
+ * @param formVitalsCollection
139
+ * @param formVitalsByDevice
140
+ * @returns {*[]}
141
+ */
142
+ export function getHighPageViewsLowFormCtrMetrics(formVitalsCollection, interval) {
143
+ const urls = [];
144
+ const formVitalsByDevice = aggregateFormVitalsByDevice(formVitalsCollection);
145
+ formVitalsCollection.forEach((entry) => {
146
+ const { forminternalnavigation, pageview } = entry;
147
+ // Calculate `x`: sum of pageview for the URL with the highest sum
148
+ let x = 0;
149
+ let maxPageviewUrl = null;
150
+ if (forminternalnavigation) {
151
+ forminternalnavigation.forEach((nav) => {
152
+ if (nav.pageview) {
153
+ const pageviewSum = Object.values(nav.pageview).reduce((sum, val) => sum + val, 0);
154
+ if (pageviewSum > x) {
155
+ x = pageviewSum;
156
+ maxPageviewUrl = nav;
157
+ }
158
+ }
159
+ });
160
+ }
161
+
162
+ // Skip entry if no valid maxPageviewUrl is found
163
+ if (!maxPageviewUrl) return;
164
+
165
+ // Calculate `y`: find the CTA with the highest clicks and include the source
166
+ const y = maxPageviewUrl.CTAs.reduce((maxCta, cta) => {
167
+ if (cta.clicks > (maxCta.clicks || 0)) {
168
+ return cta;
169
+ }
170
+ return maxCta;
171
+ }, { clicks: 0, source: '' });
172
+
173
+ // Get `z`: totalClicksOnPage for the matched URL
174
+ const z = maxPageviewUrl.totalClicksOnPage || 0;
175
+ // Calculate `f`: sum of `pageview` for `formengagement`
176
+ const f = Object.values(pageview).reduce((sum, val) => sum + val, 0);
177
+
178
+ // Evaluate conditions and add URL to the result if all are met
179
+ if (hasHighPageViews(interval, x) && hasHighPageViewLowFormCtr(x, y.clicks, z, f)) {
180
+ const deviceData = formVitalsByDevice.get(entry.url);
181
+ if (deviceData != null) {
182
+ urls.push({
183
+ url: entry.url,
184
+ pageViews: deviceData.pageview.total,
185
+ formViews: deviceData.formview.total,
186
+ formEngagement: deviceData.formengagement.total,
187
+ CTA: {
188
+ url: maxPageviewUrl.url,
189
+ source: y.source,
190
+ },
191
+ });
192
+ }
193
+ }
194
+ });
195
+ return urls;
196
+ }
package/src/index.d.ts CHANGED
@@ -99,10 +99,11 @@ declare function composeBaseURL(domain: string): string;
99
99
 
100
100
  /**
101
101
  * Composes an audit URL by applying a series of transformations to the given url.
102
- * @param url - The url to compose the audit URL from.
102
+ * @param {string} url - The url to compose the audit URL from.
103
+ * @param {string} [userAgent] - Optional user agent to use in the audit URL.
103
104
  * @returns a promise that resolves the composed audit URL.
104
105
  */
105
- declare function composeAuditURL(url: string): Promise<string>;
106
+ declare function composeAuditURL(url: string, userAgent: string): Promise<string>;
106
107
 
107
108
  /**
108
109
  * Resolves the name of the secret based on the function version.
@@ -174,6 +175,22 @@ declare function getPrompt(placeholders: object, filename: string, log: object):
174
175
  declare function getHighFormViewsLowConversionMetrics(formVitals: object[], interval: number):
175
176
  object[];
176
177
 
178
+ /**
179
+ * Retrieves the high-page-view-low-form-view metrics from the provided array of form vitals.
180
+ * @param {Object[]} formVitals - An array of form vitals.
181
+ * @returns {Object[]} - An array of high-page-view-low-form-view metrics.
182
+ */
183
+ declare function getHighPageViewsLowFormViewsMetrics(formVitals: object[], interval: number):
184
+ object[];
185
+
186
+ /**
187
+ * Retrieves the high-page-view-low-form-ctr metrics from the provided array of form vitals.
188
+ * @param {Object[]} formVitals - An array of form vitals.
189
+ * @returns {Object[]} - An array of high-page-view-low-form-ctr metrics.
190
+ */
191
+ declare function getHighPageViewsLowFormCtrMetrics(formVitals: object[], interval: number):
192
+ object[];
193
+
177
194
  /**
178
195
  * Retrieves stored metrics from S3.
179
196
  * @param config - Configuration object
package/src/index.js CHANGED
@@ -61,4 +61,4 @@ export { s3Wrapper } from './s3.js';
61
61
 
62
62
  export { fetch } from './adobe-fetch.js';
63
63
  export { tracingFetch } from './tracing-fetch.js';
64
- export { getHighFormViewsLowConversionMetrics } from './formcalc.js';
64
+ export { getHighFormViewsLowConversionMetrics, getHighPageViewsLowFormViewsMetrics, getHighPageViewsLowFormCtrMetrics } from './formcalc.js';
@@ -83,13 +83,23 @@ function composeBaseURL(domain) {
83
83
  return baseURL;
84
84
  }
85
85
 
86
- async function composeAuditURL(url) {
86
+ /**
87
+ * Composes an audit URL by applying a series of transformations to the given url.
88
+ * @param {string} url - The url to compose the audit URL from.
89
+ * @param {string} [userAgent] - Optional user agent to use in the audit URL.
90
+ * @returns a promise that resolves the composed audit URL.
91
+ */
92
+ async function composeAuditURL(url, userAgent) {
87
93
  const urlWithScheme = prependSchema(url);
94
+
95
+ const headers = {};
96
+ if (userAgent) {
97
+ headers['User-Agent'] = userAgent;
98
+ }
99
+
88
100
  const resp = await fetch(urlWithScheme, {
89
101
  method: 'GET',
90
- headers: {
91
- 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
92
- },
102
+ headers,
93
103
  });
94
104
  const finalUrl = resp.url.split('://')[1];
95
105
  return stripTrailingSlash(finalUrl);