1919 * @param {string } data.target subject of the checkpoint event,
2020 * for instance the href of a link, or a search term
2121 */
22- export function sampleRUM ( checkpoint , data = { } ) {
23- const SESSION_STORAGE_KEY = 'aem-rum' ;
24- sampleRUM . baseURL = sampleRUM . baseURL || new URL ( window . RUM_BASE == null ? 'https://rum.hlx.page' : window . RUM_BASE , window . location ) ;
25- sampleRUM . defer = sampleRUM . defer || [ ] ;
26- const defer = ( fnname ) => {
27- sampleRUM [ fnname ] = sampleRUM [ fnname ]
28- || ( ( ...args ) => sampleRUM . defer . push ( { fnname, args } ) ) ;
29- } ;
30- sampleRUM . drain = sampleRUM . drain
31- || ( ( dfnname , fn ) => {
32- sampleRUM [ dfnname ] = fn ;
33- sampleRUM . defer
34- . filter ( ( { fnname } ) => dfnname === fnname )
35- . forEach ( ( { fnname, args } ) => sampleRUM [ fnname ] ( ...args ) ) ;
36- } ) ;
37- sampleRUM . always = sampleRUM . always || [ ] ;
38- sampleRUM . always . on = ( chkpnt , fn ) => {
39- sampleRUM . always [ chkpnt ] = fn ;
40- } ;
41- sampleRUM . on = ( chkpnt , fn ) => {
42- sampleRUM . cases [ chkpnt ] = fn ;
43- } ;
44- defer ( 'observe' ) ;
45- defer ( 'cwv' ) ;
22+ export function sampleRUM ( checkpoint , data ) {
23+ // eslint-disable-next-line max-len
24+ const timeShift = ( ) => ( window . performance ? window . performance . now ( ) : Date . now ( ) - window . hlx . rum . firstReadTime ) ;
4625 try {
4726 window . hlx = window . hlx || { } ;
27+ sampleRUM . enhance = ( ) => { } ;
4828 if ( ! window . hlx . rum ) {
49- const usp = new URLSearchParams ( window . location . search ) ;
50- const weight = ( usp . get ( 'rum' ) === 'on' ) ? 1 : 100 ; // with parameter, weight is 1. Defaults to 100.
51- const id = Array . from ( { length : 75 } , ( _ , i ) => String . fromCharCode ( 48 + i ) ) . filter ( ( a ) => / \d | [ A - Z ] / i. test ( a ) ) . filter ( ( ) => Math . random ( ) * 75 > 70 ) . join ( '' ) ;
52- const random = Math . random ( ) ;
53- const isSelected = ( random * weight < 1 ) ;
54- const firstReadTime = window . performance ? window . performance . timeOrigin : Date . now ( ) ;
55- const urlSanitizers = {
56- full : ( ) => window . location . href ,
57- origin : ( ) => window . location . origin ,
58- path : ( ) => window . location . href . replace ( / \? .* $ / , '' ) ,
59- } ;
60- // eslint-disable-next-line max-len
61- const rumSessionStorage = sessionStorage . getItem ( SESSION_STORAGE_KEY ) ? JSON . parse ( sessionStorage . getItem ( SESSION_STORAGE_KEY ) ) : { } ;
62- // eslint-disable-next-line max-len
63- rumSessionStorage . pages = ( rumSessionStorage . pages ? rumSessionStorage . pages : 0 ) + 1 + /* noise */ ( Math . floor ( Math . random ( ) * 20 ) - 10 ) ;
64- sessionStorage . setItem ( SESSION_STORAGE_KEY , JSON . stringify ( rumSessionStorage ) ) ;
29+ const param = new URLSearchParams ( window . location . search ) . get ( 'rum' ) ;
30+ const weight = ( window . SAMPLE_PAGEVIEWS_AT_RATE === 'high' && 10 )
31+ || ( window . SAMPLE_PAGEVIEWS_AT_RATE === 'low' && 1000 )
32+ || ( param === 'on' && 1 )
33+ || 100 ;
34+ const id = Math . random ( ) . toString ( 36 ) . slice ( - 4 ) ;
35+ const isSelected = param !== 'off' && Math . random ( ) * weight < 1 ;
6536 // eslint-disable-next-line object-curly-newline, max-len
66- window . hlx . rum = { weight, id, random, isSelected, firstReadTime, sampleRUM, sanitizeURL : urlSanitizers [ window . hlx . RUM_MASK_URL || 'path' ] , rumSessionStorage } ;
67- }
68-
69- const { weight, id, firstReadTime } = window . hlx . rum ;
70- if ( window . hlx && window . hlx . rum && window . hlx . rum . isSelected ) {
71- const knownProperties = [ 'weight' , 'id' , 'referer' , 'checkpoint' , 't' , 'source' , 'target' , 'cwv' , 'CLS' , 'FID' , 'LCP' , 'INP' , 'TTFB' ] ;
72- const sendPing = ( pdata = data ) => {
73- // eslint-disable-next-line max-len
74- const t = Math . round ( window . performance ? window . performance . now ( ) : ( Date . now ( ) - firstReadTime ) ) ;
75- // eslint-disable-next-line object-curly-newline, max-len, no-use-before-define
76- const body = JSON . stringify ( { weight, id, referer : window . hlx . rum . sanitizeURL ( ) , checkpoint, t, ...data } , knownProperties ) ;
77- const url = new URL ( `.rum/${ weight } ` , sampleRUM . baseURL ) . href ;
78- navigator . sendBeacon ( url , body ) ;
79- // eslint-disable-next-line no-console
80- console . debug ( `ping:${ checkpoint } ` , pdata ) ;
37+ window . hlx . rum = {
38+ weight,
39+ id,
40+ isSelected,
41+ firstReadTime : window . performance ? window . performance . timeOrigin : Date . now ( ) ,
42+ sampleRUM,
43+ queue : [ ] ,
44+ collector : ( ...args ) => window . hlx . rum . queue . push ( args ) ,
8145 } ;
82- sampleRUM . cases = sampleRUM . cases || {
83- load : ( ) => sampleRUM ( 'pagesviewed' , { source : window . hlx . rum . rumSessionStorage . pages } ) || true ,
84- cwv : ( ) => sampleRUM . cwv ( data ) || true ,
85- lazy : ( ) => {
86- // use classic script to avoid CORS issues
46+ if ( isSelected ) {
47+ const dataFromErrorObj = ( error ) => {
48+ const errData = { source : 'undefined error' } ;
49+ try {
50+ errData . target = error . toString ( ) ;
51+ errData . source = error . stack
52+ . split ( '\n' )
53+ . filter ( ( line ) => line . match ( / h t t p s ? : \/ \/ / ) )
54+ . shift ( )
55+ . replace ( / a t ( [ ^ ] + ) \( ( .+ ) \) / , '$1@$2' )
56+ . replace ( / a t / , '@' )
57+ . trim ( ) ;
58+ } catch ( err ) {
59+ /* error structure was not as expected */
60+ }
61+ return errData ;
62+ } ;
63+
64+ window . addEventListener ( 'error' , ( { error } ) => {
65+ const errData = dataFromErrorObj ( error ) ;
66+ sampleRUM ( 'error' , errData ) ;
67+ } ) ;
68+
69+ window . addEventListener ( 'unhandledrejection' , ( { reason } ) => {
70+ let errData = {
71+ source : 'Unhandled Rejection' ,
72+ target : reason || 'Unknown' ,
73+ } ;
74+ if ( reason instanceof Error ) {
75+ errData = dataFromErrorObj ( reason ) ;
76+ }
77+ sampleRUM ( 'error' , errData ) ;
78+ } ) ;
79+
80+ sampleRUM . baseURL = sampleRUM . baseURL || new URL ( window . RUM_BASE || '/' , new URL ( 'https://rum.hlx.page' ) ) ;
81+ sampleRUM . collectBaseURL = sampleRUM . collectBaseURL || sampleRUM . baseURL ;
82+ sampleRUM . sendPing = ( ck , time , pingData = { } ) => {
83+ // eslint-disable-next-line max-len, object-curly-newline
84+ const rumData = JSON . stringify ( {
85+ weight,
86+ id,
87+ referer : window . location . href ,
88+ checkpoint : ck ,
89+ t : time ,
90+ ...pingData ,
91+ } ) ;
92+ const urlParams = window . RUM_PARAMS
93+ ? `?${ new URLSearchParams ( window . RUM_PARAMS ) . toString ( ) } `
94+ : '' ;
95+ const { href : url , origin } = new URL (
96+ `.rum/${ weight } ${ urlParams } ` ,
97+ sampleRUM . collectBaseURL ,
98+ ) ;
99+ const body = origin === window . location . origin
100+ ? new Blob ( [ rumData ] , { type : 'application/json' } )
101+ : rumData ;
102+ navigator . sendBeacon ( url , body ) ;
103+ // eslint-disable-next-line no-console
104+ console . debug ( `ping:${ ck } ` , pingData ) ;
105+ } ;
106+ sampleRUM . sendPing ( 'top' , timeShift ( ) ) ;
107+
108+ sampleRUM . enhance = ( ) => {
109+ // only enhance once
110+ if ( document . querySelector ( 'script[src*="rum-enhancer"]' ) ) return ;
111+ const { enhancerVersion, enhancerHash } = sampleRUM . enhancerContext || { } ;
87112 const script = document . createElement ( 'script' ) ;
88- script . src = new URL ( '.rum/@adobe/helix-rum-enhancer@^1/src/index.js' , sampleRUM . baseURL ) . href ;
113+ if ( enhancerHash ) {
114+ script . integrity = enhancerHash ;
115+ script . setAttribute ( 'crossorigin' , 'anonymous' ) ;
116+ }
117+ script . src = new URL (
118+ `.rum/@adobe/helix-rum-enhancer@${ enhancerVersion || '^2' } /src/index.js` ,
119+ sampleRUM . baseURL ,
120+ ) . href ;
89121 document . head . appendChild ( script ) ;
90- return true ;
91- } ,
92- } ;
93- sendPing ( data ) ;
94- if ( sampleRUM . cases [ checkpoint ] ) {
95- sampleRUM . cases [ checkpoint ] ( ) ;
122+ } ;
123+ if ( ! window . hlx . RUM_MANUAL_ENHANCE ) {
124+ sampleRUM . enhance ( ) ;
125+ }
96126 }
97127 }
98- if ( sampleRUM . always [ checkpoint ] ) {
99- sampleRUM . always [ checkpoint ] ( data ) ;
128+ if ( window . hlx . rum && window . hlx . rum . isSelected && checkpoint ) {
129+ window . hlx . rum . collector ( checkpoint , data , timeShift ( ) ) ;
100130 }
131+ document . dispatchEvent ( new CustomEvent ( 'rum' , { detail : { checkpoint, data } } ) ) ;
101132 } catch ( error ) {
102- // something went wrong
133+ // something went awry
103134 }
104135}
105136
@@ -227,6 +258,9 @@ function updateSectionsStatus($main) {
227258 break ;
228259 } else {
229260 section . setAttribute ( 'data-section-status' , 'loaded' ) ;
261+ if ( i === 0 && sampleRUM . enhance ) {
262+ sampleRUM . enhance ( ) ;
263+ }
230264 }
231265 }
232266 }
@@ -517,6 +551,8 @@ async function loadPage(doc) {
517551function initHlx ( ) {
518552 window . hlx = window . hlx || { } ;
519553 window . hlx . lighthouse = new URLSearchParams ( window . location . search ) . get ( 'lighthouse' ) === 'on' ;
554+ window . hlx . RUM_MASK_URL = 'full' ;
555+ window . hlx . RUM_MANUAL_ENHANCE = true ;
520556 window . hlx . codeBasePath = '' ;
521557
522558 const scriptEl = document . querySelector ( 'script[src$="/scripts/scripts.js"]' ) ;
@@ -567,9 +603,7 @@ const LCP_BLOCKS = ['hero']; // add your LCP blocks to the list
567603const PRODUCTION_DOMAINS = [ 'adobe.design' ] ;
568604const ICON_ROOT = '/icons' ;
569605
570- sampleRUM ( 'top' ) ;
571- window . addEventListener ( 'load' , ( ) => sampleRUM ( 'load' ) ) ;
572- document . addEventListener ( 'click' , ( ) => sampleRUM ( 'click' ) ) ;
606+ sampleRUM ( ) ;
573607
574608loadPage ( document ) ;
575609
@@ -713,10 +747,6 @@ async function loadLazy(doc) {
713747
714748 loadCSS ( `${ window . hlx . codeBasePath } /styles/lazy-styles.css` ) ;
715749 addFavIcon ( `${ window . hlx . codeBasePath } /icon.svg` ) ;
716-
717- sampleRUM ( 'lazy' ) ;
718- sampleRUM . observe ( main . querySelectorAll ( 'div[data-block-name]' ) ) ;
719- sampleRUM . observe ( main . querySelectorAll ( 'picture > img' ) ) ;
720750}
721751
722752/**
@@ -728,9 +758,6 @@ function loadDelayed() {
728758 setTimeout ( ( ) => {
729759 loadScript ( 'https://assets.adobedtm.com/a7d65461e54e/9ee19a80de10/launch-882c01867cbb.min.js' ) ;
730760 } , 4000 ) ;
731-
732- // Core Web Vitals RUM collection
733- sampleRUM ( 'cwv' ) ;
734761}
735762
736763/*
0 commit comments