@adobe/helix-rum-enhancer 2.19.2 → 2.21.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/.husky/pre-commit +0 -1
- package/.releaserc.cjs +12 -1
- package/CHANGELOG.md +22 -0
- package/README.md +43 -0
- package/modules/dom.js +57 -35
- package/modules/fflags.js +1 -0
- package/modules/index.js +54 -13
- package/package.json +10 -9
- package/rollup.config.js +9 -11
- package/src/index.js +101 -116
- package/src/index.md5 +1 -0
- package/web-test-runner.config.js +1 -1
package/.husky/pre-commit
CHANGED
package/.releaserc.cjs
CHANGED
|
@@ -10,7 +10,18 @@ module.exports = {
|
|
|
10
10
|
"assets": ["package.json", "CHANGELOG.md"],
|
|
11
11
|
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
12
12
|
}],
|
|
13
|
-
["@semantic-release/github", {
|
|
13
|
+
["@semantic-release/github", {
|
|
14
|
+
"assets": [
|
|
15
|
+
{
|
|
16
|
+
"path": "src/index.js",
|
|
17
|
+
"label": "RUM Enhancer JS"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "src/index.md5",
|
|
21
|
+
"label": "RUM Enhancer Hash"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}]
|
|
14
25
|
],
|
|
15
26
|
branches: ['main'],
|
|
16
27
|
};
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
# [2.21.0](https://github.com/adobe/helix-rum-enhancer/compare/v2.20.0...v2.21.0) (2024-09-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **dom:** apply change ([67803e6](https://github.com/adobe/helix-rum-enhancer/commit/67803e60f57ef29b9ea1c51eea26d99c778b5f97))
|
|
7
|
+
* **dom:** better handling of empty type form inputs ([d53deb5](https://github.com/adobe/helix-rum-enhancer/commit/d53deb5c6e94ff18df2a01996c39b5cff7636fe4))
|
|
8
|
+
* **dom:** better handling of fake blocks ([66a9049](https://github.com/adobe/helix-rum-enhancer/commit/66a90497a45d754ed0fa4e8f8bc0917be64b3245))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **checkpoints:** add support for the `language` checkpoint ([f99755a](https://github.com/adobe/helix-rum-enhancer/commit/f99755a5cc8eef83b655a6beff5e7e371196c90d))
|
|
14
|
+
* **dom:** more fine-grained sourceselector implementation ([ada279d](https://github.com/adobe/helix-rum-enhancer/commit/ada279d423590fb3feeb304b3a57d6da4ee3c9bf))
|
|
15
|
+
|
|
16
|
+
# [2.20.0](https://github.com/adobe/helix-rum-enhancer/compare/v2.19.2...v2.20.0) (2024-08-19)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* observe all mutations to capture late added medias ([#261](https://github.com/adobe/helix-rum-enhancer/issues/261)) ([56844b2](https://github.com/adobe/helix-rum-enhancer/commit/56844b2aa61fe5cc837cd5a887f0c8669a335e0f))
|
|
22
|
+
|
|
1
23
|
## [2.19.2](https://github.com/adobe/helix-rum-enhancer/compare/v2.19.1...v2.19.2) (2024-08-15)
|
|
2
24
|
|
|
3
25
|
|
package/README.md
CHANGED
|
@@ -23,6 +23,49 @@ It will add following new checkpoints:
|
|
|
23
23
|
- `reload`, `navigate`, `enter`: depending on how the current page was accessed
|
|
24
24
|
- `formsubmit`: when a form is submitted
|
|
25
25
|
|
|
26
|
+
### The `source` parameter and the `sourceSelector`
|
|
27
|
+
|
|
28
|
+
The `source` parameter is a string that can be used to identify the source of the event. It can be used to identify the source of the event, e.g. a button, a link, a form, etc.
|
|
29
|
+
It represents an idealized CSS selector that is both human-readable and specific enough to identify the source of the event in the document, even when not having access to the
|
|
30
|
+
orginal document. It is idealized because it pretends the DOM would use modern HTML with concise semantics, even if the actual document uses `class` values for things that would
|
|
31
|
+
be better represented by semantic HTML elements.
|
|
32
|
+
|
|
33
|
+
The `sourceSelector` function is a function that takes a DOM element and returns a descriptive `source` parameter. If the element has a `data-rum-source` attribute, its value is used as the `source` parameter. Otherwise, the function tries to generate a `source` parameter based on the element's tag name, class names, and text content.
|
|
34
|
+
|
|
35
|
+
The structure of the `source` parameter is as follows:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
<context> <element>#<identifier>
|
|
39
|
+
```
|
|
40
|
+
All three parts are optional
|
|
41
|
+
|
|
42
|
+
`context` is
|
|
43
|
+
- `form` for form elements
|
|
44
|
+
- `dialog` for dialog elements, or parent containers that are fixed positioned and have a positive high z-index
|
|
45
|
+
- `.block-name` for Helix blocks
|
|
46
|
+
- `header`, `footer`, `nav`, `aside` for main site structure
|
|
47
|
+
- `#id` as a fallback, if a container ID is available
|
|
48
|
+
|
|
49
|
+
`element` is
|
|
50
|
+
- `button` for buttons, or links that look like buttons (e.g. with a class `button` or `btn` or `cta`)
|
|
51
|
+
- `img` for images
|
|
52
|
+
- `video` for videos
|
|
53
|
+
- `a` for links that are not buttons
|
|
54
|
+
- `input[type="text"]` for input elements (all types are supported)
|
|
55
|
+
- `select`, `textarea`, etc. for other form elements
|
|
56
|
+
|
|
57
|
+
`identifier` is
|
|
58
|
+
- the `id` attribute of the element, if provided
|
|
59
|
+
- the first `.class` if there are any
|
|
60
|
+
- else omitted
|
|
61
|
+
|
|
62
|
+
Even if an `identifier` is provided, having a `context` and `element` is recommended, as it makes the `source` parameter more readable and easier to understand.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
#### Examples
|
|
66
|
+
|
|
67
|
+
- ``
|
|
68
|
+
|
|
26
69
|
## Development
|
|
27
70
|
|
|
28
71
|
### Build
|
package/modules/dom.js
CHANGED
|
@@ -30,6 +30,59 @@ export const targetSelector = (element) => {
|
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
function walk(element, checkFn) {
|
|
34
|
+
if (!element || element === document.body || element === document.documentElement) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const checkValue = checkFn(element);
|
|
38
|
+
return checkValue || walk(element.parentElement, checkFn);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isDialog(element) {
|
|
42
|
+
// doing it well
|
|
43
|
+
if (element.tagName === 'DIALOG') return true;
|
|
44
|
+
// making the best of it
|
|
45
|
+
if (element.getAttribute('role') === 'dialog') return true;
|
|
46
|
+
if (element.getAttribute('role') === 'alertdialog') return true;
|
|
47
|
+
if (element.getAttribute('aria-modal') === 'true') return true;
|
|
48
|
+
// doing it wrong
|
|
49
|
+
const computedStyle = window.getComputedStyle(element);
|
|
50
|
+
return (computedStyle && computedStyle.position === 'fixed' && computedStyle.zIndex > 100);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isButton(element) {
|
|
54
|
+
if (element.tagName === 'BUTTON') return true;
|
|
55
|
+
if (element.tagName === 'INPUT' && element.getAttribute('type') === 'button') return true;
|
|
56
|
+
if (element.tagName === 'A') {
|
|
57
|
+
const classes = Array.from(element.classList);
|
|
58
|
+
return classes.some((className) => className.match(/button|cta/));
|
|
59
|
+
}
|
|
60
|
+
return element.getAttribute('role') === 'button';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getSourceContext(element) {
|
|
64
|
+
if (element.closest('form')) return 'form';
|
|
65
|
+
const block = element.closest('.block[data-block-name]');
|
|
66
|
+
if (block) return `.${block.getAttribute('data-block-name')}`;
|
|
67
|
+
if (walk(element, isDialog)) return 'dialog';
|
|
68
|
+
if (element.closest('nav')) return 'nav';
|
|
69
|
+
if (element.closest('header')) return 'header';
|
|
70
|
+
if (element.closest('footer')) return 'footer';
|
|
71
|
+
if (element.closest('aside')) return 'aside';
|
|
72
|
+
return (walk(element, (e) => e.id && `#${e.id}`));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function getSourceElement(element) {
|
|
76
|
+
if (element.closest('form') && Array.from(element.closest('form').elements).includes(element)) return element.tagName.toLowerCase() + (element.tagName === 'INPUT' ? `[type='${element.getAttribute('type') || ''}']` : '');
|
|
77
|
+
if (walk(element, isButton)) return 'button';
|
|
78
|
+
return element.tagName.toLowerCase().match(/^(a|img|video)$/) && element.tagName.toLowerCase();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getSourceIdentifier(element) {
|
|
82
|
+
if (element.id) return `#${element.id}`;
|
|
83
|
+
if (element.getAttribute('data-block-name')) return `.${element.getAttribute('data-block-name')}`;
|
|
84
|
+
return (element.classList.length > 0 && `.${element.classList[0]}`);
|
|
85
|
+
}
|
|
33
86
|
export const sourceSelector = (element) => {
|
|
34
87
|
try {
|
|
35
88
|
if (!element || element === document.body || element === document.documentElement) {
|
|
@@ -38,41 +91,10 @@ export const sourceSelector = (element) => {
|
|
|
38
91
|
if (element.getAttribute('data-rum-source')) {
|
|
39
92
|
return element.getAttribute('data-rum-source');
|
|
40
93
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const blockName = element.closest('.block') ? element.closest('.block').getAttribute('data-block-name') : '';
|
|
48
|
-
if (element.id || formElementSelector) {
|
|
49
|
-
const id = element.id ? `#${element.id}` : '';
|
|
50
|
-
return blockName ? `.${blockName} ${formElementSelector}${id}` : `${formElementSelector}${id}`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (element.getAttribute('data-block-name')) {
|
|
54
|
-
return `.${element.getAttribute('data-block-name')}`;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const classes = Array.from(element.classList);
|
|
58
|
-
const label = element.tagName.toLowerCase();
|
|
59
|
-
const firstClass = classes.length > 0 ? `.${classes[0]}` : '';
|
|
60
|
-
const labelWithClass = `${element.tagName.toLowerCase()}${firstClass}`;
|
|
61
|
-
if (element.tagName.toLowerCase() === 'button'
|
|
62
|
-
|| element.type === 'button'
|
|
63
|
-
|| classes.some((className) => className.match(/button|cta/))) {
|
|
64
|
-
let parent = element.parentElement;
|
|
65
|
-
if (!parent) return labelWithClass;
|
|
66
|
-
if (parent.id) return `#${parent.id} ${label}`;
|
|
67
|
-
while (parent.tagName !== 'BODY' && !parent.id) parent = parent.parentElement;
|
|
68
|
-
if (parent.id) return `#${parent.id} ${labelWithClass}`;
|
|
69
|
-
return blockName ? `.${blockName} ${labelWithClass}` : labelWithClass;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const parent = sourceSelector(element.parentElement);
|
|
73
|
-
if (parent) return parent;
|
|
74
|
-
|
|
75
|
-
return labelWithClass;
|
|
94
|
+
const context = getSourceContext(element.parentElement) || '';
|
|
95
|
+
const elementName = getSourceElement(element) || '';
|
|
96
|
+
const identifier = getSourceIdentifier(element) || '';
|
|
97
|
+
return `${context} ${elementName}${identifier}`.trim() || `"${element.textContent.substring(0, 10)}"`;
|
|
76
98
|
/* c8 ignore next 3 */
|
|
77
99
|
} catch (error) {
|
|
78
100
|
return null;
|
package/modules/fflags.js
CHANGED
package/modules/index.js
CHANGED
|
@@ -26,9 +26,14 @@ const { sampleRUM, queue, isSelected } = (window.hlx && window.hlx.rum) ? window
|
|
|
26
26
|
/* c8 ignore next */ : {};
|
|
27
27
|
|
|
28
28
|
const formSubmitListener = (e) => sampleRUM('formsubmit', { target: targetSelector(e.target), source: sourceSelector(e.target) });
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
|
|
30
|
+
// eslint-disable-next-line no-use-before-define, max-len
|
|
31
|
+
const blocksMutationObserver = window.MutationObserver ? new MutationObserver(blocksMutationsCallback)
|
|
32
|
+
/* c8 ignore next */ : {};
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line no-use-before-define, max-len
|
|
35
|
+
const mediaMutationObserver = window.MutationObserver ? new MutationObserver(mediaMutationsCallback)
|
|
36
|
+
/* c8 ignore next */ : {};
|
|
32
37
|
|
|
33
38
|
function trackCheckpoint(checkpoint, data, t) {
|
|
34
39
|
const { weight, id } = window.hlx.rum;
|
|
@@ -52,7 +57,7 @@ function trackCheckpoint(checkpoint, data, t) {
|
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
function processQueue() {
|
|
55
|
-
while (queue.length) {
|
|
60
|
+
while (queue && queue.length) {
|
|
56
61
|
const ck = queue.shift();
|
|
57
62
|
trackCheckpoint(...ck);
|
|
58
63
|
}
|
|
@@ -148,21 +153,36 @@ function addLoadResourceTracking() {
|
|
|
148
153
|
}
|
|
149
154
|
|
|
150
155
|
function activateBlocksMutationObserver() {
|
|
151
|
-
if (!
|
|
156
|
+
if (!blocksMutationObserver || blocksMutationObserver.active) {
|
|
152
157
|
return;
|
|
153
158
|
}
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
blocksMutationObserver.active = true;
|
|
160
|
+
blocksMutationObserver.observe(
|
|
156
161
|
document.body,
|
|
157
162
|
// eslint-disable-next-line object-curly-newline
|
|
158
163
|
{ subtree: true, attributes: true, attributeFilter: ['data-block-status'] },
|
|
159
164
|
);
|
|
160
165
|
}
|
|
161
166
|
|
|
167
|
+
function activateMediaMutationObserver() {
|
|
168
|
+
if (!mediaMutationObserver || mediaMutationObserver.active) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
mediaMutationObserver.active = true;
|
|
172
|
+
mediaMutationObserver.observe(
|
|
173
|
+
document.body,
|
|
174
|
+
// eslint-disable-next-line object-curly-newline
|
|
175
|
+
{ subtree: true, attributes: false, childList: true },
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
162
179
|
function getIntersectionObsever(checkpoint) {
|
|
163
|
-
/* c8 ignore next */
|
|
164
|
-
if (!window.IntersectionObserver)
|
|
180
|
+
/* c8 ignore next 3 */
|
|
181
|
+
if (!window.IntersectionObserver) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
165
184
|
activateBlocksMutationObserver();
|
|
185
|
+
activateMediaMutationObserver();
|
|
166
186
|
const observer = new IntersectionObserver((entries) => {
|
|
167
187
|
try {
|
|
168
188
|
entries
|
|
@@ -188,11 +208,13 @@ function addViewBlockTracking(element) {
|
|
|
188
208
|
}
|
|
189
209
|
}
|
|
190
210
|
|
|
211
|
+
const observedMedia = new Set();
|
|
191
212
|
function addViewMediaTracking(parent) {
|
|
192
213
|
const mediaobserver = getIntersectionObsever('viewmedia');
|
|
193
214
|
if (mediaobserver) {
|
|
194
215
|
parent.querySelectorAll('img, video, audio, iframe').forEach((m) => {
|
|
195
|
-
if (!
|
|
216
|
+
if (!observedMedia.has(m)) {
|
|
217
|
+
observedMedia.add(m);
|
|
196
218
|
mediaobserver.observe(m);
|
|
197
219
|
}
|
|
198
220
|
});
|
|
@@ -201,19 +223,32 @@ function addViewMediaTracking(parent) {
|
|
|
201
223
|
|
|
202
224
|
function addFormTracking(parent) {
|
|
203
225
|
activateBlocksMutationObserver();
|
|
226
|
+
activateMediaMutationObserver();
|
|
204
227
|
parent.querySelectorAll('form').forEach((form) => {
|
|
205
228
|
form.removeEventListener('submit', formSubmitListener); // listen only once
|
|
206
229
|
form.addEventListener('submit', formSubmitListener);
|
|
207
230
|
});
|
|
208
231
|
}
|
|
209
232
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
233
|
+
function addObserver(ck, fn, block) {
|
|
234
|
+
return DEFAULT_TRACKING_EVENTS.includes(ck) && fn(block);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function blocksMutationsCallback(mutations) {
|
|
238
|
+
// block specific mutations
|
|
239
|
+
mutations
|
|
240
|
+
.filter((m) => m.type === 'attributes' && m.attributeName === 'data-block-status')
|
|
213
241
|
.filter((m) => m.target.dataset.blockStatus === 'loaded')
|
|
214
242
|
.forEach((m) => {
|
|
215
243
|
addObserver('form', addFormTracking, m.target);
|
|
216
244
|
addObserver('viewblock', addViewBlockTracking, m.target);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function mediaMutationsCallback(mutations) {
|
|
249
|
+
// media mutations
|
|
250
|
+
mutations
|
|
251
|
+
.forEach((m) => {
|
|
217
252
|
addObserver('viewmedia', addViewMediaTracking, m.target);
|
|
218
253
|
});
|
|
219
254
|
}
|
|
@@ -232,6 +267,11 @@ function addTrackingFromConfig() {
|
|
|
232
267
|
addCookieConsentTracking(sampleRUM);
|
|
233
268
|
addAdsParametersTracking(sampleRUM);
|
|
234
269
|
addEmailParameterTracking(sampleRUM);
|
|
270
|
+
fflags.enabled('language', () => {
|
|
271
|
+
const target = navigator.language;
|
|
272
|
+
const source = document.documentElement.lang;
|
|
273
|
+
sampleRUM('language', { source, target });
|
|
274
|
+
});
|
|
235
275
|
}
|
|
236
276
|
|
|
237
277
|
function initEnhancer() {
|
|
@@ -241,6 +281,7 @@ function initEnhancer() {
|
|
|
241
281
|
window.hlx.rum.collector = trackCheckpoint;
|
|
242
282
|
processQueue();
|
|
243
283
|
}
|
|
284
|
+
/* c8 ignore next 3 */
|
|
244
285
|
} catch (error) {
|
|
245
286
|
// something went wrong
|
|
246
287
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-rum-enhancer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.21.0",
|
|
4
4
|
"description": "Helix RUM Enhancer",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"reporter-options": "configFile=.mocha-multi.json"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@adobe/eslint-config-helix": "2.0.
|
|
37
|
-
"@adobe/helix-rum-js": "2.
|
|
36
|
+
"@adobe/eslint-config-helix": "2.0.7",
|
|
37
|
+
"@adobe/helix-rum-js": "2.4.0",
|
|
38
38
|
"@esm-bundle/chai": "4.3.4-fix.0",
|
|
39
39
|
"@semantic-release/changelog": "6.0.3",
|
|
40
40
|
"@semantic-release/git": "10.0.1",
|
|
@@ -47,17 +47,18 @@
|
|
|
47
47
|
"codecov": "3.8.3",
|
|
48
48
|
"eslint": "8.57.0",
|
|
49
49
|
"eslint-plugin-header": "3.1.1",
|
|
50
|
-
"eslint-plugin-import": "2.
|
|
51
|
-
"husky": "9.1.
|
|
52
|
-
"jsdoc-to-markdown": "
|
|
50
|
+
"eslint-plugin-import": "2.30.0",
|
|
51
|
+
"husky": "9.1.5",
|
|
52
|
+
"jsdoc-to-markdown": "9.0.0",
|
|
53
53
|
"junit-report-builder": "5.0.0",
|
|
54
|
-
"lint-staged": "15.2.
|
|
54
|
+
"lint-staged": "15.2.10",
|
|
55
55
|
"mocha": "10.7.3",
|
|
56
56
|
"mocha-multi-reporters": "1.5.1",
|
|
57
|
-
"rollup": "4.
|
|
57
|
+
"rollup": "4.21.2",
|
|
58
58
|
"rollup-plugin-cleanup": "3.2.1",
|
|
59
|
+
"rollup-plugin-checksum": "1.0.1",
|
|
59
60
|
"rollup-plugin-eslint-bundle": "9.0.0",
|
|
60
|
-
"semantic-release": "24.
|
|
61
|
+
"semantic-release": "24.1.0",
|
|
61
62
|
"web-vitals": "4.2.3"
|
|
62
63
|
},
|
|
63
64
|
"lint-staged": {
|
package/rollup.config.js
CHANGED
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import cleanup from 'rollup-plugin-cleanup';
|
|
14
|
-
import
|
|
14
|
+
import pkg from 'rollup-plugin-checksum';
|
|
15
|
+
|
|
16
|
+
const checksum = pkg.default;
|
|
15
17
|
|
|
16
18
|
const banner = `/*
|
|
17
19
|
* Copyright 2024 Adobe. All rights reserved.
|
|
@@ -23,10 +25,7 @@ const banner = `/*
|
|
|
23
25
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
24
26
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
25
27
|
* governing permissions and limitations under the License.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/* eslint-disable max-classes-per-file, wrap-iife */
|
|
29
|
-
// eslint-disable-next-line func-names`;
|
|
28
|
+
*/`;
|
|
30
29
|
|
|
31
30
|
const bundles = [
|
|
32
31
|
{
|
|
@@ -55,13 +54,12 @@ export default [...bundles.map(({ outputFile, source }) => ({
|
|
|
55
54
|
],
|
|
56
55
|
plugins: [
|
|
57
56
|
cleanup({
|
|
58
|
-
comments: [
|
|
59
|
-
maxEmptyLines:
|
|
57
|
+
comments: [],
|
|
58
|
+
maxEmptyLines: 0,
|
|
60
59
|
}),
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
},
|
|
60
|
+
checksum({
|
|
61
|
+
filename: `${outputFile.split('/').pop()}.md5`,
|
|
62
|
+
includeAssets: false,
|
|
65
63
|
}),
|
|
66
64
|
],
|
|
67
65
|
}))];
|
package/src/index.js
CHANGED
|
@@ -9,9 +9,6 @@
|
|
|
9
9
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
|
-
/* eslint-disable max-classes-per-file, wrap-iife */
|
|
14
|
-
// eslint-disable-next-line func-names
|
|
15
12
|
(function () {
|
|
16
13
|
'use strict';
|
|
17
14
|
|
|
@@ -21,10 +18,10 @@
|
|
|
21
18
|
.reduce((a, b) => a + b, 1) % 1371) !== -1
|
|
22
19
|
|| !!window.origin.match(/localhost/),
|
|
23
20
|
enabled: (flag, callback) => fflags.has(flag) && callback(),
|
|
24
|
-
|
|
25
21
|
disabled: (flag, callback) => !fflags.has(flag) && callback(),
|
|
26
22
|
eagercwv: [683],
|
|
27
23
|
example: [543, 770, 1136],
|
|
24
|
+
language: [543, 959, 1139, 620],
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
const KNOWN_PROPERTIES = ['weight', 'id', 'referer', 'checkpoint', 't', 'source', 'target', 'cwv', 'CLS', 'FID', 'LCP', 'INP', 'TTFB'];
|
|
@@ -32,26 +29,8 @@
|
|
|
32
29
|
fflags.enabled('example', () => DEFAULT_TRACKING_EVENTS.push('example'));
|
|
33
30
|
|
|
34
31
|
const urlSanitizers = {
|
|
35
|
-
/**
|
|
36
|
-
* Returns the full url.
|
|
37
|
-
* If no url is provided, it defaults to window.location.href.
|
|
38
|
-
* @param {string} url (default: window.location.href) The url to sanitize
|
|
39
|
-
* @returns {string} The sanitized url
|
|
40
|
-
*/
|
|
41
32
|
full: (url = window.location.href) => new URL(url).toString(),
|
|
42
|
-
/**
|
|
43
|
-
* Returns the origin of the provided url.
|
|
44
|
-
* If no url is provided, it defaults to window.location.href.
|
|
45
|
-
* @param {string} url (default: window.location.href) The url to sanitize
|
|
46
|
-
* @returns {string} The sanitized url
|
|
47
|
-
*/
|
|
48
33
|
origin: (url = window.location.href) => new URL(url).origin,
|
|
49
|
-
/**
|
|
50
|
-
* Returns the sanitized url: the origin and the path (no query params or hash)
|
|
51
|
-
* If no url is provided, it defaults to window.location.href.
|
|
52
|
-
* @param {string} url (default: window.location.href) The url to sanitize
|
|
53
|
-
* @returns {string} The sanitized url
|
|
54
|
-
*/
|
|
55
34
|
path: (url = window.location.href) => {
|
|
56
35
|
const u = new URL(url);
|
|
57
36
|
return `${u.origin}${u.pathname}`;
|
|
@@ -60,7 +39,6 @@
|
|
|
60
39
|
|
|
61
40
|
const getTargetValue = (element) => element.getAttribute('data-rum-target') || element.getAttribute('href')
|
|
62
41
|
|| element.currentSrc || element.getAttribute('src') || element.dataset.action || element.action;
|
|
63
|
-
|
|
64
42
|
const targetSelector = (element) => {
|
|
65
43
|
try {
|
|
66
44
|
if (!element) return undefined;
|
|
@@ -69,7 +47,6 @@
|
|
|
69
47
|
value = getTargetValue(element.closest('a'));
|
|
70
48
|
}
|
|
71
49
|
if (value && !value.startsWith('https://')) {
|
|
72
|
-
// resolve relative links
|
|
73
50
|
value = new URL(value, window.location).href;
|
|
74
51
|
}
|
|
75
52
|
return value;
|
|
@@ -77,7 +54,51 @@
|
|
|
77
54
|
return null;
|
|
78
55
|
}
|
|
79
56
|
};
|
|
80
|
-
|
|
57
|
+
function walk(element, checkFn) {
|
|
58
|
+
if (!element || element === document.body || element === document.documentElement) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const checkValue = checkFn(element);
|
|
62
|
+
return checkValue || walk(element.parentElement, checkFn);
|
|
63
|
+
}
|
|
64
|
+
function isDialog(element) {
|
|
65
|
+
if (element.tagName === 'DIALOG') return true;
|
|
66
|
+
if (element.getAttribute('role') === 'dialog') return true;
|
|
67
|
+
if (element.getAttribute('role') === 'alertdialog') return true;
|
|
68
|
+
if (element.getAttribute('aria-modal') === 'true') return true;
|
|
69
|
+
const computedStyle = window.getComputedStyle(element);
|
|
70
|
+
return (computedStyle && computedStyle.position === 'fixed' && computedStyle.zIndex > 100);
|
|
71
|
+
}
|
|
72
|
+
function isButton(element) {
|
|
73
|
+
if (element.tagName === 'BUTTON') return true;
|
|
74
|
+
if (element.tagName === 'INPUT' && element.getAttribute('type') === 'button') return true;
|
|
75
|
+
if (element.tagName === 'A') {
|
|
76
|
+
const classes = Array.from(element.classList);
|
|
77
|
+
return classes.some((className) => className.match(/button|cta/));
|
|
78
|
+
}
|
|
79
|
+
return element.getAttribute('role') === 'button';
|
|
80
|
+
}
|
|
81
|
+
function getSourceContext(element) {
|
|
82
|
+
if (element.closest('form')) return 'form';
|
|
83
|
+
const block = element.closest('.block[data-block-name]');
|
|
84
|
+
if (block) return `.${block.getAttribute('data-block-name')}`;
|
|
85
|
+
if (walk(element, isDialog)) return 'dialog';
|
|
86
|
+
if (element.closest('nav')) return 'nav';
|
|
87
|
+
if (element.closest('header')) return 'header';
|
|
88
|
+
if (element.closest('footer')) return 'footer';
|
|
89
|
+
if (element.closest('aside')) return 'aside';
|
|
90
|
+
return (walk(element, (e) => e.id && `#${e.id}`));
|
|
91
|
+
}
|
|
92
|
+
function getSourceElement(element) {
|
|
93
|
+
if (element.closest('form') && Array.from(element.closest('form').elements).includes(element)) return element.tagName.toLowerCase() + (element.tagName === 'INPUT' ? `[type='${element.getAttribute('type') || ''}']` : '');
|
|
94
|
+
if (walk(element, isButton)) return 'button';
|
|
95
|
+
return element.tagName.toLowerCase().match(/^(a|img|video)$/) && element.tagName.toLowerCase();
|
|
96
|
+
}
|
|
97
|
+
function getSourceIdentifier(element) {
|
|
98
|
+
if (element.id) return `#${element.id}`;
|
|
99
|
+
if (element.getAttribute('data-block-name')) return `.${element.getAttribute('data-block-name')}`;
|
|
100
|
+
return (element.classList.length > 0 && `.${element.classList[0]}`);
|
|
101
|
+
}
|
|
81
102
|
const sourceSelector = (element) => {
|
|
82
103
|
try {
|
|
83
104
|
if (!element || element === document.body || element === document.documentElement) {
|
|
@@ -86,41 +107,10 @@
|
|
|
86
107
|
if (element.getAttribute('data-rum-source')) {
|
|
87
108
|
return element.getAttribute('data-rum-source');
|
|
88
109
|
}
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const blockName = element.closest('.block') ? element.closest('.block').getAttribute('data-block-name') : '';
|
|
96
|
-
if (element.id || formElementSelector) {
|
|
97
|
-
const id = element.id ? `#${element.id}` : '';
|
|
98
|
-
return blockName ? `.${blockName} ${formElementSelector}${id}` : `${formElementSelector}${id}`;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (element.getAttribute('data-block-name')) {
|
|
102
|
-
return `.${element.getAttribute('data-block-name')}`;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const classes = Array.from(element.classList);
|
|
106
|
-
const label = element.tagName.toLowerCase();
|
|
107
|
-
const firstClass = classes.length > 0 ? `.${classes[0]}` : '';
|
|
108
|
-
const labelWithClass = `${element.tagName.toLowerCase()}${firstClass}`;
|
|
109
|
-
if (element.tagName.toLowerCase() === 'button'
|
|
110
|
-
|| element.type === 'button'
|
|
111
|
-
|| classes.some((className) => className.match(/button|cta/))) {
|
|
112
|
-
let parent = element.parentElement;
|
|
113
|
-
if (!parent) return labelWithClass;
|
|
114
|
-
if (parent.id) return `#${parent.id} ${label}`;
|
|
115
|
-
while (parent.tagName !== 'BODY' && !parent.id) parent = parent.parentElement;
|
|
116
|
-
if (parent.id) return `#${parent.id} ${labelWithClass}`;
|
|
117
|
-
return blockName ? `.${blockName} ${labelWithClass}` : labelWithClass;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const parent = sourceSelector(element.parentElement);
|
|
121
|
-
if (parent) return parent;
|
|
122
|
-
|
|
123
|
-
return labelWithClass;
|
|
110
|
+
const context = getSourceContext(element.parentElement) || '';
|
|
111
|
+
const elementName = getSourceElement(element) || '';
|
|
112
|
+
const identifier = getSourceIdentifier(element) || '';
|
|
113
|
+
return `${context} ${elementName}${identifier}`.trim() || `"${element.textContent.substring(0, 10)}"`;
|
|
124
114
|
} catch (error) {
|
|
125
115
|
return null;
|
|
126
116
|
}
|
|
@@ -130,12 +120,10 @@
|
|
|
130
120
|
const cmpCookie = document.cookie.split(';')
|
|
131
121
|
.map((c) => c.trim())
|
|
132
122
|
.find((cookie) => cookie.startsWith('OptanonAlertBoxClosed='));
|
|
133
|
-
|
|
134
123
|
if (cmpCookie) {
|
|
135
124
|
sampleRUM('consent', { source: 'onetrust', target: 'hidden' });
|
|
136
125
|
return;
|
|
137
126
|
}
|
|
138
|
-
|
|
139
127
|
let consentMutationObserver;
|
|
140
128
|
const trackShowConsent = () => {
|
|
141
129
|
if (document.querySelector('body > div#onetrust-consent-sdk')) {
|
|
@@ -147,27 +135,22 @@
|
|
|
147
135
|
}
|
|
148
136
|
return false;
|
|
149
137
|
};
|
|
150
|
-
|
|
151
138
|
if (!trackShowConsent()) {
|
|
152
|
-
// eslint-disable-next-line max-len
|
|
153
139
|
consentMutationObserver = window.MutationObserver
|
|
154
140
|
? new MutationObserver(trackShowConsent)
|
|
155
|
-
:
|
|
141
|
+
: null;
|
|
156
142
|
if (consentMutationObserver) {
|
|
157
143
|
consentMutationObserver.observe(
|
|
158
144
|
document.body,
|
|
159
|
-
// eslint-disable-next-line object-curly-newline
|
|
160
145
|
{ attributes: false, childList: true, subtree: false },
|
|
161
146
|
);
|
|
162
147
|
}
|
|
163
148
|
}
|
|
164
149
|
}
|
|
165
|
-
|
|
166
150
|
function addUTMParametersTracking(sampleRUM) {
|
|
167
151
|
const usp = new URLSearchParams(window.location.search);
|
|
168
152
|
[...usp.entries()]
|
|
169
153
|
.filter(([key]) => key.startsWith('utm_'))
|
|
170
|
-
// exclude keys that may leak PII
|
|
171
154
|
.filter(([key]) => key !== 'utm_id')
|
|
172
155
|
.filter(([key]) => key !== 'utm_term')
|
|
173
156
|
.forEach(([source, target]) => sampleRUM('utm', { source, target }));
|
|
@@ -200,18 +183,16 @@
|
|
|
200
183
|
}
|
|
201
184
|
|
|
202
185
|
const { sampleRUM, queue, isSelected } = (window.hlx && window.hlx.rum) ? window.hlx.rum
|
|
203
|
-
|
|
204
|
-
|
|
186
|
+
: {};
|
|
205
187
|
const formSubmitListener = (e) => sampleRUM('formsubmit', { target: targetSelector(e.target), source: sourceSelector(e.target) });
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
188
|
+
const blocksMutationObserver = window.MutationObserver ? new MutationObserver(blocksMutationsCallback)
|
|
189
|
+
: {};
|
|
190
|
+
const mediaMutationObserver = window.MutationObserver ? new MutationObserver(mediaMutationsCallback)
|
|
191
|
+
: {};
|
|
210
192
|
function trackCheckpoint(checkpoint, data, t) {
|
|
211
193
|
const { weight, id } = window.hlx.rum;
|
|
212
194
|
if (isSelected) {
|
|
213
195
|
const sendPing = (pdata = data) => {
|
|
214
|
-
// eslint-disable-next-line object-curly-newline, max-len
|
|
215
196
|
const body = JSON.stringify({ weight, id, referer: urlSanitizers[window.hlx.RUM_MASK_URL || 'path'](), checkpoint, t, ...data }, KNOWN_PROPERTIES);
|
|
216
197
|
const { href: url, origin } = new URL(`.rum/${weight}`, sampleRUM.collectBaseURL || sampleRUM.baseURL);
|
|
217
198
|
if (window.location.origin === origin) {
|
|
@@ -220,26 +201,22 @@
|
|
|
220
201
|
} else {
|
|
221
202
|
navigator.sendBeacon(url, body);
|
|
222
203
|
}
|
|
223
|
-
// eslint-disable-next-line no-console
|
|
224
204
|
console.debug(`ping:${checkpoint}`, pdata);
|
|
225
205
|
};
|
|
226
206
|
sendPing(data);
|
|
227
207
|
}
|
|
228
208
|
}
|
|
229
|
-
|
|
230
209
|
function processQueue() {
|
|
231
|
-
while (queue.length) {
|
|
210
|
+
while (queue && queue.length) {
|
|
232
211
|
const ck = queue.shift();
|
|
233
212
|
trackCheckpoint(...ck);
|
|
234
213
|
}
|
|
235
214
|
}
|
|
236
|
-
|
|
237
215
|
function addCWVTracking() {
|
|
238
216
|
setTimeout(() => {
|
|
239
217
|
try {
|
|
240
218
|
const cwvScript = new URL('.rum/web-vitals/dist/web-vitals.iife.js', sampleRUM.baseURL).href;
|
|
241
219
|
if (document.querySelector(`script[src="${cwvScript}"]`)) {
|
|
242
|
-
// web vitals script has been loaded already
|
|
243
220
|
return;
|
|
244
221
|
}
|
|
245
222
|
const script = document.createElement('script');
|
|
@@ -255,11 +232,7 @@
|
|
|
255
232
|
}
|
|
256
233
|
sampleRUM('cwv', data);
|
|
257
234
|
};
|
|
258
|
-
|
|
259
235
|
const isEager = (metric) => ['CLS', 'LCP'].includes(metric);
|
|
260
|
-
|
|
261
|
-
// When loading `web-vitals` using a classic script, all the public
|
|
262
|
-
// methods can be found on the `webVitals` global namespace.
|
|
263
236
|
['FID', 'INP', 'TTFB', 'CLS', 'LCP'].forEach((metric) => {
|
|
264
237
|
const metricFn = window.webVitals[`on${metric}`];
|
|
265
238
|
if (typeof metricFn === 'function') {
|
|
@@ -273,32 +246,26 @@
|
|
|
273
246
|
};
|
|
274
247
|
document.head.appendChild(script);
|
|
275
248
|
} catch (error) {
|
|
276
|
-
// something went wrong
|
|
277
249
|
}
|
|
278
|
-
}, 2000);
|
|
250
|
+
}, 2000);
|
|
279
251
|
}
|
|
280
|
-
|
|
281
252
|
function addNavigationTracking() {
|
|
282
|
-
// enter checkpoint when referrer is not the current page url
|
|
283
253
|
const navigate = (source, type) => {
|
|
284
254
|
const payload = { source, target: document.visibilityState };
|
|
285
|
-
// reload: same page, navigate: same origin, enter: everything else
|
|
286
255
|
if (type === 'reload' || source === window.location.href) {
|
|
287
256
|
sampleRUM('reload', payload);
|
|
288
257
|
} else if (type && type !== 'navigate') {
|
|
289
|
-
sampleRUM(type, payload);
|
|
258
|
+
sampleRUM(type, payload);
|
|
290
259
|
} else if (source && window.location.origin === new URL(source).origin) {
|
|
291
|
-
sampleRUM('navigate', payload);
|
|
260
|
+
sampleRUM('navigate', payload);
|
|
292
261
|
} else {
|
|
293
|
-
sampleRUM('enter', payload);
|
|
262
|
+
sampleRUM('enter', payload);
|
|
294
263
|
}
|
|
295
264
|
};
|
|
296
|
-
|
|
297
265
|
new PerformanceObserver((list) => list
|
|
298
266
|
.getEntries().map((entry) => navigate(window.hlx.referrer || document.referrer, entry.type)))
|
|
299
267
|
.observe({ type: 'navigation', buffered: true });
|
|
300
268
|
}
|
|
301
|
-
|
|
302
269
|
function addLoadResourceTracking() {
|
|
303
270
|
const observer = new PerformanceObserver((list) => {
|
|
304
271
|
try {
|
|
@@ -315,39 +282,47 @@
|
|
|
315
282
|
sampleRUM('missingresource', { source: entry.name, target: entry.hostname });
|
|
316
283
|
});
|
|
317
284
|
} catch (error) {
|
|
318
|
-
// something went wrong
|
|
319
285
|
}
|
|
320
286
|
});
|
|
321
287
|
observer.observe({ type: 'resource', buffered: true });
|
|
322
288
|
}
|
|
323
|
-
|
|
324
289
|
function activateBlocksMutationObserver() {
|
|
325
|
-
if (!
|
|
290
|
+
if (!blocksMutationObserver || blocksMutationObserver.active) {
|
|
326
291
|
return;
|
|
327
292
|
}
|
|
328
|
-
|
|
329
|
-
|
|
293
|
+
blocksMutationObserver.active = true;
|
|
294
|
+
blocksMutationObserver.observe(
|
|
330
295
|
document.body,
|
|
331
|
-
// eslint-disable-next-line object-curly-newline
|
|
332
296
|
{ subtree: true, attributes: true, attributeFilter: ['data-block-status'] },
|
|
333
297
|
);
|
|
334
298
|
}
|
|
335
|
-
|
|
299
|
+
function activateMediaMutationObserver() {
|
|
300
|
+
if (!mediaMutationObserver || mediaMutationObserver.active) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
mediaMutationObserver.active = true;
|
|
304
|
+
mediaMutationObserver.observe(
|
|
305
|
+
document.body,
|
|
306
|
+
{ subtree: true, attributes: false, childList: true },
|
|
307
|
+
);
|
|
308
|
+
}
|
|
336
309
|
function getIntersectionObsever(checkpoint) {
|
|
337
|
-
if (!window.IntersectionObserver)
|
|
310
|
+
if (!window.IntersectionObserver) {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
338
313
|
activateBlocksMutationObserver();
|
|
314
|
+
activateMediaMutationObserver();
|
|
339
315
|
const observer = new IntersectionObserver((entries) => {
|
|
340
316
|
try {
|
|
341
317
|
entries
|
|
342
318
|
.filter((entry) => entry.isIntersecting)
|
|
343
319
|
.forEach((entry) => {
|
|
344
|
-
observer.unobserve(entry.target);
|
|
320
|
+
observer.unobserve(entry.target);
|
|
345
321
|
const target = targetSelector(entry.target);
|
|
346
322
|
const source = sourceSelector(entry.target);
|
|
347
323
|
sampleRUM(checkpoint, { target, source });
|
|
348
324
|
});
|
|
349
325
|
} catch (error) {
|
|
350
|
-
// something went wrong
|
|
351
326
|
}
|
|
352
327
|
});
|
|
353
328
|
return observer;
|
|
@@ -359,37 +334,44 @@
|
|
|
359
334
|
blocks.forEach((b) => blockobserver.observe(b));
|
|
360
335
|
}
|
|
361
336
|
}
|
|
362
|
-
|
|
337
|
+
const observedMedia = new Set();
|
|
363
338
|
function addViewMediaTracking(parent) {
|
|
364
339
|
const mediaobserver = getIntersectionObsever('viewmedia');
|
|
365
340
|
if (mediaobserver) {
|
|
366
341
|
parent.querySelectorAll('img, video, audio, iframe').forEach((m) => {
|
|
367
|
-
if (!
|
|
342
|
+
if (!observedMedia.has(m)) {
|
|
343
|
+
observedMedia.add(m);
|
|
368
344
|
mediaobserver.observe(m);
|
|
369
345
|
}
|
|
370
346
|
});
|
|
371
347
|
}
|
|
372
348
|
}
|
|
373
|
-
|
|
374
349
|
function addFormTracking(parent) {
|
|
375
350
|
activateBlocksMutationObserver();
|
|
351
|
+
activateMediaMutationObserver();
|
|
376
352
|
parent.querySelectorAll('form').forEach((form) => {
|
|
377
|
-
form.removeEventListener('submit', formSubmitListener);
|
|
353
|
+
form.removeEventListener('submit', formSubmitListener);
|
|
378
354
|
form.addEventListener('submit', formSubmitListener);
|
|
379
355
|
});
|
|
380
356
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
357
|
+
function addObserver(ck, fn, block) {
|
|
358
|
+
return DEFAULT_TRACKING_EVENTS.includes(ck) && fn(block);
|
|
359
|
+
}
|
|
360
|
+
function blocksMutationsCallback(mutations) {
|
|
361
|
+
mutations
|
|
362
|
+
.filter((m) => m.type === 'attributes' && m.attributeName === 'data-block-status')
|
|
385
363
|
.filter((m) => m.target.dataset.blockStatus === 'loaded')
|
|
386
364
|
.forEach((m) => {
|
|
387
365
|
addObserver('form', addFormTracking, m.target);
|
|
388
366
|
addObserver('viewblock', addViewBlockTracking, m.target);
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
function mediaMutationsCallback(mutations) {
|
|
370
|
+
mutations
|
|
371
|
+
.forEach((m) => {
|
|
389
372
|
addObserver('viewmedia', addViewMediaTracking, m.target);
|
|
390
373
|
});
|
|
391
374
|
}
|
|
392
|
-
|
|
393
375
|
function addTrackingFromConfig() {
|
|
394
376
|
document.addEventListener('click', (event) => {
|
|
395
377
|
sampleRUM('click', { target: targetSelector(event.target), source: sourceSelector(event.target) });
|
|
@@ -404,8 +386,12 @@
|
|
|
404
386
|
addCookieConsentTracking(sampleRUM);
|
|
405
387
|
addAdsParametersTracking(sampleRUM);
|
|
406
388
|
addEmailParameterTracking(sampleRUM);
|
|
389
|
+
fflags.enabled('language', () => {
|
|
390
|
+
const target = navigator.language;
|
|
391
|
+
const source = document.documentElement.lang;
|
|
392
|
+
sampleRUM('language', { source, target });
|
|
393
|
+
});
|
|
407
394
|
}
|
|
408
|
-
|
|
409
395
|
function initEnhancer() {
|
|
410
396
|
try {
|
|
411
397
|
if (sampleRUM) {
|
|
@@ -414,9 +400,8 @@
|
|
|
414
400
|
processQueue();
|
|
415
401
|
}
|
|
416
402
|
} catch (error) {
|
|
417
|
-
// something went wrong
|
|
418
403
|
}
|
|
419
404
|
}
|
|
420
|
-
|
|
421
405
|
initEnhancer();
|
|
406
|
+
|
|
422
407
|
})();
|
package/src/index.md5
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
65cf540e7fe93b6d3d67567cbf215544
|
|
@@ -43,7 +43,7 @@ export default {
|
|
|
43
43
|
context.url = '/node_modules/@adobe/helix-rum-js/dist/rum-standalone.js';
|
|
44
44
|
await next();
|
|
45
45
|
context.body = context.body
|
|
46
|
-
.replace(/const weight.*/, 'const weight = 1
|
|
46
|
+
.replace(/const weight.*/, 'const weight = 1')
|
|
47
47
|
.replace(/navigator\.sendBeacon/g, 'fakeSendBeacon')
|
|
48
48
|
.replace('.rum/@adobe/helix-rum-enhancer@^2/src/index.js', 'src/index.map.js');
|
|
49
49
|
return true;
|