@adobe/helix-rum-enhancer 2.7.3 → 2.7.4

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,10 @@
1
+ ## [2.7.4](https://github.com/adobe/helix-rum-enhancer/compare/v2.7.3...v2.7.4) (2024-05-02)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * catch potential exceptions and errors ([99ab83e](https://github.com/adobe/helix-rum-enhancer/commit/99ab83eae7ebc3a2c27df7887a57f58307e6ca61))
7
+
1
8
  ## [2.7.3](https://github.com/adobe/helix-rum-enhancer/compare/v2.7.2...v2.7.3) (2024-04-22)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-rum-enhancer",
3
- "version": "2.7.3",
3
+ "version": "2.7.4",
4
4
  "description": "Helix RUM Enhancer",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -12,7 +12,7 @@
12
12
  /* eslint-env browser */
13
13
  const KNOWN_PROPERTIES = ['weight', 'id', 'referer', 'checkpoint', 't', 'source', 'target', 'cwv', 'CLS', 'FID', 'LCP', 'INP', 'TTFB'];
14
14
  const DEFAULT_TRACKING_EVENTS = ['click', 'cwv', 'form', 'enterleave', 'viewblock', 'viewmedia', 'loadresource', 'utm'];
15
- const { sampleRUM, queue, isSelected } = window.hlx.rum;
15
+ const { sampleRUM, queue, isSelected } = window.hlx ? window.hlx.rum : {};
16
16
 
