From 985a76bfcf3d4df0a1dd325b208ed0dd4d071246 Mon Sep 17 00:00:00 2001 From: WordPress Fan <146129302+wordpressfan@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:06:41 +0300 Subject: [PATCH] 3.16 - Handle different errors from the beacon script (#6603) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Perona --- assets/js/lcp-beacon.js | 46 +++++++++--- assets/js/lcp-beacon.js.min.map | 3 +- assets/js/lcp-beacon.min.js | 2 +- .../Media/AboveTheFold/AJAX/Controller.php | 31 +++++++- .../AJAX/Controller/addLcpData.php | 72 +++++++++++++++++++ .../AJAX/Subscriber/addLcpData.php | 1 + .../AJAX/Controller/addLcpData.php | 2 + 7 files changed, 144 insertions(+), 13 deletions(-) diff --git a/assets/js/lcp-beacon.js b/assets/js/lcp-beacon.js index cf52ceff16..ca8d599379 100644 --- a/assets/js/lcp-beacon.js +++ b/assets/js/lcp-beacon.js @@ -2,6 +2,9 @@ class RocketLcpBeacon { constructor( config ) { this.config = config; this.performanceImages = []; + this.errorCode = ''; + this.scriptTimer = new Date(); + this.infiniteLoopId = null; } init() { @@ -10,11 +13,20 @@ class RocketLcpBeacon { return; } - // Use _generateLcpCandidates method to get all the elements in the viewport. - const above_the_fold_images = this._generateLcpCandidates( Infinity ); - if ( above_the_fold_images ) { - this._initWithFirstElementWithInfo( above_the_fold_images ); - this._fillATFWithoutDuplications( above_the_fold_images ); + this.infiniteLoopId = setTimeout( () => { + this._handleInfiniteLoop(); + }, 10000 ); + + try { + // Use _generateLcpCandidates method to get all the elements in the viewport. + const above_the_fold_images = this._generateLcpCandidates( Infinity ); + if ( above_the_fold_images ) { + this._initWithFirstElementWithInfo( above_the_fold_images ); + this._fillATFWithoutDuplications( above_the_fold_images ); + } + } catch ( err ) { + this.errorCode = 'script_error'; + this._logMessage( 'Script Error: ' + err ); } this._saveFinalResultIntoDB(); @@ -245,20 +257,29 @@ class RocketLcpBeacon { this.performanceImages.some(item => item.src === elementInfo.src); } - _saveFinalResultIntoDB() { - if ( ! this.performanceImages ) { - return; + _getFinalStatus() { + if ( '' !== this.errorCode ) { + return this.errorCode; + } + + const scriptTime = ( new Date() - this.scriptTimer ) / 1000; + if ( 10 <= scriptTime ) { + return 'timeout'; } + return 'success'; + } + + _saveFinalResultIntoDB() { const data = new FormData(); data.append('action', 'rocket_lcp'); data.append('rocket_lcp_nonce', this.config.nonce); data.append('url', this.config.url); data.append('is_mobile', this.config.is_mobile); data.append('images', JSON.stringify(this.performanceImages)); - data.append('status', 'success'); + data.append('status', this._getFinalStatus()); - fetch(rocket_lcp_data.ajax_url, { + fetch(this.config.ajax_url, { method: "POST", credentials: 'same-origin', body: data, @@ -278,9 +299,14 @@ class RocketLcpBeacon { }); } + _handleInfiniteLoop() { + this._saveFinalResultIntoDB(); + } + _finalize() { const beaconscript = document.querySelector('[data-name="wpr-lcp-beacon"]'); beaconscript.setAttribute('beacon-completed', 'true'); + clearTimeout( this.infiniteLoopId ); } _logMessage( msg ) { diff --git a/assets/js/lcp-beacon.js.min.map b/assets/js/lcp-beacon.js.min.map index 862ea66c80..84ede21c65 100644 --- a/assets/js/lcp-beacon.js.min.map +++ b/assets/js/lcp-beacon.js.min.map @@ -1 +1,2 @@ -{"version":3,"names":[],"mappings":"","sources":["lcp-beacon.js"],"sourcesContent":["!function n(r,s,o){function c(t,e){if(!s[t]){if(!r[t]){var i=\"function\"==typeof require&&require;if(!e&&i)return i(t,!0);if(a)return a(t,!0);throw(e=new Error(\"Cannot find module '\"+t+\"'\")).code=\"MODULE_NOT_FOUND\",e}i=s[t]={exports:{}},r[t][0].call(i.exports,function(e){return c(r[t][1][e]||e)},i,i.exports,n,r,s,o)}return s[t].exports}for(var a=\"function\"==typeof require&&require,e=0;ethis.config.width_threshold||t>this.config.height_threshold),e=!this.config.is_mobile&&(e{var t=e.getBoundingClientRect();return{element:e,rect:t}}).filter(e=>0({item:e,area:this._getElementArea(e.rect),elementInfo:this._getElementInfo(e.element)})).sort((e,t)=>t.area-e.area).slice(0,e).map(e=>({element:e.item.element,elementInfo:e.elementInfo}))}_isIntersecting(e){return 0<=e.bottom&&0<=e.right&&e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.left<=(window.innerWidth||document.documentElement.clientWidth)}_getElementArea(e){return Math.min(e.width,(window.innerWidth||document.documentElement.clientWidth)-e.left)*Math.min(e.height,(window.innerHeight||document.documentElement.clientHeight)-e.top)}_getElementInfo(e){var t=e.nodeName.toLowerCase(),i={type:\"\",src:\"\",srcset:\"\",sizes:\"\",sources:[],bg_set:[],current_src:\"\"};if(\"img\"===t&&e.srcset)i.type=\"img-srcset\",i.src=e.src,i.srcset=e.srcset,i.sizes=e.sizes,i.current_src=e.currentSrc;else if(\"img\"===t)i.type=\"img\",i.src=e.src,i.current_src=e.currentSrc;else if(\"video\"===t){i.type=\"img\";var n=e.querySelector(\"source\");i.src=e.poster||(n?n.src:\"\"),i.current_src=i.src}else if(\"svg\"===t)(n=e.querySelector(\"image\"))&&(i.type=\"img\",i.src=n.getAttribute(\"href\")||\"\",i.current_src=i.src);else if(\"picture\"===t)i.type=\"picture\",n=e.querySelector(\"img:not(picture>img)\"),i.src=n?n.src:\"\",i.sources=Array.from(e.querySelectorAll(\"source\")).map(e=>({srcset:e.srcset||\"\",media:e.media||\"\"}));else{if(t=[window.getComputedStyle(e,null).getPropertyValue(\"background-image\"),getComputedStyle(e,\":after\").getPropertyValue(\"background-image\"),getComputedStyle(e,\":before\").getPropertyValue(\"background-image\")].filter(e=>\"none\"!==e).join(\"\"),i.type=\"bg-img\",t.includes(\"image-set(\")&&(i.type=\"bg-img-set\"),!t||\"\"===t)return null;n=[...t.matchAll(/url\\(\\s*?['\"]?\\s*?(\\S+?)\\s*?[\"']?\\s*?\\)\\s*?([a-zA-Z0-9\\s]*[x|dpcm|dpi|dppx]?)/gi)],i.bg_set=n.map(e=>e[1]?{src:e[1].trim()+(e[2]?\" \"+e[2].trim():\"\")}:{}),i.bg_set.every(e=>\"\"===e.src)&&(i.bg_set=n.map(e=>e[1]?{src:e[1].trim()}:{})),0null!==e.elementInfo))?this.performanceImages=[{...e.elementInfo,label:\"lcp\"}]:(this._logMessage(\"No LCP candidate found.\"),this.performanceImages=[])}_fillATFWithoutDuplications(e){e.forEach(e=>{var{element:e,elementInfo:t}=e;this._isDuplicateImage(e)||this.performanceImages.push({...t,label:\"above-the-fold\"})})}_isDuplicateImage(e){const t=this._getElementInfo(e);var i;return null!==t&&(e=\"img\"===t.type||\"img-srcset\"===t.type||\"video\"===t.type,i=\"bg-img\"===t.type||\"bg-img-set\"===t.type||\"picture\"===t.type,e||i)&&this.performanceImages.some(e=>e.src===t.src)}_saveFinalResultIntoDB(){var e;this.performanceImages&&((e=new FormData).append(\"action\",\"rocket_lcp\"),e.append(\"rocket_lcp_nonce\",this.config.nonce),e.append(\"url\",this.config.url),e.append(\"is_mobile\",this.config.is_mobile),e.append(\"images\",JSON.stringify(this.performanceImages)),e.append(\"status\",\"success\"),fetch(rocket_lcp_data.ajax_url,{method:\"POST\",credentials:\"same-origin\",body:e,headers:{\"wpr-saas-no-intercept\":!0}}).then(e=>e.json()).then(e=>{this._logMessage(e)}).catch(e=>{this._logMessage(e)}).finally(()=>{this._finalize()}))}_finalize(){document.querySelector('[data-name=\"wpr-lcp-beacon\"]').setAttribute(\"beacon-completed\",\"true\")}_logMessage(e){this.config.debug&&console.log(e)}static run(){if(window.rocket_lcp_data){const e=new n(window.rocket_lcp_data);\"loading\"!==document.readyState?setTimeout(()=>{e.init()},500):document.addEventListener(\"DOMContentLoaded\",()=>{setTimeout(()=>{e.init()},500)})}}}).run()},{}]},{},[1]);"],"file":"lcp-beacon.js"} +{"version":3,"names":[],"mappings":"","sources":["lcp-beacon.js"],"sourcesContent":["!function r(n,s,o){function c(t,e){if(!s[t]){if(!n[t]){var i=\"function\"==typeof require&&require;if(!e&&i)return i(t,!0);if(a)return a(t,!0);throw(e=new Error(\"Cannot find module '\"+t+\"'\")).code=\"MODULE_NOT_FOUND\",e}i=s[t]={exports:{}},n[t][0].call(i.exports,function(e){return c(n[t][1][e]||e)},i,i.exports,r,n,s,o)}return s[t].exports}for(var a=\"function\"==typeof require&&require,e=0;e{this._handleInfiniteLoop()},1e4);try{var e=this._generateLcpCandidates(1/0);e&&(this._initWithFirstElementWithInfo(e),this._fillATFWithoutDuplications(e))}catch(e){this.errorCode=\"script_error\",this._logMessage(\"Script Error: \"+e)}this._saveFinalResultIntoDB()}else this._finalize()}_isValidPreconditions(){return this._isNotValidScreensize()?(this._logMessage(\"Bailing out because screen size is not acceptable\"),!1):!this._isGeneratedBefore()||(this._logMessage(\"Bailing out because data is already available\"),!1)}_isGeneratedBefore(){var e=new FormData;return e.append(\"action\",\"rocket_check_lcp\"),e.append(\"rocket_lcp_nonce\",this.config.nonce),e.append(\"url\",this.config.url),e.append(\"is_mobile\",this.config.is_mobile),(e=fetch(this.config.ajax_url,{method:\"POST\",credentials:\"same-origin\",body:e})).success}_isNotValidScreensize(){var e=window.innerWidth||document.documentElement.clientWidth,t=window.innerHeight||document.documentElement.clientHeight,i=this.config.is_mobile&&(e>this.config.width_threshold||t>this.config.height_threshold),e=!this.config.is_mobile&&(e{var t=e.getBoundingClientRect();return{element:e,rect:t}}).filter(e=>0({item:e,area:this._getElementArea(e.rect),elementInfo:this._getElementInfo(e.element)})).sort((e,t)=>t.area-e.area).slice(0,e).map(e=>({element:e.item.element,elementInfo:e.elementInfo}))}_isIntersecting(e){return 0<=e.bottom&&0<=e.right&&e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.left<=(window.innerWidth||document.documentElement.clientWidth)}_getElementArea(e){return Math.min(e.width,(window.innerWidth||document.documentElement.clientWidth)-e.left)*Math.min(e.height,(window.innerHeight||document.documentElement.clientHeight)-e.top)}_getElementInfo(e){var t=e.nodeName.toLowerCase(),i={type:\"\",src:\"\",srcset:\"\",sizes:\"\",sources:[],bg_set:[],current_src:\"\"};if(\"img\"===t&&e.srcset)i.type=\"img-srcset\",i.src=e.src,i.srcset=e.srcset,i.sizes=e.sizes,i.current_src=e.currentSrc;else if(\"img\"===t)i.type=\"img\",i.src=e.src,i.current_src=e.currentSrc;else if(\"video\"===t){i.type=\"img\";var r=e.querySelector(\"source\");i.src=e.poster||(r?r.src:\"\"),i.current_src=i.src}else if(\"svg\"===t)(r=e.querySelector(\"image\"))&&(i.type=\"img\",i.src=r.getAttribute(\"href\")||\"\",i.current_src=i.src);else if(\"picture\"===t)i.type=\"picture\",r=e.querySelector(\"img:not(picture>img)\"),i.src=r?r.src:\"\",i.sources=Array.from(e.querySelectorAll(\"source\")).map(e=>({srcset:e.srcset||\"\",media:e.media||\"\"}));else{if(t=[window.getComputedStyle(e,null).getPropertyValue(\"background-image\"),getComputedStyle(e,\":after\").getPropertyValue(\"background-image\"),getComputedStyle(e,\":before\").getPropertyValue(\"background-image\")].filter(e=>\"none\"!==e).join(\"\"),i.type=\"bg-img\",t.includes(\"image-set(\")&&(i.type=\"bg-img-set\"),!t||\"\"===t)return null;r=[...t.matchAll(/url\\(\\s*?['\"]?\\s*?(\\S+?)\\s*?[\"']?\\s*?\\)\\s*?([a-zA-Z0-9\\s]*[x|dpcm|dpi|dppx]?)/gi)],i.bg_set=r.map(e=>e[1]?{src:e[1].trim()+(e[2]?\" \"+e[2].trim():\"\")}:{}),i.bg_set.every(e=>\"\"===e.src)&&(i.bg_set=r.map(e=>e[1]?{src:e[1].trim()}:{})),0null!==e.elementInfo))?this.performanceImages=[{...e.elementInfo,label:\"lcp\"}]:(this._logMessage(\"No LCP candidate found.\"),this.performanceImages=[])}_fillATFWithoutDuplications(e){e.forEach(e=>{var{element:e,elementInfo:t}=e;this._isDuplicateImage(e)||this.performanceImages.push({...t,label:\"above-the-fold\"})})}_isDuplicateImage(e){const t=this._getElementInfo(e);var i;return null!==t&&(e=\"img\"===t.type||\"img-srcset\"===t.type||\"video\"===t.type,i=\"bg-img\"===t.type||\"bg-img-set\"===t.type||\"picture\"===t.type,e||i)&&this.performanceImages.some(e=>e.src===t.src)}_getFinalStatus(){return\"\"!==this.errorCode?this.errorCode:10<=(new Date-this.scriptTimer)/1e3?\"timeout\":\"success\"}_saveFinalResultIntoDB(){var e=new FormData;e.append(\"action\",\"rocket_lcp\"),e.append(\"rocket_lcp_nonce\",this.config.nonce),e.append(\"url\",this.config.url),e.append(\"is_mobile\",this.config.is_mobile),e.append(\"images\",JSON.stringify(this.performanceImages)),e.append(\"status\",this._getFinalStatus()),fetch(this.config.ajax_url,{method:\"POST\",credentials:\"same-origin\",body:e,headers:{\"wpr-saas-no-intercept\":!0}}).then(e=>e.json()).then(e=>{this._logMessage(e)}).catch(e=>{this._logMessage(e)}).finally(()=>{this._finalize()})}_handleInfiniteLoop(){this._saveFinalResultIntoDB()}_finalize(){document.querySelector('[data-name=\"wpr-lcp-beacon\"]').setAttribute(\"beacon-completed\",\"true\"),clearTimeout(this.infiniteLoopId)}_logMessage(e){this.config.debug&&console.log(e)}static run(){if(window.rocket_lcp_data){const e=new r(window.rocket_lcp_data);\"loading\"!==document.readyState?setTimeout(()=>{e.init()},500):document.addEventListener(\"DOMContentLoaded\",()=>{setTimeout(()=>{e.init()},500)})}}}).run()},{}]},{},[1]);"],"file":"lcp-beacon.js"} + diff --git a/assets/js/lcp-beacon.min.js b/assets/js/lcp-beacon.min.js index d15b911ce8..24119d9b91 100644 --- a/assets/js/lcp-beacon.min.js +++ b/assets/js/lcp-beacon.min.js @@ -1,2 +1,2 @@ -!function n(r,s,o){function c(t,e){if(!s[t]){if(!r[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(a)return a(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}i=s[t]={exports:{}},r[t][0].call(i.exports,function(e){return c(r[t][1][e]||e)},i,i.exports,n,r,s,o)}return s[t].exports}for(var a="function"==typeof require&&require,e=0;ethis.config.width_threshold||t>this.config.height_threshold),e=!this.config.is_mobile&&(e{var t=e.getBoundingClientRect();return{element:e,rect:t}}).filter(e=>0({item:e,area:this._getElementArea(e.rect),elementInfo:this._getElementInfo(e.element)})).sort((e,t)=>t.area-e.area).slice(0,e).map(e=>({element:e.item.element,elementInfo:e.elementInfo}))}_isIntersecting(e){return 0<=e.bottom&&0<=e.right&&e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.left<=(window.innerWidth||document.documentElement.clientWidth)}_getElementArea(e){return Math.min(e.width,(window.innerWidth||document.documentElement.clientWidth)-e.left)*Math.min(e.height,(window.innerHeight||document.documentElement.clientHeight)-e.top)}_getElementInfo(e){var t=e.nodeName.toLowerCase(),i={type:"",src:"",srcset:"",sizes:"",sources:[],bg_set:[],current_src:""};if("img"===t&&e.srcset)i.type="img-srcset",i.src=e.src,i.srcset=e.srcset,i.sizes=e.sizes,i.current_src=e.currentSrc;else if("img"===t)i.type="img",i.src=e.src,i.current_src=e.currentSrc;else if("video"===t){i.type="img";var n=e.querySelector("source");i.src=e.poster||(n?n.src:""),i.current_src=i.src}else if("svg"===t)(n=e.querySelector("image"))&&(i.type="img",i.src=n.getAttribute("href")||"",i.current_src=i.src);else if("picture"===t)i.type="picture",n=e.querySelector("img:not(picture>img)"),i.src=n?n.src:"",i.sources=Array.from(e.querySelectorAll("source")).map(e=>({srcset:e.srcset||"",media:e.media||""}));else{if(t=[window.getComputedStyle(e,null).getPropertyValue("background-image"),getComputedStyle(e,":after").getPropertyValue("background-image"),getComputedStyle(e,":before").getPropertyValue("background-image")].filter(e=>"none"!==e).join(""),i.type="bg-img",t.includes("image-set(")&&(i.type="bg-img-set"),!t||""===t)return null;n=[...t.matchAll(/url\(\s*?['"]?\s*?(\S+?)\s*?["']?\s*?\)\s*?([a-zA-Z0-9\s]*[x|dpcm|dpi|dppx]?)/gi)],i.bg_set=n.map(e=>e[1]?{src:e[1].trim()+(e[2]?" "+e[2].trim():"")}:{}),i.bg_set.every(e=>""===e.src)&&(i.bg_set=n.map(e=>e[1]?{src:e[1].trim()}:{})),0null!==e.elementInfo))?this.performanceImages=[{...e.elementInfo,label:"lcp"}]:(this._logMessage("No LCP candidate found."),this.performanceImages=[])}_fillATFWithoutDuplications(e){e.forEach(e=>{var{element:e,elementInfo:t}=e;this._isDuplicateImage(e)||this.performanceImages.push({...t,label:"above-the-fold"})})}_isDuplicateImage(e){const t=this._getElementInfo(e);var i;return null!==t&&(e="img"===t.type||"img-srcset"===t.type||"video"===t.type,i="bg-img"===t.type||"bg-img-set"===t.type||"picture"===t.type,e||i)&&this.performanceImages.some(e=>e.src===t.src)}_saveFinalResultIntoDB(){var e;this.performanceImages&&((e=new FormData).append("action","rocket_lcp"),e.append("rocket_lcp_nonce",this.config.nonce),e.append("url",this.config.url),e.append("is_mobile",this.config.is_mobile),e.append("images",JSON.stringify(this.performanceImages)),e.append("status","success"),fetch(rocket_lcp_data.ajax_url,{method:"POST",credentials:"same-origin",body:e,headers:{"wpr-saas-no-intercept":!0}}).then(e=>e.json()).then(e=>{this._logMessage(e)}).catch(e=>{this._logMessage(e)}).finally(()=>{this._finalize()}))}_finalize(){document.querySelector('[data-name="wpr-lcp-beacon"]').setAttribute("beacon-completed","true")}_logMessage(e){this.config.debug&&console.log(e)}static run(){if(window.rocket_lcp_data){const e=new n(window.rocket_lcp_data);"loading"!==document.readyState?setTimeout(()=>{e.init()},500):document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>{e.init()},500)})}}}).run()},{}]},{},[1]); +!function r(n,s,o){function c(t,e){if(!s[t]){if(!n[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(a)return a(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}i=s[t]={exports:{}},n[t][0].call(i.exports,function(e){return c(n[t][1][e]||e)},i,i.exports,r,n,s,o)}return s[t].exports}for(var a="function"==typeof require&&require,e=0;e{this._handleInfiniteLoop()},1e4);try{var e=this._generateLcpCandidates(1/0);e&&(this._initWithFirstElementWithInfo(e),this._fillATFWithoutDuplications(e))}catch(e){this.errorCode="script_error",this._logMessage("Script Error: "+e)}this._saveFinalResultIntoDB()}else this._finalize()}_isValidPreconditions(){return this._isNotValidScreensize()?(this._logMessage("Bailing out because screen size is not acceptable"),!1):!this._isGeneratedBefore()||(this._logMessage("Bailing out because data is already available"),!1)}_isGeneratedBefore(){var e=new FormData;return e.append("action","rocket_check_lcp"),e.append("rocket_lcp_nonce",this.config.nonce),e.append("url",this.config.url),e.append("is_mobile",this.config.is_mobile),(e=fetch(this.config.ajax_url,{method:"POST",credentials:"same-origin",body:e})).success}_isNotValidScreensize(){var e=window.innerWidth||document.documentElement.clientWidth,t=window.innerHeight||document.documentElement.clientHeight,i=this.config.is_mobile&&(e>this.config.width_threshold||t>this.config.height_threshold),e=!this.config.is_mobile&&(e{var t=e.getBoundingClientRect();return{element:e,rect:t}}).filter(e=>0({item:e,area:this._getElementArea(e.rect),elementInfo:this._getElementInfo(e.element)})).sort((e,t)=>t.area-e.area).slice(0,e).map(e=>({element:e.item.element,elementInfo:e.elementInfo}))}_isIntersecting(e){return 0<=e.bottom&&0<=e.right&&e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.left<=(window.innerWidth||document.documentElement.clientWidth)}_getElementArea(e){return Math.min(e.width,(window.innerWidth||document.documentElement.clientWidth)-e.left)*Math.min(e.height,(window.innerHeight||document.documentElement.clientHeight)-e.top)}_getElementInfo(e){var t=e.nodeName.toLowerCase(),i={type:"",src:"",srcset:"",sizes:"",sources:[],bg_set:[],current_src:""};if("img"===t&&e.srcset)i.type="img-srcset",i.src=e.src,i.srcset=e.srcset,i.sizes=e.sizes,i.current_src=e.currentSrc;else if("img"===t)i.type="img",i.src=e.src,i.current_src=e.currentSrc;else if("video"===t){i.type="img";var r=e.querySelector("source");i.src=e.poster||(r?r.src:""),i.current_src=i.src}else if("svg"===t)(r=e.querySelector("image"))&&(i.type="img",i.src=r.getAttribute("href")||"",i.current_src=i.src);else if("picture"===t)i.type="picture",r=e.querySelector("img:not(picture>img)"),i.src=r?r.src:"",i.sources=Array.from(e.querySelectorAll("source")).map(e=>({srcset:e.srcset||"",media:e.media||""}));else{if(t=[window.getComputedStyle(e,null).getPropertyValue("background-image"),getComputedStyle(e,":after").getPropertyValue("background-image"),getComputedStyle(e,":before").getPropertyValue("background-image")].filter(e=>"none"!==e).join(""),i.type="bg-img",t.includes("image-set(")&&(i.type="bg-img-set"),!t||""===t)return null;r=[...t.matchAll(/url\(\s*?['"]?\s*?(\S+?)\s*?["']?\s*?\)\s*?([a-zA-Z0-9\s]*[x|dpcm|dpi|dppx]?)/gi)],i.bg_set=r.map(e=>e[1]?{src:e[1].trim()+(e[2]?" "+e[2].trim():"")}:{}),i.bg_set.every(e=>""===e.src)&&(i.bg_set=r.map(e=>e[1]?{src:e[1].trim()}:{})),0null!==e.elementInfo))?this.performanceImages=[{...e.elementInfo,label:"lcp"}]:(this._logMessage("No LCP candidate found."),this.performanceImages=[])}_fillATFWithoutDuplications(e){e.forEach(e=>{var{element:e,elementInfo:t}=e;this._isDuplicateImage(e)||this.performanceImages.push({...t,label:"above-the-fold"})})}_isDuplicateImage(e){const t=this._getElementInfo(e);var i;return null!==t&&(e="img"===t.type||"img-srcset"===t.type||"video"===t.type,i="bg-img"===t.type||"bg-img-set"===t.type||"picture"===t.type,e||i)&&this.performanceImages.some(e=>e.src===t.src)}_getFinalStatus(){return""!==this.errorCode?this.errorCode:10<=(new Date-this.scriptTimer)/1e3?"timeout":"success"}_saveFinalResultIntoDB(){var e=new FormData;e.append("action","rocket_lcp"),e.append("rocket_lcp_nonce",this.config.nonce),e.append("url",this.config.url),e.append("is_mobile",this.config.is_mobile),e.append("images",JSON.stringify(this.performanceImages)),e.append("status",this._getFinalStatus()),fetch(this.config.ajax_url,{method:"POST",credentials:"same-origin",body:e,headers:{"wpr-saas-no-intercept":!0}}).then(e=>e.json()).then(e=>{this._logMessage(e)}).catch(e=>{this._logMessage(e)}).finally(()=>{this._finalize()})}_handleInfiniteLoop(){this._saveFinalResultIntoDB()}_finalize(){document.querySelector('[data-name="wpr-lcp-beacon"]').setAttribute("beacon-completed","true"),clearTimeout(this.infiniteLoopId)}_logMessage(e){this.config.debug&&console.log(e)}static run(){if(window.rocket_lcp_data){const e=new r(window.rocket_lcp_data);"loading"!==document.readyState?setTimeout(()=>{e.init()},500):document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>{e.init()},500)})}}}).run()},{}]},{},[1]); //# sourceMappingURL=lcp-beacon.js.map diff --git a/inc/Engine/Media/AboveTheFold/AJAX/Controller.php b/inc/Engine/Media/AboveTheFold/AJAX/Controller.php index 9b85244571..62b1f4e7ce 100644 --- a/inc/Engine/Media/AboveTheFold/AJAX/Controller.php +++ b/inc/Engine/Media/AboveTheFold/AJAX/Controller.php @@ -93,10 +93,14 @@ public function add_lcp_data() { return; } + $status = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : ''; + list( $status_code, $status_message ) = $this->get_status_code_message( $status ); + $item = [ 'url' => $url, 'is_mobile' => $is_mobile, - 'status' => 'completed', + 'status' => $status_code, + 'error_message' => $status_message, 'lcp' => ( is_array( $lcp ) || is_object( $lcp ) ) ? wp_json_encode( $lcp ) : $lcp, 'viewport' => wp_json_encode( $viewport ), 'last_accessed' => current_time( 'mysql', true ), @@ -112,6 +116,31 @@ public function add_lcp_data() { wp_send_json_success( $item ); } + /** + * Get status code and message to be saved into the database + * + * @param string $status Current status code from $_POST. + * @return array + */ + private function get_status_code_message( $status ) { + $status_code = 'success' !== $status ? 'failed' : 'completed'; + $status_message = ''; + + switch ( $status ) { + case 'script_error': + $status_message = esc_html__( 'Script error', 'rocket' ); + break; + case 'timeout': + $status_message = esc_html__( 'Script timeout', 'rocket' ); + break; + } + + return [ + $status_code, + $status_message, + ]; + } + /** * Creates an object with the 'type' property and the first key that exists in the image object. * diff --git a/tests/Fixtures/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php b/tests/Fixtures/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php index 48fbaa1a23..3d00e94f0c 100644 --- a/tests/Fixtures/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php +++ b/tests/Fixtures/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php @@ -84,6 +84,7 @@ ], ] ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], 'result' => false, 'message' => 'error when adding the entry to the database', @@ -127,6 +128,7 @@ ], ] ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], 'result' => true, 'message' => [ @@ -146,6 +148,7 @@ ], ] ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], ], ], @@ -189,6 +192,7 @@ ], ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], 'result' => true, 'message' => [ @@ -208,6 +212,7 @@ ], ] ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], ], ], @@ -249,6 +254,7 @@ ], ] ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], 'result' => true, 'message' => [ @@ -268,6 +274,7 @@ ], ] ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], ], ], @@ -288,6 +295,7 @@ 'lcp' => json_encode( $long_array_2[0] ), 'viewport' => json_encode( array_slice( $long_array_2, 1, 20 ) ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], 'result' => true, 'message' => [ @@ -297,6 +305,7 @@ 'lcp' => json_encode( $long_array_2[0] ), 'viewport' => json_encode( array_slice( $long_array_2, 1, 20 ) ), 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], ], ], @@ -315,6 +324,7 @@ 'lcp' => 'not found', 'viewport' => '[]', 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', ], 'result' => true, 'message' => [ @@ -324,6 +334,68 @@ 'lcp' => 'not found', 'viewport' => '[]', 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => '', + ], + ], + ], + + 'testShouldAddItemToDBWhenScriptError' => [ + 'config' => [ + 'filter' => true, + 'url' => 'http://example.org', + 'is_mobile' => false, + 'images' => '', + 'status' => 'script_error', + ], + 'expected' => [ + 'item' => [ + 'url' => 'http://example.org', + 'is_mobile' => false, + 'status' => 'failed', + 'lcp' => 'not found', + 'viewport' => '[]', + 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => 'Script error', + ], + 'result' => true, + 'message' => [ + 'url' => 'http://example.org', + 'is_mobile' => false, + 'status' => 'failed', + 'lcp' => 'not found', + 'viewport' => '[]', + 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => 'Script error', + ], + ], + ], + 'testShouldAddItemToDBWhenScriptTimeout' => [ + 'config' => [ + 'filter' => true, + 'url' => 'http://example.org', + 'is_mobile' => false, + 'images' => '', + 'status' => 'timeout', + ], + 'expected' => [ + 'item' => [ + 'url' => 'http://example.org', + 'is_mobile' => false, + 'status' => 'failed', + 'lcp' => 'not found', + 'viewport' => '[]', + 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => 'Script timeout', + ], + 'result' => true, + 'message' => [ + 'url' => 'http://example.org', + 'is_mobile' => false, + 'status' => 'failed', + 'lcp' => 'not found', + 'viewport' => '[]', + 'last_accessed' => '2024-01-01 00:00:00', + 'error_message' => 'Script timeout', ], ], ], diff --git a/tests/Integration/inc/Engine/Media/AboveTheFold/AJAX/Subscriber/addLcpData.php b/tests/Integration/inc/Engine/Media/AboveTheFold/AJAX/Subscriber/addLcpData.php index d6ffaec6ba..f4e86b939c 100644 --- a/tests/Integration/inc/Engine/Media/AboveTheFold/AJAX/Subscriber/addLcpData.php +++ b/tests/Integration/inc/Engine/Media/AboveTheFold/AJAX/Subscriber/addLcpData.php @@ -41,6 +41,7 @@ public function testShouldReturnExpected( $config, $expected ) { $_POST['url'] = $config['url']; $_POST['is_mobile'] = $config['is_mobile']; $_POST['images'] = $config['images']; + $_POST['status'] = $config['status'] ?? 'success'; $this->allowed = $config['filter']; diff --git a/tests/Unit/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php b/tests/Unit/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php index ec38f33ab0..f2af5eee18 100644 --- a/tests/Unit/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php +++ b/tests/Unit/inc/Engine/Media/AboveTheFold/AJAX/Controller/addLcpData.php @@ -44,11 +44,13 @@ protected function tearDown(): void { */ public function testShouldReturnExpected( $config, $expected ) { $this->stubEscapeFunctions(); + $this->stubTranslationFunctions(); $_POST = [ 'url' => addslashes( $config['url'] ), 'is_mobile' => addslashes( $config['is_mobile'] ), 'images' => addslashes( $config['images'] ), + 'status' => addslashes( $config['status'] ?? 'success' ), ]; Functions\expect( 'check_ajax_referer' )