From 6936b93cba5150e0eaa879aebf3662b3e279d045 Mon Sep 17 00:00:00 2001 From: Stefan Giehl Date: Fri, 17 Apr 2020 15:00:51 +0200 Subject: New page performance reports (#15736) * Adds various new performance metrics and dimensions * Adds tracking for new performance values * track performance metrics only for page views * Archive new performance metrics * move everything into a new plugin * fix archiving of overall metrics * Adds new overview reports * show performance metric on some more reports * adds new page performance icon * Adds new row action to view page performance evolution for pages * Adds new stacked bar visualization for page performance evolutions * show total value in stacked bar chart tooltips * [TEMP] use php tracker package branch * Adds some simple System tests * Adds some UI tests * remove performance metrics from action reports that don't support it * move calculation to api * mark as tracker plugin * improve calculation of maximum value in bar evolution chart * enrich existing tests with performance metrics * updates expected test files * send performance metrics with the next request after they are available this might not be the pageview it self but any request after it, like a ping, goal, ... * Adds request processor to process performance metrics not sent directly with the page view * rebuilt js * Add metric decriptions to evolution chart documentation * fix convertion of microseconds part * Ensure average page load time is displayed in evolution graph in scheduled reports * fix some more tests * move page performance overview to visitors overview * Adds new table with performance metrics visualization * Adds some additional information to page performance evolution overlay * update omnifixture * updates expected UI files * Use mediumints for new dimensions * Adds additional permission check * Encode label in page performance overlay title * Improve updating performance metrics in later requests * Adds some integration tests * improves metric documentations * Send already available performance data with page view request * update tests * updates expected UI test screenshots * updates expected test files * improves archiving * show page generation time in performance metrics table if matomo was installed before 4.0 * Hide page generation time in ui reports if Matomo was installed after 4.0 * Fix removal of unavailable columns from being displayed that was done too early in the process causing to be overwritten again by the reports configureView * do not track automatically calculated generation time any more * split latency into network and server time * [TEMP] update php tracker * rebuilt piwik.js * Ensure to count zero values as hits * updates Omnifixture * updates expected test files * remove possibility to set generation time * rebuilt piwik.js * adjust tests * update php tracker * update test logs * submodule * update Omnifixture * show page load time in action tooltip and visitor summary instead of generation time * updates expected ui files * mark page generation time metric as deprecated * fix tests * [TEMP] use submodule branches * ensure lower metric values are shown as better * use 4.x-dev branch of php-tracker * update submodules --- js/piwik.js | 82 +++++++++++++++++++++++++++++++++++++++++---------------- js/piwik.min.js | 75 ++++++++++++++++++++++++++-------------------------- 2 files changed, 98 insertions(+), 59 deletions(-) (limited to 'js') diff --git a/js/piwik.js b/js/piwik.js index 6f734b933b..9b01fc5350 100644 --- a/js/piwik.js +++ b/js/piwik.js @@ -39,8 +39,9 @@ addEventListener, attachEvent, removeEventListener, detachEvent, disableCookies, cookie, domain, readyState, documentElement, doScroll, title, text, contentWindow, postMessage, location, top, onerror, document, referrer, parent, links, href, protocol, name, GearsFactory, - performance, mozPerformance, msPerformance, webkitPerformance, timing, requestStart, - responseEnd, event, which, button, srcElement, type, target, data, + performance, mozPerformance, msPerformance, webkitPerformance, timing, connectEnd, requestStart, responseStart, + responseEnd, fetchStart, domInteractive, domLoading, domComplete, loadEventStart, loadEventEnd, + event, which, button, srcElement, type, target, data, parentNode, tagName, hostname, className, userAgent, cookieEnabled, sendBeacon, platform, mimeTypes, enabledPlugin, javaEnabled, XMLHttpRequest, ActiveXObject, open, setRequestHeader, onreadystatechange, send, readyState, status, @@ -69,7 +70,7 @@ setCookieNamePrefix, setCookieDomain, setCookiePath, setSecureCookie, setVisitorIdCookie, getCookieDomain, hasCookies, setSessionCookie, setVisitorCookieTimeout, setSessionCookieTimeout, setReferralCookieTimeout, getCookie, getCookiePath, getSessionCookieTimeout, setConversionAttributionFirstReferrer, tracker, request, - disablePerformanceTracking, setGenerationTimeMs, maq_confirm_opted_in, + disablePerformanceTracking, maq_confirm_opted_in, doNotTrack, setDoNotTrack, msDoNotTrack, getValuesFromVisitorIdCookie, enableCrossDomainLinking, disableCrossDomainLinking, isCrossDomainLinkingEnabled, setCrossDomainLinkingTimeout, getCrossDomainLinkingUrlParameter, addListener, enableLinkTracking, enableJSErrorTracking, setLinkTrackingTimer, getLinkTrackingTimer, @@ -2250,8 +2251,11 @@ if (typeof window.Piwik !== 'object') { // Is performance tracking enabled configPerformanceTrackingEnabled = true, - // Generation time set from the server - configPerformanceGenerationTime = 0, + // will be set to true automatically once the onload event has finished + performanceAvailable = false, + + // indicates if performance metrics for the page view have been sent with a request + performanceTracked = false, // Whether Custom Variables scope "visit" should be stored in a cookie during the time of the visit configStoreCustomVariablesInCookie = false, @@ -3486,6 +3490,40 @@ if (typeof window.Piwik !== 'object') { return id; } + function appendAvailablePerformanceMetrics(request) { + if (performanceAlias && performanceAlias.timing && performanceAlias + && performanceAlias.timing.connectEnd && performanceAlias.timing.fetchStart) { + request += '&pf_net=' + (performanceAlias.timing.connectEnd - performanceAlias.timing.fetchStart); + } + + if (performanceAlias && performanceAlias.timing && performanceAlias + && performanceAlias.timing.responseStart && performanceAlias.timing.requestStart) { + request += '&pf_srv=' + (performanceAlias.timing.responseStart - performanceAlias.timing.requestStart); + } + + if (performanceAlias && performanceAlias.timing && performanceAlias + && performanceAlias.timing.responseStart && performanceAlias.timing.responseEnd) { + request += '&pf_tfr=' + (performanceAlias.timing.responseEnd - performanceAlias.timing.responseStart); + } + + if (performanceAlias && performanceAlias.timing && performanceAlias + && performanceAlias.timing.domInteractive && performanceAlias.timing.domLoading) { + request += '&pf_dm1=' + (performanceAlias.timing.domInteractive - performanceAlias.timing.domLoading); + } + + if (performanceAlias && performanceAlias.timing && performanceAlias + && performanceAlias.timing.domComplete && performanceAlias.timing.domInteractive) { + request += '&pf_dm2=' + (performanceAlias.timing.domComplete - performanceAlias.timing.domInteractive); + } + + if (performanceAlias && performanceAlias.timing && performanceAlias + && performanceAlias.timing.loadEventEnd && performanceAlias.timing.loadEventStart) { + request += '&pf_onl=' + (performanceAlias.timing.loadEventEnd - performanceAlias.timing.loadEventStart); + } + + return request; + } + /** * Returns the URL to call piwik.php, * with the standard parameters (plugins, resolution, url, referrer, etc.). @@ -3702,13 +3740,9 @@ if (typeof window.Piwik !== 'object') { } // performance tracking - if (configPerformanceTrackingEnabled) { - if (configPerformanceGenerationTime) { - request += '>_ms=' + configPerformanceGenerationTime; - } else if (performanceAlias && performanceAlias.timing - && performanceAlias.timing.requestStart && performanceAlias.timing.responseEnd) { - request += '>_ms=' + (performanceAlias.timing.responseEnd - performanceAlias.timing.requestStart); - } + if (configPerformanceTrackingEnabled && performanceAvailable && !performanceTracked) { + request = appendAvailablePerformanceMetrics(request); + performanceTracked = true; } if (configIdPageView) { @@ -3851,6 +3885,11 @@ if (typeof window.Piwik !== 'object') { var request = getRequest('action_name=' + encodeWrapper(titleFixup(customTitle || configTitle)), customData, 'log'); + // append already available performance metrics if they were not already tracked (or appended) + if (!performanceTracked) { + request = appendAvailablePerformanceMetrics(request); + } + sendRequest(request, configTrackerPause, callback); } @@ -5860,16 +5899,6 @@ if (typeof window.Piwik !== 'object') { configPerformanceTrackingEnabled = false; }; - /** - * Set the server generation time. - * If set, the browser's performance.timing API in not used anymore to determine the time. - * - * @param int generationTime - */ - this.setGenerationTimeMs = function (generationTime) { - configPerformanceGenerationTime = parseInt(generationTime, 10); - }; - /** * Set visit standard length (in seconds). This should ideally match the visit_standard_length setting * in Matomo in case you customised it. This setting only has an effect if heart beat timer is active @@ -6623,6 +6652,15 @@ if (typeof window.Piwik !== 'object') { */ this.forgetUserOptOut = this.rememberConsentGiven; + /** + * Mark performance metrics as available, once onload event has finished + */ + trackCallbackOnLoad(function(){ + setTimeout(function(){ + performanceAvailable = true; + }, 0); + }); + Piwik.trigger('TrackerSetup', [this]); } diff --git a/js/piwik.min.js b/js/piwik.min.js index 745da994ef..74eafa4f96 100644 --- a/js/piwik.min.js +++ b/js/piwik.min.js @@ -28,42 +28,43 @@ if(-1!==M(aq,ao)&&ae.findFirstNodeHavingAttributeWithValue(at,"src")){var ar=ae. if(T.innerHeight&&ao>T.innerHeight){ao=T.innerHeight}return((at.bottom>0||aq)&&at.right>0&&at.left=0){di=di.slice(0,dh)}dh=di.lastIndexOf("/");if(dh!==di.length-1){di=di.slice(0,dh+1)}return di+dg}function cE(di,dg){var dh;di=String(di).toLowerCase();dg=String(dg).toLowerCase();if(di===dg){return true}if(dg.slice(0,1)==="."){if(di===dg.slice(1)){return true}dh=di.length-dg.length;if((dh>0)&&(di.slice(dh)===dg)){return true}}return false}function ci(dg){var dh=document.createElement("a"); -if(dg.indexOf("//")!==0&&dg.indexOf("http")!==0){if(dg.indexOf("*")===0){dg=dg.substr(1)}if(dg.indexOf(".")===0){dg=dg.substr(1)}dg="http://"+dg}dh.href=v.toAbsoluteUrl(dg);if(dh.pathname){return dh.pathname}return""}function a2(dh,dg){if(!aj(dg,"/")){dg="/"+dg}if(!aj(dh,"/")){dh="/"+dh}var di=(dg==="/"||dg==="/*");if(di){return true}if(dh===dg){return true}dg=String(dg).toLowerCase();dh=String(dh).toLowerCase();if(R(dg,"*")){dg=dg.slice(0,-1);di=(!dg||dg==="/");if(di){return true}if(dh===dg){return true}return dh.indexOf(dg)===0}if(!R(dh,"/")){dh+="/"}if(!R(dg,"/")){dg+="/"}return dh.indexOf(dg)===0}function ar(dk,dm){var dh,dg,di,dj,dl;for(dh=0;dh0)&&(dj.slice(di)===dg)){return true}}}return false}function cn(dg,di){dg=dg.replace("send_image=0","send_image=1"); -var dh=new Image(1,1);dh.onload=function(){E=0;if(typeof di==="function"){di({request:dg,trackerUrl:aD,success:true})}};dh.onerror=function(){if(typeof di==="function"){di({request:dg,trackerUrl:aD,success:false})}};dh.src=aD+(aD.indexOf("?")<0?"?":"&")+dg}function cB(dg){if(c7==="POST"){return true}return dg&&(dg.length>2000||dg.indexOf('{"requests"')===0)}function aJ(){return"object"===typeof h&&"function"===typeof h.sendBeacon&&"function"===typeof Blob}function a5(dk,dn,dm){var di=aJ();if(!di){return false}var dj={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dp=false;var dh=aD;try{var dg=new Blob([dk],dj);if(dm&&!cB(dk)){dg=new Blob([],dj);dh=dh+(dh.indexOf("?")<0?"?":"&")+dk}dp=h.sendBeacon(dh,dg)}catch(dl){return false}if(dp&&typeof dn==="function"){dn({request:dk,trackerUrl:aD,success:true,isSendBeacon:true})}return dp}function c1(dh,di,dg){if(!J(dg)||null===dg){dg=true}if(m&&a5(dh,di,dg)){return}setTimeout(function(){if(m&&a5(dh,di,dg)){return}var dl;try{var dk=T.XMLHttpRequest?new T.XMLHttpRequest():T.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null; -dk.open("POST",aD,true);dk.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dm=m&&a5(dh,di,dg);if(!dm&&dg){cn(dh,di)}else{if(typeof di==="function"){di({request:dh,trackerUrl:aD,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof di==="function")){di({request:dh,trackerUrl:aD,success:true,xhr:this})}}};dk.setRequestHeader("Content-Type",cu);dk.withCredentials=true;dk.send(dh)}catch(dj){dl=m&&a5(dh,di,dg);if(!dl&&dg){cn(dh,di)}else{if(typeof di==="function"){di({request:dh,trackerUrl:aD,success:false})}}}},50)}function cd(dh){var dg=new Date();var di=dg.getTime()+dh;if(!r||di>r){r=di}}function cl(dg){if(b9||!a4||!bz){return}b9=setTimeout(function dh(){b9=null;if(!bb){bb=(!G.hasFocus||G.hasFocus())}if(!bb){cl(a4);return}if(bO()){return}var di=new Date(),dj=a4-(di.getTime()-cV);dj=Math.min(a4,dj);cl(dj)},dg||a4)}function bH(){if(!b9){return}clearTimeout(b9);b9=null}function a9(){bb=true;cv=new Date().getTime()}function da(){var dg=new Date().getTime(); -return !cv||(dg-cv)>a4}function ay(){if(da()){bO()}bH()}function dd(){if(aM||!a4){return}aM=true;an(T,"focus",a9);an(T,"blur",ay);ab++;e.addPlugin("HeartBeat"+ab,{unload:function(){if(aM&&da()){bO()}}})}function cA(dk){var dh=new Date();var dg=dh.getTime();cV=dg;if(cz&&dg=dg.length){return[dg]}var dh=0;var di=dg.length;var dj=[];for(dh;dh=dh&&dg<=(dh+aY)){return true}}return false}function de(dg){if(!cK){return""}var dk=f(dg,av);if(!dk){return""}dk=String(dk); -var di=new RegExp("^[a-zA-Z0-9]+$");if(dk.length===32&&di.test(dk)){var dh=dk.substr(16,32);if(cZ(dh)){var dj=dk.substr(0,16);return dj}}return""}function cL(){if(!bL){bL=de(bK)}var di=new Date(),dg=Math.round(di.getTime()/1000),dh=aS("id"),dl=aC(dh),dk,dj;if(dl){dk=dl.split(".");dk.unshift("0");if(bL.length){dk[1]=bL}return dk}if(bL.length){dj=bL}else{if("0"===b2()){dj=""}else{dj=cO()}}dk=["1",dj,dg,0,dg,"",""];return dk}function aX(){var dn=cL(),dj=dn[0],dk=dn[1],dh=dn[2],dg=dn[3],dl=dn[4],di=dn[5];if(!J(dn[6])){dn[6]=""}var dm=dn[6];return{newVisitor:dj,uuid:dk,createTs:dh,visitCount:dg,currentVisitTs:dl,lastVisitTs:di,lastEcommerceOrderTs:dm}}function aG(){var dj=new Date(),dh=dj.getTime(),dk=aX().createTs;var dg=parseInt(dk,10);var di=(dg*1000)+cH-dh;return di}function aL(dg){if(!b3){return}var di=new Date(),dh=Math.round(di.getTime()/1000);if(!J(dg)){dg=aX()}var dj=dg.uuid+"."+dg.createTs+"."+dg.visitCount+"."+dh+"."+dg.lastVisitTs+"."+dg.lastEcommerceOrderTs;db(aS("id"),dj,aG(),bn,cU,bP) -}function bJ(){var dg=aC(aS("ref"));if(dg.length){try{dg=T.JSON.parse(dg);if(W(dg)){return dg}}catch(dh){}}return["","",0,""]}function bu(dh){var dg="testvalue";db("test",dg,10000,null,dh);if(aC("test")===dg){bV("test",null,dh);return true}return false}function aE(){var dh=bj;bj=false;var dg,di;for(dg=0;dgdG){dx.visitCount++;dx.lastVisitTs=dx.currentVisitTs}if(!bt||!dp.length){for(dD in co){if(Object.prototype.hasOwnProperty.call(co,dD)){dp=f(dH,co[dD]);if(dp.length){break}}}for(dD in bD){if(Object.prototype.hasOwnProperty.call(bD,dD)){dg=f(dH,bD[dD]);if(dg.length){break}}}}dL=d(bl);ds=dC.length?d(dC):"";if(dL.length&&!aU(dL)&&(!bt||!ds.length||aU(ds))){dC=bl}if(dC.length||dp.length){dn=dr;dB=[dp,dg,dn,bZ(dC.slice(0,dk))];db(dy,T.JSON.stringify(dB),c2,bn,cU,bP)}}di+="&idsite="+b3+"&rec=1&r="+String(Math.random()).slice(2,8)+"&h="+dh.getHours()+"&m="+dh.getMinutes()+"&s="+dh.getSeconds()+"&url="+t(bZ(dH))+(bl.length?"&urlref="+t(bZ(bl)):"")+((bw&&bw.length)?"&uid="+t(bw):"")+"&_id="+dx.uuid+"&_idts="+dx.createTs+"&_idvc="+dx.visitCount+"&_idn="+dx.newVisitor+(dp.length?"&_rcn="+t(dp):"")+(dg.length?"&_rck="+t(dg):"")+"&_refts="+dn+"&_viewts="+dx.lastVisitTs+(String(dx.lastEcommerceOrderTs).length?"&_ects="+dx.lastEcommerceOrderTs:"")+(String(dC).length?"&_ref="+t(bZ(dC.slice(0,dk))):"")+(du?"&cs="+t(du):"")+"&send_image=0"; -var dK=cF();for(dD in dK){if(Object.prototype.hasOwnProperty.call(dK,dD)){di+="&"+dD+"="+dK[dD]}}var dJ=[];if(dE){for(dD in dE){if(Object.prototype.hasOwnProperty.call(dE,dD)&&/^dimension\d+$/.test(dD)){var dm=dD.replace("dimension","");dJ.push(parseInt(dm,10));dJ.push(String(dm));di+="&"+dD+"="+t(dE[dD]);delete dE[dD]}}}if(dE&&B(dE)){dE=null}for(dD in bk){if(Object.prototype.hasOwnProperty.call(bk,dD)){var dt=(-1===M(dJ,dD));if(dt){di+="&dimension"+dD+"="+t(bk[dD])}}}if(dE){di+="&data="+t(T.JSON.stringify(dE))}else{if(ao){di+="&data="+t(T.JSON.stringify(ao))}}function dq(dM,dN){var dO=T.JSON.stringify(dM);if(dO.length>2){return"&"+dN+"="+t(dO)}return""}var dI=df(bT);var dz=df(cj);di+=dq(dI,"cvar");di+=dq(dz,"e_cvar");if(aP){di+=dq(aP,"_cvar");for(dD in dA){if(Object.prototype.hasOwnProperty.call(dA,dD)){if(aP[dD][0]===""||aP[dD][1]===""){delete aP[dD]}}}if(bN){db(dv,T.JSON.stringify(aP),cm,bn,cU,bP)}}if(a1){if(ck){di+=">_ms="+ck}else{if(i&&i.timing&&i.timing.requestStart&&i.timing.responseEnd){di+=">_ms="+(i.timing.responseEnd-i.timing.requestStart) -}}}if(aK){di+="&pv_id="+aK}dx.lastEcommerceOrderTs=J(dj)&&String(dj).length?dj:dx.lastEcommerceOrderTs;aL(dx);ca();di+=ac(dF,{tracker:bF,request:di});if(cW.length){di+="&"+cW}if(A(b8)){di=b8(di)}return di}bO=function a6(){var dg=new Date();dg=dg.getTime();if(!cV){return false}if((cV+(1000*c4))<=dg){return false}if(cV+a4<=dg){bF.ping();return true}return false};function bo(dj,di,dp,dk,dg,ds){var dm="idgoal=0",dn,dh=new Date(),dq=[],dr,dl=String(dj).length;if(dl){dm+="&ec_id="+t(dj);dn=Math.round(dh.getTime()/1000)}dm+="&revenue="+di;if(String(dp).length){dm+="&ec_st="+dp}if(String(dk).length){dm+="&ec_tx="+dk}if(String(dg).length){dm+="&ec_sh="+dg}if(String(ds).length){dm+="&ec_dt="+ds}if(cX){for(dr in cX){if(Object.prototype.hasOwnProperty.call(cX,dr)){if(!J(cX[dr][1])){cX[dr][1]=""}if(!J(cX[dr][2])){cX[dr][2]=""}if(!J(cX[dr][3])||String(cX[dr][3]).length===0){cX[dr][3]=0}if(!J(cX[dr][4])||String(cX[dr][4]).length===0){cX[dr][4]=1}dq.push(cX[dr])}}dm+="&ec_items="+t(T.JSON.stringify(dq)) -}dm=cq(dm,ao,"ecommerce",dn);bC(dm,bG);if(dl){cX={}}}function bW(dg,dk,dj,di,dh,dl){if(String(dg).length&&J(dk)){bo(dg,dk,dj,di,dh,dl)}}function bq(dg){if(J(dg)){bo("",dg,"","","","")}}function bX(dh,dj,di){aK=bf();var dg=cq("action_name="+t(al(dh||bh)),dj,"log");bC(dg,bG,di)}function aZ(di,dh){var dj,dg="(^| )(piwik[_-]"+dh;if(di){for(dj=0;dj0){dk=parseInt(dk,10);dn(dk)}})}var bA={enabled:true,requests:[],timeout:null,interval:2500,sendRequests:function(){var dg=this.requests;this.requests=[];if(dg.length===1){bC(dg[0],bG)}else{dc(dg,bG)}},push:function(dg){if(!dg){return}if(m||!this.enabled){bC(dg,bG);return}bA.requests.push(dg);if(this.timeout){clearTimeout(this.timeout);this.timeout=null}this.timeout=setTimeout(function(){bA.timeout=null;bA.sendRequests()},bA.interval);var dh="RequestQueue"+aw;if(!Object.prototype.hasOwnProperty.call(b,dh)){b[dh]={unload:function(){if(bA.timeout){clearTimeout(bA.timeout)}bA.sendRequests()}}}}};bg();aL();this.hasConsent=function(){return bz};this.getVisitorId=function(){return aX().uuid};this.getVisitorInfo=function(){return cL()};this.getAttributionInfo=function(){return bJ()};this.getAttributionCampaignName=function(){return bJ()[0]};this.getAttributionCampaignKeyword=function(){return bJ()[1] -};this.getAttributionReferrerTimestamp=function(){return bJ()[2]};this.getAttributionReferrerUrl=function(){return bJ()[3]};this.setTrackerUrl=function(dg){aD=dg};this.getTrackerUrl=function(){return aD};this.getPiwikUrl=function(){return O(this.getTrackerUrl(),bE)};this.addTracker=function(dg,di){if(!J(dg)||null===dg){dg=this.getTrackerUrl()}var dh=new Q(dg,di);I.push(dh);e.trigger("TrackerAdded",[this]);return dh};this.getSiteId=function(){return b3};this.setSiteId=function(dg){b0(dg)};this.resetUserId=function(){bw=""};this.setUserId=function(dg){if(Y(dg)){bw=dg}};this.getUserId=function(){return bw};this.setCustomData=function(dg,dh){if(W(dg)){ao=dg}else{if(!ao){ao={}}ao[dg]=dh}};this.getCustomData=function(){return ao};this.setCustomRequestProcessing=function(dg){b8=dg};this.appendToTrackingUrl=function(dg){cW=dg};this.getRequest=function(dg){return cq(dg)};this.addPlugin=function(dg,dh){b[dg]=dh};this.setCustomDimension=function(dg,dh){dg=parseInt(dg,10);if(dg>0){if(!J(dh)){dh=""}if(!w(dh)){dh=String(dh) -}bk[dg]=dh}};this.getCustomDimension=function(dg){dg=parseInt(dg,10);if(dg>0&&Object.prototype.hasOwnProperty.call(bk,dg)){return bk[dg]}};this.deleteCustomDimension=function(dg){dg=parseInt(dg,10);if(dg>0){delete bk[dg]}};this.setCustomVariable=function(dh,dg,dk,di){var dj;if(!J(di)){di="visit"}if(!J(dg)){return}if(!J(dk)){dk=""}if(dh>0){dg=!w(dg)?String(dg):dg;dk=!w(dk)?String(dk):dk;dj=[dg.slice(0,br),dk.slice(0,br)];if(di==="visit"||di===2){cC();aP[dh]=dj}else{if(di==="page"||di===3){bT[dh]=dj}else{if(di==="event"){cj[dh]=dj}}}}};this.getCustomVariable=function(dh,di){var dg;if(!J(di)){di="visit"}if(di==="page"||di===3){dg=bT[dh]}else{if(di==="event"){dg=cj[dh]}else{if(di==="visit"||di===2){cC();dg=aP[dh]}}}if(!J(dg)||(dg&&dg[0]==="")){return false}return dg};this.deleteCustomVariable=function(dg,dh){if(this.getCustomVariable(dg,dh)){this.setCustomVariable(dg,"","",dh)}};this.deleteCustomVariables=function(dg){if(dg==="page"||dg===3){bT={}}else{if(dg==="event"){cj={}}else{if(dg==="visit"||dg===2){aP={} -}}}};this.storeCustomVariablesInCookie=function(){bN=true};this.setLinkTrackingTimer=function(dg){bG=dg};this.getLinkTrackingTimer=function(){return bG};this.setDownloadExtensions=function(dg){if(w(dg)){dg=dg.split("|")}c3=dg};this.addDownloadExtensions=function(dh){var dg;if(w(dh)){dh=dh.split("|")}for(dg=0;dg1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setCookieNamePrefix","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);an(T,"message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0; -ar=0){dk=dk.slice(0,dj)}dj=dk.lastIndexOf("/");if(dj!==dk.length-1){dk=dk.slice(0,dj+1)}return dk+di}function cG(dk,di){var dj;dk=String(dk).toLowerCase();di=String(di).toLowerCase();if(dk===di){return true}if(di.slice(0,1)==="."){if(dk===di.slice(1)){return true}dj=dk.length-di.length;if((dj>0)&&(dk.slice(dj)===di)){return true}}return false}function cl(di){var dj=document.createElement("a"); +if(di.indexOf("//")!==0&&di.indexOf("http")!==0){if(di.indexOf("*")===0){di=di.substr(1)}if(di.indexOf(".")===0){di=di.substr(1)}di="http://"+di}dj.href=v.toAbsoluteUrl(di);if(dj.pathname){return dj.pathname}return""}function a3(dj,di){if(!aj(di,"/")){di="/"+di}if(!aj(dj,"/")){dj="/"+dj}var dk=(di==="/"||di==="/*");if(dk){return true}if(dj===di){return true}di=String(di).toLowerCase();dj=String(dj).toLowerCase();if(R(di,"*")){di=di.slice(0,-1);dk=(!di||di==="/");if(dk){return true}if(dj===di){return true}return dj.indexOf(di)===0}if(!R(dj,"/")){dj+="/"}if(!R(di,"/")){di+="/"}return dj.indexOf(di)===0}function ar(dm,dp){var dj,di,dk,dl,dn;for(dj=0;dj0)&&(dl.slice(dk)===di)){return true}}}return false}function cp(di,dk){di=di.replace("send_image=0","send_image=1"); +var dj=new Image(1,1);dj.onload=function(){E=0;if(typeof dk==="function"){dk({request:di,trackerUrl:aE,success:true})}};dj.onerror=function(){if(typeof dk==="function"){dk({request:di,trackerUrl:aE,success:false})}};dj.src=aE+(aE.indexOf("?")<0?"?":"&")+di}function cD(di){if(c9==="POST"){return true}return di&&(di.length>2000||di.indexOf('{"requests"')===0)}function aK(){return"object"===typeof h&&"function"===typeof h.sendBeacon&&"function"===typeof Blob}function a6(dm,dq,dp){var dk=aK();if(!dk){return false}var dl={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dr=false;var dj=aE;try{var di=new Blob([dm],dl);if(dp&&!cD(dm)){di=new Blob([],dl);dj=dj+(dj.indexOf("?")<0?"?":"&")+dm}dr=h.sendBeacon(dj,di)}catch(dn){return false}if(dr&&typeof dq==="function"){dq({request:dm,trackerUrl:aE,success:true,isSendBeacon:true})}return dr}function c3(dj,dk,di){if(!J(di)||null===di){di=true}if(m&&a6(dj,dk,di)){return}setTimeout(function(){if(m&&a6(dj,dk,di)){return}var dn;try{var dm=T.XMLHttpRequest?new T.XMLHttpRequest():T.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null; +dm.open("POST",aE,true);dm.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dp=m&&a6(dj,dk,di);if(!dp&&di){cp(dj,dk)}else{if(typeof dk==="function"){dk({request:dj,trackerUrl:aE,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof dk==="function")){dk({request:dj,trackerUrl:aE,success:true,xhr:this})}}};dm.setRequestHeader("Content-Type",cw);dm.withCredentials=true;dm.send(dj)}catch(dl){dn=m&&a6(dj,dk,di);if(!dn&&di){cp(dj,dk)}else{if(typeof dk==="function"){dk({request:dj,trackerUrl:aE,success:false})}}}},50)}function cg(dj){var di=new Date();var dk=di.getTime()+dj;if(!r||dk>r){r=dk}}function cn(di){if(cc||!a5||!bB){return}cc=setTimeout(function dj(){cc=null;if(!bc){bc=(!G.hasFocus||G.hasFocus())}if(!bc){cn(a5);return}if(bR()){return}var dk=new Date(),dl=a5-(dk.getTime()-cX);dl=Math.min(a5,dl);cn(dl)},di||a5)}function bK(){if(!cc){return}clearTimeout(cc);cc=null}function ba(){bc=true;cx=new Date().getTime()}function dc(){var di=new Date().getTime(); +return !cx||(di-cx)>a5}function ay(){if(dc()){bR()}bK()}function df(){if(aN||!a5){return}aN=true;an(T,"focus",ba);an(T,"blur",ay);ab++;e.addPlugin("HeartBeat"+ab,{unload:function(){if(aN&&dc()){bR()}}})}function cC(dm){var dj=new Date();var di=dj.getTime();cX=di;if(cB&&di=di.length){return[di]}var dj=0;var dk=di.length;var dl=[];for(dj;dj=dj&&di<=(dj+aZ)){return true}}return false}function dg(di){if(!cM){return""}var dm=f(di,av);if(!dm){return""}dm=String(dm); +var dk=new RegExp("^[a-zA-Z0-9]+$");if(dm.length===32&&dk.test(dm)){var dj=dm.substr(16,32);if(c1(dj)){var dl=dm.substr(0,16);return dl}}return""}function cN(){if(!bO){bO=dg(bN)}var dk=new Date(),di=Math.round(dk.getTime()/1000),dj=aT("id"),dn=aD(dj),dm,dl;if(dn){dm=dn.split(".");dm.unshift("0");if(bO.length){dm[1]=bO}return dm}if(bO.length){dl=bO}else{if("0"===b5()){dl=""}else{dl=cQ()}}dm=["1",dl,di,0,di,"",""];return dm}function aY(){var dq=cN(),dl=dq[0],dm=dq[1],dj=dq[2],di=dq[3],dn=dq[4],dk=dq[5];if(!J(dq[6])){dq[6]=""}var dp=dq[6];return{newVisitor:dl,uuid:dm,createTs:dj,visitCount:di,currentVisitTs:dn,lastVisitTs:dk,lastEcommerceOrderTs:dp}}function aH(){var dl=new Date(),dj=dl.getTime(),dm=aY().createTs;var di=parseInt(dm,10);var dk=(di*1000)+cJ-dj;return dk}function aM(di){if(!b6){return}var dk=new Date(),dj=Math.round(dk.getTime()/1000);if(!J(di)){di=aY()}var dl=di.uuid+"."+di.createTs+"."+di.visitCount+"."+dj+"."+di.lastVisitTs+"."+di.lastEcommerceOrderTs;dd(aT("id"),dl,aH(),bp,cW,bS) +}function bM(){var di=aD(aT("ref"));if(di.length){try{di=T.JSON.parse(di);if(W(di)){return di}}catch(dj){}}return["","",0,""]}function bw(dj){var di="testvalue";dd("test",di,10000,null,dj);if(aD("test")===di){bY("test",null,dj);return true}return false}function aF(){var dj=bl;bl=false;var di,dk;for(di=0;didI){dz.visitCount++;dz.lastVisitTs=dz.currentVisitTs}if(!bv||!dr.length){for(dF in cq){if(Object.prototype.hasOwnProperty.call(cq,dF)){dr=f(dJ,cq[dF]);if(dr.length){break}}}for(dF in bG){if(Object.prototype.hasOwnProperty.call(bG,dF)){di=f(dJ,bG[dF]);if(di.length){break}}}}dN=d(bn);du=dE.length?d(dE):"";if(dN.length&&!aV(dN)&&(!bv||!du.length||aV(du))){dE=bn}if(dE.length||dr.length){dq=dt;dD=[dr,di,dq,b2(dE.slice(0,dm))];dd(dA,T.JSON.stringify(dD),c4,bp,cW,bS)}}dk+="&idsite="+b6+"&rec=1&r="+String(Math.random()).slice(2,8)+"&h="+dj.getHours()+"&m="+dj.getMinutes()+"&s="+dj.getSeconds()+"&url="+t(b2(dJ))+(bn.length?"&urlref="+t(b2(bn)):"")+((by&&by.length)?"&uid="+t(by):"")+"&_id="+dz.uuid+"&_idts="+dz.createTs+"&_idvc="+dz.visitCount+"&_idn="+dz.newVisitor+(dr.length?"&_rcn="+t(dr):"")+(di.length?"&_rck="+t(di):"")+"&_refts="+dq+"&_viewts="+dz.lastVisitTs+(String(dz.lastEcommerceOrderTs).length?"&_ects="+dz.lastEcommerceOrderTs:"")+(String(dE).length?"&_ref="+t(b2(dE.slice(0,dm))):"")+(dw?"&cs="+t(dw):"")+"&send_image=0"; +var dM=cH();for(dF in dM){if(Object.prototype.hasOwnProperty.call(dM,dF)){dk+="&"+dF+"="+dM[dF]}}var dL=[];if(dG){for(dF in dG){if(Object.prototype.hasOwnProperty.call(dG,dF)&&/^dimension\d+$/.test(dF)){var dp=dF.replace("dimension","");dL.push(parseInt(dp,10));dL.push(String(dp));dk+="&"+dF+"="+t(dG[dF]);delete dG[dF]}}}if(dG&&B(dG)){dG=null}for(dF in bm){if(Object.prototype.hasOwnProperty.call(bm,dF)){var dv=(-1===M(dL,dF));if(dv){dk+="&dimension"+dF+"="+t(bm[dF])}}}if(dG){dk+="&data="+t(T.JSON.stringify(dG))}else{if(ao){dk+="&data="+t(T.JSON.stringify(ao))}}function ds(dO,dP){var dQ=T.JSON.stringify(dO);if(dQ.length>2){return"&"+dP+"="+t(dQ)}return""}var dK=dh(bW);var dB=dh(cm);dk+=ds(dK,"cvar");dk+=ds(dB,"e_cvar");if(aQ){dk+=ds(aQ,"_cvar");for(dF in dC){if(Object.prototype.hasOwnProperty.call(dC,dF)){if(aQ[dF][0]===""||aQ[dF][1]===""){delete aQ[dF]}}}if(bQ){dd(dx,T.JSON.stringify(aQ),co,bp,cW,bS)}}if(a2&&bE&&!bh){dk=az(dk);bh=true}if(aL){dk+="&pv_id="+aL}dz.lastEcommerceOrderTs=J(dl)&&String(dl).length?dl:dz.lastEcommerceOrderTs; +aM(dz);cd();dk+=ac(dH,{tracker:bI,request:dk});if(cY.length){dk+="&"+cY}if(A(cb)){dk=cb(dk)}return dk}bR=function a7(){var di=new Date();di=di.getTime();if(!cX){return false}if((cX+(1000*c6))<=di){return false}if(cX+a5<=di){bI.ping();return true}return false};function bq(dl,dk,dr,dm,di,du){var dp="idgoal=0",dq,dj=new Date(),ds=[],dt,dn=String(dl).length;if(dn){dp+="&ec_id="+t(dl);dq=Math.round(dj.getTime()/1000)}dp+="&revenue="+dk;if(String(dr).length){dp+="&ec_st="+dr}if(String(dm).length){dp+="&ec_tx="+dm}if(String(di).length){dp+="&ec_sh="+di}if(String(du).length){dp+="&ec_dt="+du}if(cZ){for(dt in cZ){if(Object.prototype.hasOwnProperty.call(cZ,dt)){if(!J(cZ[dt][1])){cZ[dt][1]=""}if(!J(cZ[dt][2])){cZ[dt][2]=""}if(!J(cZ[dt][3])||String(cZ[dt][3]).length===0){cZ[dt][3]=0}if(!J(cZ[dt][4])||String(cZ[dt][4]).length===0){cZ[dt][4]=1}ds.push(cZ[dt])}}dp+="&ec_items="+t(T.JSON.stringify(ds))}dp=cs(dp,ao,"ecommerce",dq);bF(dp,bJ);if(dn){cZ={}}}function bZ(di,dm,dl,dk,dj,dn){if(String(di).length&&J(dm)){bq(di,dm,dl,dk,dj,dn) +}}function bs(di){if(J(di)){bq("",di,"","","","")}}function b0(dj,dl,dk){aL=bg();var di=cs("action_name="+t(al(dj||bj)),dl,"log");if(!bh){di=az(di)}bF(di,bJ,dk)}function a0(dk,dj){var dl,di="(^| )(piwik[_-]"+dj;if(dk){for(dl=0;dl0){dm=parseInt(dm,10);dq(dm)}})}var bC={enabled:true,requests:[],timeout:null,interval:2500,sendRequests:function(){var di=this.requests;this.requests=[];if(di.length===1){bF(di[0],bJ)}else{de(di,bJ)}},push:function(di){if(!di){return}if(m||!this.enabled){bF(di,bJ);return}bC.requests.push(di);if(this.timeout){clearTimeout(this.timeout);this.timeout=null}this.timeout=setTimeout(function(){bC.timeout=null;bC.sendRequests()},bC.interval);var dj="RequestQueue"+aw;if(!Object.prototype.hasOwnProperty.call(b,dj)){b[dj]={unload:function(){if(bC.timeout){clearTimeout(bC.timeout)}bC.sendRequests()}}}}};bi();aM();this.hasConsent=function(){return bB};this.getVisitorId=function(){return aY().uuid};this.getVisitorInfo=function(){return cN()};this.getAttributionInfo=function(){return bM()};this.getAttributionCampaignName=function(){return bM()[0]};this.getAttributionCampaignKeyword=function(){return bM()[1]};this.getAttributionReferrerTimestamp=function(){return bM()[2]};this.getAttributionReferrerUrl=function(){return bM()[3] +};this.setTrackerUrl=function(di){aE=di};this.getTrackerUrl=function(){return aE};this.getPiwikUrl=function(){return O(this.getTrackerUrl(),bH)};this.addTracker=function(di,dk){if(!J(di)||null===di){di=this.getTrackerUrl()}var dj=new Q(di,dk);I.push(dj);e.trigger("TrackerAdded",[this]);return dj};this.getSiteId=function(){return b6};this.setSiteId=function(di){b3(di)};this.resetUserId=function(){by=""};this.setUserId=function(di){if(Y(di)){by=di}};this.getUserId=function(){return by};this.setCustomData=function(di,dj){if(W(di)){ao=di}else{if(!ao){ao={}}ao[di]=dj}};this.getCustomData=function(){return ao};this.setCustomRequestProcessing=function(di){cb=di};this.appendToTrackingUrl=function(di){cY=di};this.getRequest=function(di){return cs(di)};this.addPlugin=function(di,dj){b[di]=dj};this.setCustomDimension=function(di,dj){di=parseInt(di,10);if(di>0){if(!J(dj)){dj=""}if(!w(dj)){dj=String(dj)}bm[di]=dj}};this.getCustomDimension=function(di){di=parseInt(di,10);if(di>0&&Object.prototype.hasOwnProperty.call(bm,di)){return bm[di] +}};this.deleteCustomDimension=function(di){di=parseInt(di,10);if(di>0){delete bm[di]}};this.setCustomVariable=function(dj,di,dm,dk){var dl;if(!J(dk)){dk="visit"}if(!J(di)){return}if(!J(dm)){dm=""}if(dj>0){di=!w(di)?String(di):di;dm=!w(dm)?String(dm):dm;dl=[di.slice(0,bt),dm.slice(0,bt)];if(dk==="visit"||dk===2){cE();aQ[dj]=dl}else{if(dk==="page"||dk===3){bW[dj]=dl}else{if(dk==="event"){cm[dj]=dl}}}}};this.getCustomVariable=function(dj,dk){var di;if(!J(dk)){dk="visit"}if(dk==="page"||dk===3){di=bW[dj]}else{if(dk==="event"){di=cm[dj]}else{if(dk==="visit"||dk===2){cE();di=aQ[dj]}}}if(!J(di)||(di&&di[0]==="")){return false}return di};this.deleteCustomVariable=function(di,dj){if(this.getCustomVariable(di,dj)){this.setCustomVariable(di,"","",dj)}};this.deleteCustomVariables=function(di){if(di==="page"||di===3){bW={}}else{if(di==="event"){cm={}}else{if(di==="visit"||di===2){aQ={}}}}};this.storeCustomVariablesInCookie=function(){bQ=true};this.setLinkTrackingTimer=function(di){bJ=di};this.getLinkTrackingTimer=function(){return bJ +};this.setDownloadExtensions=function(di){if(w(di)){di=di.split("|")}c5=di};this.addDownloadExtensions=function(dj){var di;if(w(dj)){dj=dj.split("|")}for(di=0;di1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers') +}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setCookieNamePrefix","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);an(T,"message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0;ar