17
17
  const urlSanitizers = {
18
18
  full: () => window.location.href,
@@ -24,46 +24,55 @@ const getTargetValue = (element) => element.getAttribute('data-rum-target') || e
24
24
  || element.currentSrc || element.getAttribute('src') || element.dataset.action || element.action;
25
25
 
26
26
  const targetselector = (element) => {
27
- if (!element) return undefined;
28
- let value = getTargetValue(element);
29
- if (!value && element.tagName !== 'A' && element.closest('a')) {
30
- value = getTargetValue(element.closest('a'));
31
- }
32
- if (value && !value.startsWith('https://')) {
33
- // resolve relative links
34
- value = new URL(value, window.location).href;
27
+ try {
28
+ if (!element) return undefined;
29
+ let value = getTargetValue(element);
30
+ if (!value && element.tagName !== 'A' && element.closest('a')) {
31
+ value = getTargetValue(element.closest('a'));
32
+ }
33
+ if (value && !value.startsWith('https://')) {
34
+ // resolve relative links
35
+ value = new URL(value, window.location).href;
36
+ }
37
+ return value;
38
+ } catch (error) {
39
+ // something went wrong
40
+ return null;
35
41
  }
36
- return value;
37
42
  };
38
43
 
39
44
  const sourceselector = (element) => {
40
- if (element === document.body || element === document.documentElement || !element) {
41
- return undefined;
42
- }
43
- if (element.getAttribute('data-rum-source')) {
44
- return element.getAttribute('data-rum-source');
45
- }
46
- const form = element.closest('form');
47
- let formElementSelector = '';
48
- if (form && Array.from(form.elements).includes(element)) {
49
- formElementSelector = element.tagName === 'INPUT' ? `form input[type='${element.getAttribute('type')}']` : `form ${element.tagName.toLowerCase()}`;
50
- }
45
+ try {
46
+ if (element === document.body || element === document.documentElement || !element) {
47
+ return undefined;
48
+ }
49
+ if (element.getAttribute('data-rum-source')) {
50
+ return element.getAttribute('data-rum-source');
51
+ }
52
+ const form = element.closest('form');
53
+ let formElementSelector = '';
54
+ if (form && Array.from(form.elements).includes(element)) {
55
+ formElementSelector = element.tagName === 'INPUT' ? `form input[type='${element.getAttribute('type')}']` : `form ${element.tagName.toLowerCase()}`;
56
+ }
51
57
 
52
- const blockName = element.closest('.block') ? element.closest('.block').getAttribute('data-block-name') : '';
53
- if (element.id || formElementSelector) {
54
- const id = element.id ? `#${element.id}` : '';
55
- return blockName ? `.${blockName} ${formElementSelector}${id}` : `${formElementSelector}${id}`;
56
- }
58
+ const blockName = element.closest('.block') ? element.closest('.block').getAttribute('data-block-name') : '';
59
+ if (element.id || formElementSelector) {
60
+ const id = element.id ? `#${element.id}` : '';
61
+ return blockName ? `.${blockName} ${formElementSelector}${id}` : `${formElementSelector}${id}`;
62
+ }
57
63
 
58
- if (element.getAttribute('data-block-name')) {
59
- return `.${element.getAttribute('data-block-name')}`;
60
- }
64
+ if (element.getAttribute('data-block-name')) {
65
+ return `.${element.getAttribute('data-block-name')}`;
66
+ }
61
67
 
62
- if (Array.from(element.classList).some((className) => className.match(/button|cta/))) {
63
- return blockName ? `.${blockName} .button` : '.button';
64
- }
68
+ if (Array.from(element.classList).some((className) => className.match(/button|cta/))) {
69
+ return blockName ? `.${blockName} .button` : '.button';
70
+ }
65
71
 
66
- return sourceselector(element.parentElement);
72
+ return sourceselector(element.parentElement);
73
+ } catch (error) {
74
+ return null;
75
+ }
67
76
  };
68
77
 
69
78
  const formSubmitListener = (e) => sampleRUM('formsubmit', { target: targetselector(e.target), source: sourceselector(e.target) });
@@ -105,39 +114,43 @@ function processQueue() {
105
114
 
106
115
  function addCWVTracking() {
107
116
  setTimeout(() => {
108
- const cwvScript = new URL('.rum/web-vitals/dist/web-vitals.iife.js', sampleRUM.baseURL).href;
109
- if (document.querySelector(`script[src="${cwvScript}"]`)) {
110
- // web vitals script has been loaded already
111
- return;
112
- }
113
- const script = document.createElement('script');
114
- script.src = cwvScript;
115
- script.onload = () => {
116
- const storeCWV = (measurement) => {
117
- const data = { cwv: {} };
118
- data.cwv[measurement.name] = measurement.value;
119
- if (measurement.name === 'LCP' && measurement.entries.length > 0) {
120
- const { element } = measurement.entries.pop();
121
- data.target = targetselector(element);
122
- data.source = sourceselector(element) || (element && element.outerHTML.slice(0, 30));
123
- }
124
- sampleRUM('cwv', data);
125
- };
117
+ try {
118
+ const cwvScript = new URL('.rum/web-vitals/dist/web-vitals.iife.js', sampleRUM.baseURL).href;
119
+ if (document.querySelector(`script[src="${cwvScript}"]`)) {
120
+ // web vitals script has been loaded already
121
+ return;
122
+ }
123
+ const script = document.createElement('script');
124
+ script.src = cwvScript;
125
+ script.onload = () => {
126
+ const storeCWV = (measurement) => {
127
+ const data = { cwv: {} };
128
+ data.cwv[measurement.name] = measurement.value;
129
+ if (measurement.name === 'LCP' && measurement.entries.length > 0) {
130
+ const { element } = measurement.entries.pop();
131
+ data.target = targetselector(element);
132
+ data.source = sourceselector(element) || (element && element.outerHTML.slice(0, 30));
133
+ }
134
+ sampleRUM('cwv', data);
135
+ };
126
136
 
127
- const featureToggle = () => window.location.hostname === 'blog.adobe.com';
128
- const isEager = (metric) => ['CLS', 'LCP'].includes(metric);
137
+ const featureToggle = () => window.location.hostname === 'blog.adobe.com';
138
+ const isEager = (metric) => ['CLS', 'LCP'].includes(metric);
129
139
 
130
- // When loading `web-vitals` using a classic script, all the public
131
- // methods can be found on the `webVitals` global namespace.
132
- ['FID', 'INP', 'TTFB', 'CLS', 'LCP'].forEach((metric) => {
133
- const metricFn = window.webVitals[`on${metric}`];
134
- if (typeof metricFn === 'function') {
135
- const opts = isEager(metric) ? { reportAllChanges: featureToggle() } : undefined;
136
- metricFn(storeCWV, opts);
137
- }
138
- });
139
- };
140
- document.head.appendChild(script);
140
+ // When loading `web-vitals` using a classic script, all the public
141
+ // methods can be found on the `webVitals` global namespace.
142
+ ['FID', 'INP', 'TTFB', 'CLS', 'LCP'].forEach((metric) => {
143
+ const metricFn = window.webVitals[`on${metric}`];
144
+ if (typeof metricFn === 'function') {
145
+ const opts = isEager(metric) ? { reportAllChanges: featureToggle() } : undefined;
146
+ metricFn(storeCWV, opts);
147
+ }
148
+ });
149
+ };
150
+ document.head.appendChild(script);
151
+ } catch (error) {
152
+ // something went wrong
153
+ }
141
154
  }, 2000); // wait for delayed
142
155
  }
143
156
 
@@ -163,11 +176,15 @@ function addEnterLeaveTracking() {
163
176
  .observe({ type: 'navigation', buffered: true });
164
177
 
165
178
  const leave = ((event) => {
166
- if (leave.left || (event.type === 'visibilitychange' && document.visibilityState !== 'hidden')) {
167
- return;
179
+ try {
180
+ if (leave.left || (event.type === 'visibilitychange' && document.visibilityState !== 'hidden')) {
181
+ return;
182
+ }
183
+ leave.left = true;
184
+ sampleRUM('leave');
185
+ } catch (error) {
186
+ // something went wrong
168
187
  }
169
- leave.left = true;
170
- sampleRUM('leave');
171
188
  });
172
189
  window.addEventListener('visibilitychange', ((event) => leave(event)));
173
190
  window.addEventListener('pagehide', ((event) => leave(event)));
@@ -175,21 +192,25 @@ function addEnterLeaveTracking() {
175
192
 
176
193
  function addLoadResourceTracking() {
177
194
  const observer = new PerformanceObserver((list) => {
178
- list.getEntries()
179
- .filter((entry) => !entry.responseStatus || entry.responseStatus < 400)
180
- .filter((entry) => window.location.hostname === new URL(entry.name).hostname)
181
- .filter((entry) => new URL(entry.name).pathname.match('.*(\\.plain\\.html|\\.json)$'))
182
- .forEach((entry) => {
183
- sampleRUM('loadresource', { source: entry.name, target: Math.round(entry.duration) });
184
- });
185
-
186
- if (window.origin === 'business.adobe.com') {
187
- // feature flagged for now
195
+ try {
188
196
  list.getEntries()
189
- .filter((entry) => entry.responseStatus === 404)
197
+ .filter((entry) => !entry.responseStatus || entry.responseStatus < 400)
198
+ .filter((entry) => window.location.hostname === new URL(entry.name).hostname)
199
+ .filter((entry) => new URL(entry.name).pathname.match('.*(\\.plain\\.html|\\.json)$'))
190
200
  .forEach((entry) => {
191
- sampleRUM('missingresource', { source: entry.name, target: entry.hostname });
201
+ sampleRUM('loadresource', { source: entry.name, target: Math.round(entry.duration) });
192
202
  });
203
+
204
+ if (window.origin === 'business.adobe.com') {
205
+ // feature flagged for now
206
+ list.getEntries()
207
+ .filter((entry) => entry.responseStatus === 404)
208
+ .forEach((entry) => {
209
+ sampleRUM('missingresource', { source: entry.name, target: entry.hostname });
210
+ });
211
+ }
212
+ } catch (error) {
213
+ // something went wrong
193
214
  }
194
215
  });
195
216
  observer.observe({ type: 'resource', buffered: true });
@@ -213,14 +234,18 @@ function getIntersectionObsever(checkpoint) {
213
234
  }
214
235
  activateBlocksMutationObserver();
215
236
  const observer = new IntersectionObserver((entries) => {
216
- entries
217
- .filter((entry) => entry.isIntersecting)
218
- .forEach((entry) => {
219
- observer.unobserve(entry.target); // observe only once
220
- const target = targetselector(entry.target);
221
- const source = sourceselector(entry.target);
222
- sampleRUM(checkpoint, { target, source });
223
- });
237
+ try {
238
+ entries
239
+ .filter((entry) => entry.isIntersecting)
240
+ .forEach((entry) => {
241
+ observer.unobserve(entry.target); // observe only once
242
+ const target = targetselector(entry.target);
243
+ const source = sourceselector(entry.target);
244
+ sampleRUM(checkpoint, { target, source });
245
+ });
246
+ } catch (error) {
247
+ // something went wrong
248
+ }
224
249
  }, { threshold: 0.25 });
225
250
  return observer;
226
251
  }
@@ -293,9 +318,15 @@ function addTrackingFromConfig() {
293
318
  }
294
319
 
295
320
  function initEnhancer() {
296
- addTrackingFromConfig();
297
- window.hlx.rum.collector = trackCheckpoint;
298
- processQueue();
321
+ try {
322
+ if (sampleRUM) {
323
+ addTrackingFromConfig();
324
+ window.hlx.rum.collector = trackCheckpoint;
325
+ processQueue();
326
+ }
327
+ } catch (error) {
328
+ // something went wrong
329
+ }
299
330
  }
300
331
 
301
332
  initEnhancer();