From 084adc6b03453d753d54825da060cdafa71c8b77 Mon Sep 17 00:00:00 2001 From: Adriaan van Rossum <1079135+adriaanvanrossum@users.noreply.github.com> Date: Thu, 25 Jun 2026 11:59:38 +0200 Subject: [PATCH 1/6] Navigate target=_self links in auto events Links with target="_self" stopped navigating when auto events was active. collectLink adds "return false" to the onclick for links with no target or target="_self", which cancels the browser navigation, but the saAutomatedLink callback only navigated when the link had no target at all. So target="_self" links sent the event and then never navigated. The callback now uses the same target check as collectLink, so target="_self" navigates in the same tab after the event, while target="_blank" and other targets keep their native behaviour. Fix for YourHosting, button "Ik wil zelf alles regelen" on https://www.yourhosting.nl/webhosting-2/ --- src/auto-events.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/auto-events.js b/src/auto-events.js index 0df03611..0a982f75 100644 --- a/src/auto-events.js +++ b/src/auto-events.js @@ -79,7 +79,11 @@ var sent = false; var callback = function () { - if (!sent && !element.hasAttribute("target")) + if ( + !sent && + (!element.hasAttribute("target") || + element.getAttribute("target") === "_self") + ) document.location = element.getAttribute("href"); sent = true; }; From d8aec338520e8d38759ed8bdc170b85f3bcc1bd1 Mon Sep 17 00:00:00 2001 From: Adriaan van Rossum <1079135+adriaanvanrossum@users.noreply.github.com> Date: Thu, 25 Jun 2026 11:59:52 +0200 Subject: [PATCH 2/6] Run npm run build --- dist/latest/auto-events.js | 4 ++-- dist/latest/auto-events.js.map | 2 +- dist/latest/cloudflare.js | 2 +- dist/latest/custom/app.js | 2 +- dist/latest/custom/auto-events.js | 4 ++-- dist/latest/custom/auto-events.js.map | 2 +- dist/latest/custom/e.js | 2 +- dist/latest/custom/latest.dev.js | 2 +- dist/latest/custom/latest.js | 2 +- dist/latest/custom/light.js | 2 +- dist/latest/custom/proxy.js | 2 +- dist/latest/hello.js | 2 +- dist/latest/latest.dev.js | 2 +- dist/latest/latest.js | 2 +- dist/latest/light.js | 2 +- dist/v11/app.js | 2 +- dist/v11/auto-events.js | 4 ++-- dist/v11/auto-events.js.map | 2 +- dist/v11/custom/app.js | 2 +- dist/v11/custom/auto-events.js | 4 ++-- dist/v11/custom/auto-events.js.map | 2 +- dist/v11/custom/light.js | 2 +- dist/v11/custom/proxy.js | 2 +- dist/v11/light.js | 2 +- 24 files changed, 28 insertions(+), 28 deletions(-) diff --git a/dist/latest/auto-events.js b/dist/latest/auto-events.js index df23dcae..330893a0 100644 --- a/dist/latest/auto-events.js +++ b/dist/latest/auto-events.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 19c1; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 0a7d; v11) */ -function r(t,e){var a,o=!1;h.downloads&&/^https?:\/\//i.test(t.href)&&new RegExp("\\.("+(h.downloadsExtensions||[]).join("|")+")$","i").test(t.pathname)?o="download":h.outbound&&/^https?:\/\//i.test(t.href)&&t.hostname!==m.location.hostname?o="outbound":h.emails&&/^mailto:/i.test(t.href)&&(o="email"),o&&(e?(a="saAutomatedLink(this, '"+o+"');",t.hasAttribute("target")&&"_self"!==t.getAttribute("target")||(a+=" return false;"),t.setAttribute("onclick",a)):t.addEventListener("click",function(t){saAutomatedLink(t.target,o)}))}function e(){try{for(var t=document.getElementsByTagName("a"),e=0;e -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (!sent && !element.hasAttribute(\"target\"))\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"auto-events.source.js","sources":["auto-events.source.js"],"sourcesContent":["(function saAutomatedEvents(window) {\n // Skip server side rendered pages\n if (typeof window === \"undefined\") return;\n\n var log = function (message, type) {\n var logger = type === \"warn\" ? console.warn : console.info;\n return logger && logger(\"Simple Analytics auto events:\", message);\n };\n\n var doc = window.document;\n\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"auto-events.js\"]');\n\n var setting = function (attribute, type, defaultValue) {\n var value = scriptElement && scriptElement.dataset[attribute];\n\n // Booleans\n if (type === \"bool\" && (value === \"true\" || value === \"false\"))\n return value === \"true\";\n else if (type === \"bool\") return defaultValue;\n\n // Arrays\n if (type === \"array\" && value)\n return value\n .split(\",\")\n .map(function (item) {\n return item.trim();\n })\n .filter(Boolean);\n else if (type === \"array\") return defaultValue;\n\n return value || defaultValue;\n };\n\n var collectTypes = setting(\"collect\", \"array\", [\n \"outbound\",\n \"emails\",\n \"downloads\",\n ]);\n var fullUrls = setting(\"fullUrls\", \"bool\", false);\n\n var options = {\n // What to collect\n outbound: collectTypes.indexOf(\"outbound\") > -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (\n !sent &&\n (!element.hasAttribute(\"target\") ||\n element.getAttribute(\"target\") === \"_self\")\n )\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/cloudflare.js b/dist/latest/cloudflare.js index 9142e785..451e5a6c 100644 --- a/dist/latest/cloudflare.js +++ b/dist/latest/cloudflare.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 0dec; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 0dec; v11) */ /* eslint-env browser */ (function ( diff --git a/dist/latest/custom/app.js b/dist/latest/custom/app.js index a3febd38..cc71c925 100644 --- a/dist/latest/custom/app.js +++ b/dist/latest/custom/app.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 527b; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 527b; v11) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",E=d,O=encodeURIComponent,x=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://"+e,A=y.documentElement||{},q="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,H="offset"+$,R="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Ot.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Ot.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(qt,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return O(t)+"="+O(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"custom_app_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1"); //# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/dist/latest/custom/auto-events.js b/dist/latest/custom/auto-events.js index df23dcae..330893a0 100644 --- a/dist/latest/custom/auto-events.js +++ b/dist/latest/custom/auto-events.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 19c1; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 0a7d; v11) */ -function r(t,e){var a,o=!1;h.downloads&&/^https?:\/\//i.test(t.href)&&new RegExp("\\.("+(h.downloadsExtensions||[]).join("|")+")$","i").test(t.pathname)?o="download":h.outbound&&/^https?:\/\//i.test(t.href)&&t.hostname!==m.location.hostname?o="outbound":h.emails&&/^mailto:/i.test(t.href)&&(o="email"),o&&(e?(a="saAutomatedLink(this, '"+o+"');",t.hasAttribute("target")&&"_self"!==t.getAttribute("target")||(a+=" return false;"),t.setAttribute("onclick",a)):t.addEventListener("click",function(t){saAutomatedLink(t.target,o)}))}function e(){try{for(var t=document.getElementsByTagName("a"),e=0;e -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (!sent && !element.hasAttribute(\"target\"))\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"auto-events.source.js","sources":["auto-events.source.js"],"sourcesContent":["(function saAutomatedEvents(window) {\n // Skip server side rendered pages\n if (typeof window === \"undefined\") return;\n\n var log = function (message, type) {\n var logger = type === \"warn\" ? console.warn : console.info;\n return logger && logger(\"Simple Analytics auto events:\", message);\n };\n\n var doc = window.document;\n\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"auto-events.js\"]');\n\n var setting = function (attribute, type, defaultValue) {\n var value = scriptElement && scriptElement.dataset[attribute];\n\n // Booleans\n if (type === \"bool\" && (value === \"true\" || value === \"false\"))\n return value === \"true\";\n else if (type === \"bool\") return defaultValue;\n\n // Arrays\n if (type === \"array\" && value)\n return value\n .split(\",\")\n .map(function (item) {\n return item.trim();\n })\n .filter(Boolean);\n else if (type === \"array\") return defaultValue;\n\n return value || defaultValue;\n };\n\n var collectTypes = setting(\"collect\", \"array\", [\n \"outbound\",\n \"emails\",\n \"downloads\",\n ]);\n var fullUrls = setting(\"fullUrls\", \"bool\", false);\n\n var options = {\n // What to collect\n outbound: collectTypes.indexOf(\"outbound\") > -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (\n !sent &&\n (!element.hasAttribute(\"target\") ||\n element.getAttribute(\"target\") === \"_self\")\n )\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/custom/e.js b/dist/latest/custom/e.js index 2313f007..a4bcc19a 100644 --- a/dist/latest/custom/e.js +++ b/dist/latest/custom/e.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; e5db; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; e5db; v11) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",E=d,O=encodeURIComponent,x=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://"+e,A=y.documentElement||{},q="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,H="offset"+$,R="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Ot.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Ot.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(qt,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return O(t)+"="+O(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"custom_events_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1"); //# sourceMappingURL=e.js.map \ No newline at end of file diff --git a/dist/latest/custom/latest.dev.js b/dist/latest/custom/latest.dev.js index 51d316c7..0d2c58ac 100644 --- a/dist/latest/custom/latest.dev.js +++ b/dist/latest/custom/latest.dev.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 761d; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 761d; v11) */ /* eslint-env browser */ (function ( diff --git a/dist/latest/custom/latest.js b/dist/latest/custom/latest.js index 003984e2..4f198d78 100644 --- a/dist/latest/custom/latest.js +++ b/dist/latest/custom/latest.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; b8c6; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; b8c6; v11) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",E=d,O=encodeURIComponent,x=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://"+e,A=y.documentElement||{},q="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,H="offset"+$,R="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Ot.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Ot.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(qt,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return O(t)+"="+O(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"custom_latest_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1"); //# sourceMappingURL=latest.js.map \ No newline at end of file diff --git a/dist/latest/custom/light.js b/dist/latest/custom/light.js index 20bf335c..6079617a 100644 --- a/dist/latest/custom/light.js +++ b/dist/latest/custom/light.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; a797; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; a797; v11) */ !function(s,e,t,u){try{var i=undefined,n="https:",r=s.console,a="doNotTrack",p=s.navigator,c=s.location,d=c.host,o=s.document,l=p.userAgent,m="Not sending request ",f=!1,g=encodeURIComponent,h=decodeURIComponent,v=JSON.stringify,y=s.addEventListener,_="https://"+t,w=(o.documentElement,"language"),b=p.userAgentData,O="platform",S="platformVersion",k="https://docs.simpleanalytics.com",j=/(bot|spider|crawl)/i.test(l)&&!/(cubot)/i.test(l),E=o.currentScript||o.querySelector('script[src*="'+t+'"]');u=function(){var e=[].slice.call(arguments);return e.unshift("Simple Analytics:"),Function.prototype.apply.call(r.warn,r,e)};var x=function(e,t){return e&&e.getAttribute("data-"+t)},A=function(){for(var e,t,n,r={},a=arguments,o=0;o>e/4).toString(16)})}catch(r){return e.replace(n,function(e){var t=16*Math.random()|0;return(e<2?t:3&t|8).toString(16)})}},I="namespace",N=e[I]||x(E,I)||"sa",R=e.strictUtm||"true"==x(E,"strict-utm"),U=N+"_loaded";if(1==s[U])return u(m+"twice");s.sa_event_loaded=!0,s[U]=!0;var V,B=function(t,e,n){t=n?t:A(F,J,t),p.brave&&!n&&(t.brave=!0),p._duckduckgoloader_&&!n&&(t.duck=!0),(new Image).src=_+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=i}).map(function(e){return g(e)+"="+g(t[e])}).join("&")+"&time="+Date.now()},C=e.hostname||x(E,"hostname"),H=C||d,T={version:"custom_light_11",hostname:H};e.mode||x(E,"mode");try{V=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(Q){u(Q)}j&&(T.bot=!0);var F=A(T,{ua:l,https:c.protocol==n,timezone:V,page_id:D(),session_id:D()});if(F.sri=!1,b&&(F.mobile=b.mobile,F.brands=v(b.brands)),H!==d&&(F.hostname_original=d),a in p&&"1"==p[a])return u("Not sending request when "+a+" is enabled. See "+k+"/dnt");-1!=d.indexOf(".")&&!/^[0-9.:]+$/.test(d)||C||u("Set hostname on "+d+". See "+k+"/overwrite-domain-name");var z,J={},L=(o.referrer||"").replace(d,H).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||i,M=function(e,t){var n=A(T,{type:"append",original_id:t?e:F.page_id});t||!p.sendBeacon?B(n,0,!0):p.sendBeacon(_+"/append",v(n))};y("pagehide",M,!1);var P,Z,G=function(e){var t="";try{t=e||h(c.pathname)}catch(Q){u(Q)}return t},K=function(e,t,n,r){e&&M(""+F.page_id,!0),F.page_id=D();var a,o=H+G();B({id:F.page_id,type:"pageview",referrer:!t||n?L:null,query:(a=t,c.search.slice(1).split("&").filter(function(e){return!a&&new RegExp("^((utm_)"+(R?"":"?")+"(source|medium|content|term|campaign)"+(R?"":"|ref")+")=").test(e)}).join("&")||i)}),L=o,0};!function(e,t){var n=G(t);if(n&&z!=n){z=n,J.path=n,p[w]&&(J[w]=p[w]);var r,a=s.performance,o="navigation";try{r=a.getEntriesByType(o)[0].type}catch(Q){u(Q)}Z=r?-1<["reload","back_forward"].indexOf(r):a&&a[o]&&-1<[1,2].indexOf(a[o].type),P=!!L&&L.split("/")[0]==d;var i=function(){f=!0,K(e,e||Z||!1,P)};if(f)i();else try{b&&"function"==typeof b.getHighEntropyValues?b.getHighEntropyValues([O,S]).then(function(e){F.os_name=e[O],F.os_version=e[S],i()})["catch"](i):i()}catch(c){i()}}}()}catch(W){u(W)}}(window,{},""); //# sourceMappingURL=light.js.map \ No newline at end of file diff --git a/dist/latest/custom/proxy.js b/dist/latest/custom/proxy.js index 3c4bf08d..9276e38a 100644 --- a/dist/latest/custom/proxy.js +++ b/dist/latest/custom/proxy.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 9b4d; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 9b4d; v11) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",x=d,E=encodeURIComponent,O=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://"+e,A=y.documentElement||{},q="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,H="offset"+$,P="client"+$,R="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Et.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Et.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(qt,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return E(t)+"="+E(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"custom_proxy_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1"); //# sourceMappingURL=proxy.js.map \ No newline at end of file diff --git a/dist/latest/hello.js b/dist/latest/hello.js index 289727ae..88a042bd 100644 --- a/dist/latest/hello.js +++ b/dist/latest/hello.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; f60b) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; f60b) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",E=d,O=encodeURIComponent,x=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://queue."+e,q=y.documentElement||{},A="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,R="offset"+$,H="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Ot.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Ot.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(At,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return O(t)+"="+O(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"cdn_hello_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Ot.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Ot.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(At,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return O(t)+"="+O(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"cdn_latest_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1>e/4).toString(16)})}catch(r){return e.replace(n,function(e){var t=16*Math.random()|0;return(e<2?t:3&t|8).toString(16)})}},I="namespace",N=e[I]||q(E,I)||"sa",R=e.strictUtm||"true"==q(E,"strict-utm"),U=N+"_loaded";if(1==s[U])return u(m+"twice");s.sa_event_loaded=!0,s[U]=!0;var V,B=function(t,e,n){t=n?t:A(H,J,t),p.brave&&!n&&(t.brave=!0),p._duckduckgoloader_&&!n&&(t.duck=!0),(new Image).src=_+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=i}).map(function(e){return g(e)+"="+g(t[e])}).join("&")+"&time="+Date.now()},C=e.hostname||q(E,"hostname"),T=C||d,F={version:"cdn_light_11",hostname:T};e.mode||q(E,"mode");try{V=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(Q){u(Q)}j&&(F.bot=!0);var H=A(F,{ua:l,https:c.protocol==n,timezone:V,page_id:D(),session_id:D()});if(H.sri=!1,b&&(H.mobile=b.mobile,H.brands=v(b.brands)),T!==d&&(H.hostname_original=d),a in p&&"1"==p[a])return u("Not sending request when "+a+" is enabled. See "+k+"/dnt");-1!=d.indexOf(".")&&!/^[0-9.:]+$/.test(d)||C||u("Set hostname on "+d+". See "+k+"/overwrite-domain-name");var z,J={},L=(o.referrer||"").replace(d,T).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||i,M=function(e,t){var n=A(F,{type:"append",original_id:t?e:H.page_id});t||!p.sendBeacon?B(n,0,!0):p.sendBeacon(_+"/append",v(n))};y("pagehide",M,!1);var P,Z,G=function(e){var t="";try{t=e||h(c.pathname)}catch(Q){u(Q)}return t},K=function(e,t,n,r){e&&M(""+H.page_id,!0),H.page_id=D();var a,o=T+G();B({id:H.page_id,type:"pageview",referrer:!t||n?L:null,query:(a=t,c.search.slice(1).split("&").filter(function(e){return!a&&new RegExp("^((utm_)"+(R?"":"?")+"(source|medium|content|term|campaign)"+(R?"":"|ref")+")=").test(e)}).join("&")||i)}),L=o,0};!function(e,t){var n=G(t);if(n&&z!=n){z=n,J.path=n,p[w]&&(J[w]=p[w]);var r,a=s.performance,o="navigation";try{r=a.getEntriesByType(o)[0].type}catch(Q){u(Q)}Z=r?-1<["reload","back_forward"].indexOf(r):a&&a[o]&&-1<[1,2].indexOf(a[o].type),P=!!L&&L.split("/")[0]==d;var i=function(){f=!0,K(e,e||Z||!1,P)};if(f)i();else try{b&&"function"==typeof b.getHighEntropyValues?b.getHighEntropyValues([O,S]).then(function(e){H.os_name=e[O],H.os_version=e[S],i()})["catch"](i):i()}catch(c){i()}}}()}catch(W){u(W)}}(window,{},"simpleanalyticscdn.com"); //# sourceMappingURL=light.js.map \ No newline at end of file diff --git a/dist/v11/app.js b/dist/v11/app.js index ebeba2c5..2b4e9b17 100644 --- a/dist/v11/app.js +++ b/dist/v11/app.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 10ee; SRI-version; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 10ee; SRI-version; v11) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",E=d,O=encodeURIComponent,x=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://queue."+e,q=y.documentElement||{},A="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,R="offset"+$,H="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Ot.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Ot.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(At,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return O(t)+"="+O(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"cdn_latest_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1 -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (!sent && !element.hasAttribute(\"target\"))\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"auto-events.source.js","sources":["auto-events.source.js"],"sourcesContent":["(function saAutomatedEvents(window) {\n // Skip server side rendered pages\n if (typeof window === \"undefined\") return;\n\n var log = function (message, type) {\n var logger = type === \"warn\" ? console.warn : console.info;\n return logger && logger(\"Simple Analytics auto events:\", message);\n };\n\n var doc = window.document;\n\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"auto-events.js\"]');\n\n var setting = function (attribute, type, defaultValue) {\n var value = scriptElement && scriptElement.dataset[attribute];\n\n // Booleans\n if (type === \"bool\" && (value === \"true\" || value === \"false\"))\n return value === \"true\";\n else if (type === \"bool\") return defaultValue;\n\n // Arrays\n if (type === \"array\" && value)\n return value\n .split(\",\")\n .map(function (item) {\n return item.trim();\n })\n .filter(Boolean);\n else if (type === \"array\") return defaultValue;\n\n return value || defaultValue;\n };\n\n var collectTypes = setting(\"collect\", \"array\", [\n \"outbound\",\n \"emails\",\n \"downloads\",\n ]);\n var fullUrls = setting(\"fullUrls\", \"bool\", false);\n\n var options = {\n // What to collect\n outbound: collectTypes.indexOf(\"outbound\") > -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (\n !sent &&\n (!element.hasAttribute(\"target\") ||\n element.getAttribute(\"target\") === \"_self\")\n )\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v11/custom/app.js b/dist/v11/custom/app.js index cd85c13f..ba7643db 100644 --- a/dist/v11/custom/app.js +++ b/dist/v11/custom/app.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 120c; SRI-version; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 120c; SRI-version; v11) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",E=d,O=encodeURIComponent,x=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://"+e,A=y.documentElement||{},q="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,H="offset"+$,R="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Ot.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Ot.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(qt,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return O(t)+"="+O(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"custom_app_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1"); //# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/dist/v11/custom/auto-events.js b/dist/v11/custom/auto-events.js index 3f5ff6ee..4fea4a15 100644 --- a/dist/v11/custom/auto-events.js +++ b/dist/v11/custom/auto-events.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 19c1; SRI-version; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 0a7d; SRI-version; v11) */ -function r(t,e){var a,o=!1;h.downloads&&/^https?:\/\//i.test(t.href)&&new RegExp("\\.("+(h.downloadsExtensions||[]).join("|")+")$","i").test(t.pathname)?o="download":h.outbound&&/^https?:\/\//i.test(t.href)&&t.hostname!==m.location.hostname?o="outbound":h.emails&&/^mailto:/i.test(t.href)&&(o="email"),o&&(e?(a="saAutomatedLink(this, '"+o+"');",t.hasAttribute("target")&&"_self"!==t.getAttribute("target")||(a+=" return false;"),t.setAttribute("onclick",a)):t.addEventListener("click",function(t){saAutomatedLink(t.target,o)}))}function e(){try{for(var t=document.getElementsByTagName("a"),e=0;e -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (!sent && !element.hasAttribute(\"target\"))\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":";;AAoJE,SAASA,EAAYC,EAAMC,GACzB,IA6BMC,EA7BFC,GAAU,EAIZC,EAAYC,WACZ,gBAAgBC,KAAKN,EAAKO,OAC1B,IAAIC,OACF,QAAUJ,EAAYK,qBAAuB,IAAIC,KAAK,KAAO,KAC7D,KACAJ,KAAKN,EAAKW,UAEZR,EAAU,WAIVC,EAAYQ,UACZ,gBAAgBN,KAAKN,EAAKO,OAC1BP,EAAKa,WAAaC,EAAOC,SAASF,SAElCV,EAAU,WAGDC,EAAYY,QAAU,YAAYV,KAAKN,EAAKO,QACrDJ,EAAU,SAGPA,IAEDF,GACEC,EAAmB,0BAA4BC,EAAU,MAG1DH,EAAKiB,aAAa,WACa,UAAhCjB,EAAKkB,aAAa,YAElBhB,GAAoB,kBAEtBF,EAAKmB,aAAa,UAAWjB,IAE7BF,EAAKoB,iBAAiB,QAAS,SAAUC,GACvCC,gBAAgBD,EAAQE,OAAQpB,MAKtC,SAASqB,IACP,IAIE,IAHA,IAAIC,EAAIC,SAASC,qBAAqB,KAG7BC,EAAI,EAAGA,EAAIH,EAAEI,OAAQD,IAAK,CACjC,IAAI5B,EAAOyB,EAAEG,GACTrB,EAAOP,EAAKkB,aAAa,QAGxBX,IAGAP,EAAKkB,aAAa,YAAe,WAAWZ,KAAKC,GAGpDR,EAAYC,GAAM,GAFlBD,EAAYC,GAAM,KAKtB,MAAO8B,GACPC,EAAID,EAAME,QAAS,SAtNzB,IAA4BlB,EAItBiB,EAKAE,EAEAC,EAGAC,EAqBAC,EAKAC,EAEAC,EAyBAC,EAGAnC,OApEkB,KAFIU,EAiOzBA,UA7NGiB,EAAM,SAAUC,EAASQ,GAC3B,IAAIC,EAAkB,SAATD,EAAkBE,QAAQC,KAAOD,QAAQE,KACtD,OAAOH,GAAUA,EAAO,gCAAiCT,IAGvDC,EAAMnB,EAAOY,SAEbQ,EACFD,EAAIY,eAAiBZ,EAAIa,cAAc,iCAuBrCV,GArBAD,EAAU,SAAUY,EAAWP,EAAMQ,GACvC,IAAIC,EAAQf,GAAiBA,EAAcgB,QAAQH,GAGnD,MAAa,SAATP,GAA8B,SAAVS,GAA8B,UAAVA,EAE1B,SAATT,EAAwBQ,EAGpB,UAATR,GAAoBS,EACfA,EACJE,MAAM,KACNC,IAAI,SAAUC,GACb,OAAOA,EAAKC,SAEbC,OAAOC,SACM,UAAThB,GAEFS,GAF2BD,EAXf,SAAVC,IAgBgB,UAAW,QAAS,CAC7C,WACA,SACA,cAEEZ,EAAWF,EAAQ,WAAY,QAAQ,GAEvCG,EAAU,CAEZ1B,UAA8C,EAApCwB,EAAaqB,QAAQ,YAC/BzC,QAA0C,EAAlCoB,EAAaqB,QAAQ,UAC7BpD,WAAgD,EAArC+B,EAAaqB,QAAQ,aAEhChD,oBAAqB0B,EAAQ,aAAc,QAAS,CAClD,MACA,MACA,OACA,OACA,MACA,MACA,QAKFuB,MAAOvB,EAAQ,WAAY,QAAQ,GAEnCwB,gBAAiBtB,EAEjBuB,iBAAkBvB,GAGhBE,EAAWJ,EAAQ,WAAY,SAAU,iBAKlB,KAFvB/B,EAAckC,IAGhBP,EAAI,2CAA4C,QAElDjB,EAAOQ,gBAAkB,SAAyBD,EAASmB,GACzD,IACE,IAAKnB,EAAS,OAAOU,EAAI,oBACzB,IAAI8B,GAAO,EAEPC,EAAW,WACRD,GAASxC,EAAQJ,aAAa,YACjCS,SAASX,SAAWM,EAAQH,aAAa,SAC3C2C,GAAO,GAGT,GAAI/C,EAAOyB,IAAazB,EAAOyB,EAAW,WAAY,CACpD,IAWMwB,EAXFlD,EAAWQ,EAAQR,SACnBF,EAAWU,EAAQV,SAGnBqD,EAAW,CACbN,MAAOrC,EAAQH,aAAa,UAAY+C,WAEtCC,EAAM7C,EAAQd,MAAQ0D,UAEtBE,GAAW,EAMf,GALI/D,EAAYsD,OAASrC,EAAQJ,aAAa,WAE5B,KADZ8C,EAAW1C,EAAQH,aAAa,SAASoC,UACzBa,GAAW,IAG7BA,EACFC,EAAQL,OAER,OAAQvB,GACN,IAAK,WACH4B,EAAQvD,GAAYT,EAAYuD,gBAAkBhD,EAAW,IAC7DqD,EAASE,IAAMA,EACf,MAEF,IAAK,WACHE,EAAQhE,EAAYwD,iBAChB/C,EAAWF,EACXA,EAASwC,MAAM,KAAKkB,MACxBL,EAASE,IAAMA,EACf,MAEF,IAAK,QACH,IACAE,GADW/C,EAAQH,aAAa,QAClBiC,MAAM,KAAK,IAAM,IAAIA,MAAM,KAAK,GAC9Ca,EAASM,MAAQF,EAMvB,IAAIG,EACF/B,EACA,IACA4B,EAAMI,QAAQ,eAAgB,KAAKA,QAAQ,aAAc,IAM3D,OAJA1D,EAAOyB,GAAUgC,EAAOP,EAAUF,GAElC/B,EAAI,aAAewC,GAEH,UAAT/B,EACHsB,IACAhD,EAAO2D,WAAWX,EAAU,KAGhC,OADA/B,EAAIQ,EAAW,kBAAmB,QAC3BuB,IAET,MAAOhC,GACPC,EAAID,EAAME,QAAS,UA0EA,UAAnBC,EAAIyC,YAA6C,aAAnBzC,EAAIyC,WACpClD,IAEAE,SAASN,iBAAiB,mBAAoB,SAAUgD,GACtB,aAA5BA,EAAM7C,OAAOmD,YAA2BlD"} \ No newline at end of file +{"version":3,"file":"auto-events.source.js","sources":["auto-events.source.js"],"sourcesContent":["(function saAutomatedEvents(window) {\n // Skip server side rendered pages\n if (typeof window === \"undefined\") return;\n\n var log = function (message, type) {\n var logger = type === \"warn\" ? console.warn : console.info;\n return logger && logger(\"Simple Analytics auto events:\", message);\n };\n\n var doc = window.document;\n\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"auto-events.js\"]');\n\n var setting = function (attribute, type, defaultValue) {\n var value = scriptElement && scriptElement.dataset[attribute];\n\n // Booleans\n if (type === \"bool\" && (value === \"true\" || value === \"false\"))\n return value === \"true\";\n else if (type === \"bool\") return defaultValue;\n\n // Arrays\n if (type === \"array\" && value)\n return value\n .split(\",\")\n .map(function (item) {\n return item.trim();\n })\n .filter(Boolean);\n else if (type === \"array\") return defaultValue;\n\n return value || defaultValue;\n };\n\n var collectTypes = setting(\"collect\", \"array\", [\n \"outbound\",\n \"emails\",\n \"downloads\",\n ]);\n var fullUrls = setting(\"fullUrls\", \"bool\", false);\n\n var options = {\n // What to collect\n outbound: collectTypes.indexOf(\"outbound\") > -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n // Downloads: enter file extensions you want to collect\n downloadsExtensions: setting(\"extensions\", \"array\", [\n \"pdf\",\n \"csv\",\n \"docx\",\n \"xlsx\",\n \"zip\",\n \"doc\",\n \"xls\",\n ]),\n\n // All: use title attribute if set for event name (for all events)\n // THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW\n title: setting(\"useTitle\", \"bool\", true),\n // Outbound: use full URL of the links? false for just the hostname\n outboundFullUrl: fullUrls,\n // Downloads: if taking event name from URL, use full URL or just filename (default)\n downloadsFullUrl: fullUrls,\n };\n\n var saGlobal = setting(\"saGlobal\", \"string\", \"sa_event\");\n\n // For compiling the script\n var optionsLink = options;\n\n if (typeof optionsLink === \"undefined\")\n log(\"options object not found, please specify\", \"warn\");\n\n window.saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\n var sent = false;\n\n var callback = function () {\n if (\n !sent &&\n (!element.hasAttribute(\"target\") ||\n element.getAttribute(\"target\") === \"_self\")\n )\n document.location = element.getAttribute(\"href\");\n sent = true;\n };\n\n if (window[saGlobal] && window[saGlobal + \"_loaded\"]) {\n var hostname = element.hostname;\n var pathname = element.pathname;\n\n var event;\n var metadata = {\n title: element.getAttribute(\"title\") || undefined,\n };\n var url = element.href || undefined;\n\n var useTitle = false;\n if (optionsLink.title && element.hasAttribute(\"title\")) {\n var theTitle = element.getAttribute(\"title\").trim();\n if (theTitle != \"\") useTitle = true;\n }\n\n if (useTitle) {\n event = theTitle;\n } else {\n switch (type) {\n case \"outbound\": {\n event = hostname + (optionsLink.outboundFullUrl ? pathname : \"\");\n metadata.url = url;\n break;\n }\n case \"download\": {\n event = optionsLink.downloadsFullUrl\n ? hostname + pathname\n : pathname.split(\"/\").pop();\n metadata.url = url;\n break;\n }\n case \"email\": {\n var href = element.getAttribute(\"href\");\n event = (href.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.email = event;\n break;\n }\n }\n }\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, callback);\n\n log(\"collected \" + clean);\n\n return type === \"email\"\n ? callback()\n : window.setTimeout(callback, 5000);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n return callback();\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n function collectLink(link, onclick) {\n var collect = false;\n\n // Collect download clicks\n if (\n optionsLink.downloads &&\n /^https?:\\/\\//i.test(link.href) &&\n new RegExp(\n \"\\\\.(\" + (optionsLink.downloadsExtensions || []).join(\"|\") + \")$\",\n \"i\"\n ).test(link.pathname)\n ) {\n collect = \"download\";\n\n // Collect outbound links clicks\n } else if (\n optionsLink.outbound &&\n /^https?:\\/\\//i.test(link.href) &&\n link.hostname !== window.location.hostname\n ) {\n collect = \"outbound\";\n\n // Collect email clicks\n } else if (optionsLink.emails && /^mailto:/i.test(link.href)) {\n collect = \"email\";\n }\n\n if (!collect) return;\n\n if (onclick) {\n var onClickAttribute = \"saAutomatedLink(this, '\" + collect + \"');\";\n\n if (\n !link.hasAttribute(\"target\") ||\n link.getAttribute(\"target\") === \"_self\"\n )\n onClickAttribute += \" return false;\";\n\n link.setAttribute(\"onclick\", onClickAttribute);\n } else {\n link.addEventListener(\"click\", function (element) {\n saAutomatedLink(element.target, collect);\n });\n }\n }\n\n function onDOMContentLoaded() {\n try {\n var a = document.getElementsByTagName(\"a\");\n\n // Loop over all links on the page\n for (var i = 0; i < a.length; i++) {\n var link = a[i];\n var href = link.getAttribute(\"href\");\n\n // Skip links that don't have an href\n if (!href) continue;\n\n // We don't want to overwrite website behaviour so we check for the onclick attribute\n if (!link.getAttribute(\"onclick\") && !/^mailto:/.test(href)) {\n collectLink(link, true);\n } else {\n collectLink(link, false);\n }\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n }\n\n if (doc.readyState === \"ready\" || doc.readyState === \"complete\") {\n onDOMContentLoaded();\n } else {\n document.addEventListener(\"readystatechange\", function (event) {\n if (event.target.readyState === \"complete\") onDOMContentLoaded();\n });\n }\n})(window);\n"],"names":["collectLink","link","onclick","onClickAttribute","collect","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","hasAttribute","getAttribute","setAttribute","addEventListener","element","saAutomatedLink","target","onDOMContentLoaded","a","document","getElementsByTagName","i","length","error","log","message","doc","scriptElement","setting","collectTypes","fullUrls","options","saGlobal","type","logger","console","warn","info","currentScript","querySelector","attribute","defaultValue","value","dataset","split","map","item","trim","filter","Boolean","indexOf","title","outboundFullUrl","downloadsFullUrl","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState"],"mappings":";;AAwJE,SAASA,EAAYC,EAAMC,GACzB,IA6BMC,EA7BFC,GAAU,EAIZC,EAAYC,WACZ,gBAAgBC,KAAKN,EAAKO,OAC1B,IAAIC,OACF,QAAUJ,EAAYK,qBAAuB,IAAIC,KAAK,KAAO,KAC7D,KACAJ,KAAKN,EAAKW,UAEZR,EAAU,WAIVC,EAAYQ,UACZ,gBAAgBN,KAAKN,EAAKO,OAC1BP,EAAKa,WAAaC,EAAOC,SAASF,SAElCV,EAAU,WAGDC,EAAYY,QAAU,YAAYV,KAAKN,EAAKO,QACrDJ,EAAU,SAGPA,IAEDF,GACEC,EAAmB,0BAA4BC,EAAU,MAG1DH,EAAKiB,aAAa,WACa,UAAhCjB,EAAKkB,aAAa,YAElBhB,GAAoB,kBAEtBF,EAAKmB,aAAa,UAAWjB,IAE7BF,EAAKoB,iBAAiB,QAAS,SAAUC,GACvCC,gBAAgBD,EAAQE,OAAQpB,MAKtC,SAASqB,IACP,IAIE,IAHA,IAAIC,EAAIC,SAASC,qBAAqB,KAG7BC,EAAI,EAAGA,EAAIH,EAAEI,OAAQD,IAAK,CACjC,IAAI5B,EAAOyB,EAAEG,GACTrB,EAAOP,EAAKkB,aAAa,QAGxBX,IAGAP,EAAKkB,aAAa,YAAe,WAAWZ,KAAKC,GAGpDR,EAAYC,GAAM,GAFlBD,EAAYC,GAAM,KAKtB,MAAO8B,GACPC,EAAID,EAAME,QAAS,SA1NzB,IAA4BlB,EAItBiB,EAKAE,EAEAC,EAGAC,EAqBAC,EAKAC,EAEAC,EAyBAC,EAGAnC,OApEkB,KAFIU,EAqOzBA,UAjOGiB,EAAM,SAAUC,EAASQ,GAC3B,IAAIC,EAAkB,SAATD,EAAkBE,QAAQC,KAAOD,QAAQE,KACtD,OAAOH,GAAUA,EAAO,gCAAiCT,IAGvDC,EAAMnB,EAAOY,SAEbQ,EACFD,EAAIY,eAAiBZ,EAAIa,cAAc,iCAuBrCV,GArBAD,EAAU,SAAUY,EAAWP,EAAMQ,GACvC,IAAIC,EAAQf,GAAiBA,EAAcgB,QAAQH,GAGnD,MAAa,SAATP,GAA8B,SAAVS,GAA8B,UAAVA,EAE1B,SAATT,EAAwBQ,EAGpB,UAATR,GAAoBS,EACfA,EACJE,MAAM,KACNC,IAAI,SAAUC,GACb,OAAOA,EAAKC,SAEbC,OAAOC,SACM,UAAThB,GAEFS,GAF2BD,EAXf,SAAVC,IAgBgB,UAAW,QAAS,CAC7C,WACA,SACA,cAEEZ,EAAWF,EAAQ,WAAY,QAAQ,GAEvCG,EAAU,CAEZ1B,UAA8C,EAApCwB,EAAaqB,QAAQ,YAC/BzC,QAA0C,EAAlCoB,EAAaqB,QAAQ,UAC7BpD,WAAgD,EAArC+B,EAAaqB,QAAQ,aAEhChD,oBAAqB0B,EAAQ,aAAc,QAAS,CAClD,MACA,MACA,OACA,OACA,MACA,MACA,QAKFuB,MAAOvB,EAAQ,WAAY,QAAQ,GAEnCwB,gBAAiBtB,EAEjBuB,iBAAkBvB,GAGhBE,EAAWJ,EAAQ,WAAY,SAAU,iBAKlB,KAFvB/B,EAAckC,IAGhBP,EAAI,2CAA4C,QAElDjB,EAAOQ,gBAAkB,SAAyBD,EAASmB,GACzD,IACE,IAAKnB,EAAS,OAAOU,EAAI,oBACzB,IAAI8B,GAAO,EAEPC,EAAW,WAEVD,GACCxC,EAAQJ,aAAa,WACc,UAAnCI,EAAQH,aAAa,YAEvBQ,SAASX,SAAWM,EAAQH,aAAa,SAC3C2C,GAAO,GAGT,GAAI/C,EAAOyB,IAAazB,EAAOyB,EAAW,WAAY,CACpD,IAWMwB,EAXFlD,EAAWQ,EAAQR,SACnBF,EAAWU,EAAQV,SAGnBqD,EAAW,CACbN,MAAOrC,EAAQH,aAAa,UAAY+C,WAEtCC,EAAM7C,EAAQd,MAAQ0D,UAEtBE,GAAW,EAMf,GALI/D,EAAYsD,OAASrC,EAAQJ,aAAa,WAE5B,KADZ8C,EAAW1C,EAAQH,aAAa,SAASoC,UACzBa,GAAW,IAG7BA,EACFC,EAAQL,OAER,OAAQvB,GACN,IAAK,WACH4B,EAAQvD,GAAYT,EAAYuD,gBAAkBhD,EAAW,IAC7DqD,EAASE,IAAMA,EACf,MAEF,IAAK,WACHE,EAAQhE,EAAYwD,iBAChB/C,EAAWF,EACXA,EAASwC,MAAM,KAAKkB,MACxBL,EAASE,IAAMA,EACf,MAEF,IAAK,QACH,IACAE,GADW/C,EAAQH,aAAa,QAClBiC,MAAM,KAAK,IAAM,IAAIA,MAAM,KAAK,GAC9Ca,EAASM,MAAQF,EAMvB,IAAIG,EACF/B,EACA,IACA4B,EAAMI,QAAQ,eAAgB,KAAKA,QAAQ,aAAc,IAM3D,OAJA1D,EAAOyB,GAAUgC,EAAOP,EAAUF,GAElC/B,EAAI,aAAewC,GAEH,UAAT/B,EACHsB,IACAhD,EAAO2D,WAAWX,EAAU,KAGhC,OADA/B,EAAIQ,EAAW,kBAAmB,QAC3BuB,IAET,MAAOhC,GACPC,EAAID,EAAME,QAAS,UA0EA,UAAnBC,EAAIyC,YAA6C,aAAnBzC,EAAIyC,WACpClD,IAEAE,SAASN,iBAAiB,mBAAoB,SAAUgD,GACtB,aAA5BA,EAAM7C,OAAOmD,YAA2BlD"} \ No newline at end of file diff --git a/dist/v11/custom/light.js b/dist/v11/custom/light.js index bc77d998..afc2ead4 100644 --- a/dist/v11/custom/light.js +++ b/dist/v11/custom/light.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; e624; SRI-version; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; e624; SRI-version; v11) */ !function(s,e,t,u){try{var i=undefined,n="https:",r=s.console,a="doNotTrack",p=s.navigator,c=s.location,d=c.host,o=s.document,l=p.userAgent,m="Not sending request ",f=!1,g=encodeURIComponent,h=decodeURIComponent,v=JSON.stringify,y=s.addEventListener,_="https://"+t,w=(o.documentElement,"language"),b=p.userAgentData,O="platform",S="platformVersion",k="https://docs.simpleanalytics.com",j=/(bot|spider|crawl)/i.test(l)&&!/(cubot)/i.test(l),E=o.currentScript||o.querySelector('script[src*="'+t+'"]');u=function(){var e=[].slice.call(arguments);return e.unshift("Simple Analytics:"),Function.prototype.apply.call(r.warn,r,e)};var x=function(e,t){return e&&e.getAttribute("data-"+t)},A=function(){for(var e,t,n,r={},a=arguments,o=0;o>e/4).toString(16)})}catch(r){return e.replace(n,function(e){var t=16*Math.random()|0;return(e<2?t:3&t|8).toString(16)})}},I="namespace",N=e[I]||x(E,I)||"sa",R=e.strictUtm||"true"==x(E,"strict-utm"),U=N+"_loaded";if(1==s[U])return u(m+"twice");s.sa_event_loaded=!0,s[U]=!0;var V,B=function(t,e,n){t=n?t:A(F,J,t),p.brave&&!n&&(t.brave=!0),p._duckduckgoloader_&&!n&&(t.duck=!0),(new Image).src=_+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=i}).map(function(e){return g(e)+"="+g(t[e])}).join("&")+"&time="+Date.now()},C=e.hostname||x(E,"hostname"),H=C||d,T={version:"custom_light_11",hostname:H};e.mode||x(E,"mode");try{V=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(Q){u(Q)}j&&(T.bot=!0);var F=A(T,{ua:l,https:c.protocol==n,timezone:V,page_id:D(),session_id:D()});if(F.sri=!0,b&&(F.mobile=b.mobile,F.brands=v(b.brands)),H!==d&&(F.hostname_original=d),a in p&&"1"==p[a])return u("Not sending request when "+a+" is enabled. See "+k+"/dnt");-1!=d.indexOf(".")&&!/^[0-9.:]+$/.test(d)||C||u("Set hostname on "+d+". See "+k+"/overwrite-domain-name");var z,J={},L=(o.referrer||"").replace(d,H).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||i,M=function(e,t){var n=A(T,{type:"append",original_id:t?e:F.page_id});t||!p.sendBeacon?B(n,0,!0):p.sendBeacon(_+"/append",v(n))};y("pagehide",M,!1);var P,Z,G=function(e){var t="";try{t=e||h(c.pathname)}catch(Q){u(Q)}return t},K=function(e,t,n,r){e&&M(""+F.page_id,!0),F.page_id=D();var a,o=H+G();B({id:F.page_id,type:"pageview",referrer:!t||n?L:null,query:(a=t,c.search.slice(1).split("&").filter(function(e){return!a&&new RegExp("^((utm_)"+(R?"":"?")+"(source|medium|content|term|campaign)"+(R?"":"|ref")+")=").test(e)}).join("&")||i)}),L=o,0};!function(e,t){var n=G(t);if(n&&z!=n){z=n,J.path=n,p[w]&&(J[w]=p[w]);var r,a=s.performance,o="navigation";try{r=a.getEntriesByType(o)[0].type}catch(Q){u(Q)}Z=r?-1<["reload","back_forward"].indexOf(r):a&&a[o]&&-1<[1,2].indexOf(a[o].type),P=!!L&&L.split("/")[0]==d;var i=function(){f=!0,K(e,e||Z||!1,P)};if(f)i();else try{b&&"function"==typeof b.getHighEntropyValues?b.getHighEntropyValues([O,S]).then(function(e){F.os_name=e[O],F.os_version=e[S],i()})["catch"](i):i()}catch(c){i()}}}()}catch(W){u(W)}}(window,{},""); //# sourceMappingURL=light.js.map \ No newline at end of file diff --git a/dist/v11/custom/proxy.js b/dist/v11/custom/proxy.js index 1fd4bf80..3cae1b7e 100644 --- a/dist/v11/custom/proxy.js +++ b/dist/v11/custom/proxy.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; 0989; SRI-version; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; 0989; SRI-version; v11) */ !function(l,t,e,n,p){try{var h=undefined,f=!0,d=!1,r="true",a="https:",m="pageview",u="event",i="error",o=l.console,c="doNotTrack",g=l.navigator,s=l.location,v=s.host,y=l.document,_=g.userAgent,w="Not sending request ",b=w+"when ",x=d,E=encodeURIComponent,O=decodeURIComponent,S=JSON.stringify,M=l.addEventListener,k="https://"+e,A=y.documentElement||{},q="language",$="Height",j="scroll",D=g.userAgentData,C=j+$,H="offset"+$,P="client"+$,R="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(_)&&!/(cubot)/i.test(_),N=l.screen,z=y.currentScript||y.querySelector('script[src*="'+e+'"]');p=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(o.warn,o,t)};var F=function(t,e){p("Error in your "+t+" function:",e)},W=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},G=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},J=function(t,e){return t&&t.getAttribute("data-"+e)},L=function(t){return Array.isArray(t)?t:"string"==typeof t&&t.length?t.split(/, ?/):[]},Y=function(t){return t&&t.constructor===Object},Z=function(){for(var t={},e=arguments,n=0;n>t/4).toString(16)})}catch(r){return t.replace(n,function(t){var e=16*Math.random()|0;return(t<2?e:3&e|8).toString(16)})}},rt=function(t){return"function"==typeof t},at="namespace",it=t[at]||J(z,at)||"sa",ot=l[it+"_metadata"],ct=function(t,e){Y(ot)&&(t=Z(t,ot));var n=l[Mt];if(!rt(n))return t;try{return Z(t,n.call(l,Z(t,e)))}catch(r){F("metadata",r)}},st=t.strictUtm||J(z,"strict-utm")==r,ut=function(a){return s.search.slice(1).split("&").filter(function(t){var e=a||!tt("ut"),n=Et.map(G).join("|"),r=e?"^("+n+")=":"^((utm_)"+(st?"":"?")+"(source|medium|content|term|campaign)"+(st?"":"|ref")+"|"+n+")=";return e&&!Et.length?d:new RegExp(r).test(t)}).join("&")||h},lt=it+"_loaded";if(l[lt]==f)return p(w+"twice");l.sa_event_loaded=f,l[lt]=f;var pt=function(e,t,n){e=n?e:Z(qt,Dt,e),g.brave&&!n&&(e.brave=f),g._duckduckgoloader_&&!n&&(e.duck=f);var r=new Image;t&&(r.onerror=t,r.onload=t),r.src=k+"/simple.gif?"+Object.keys(e).filter(function(t){return e[t]!=h}).map(function(t){return E(t)+"="+E(e[t])}).join("&")+"&time="+Date.now()},ht=t.hostname||J(z,"hostname"),ft=ht||v,dt={version:"custom_proxy_11",hostname:ft};n=function(t){t=t.stack?t+" "+t.stack:t,p(t),pt(Z(dt,{type:i,error:t,path:s.pathname}),h,f)},M(i,function(t){t.filename&&-1"); //# sourceMappingURL=proxy.js.map \ No newline at end of file diff --git a/dist/v11/light.js b/dist/v11/light.js index f63624be..eb1885ca 100644 --- a/dist/v11/light.js +++ b/dist/v11/light.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2023-05-03; e23d; SRI-version; v11) */ +/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-06-25; e23d; SRI-version; v11) */ !function(s,e,t,u){try{var i=undefined,n="https:",r=s.console,a="doNotTrack",p=s.navigator,c=s.location,d=c.host,o=s.document,l=p.userAgent,m="Not sending request ",f=!1,g=encodeURIComponent,h=decodeURIComponent,v=JSON.stringify,y=s.addEventListener,_="https://queue."+t,w=(o.documentElement,"language"),b=p.userAgentData,O="platform",S="platformVersion",k="https://docs.simpleanalytics.com",j=/(bot|spider|crawl)/i.test(l)&&!/(cubot)/i.test(l),E=o.currentScript||o.querySelector('script[src*="'+t+'"]');u=function(){var e=[].slice.call(arguments);return e.unshift("Simple Analytics:"),Function.prototype.apply.call(r.warn,r,e)};var q=function(e,t){return e&&e.getAttribute("data-"+t)},A=function(){for(var e,t,n,r={},a=arguments,o=0;o>e/4).toString(16)})}catch(r){return e.replace(n,function(e){var t=16*Math.random()|0;return(e<2?t:3&t|8).toString(16)})}},I="namespace",N=e[I]||q(E,I)||"sa",R=e.strictUtm||"true"==q(E,"strict-utm"),U=N+"_loaded";if(1==s[U])return u(m+"twice");s.sa_event_loaded=!0,s[U]=!0;var V,B=function(t,e,n){t=n?t:A(H,J,t),p.brave&&!n&&(t.brave=!0),p._duckduckgoloader_&&!n&&(t.duck=!0),(new Image).src=_+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=i}).map(function(e){return g(e)+"="+g(t[e])}).join("&")+"&time="+Date.now()},C=e.hostname||q(E,"hostname"),T=C||d,F={version:"cdn_light_11",hostname:T};e.mode||q(E,"mode");try{V=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(Q){u(Q)}j&&(F.bot=!0);var H=A(F,{ua:l,https:c.protocol==n,timezone:V,page_id:D(),session_id:D()});if(H.sri=!0,b&&(H.mobile=b.mobile,H.brands=v(b.brands)),T!==d&&(H.hostname_original=d),a in p&&"1"==p[a])return u("Not sending request when "+a+" is enabled. See "+k+"/dnt");-1!=d.indexOf(".")&&!/^[0-9.:]+$/.test(d)||C||u("Set hostname on "+d+". See "+k+"/overwrite-domain-name");var z,J={},L=(o.referrer||"").replace(d,T).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||i,M=function(e,t){var n=A(F,{type:"append",original_id:t?e:H.page_id});t||!p.sendBeacon?B(n,0,!0):p.sendBeacon(_+"/append",v(n))};y("pagehide",M,!1);var P,Z,G=function(e){var t="";try{t=e||h(c.pathname)}catch(Q){u(Q)}return t},K=function(e,t,n,r){e&&M(""+H.page_id,!0),H.page_id=D();var a,o=T+G();B({id:H.page_id,type:"pageview",referrer:!t||n?L:null,query:(a=t,c.search.slice(1).split("&").filter(function(e){return!a&&new RegExp("^((utm_)"+(R?"":"?")+"(source|medium|content|term|campaign)"+(R?"":"|ref")+")=").test(e)}).join("&")||i)}),L=o,0};!function(e,t){var n=G(t);if(n&&z!=n){z=n,J.path=n,p[w]&&(J[w]=p[w]);var r,a=s.performance,o="navigation";try{r=a.getEntriesByType(o)[0].type}catch(Q){u(Q)}Z=r?-1<["reload","back_forward"].indexOf(r):a&&a[o]&&-1<[1,2].indexOf(a[o].type),P=!!L&&L.split("/")[0]==d;var i=function(){f=!0,K(e,e||Z||!1,P)};if(f)i();else try{b&&"function"==typeof b.getHighEntropyValues?b.getHighEntropyValues([O,S]).then(function(e){H.os_name=e[O],H.os_version=e[S],i()})["catch"](i):i()}catch(c){i()}}}()}catch(W){u(W)}}(window,{},"simpleanalyticscdn.com"); //# sourceMappingURL=light.js.map \ No newline at end of file From a6978fed0cac91baa1fc4215aaa5b7a803144402 Mon Sep 17 00:00:00 2001 From: adriaandotcom Date: Thu, 25 Jun 2026 10:06:44 +0000 Subject: [PATCH 3/6] Run prettier via GitHub Action --- compile.js | 20 ++++++------- playground/callback.html | 15 +++++----- playground/events.html | 17 +++++------ src/auto-events.js | 2 +- src/default.js | 56 ++++++++++++++++++------------------ test/helpers/get-browsers.js | 32 ++++++++++----------- test/helpers/index.js | 4 +-- test/helpers/server.js | 2 +- test/index.js | 14 ++++----- test/test-beacon.js | 18 ++++++------ test/test-events.js | 24 ++++++++-------- test/test-no-pushstate.js | 12 ++++---- test/test-one-beacon.js | 16 +++++------ test/test-pushstate.js | 16 +++++------ 14 files changed, 125 insertions(+), 123 deletions(-) diff --git a/compile.js b/compile.js index 52f4bbf1..343e22de 100644 --- a/compile.js +++ b/compile.js @@ -30,21 +30,21 @@ const fillTemplate = (template, { overwriteOptions = null } = {}) => { return template .replace( /\{\{\s?nginxHost\s?\}\}/gi, - '' + '', ) .replace( /\{\{\s?nginxProxyHost\s?\}\}/gi, - '' + '', ) .replace( /\\?"\{\{\s?overwriteOptions\s?\}\}\\?"/gi, overwriteOptions ? JSON.stringify(overwriteOptions).replace(/:"([^"]+)"/gi, ":$1") - : "{}" + : "{}", ) .replace( /"\{\{\s?cloudFlareCustomDomain\s?\}\}"/gi, - 'INSTALL_OPTIONS.custom_domain || "queue.simpleanalyticscdn.com"' + 'INSTALL_OPTIONS.custom_domain || "queue.simpleanalyticscdn.com"', ); }; @@ -284,7 +284,7 @@ const files = templates.reduce((list, template) => { if (template.variables.sri) { list.push( { ...template, variables: { ...template.variables, sri: true } }, - { ...template, variables: { ...template.variables, sri: false } } + { ...template, variables: { ...template.variables, sri: false } }, ); } else { list.push(template); @@ -346,7 +346,7 @@ for (const file of files) { filename: originalFileName, url: `${finalFileName}.map`, }, - } + }, ) : { code: prepend + rawCode, @@ -374,7 +374,7 @@ for (const file of files) { RED, `[${name}][ERROR] ${input .split("/") - .pop()} ${description} at line ${lineNumber} position ${index}` + .pop()} ${description} at line ${lineNumber} position ${index}`, ); continue; } @@ -402,7 +402,7 @@ for (const file of files) { let write = code.replace( /sourceMappingURL=latest\.js\.map/gi, - `sourceMappingURL=${cdnFileName}.map` + `sourceMappingURL=${cdnFileName}.map`, ); fs.writeFileSync(versionFile, write); @@ -410,7 +410,7 @@ for (const file of files) { if (compiledMap) { let writeCompiled = compiledMap.replace( /latest\.source\.js/gi, - cdnFileName + cdnFileName, ); fs.writeFileSync(`${versionFile}.map`, writeCompiled); @@ -438,7 +438,7 @@ for (const file of files) { console.log( ` ${name.toLowerCase()} ${fill1}Compiled ${sourceName} ${fill2} ${bytesZeroFilled} bytes ${ variables.sri ? " (SRI)" : "" - }` + }`, ); } diff --git a/playground/callback.html b/playground/callback.html index fd6069af..523f214b 100644 --- a/playground/callback.html +++ b/playground/callback.html @@ -1,4 +1,4 @@ - + @@ -46,7 +46,8 @@ @font-face { font-family: "Space Grotesk"; font-weight: 500; - src: url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Medium.woff2") + src: + url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Medium.woff2") format("woff2"), url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Medium.woff") format("woff"); @@ -54,7 +55,8 @@ @font-face { font-family: "Space Grotesk"; font-weight: 400; - src: url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Regular.woff2") + src: + url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Regular.woff2") format("woff2"), url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Regular.woff") format("woff"); @@ -179,9 +181,8 @@

Automated events

return param; }) .join(" "); - document.querySelector( - "textarea" - ).value += `${type.toUpperCase()}: ${line}\n`; + document.querySelector("textarea").value += + `${type.toUpperCase()}: ${line}\n`; } console.log = function () { @@ -253,7 +254,7 @@

Automated events

}); const callbackMetadataLink = document.querySelector( - "[data-metadata-callback]" + "[data-metadata-callback]", ); callbackMetadataLink.addEventListener("click", (event) => { event.preventDefault(); diff --git a/playground/events.html b/playground/events.html index 05f871a2..6e6336a3 100644 --- a/playground/events.html +++ b/playground/events.html @@ -1,4 +1,4 @@ - + @@ -33,9 +33,9 @@ }, () => { console.info( - "Simple Analytics auto events: collected before_script_load" + "Simple Analytics auto events: collected before_script_load", ); - } + }, ); @@ -67,7 +67,8 @@ @font-face { font-family: "Space Grotesk"; font-weight: 500; - src: url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Medium.woff2") + src: + url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Medium.woff2") format("woff2"), url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Medium.woff") format("woff"); @@ -75,7 +76,8 @@ @font-face { font-family: "Space Grotesk"; font-weight: 400; - src: url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Regular.woff2") + src: + url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Regular.woff2") format("woff2"), url("https://assets.simpleanalytics.com/fonts/SpaceGrotesk-Regular.woff") format("woff"); @@ -206,9 +208,8 @@

Automated events

return param; }) .join(" "); - document.querySelector( - "textarea" - ).value += `${type.toUpperCase()}: ${line}\n`; + document.querySelector("textarea").value += + `${type.toUpperCase()}: ${line}\n`; } console.log = function () { diff --git a/src/auto-events.js b/src/auto-events.js index 0a982f75..f6813bbf 100644 --- a/src/auto-events.js +++ b/src/auto-events.js @@ -159,7 +159,7 @@ /^https?:\/\//i.test(link.href) && new RegExp( "\\.(" + (optionsLink.downloadsExtensions || []).join("|") + ")$", - "i" + "i", ).test(link.pathname) ) { collect = "download"; diff --git a/src/default.js b/src/default.js index dfeccbd9..da412b2a 100644 --- a/src/default.js +++ b/src/default.js @@ -8,7 +8,7 @@ version, defaultNamespace, sendError, - warn + warn, ) { try { ///////////////////// @@ -117,8 +117,8 @@ return Array.isArray(csv) ? csv : isString(csv) && csv.length - ? csv.split(/, ?/) - : []; + ? csv.split(/, ?/) + : []; }; var isObject = function (object) { @@ -152,7 +152,7 @@ /** if ignoremetrics **/ // Customers can skip data points var ignoreMetrics = convertCommaSeparatedToArray( - overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics") + overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics"), ); /** endif **/ @@ -213,7 +213,7 @@ try { return assign( metadata, - metadataCollectorFunction.call(window, assign(metadata, data)) + metadataCollectorFunction.call(window, assign(metadata, data)), ); } catch (error) { warnInFunction("metadata", error); @@ -284,7 +284,7 @@ ignorePage === path || new RegExp( "^" + filterRegex(ignorePage).replace(/\\\*/gi, "(.*)") + "$", - "i" + "i", ).test(path) ) return trueVar; @@ -374,7 +374,7 @@ path: loc.pathname, }), undefinedVar, - trueVar + trueVar, ); }; @@ -387,7 +387,7 @@ sendError(event.message); } }, - falseVar + falseVar, ); /** endif **/ @@ -438,14 +438,14 @@ /** if ignorepages **/ // Customers can ignore certain pages var ignorePages = convertCommaSeparatedToArray( - overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages") + overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages"), ); /** endif **/ /** if allowparams **/ // Customers can allow params var allowParams = convertCommaSeparatedToArray( - overwriteOptions.allowParams || attr(scriptElement, "allow-params") + overwriteOptions.allowParams || attr(scriptElement, "allow-params"), ); /** endif **/ @@ -453,7 +453,7 @@ // Customers can allow params var nonUniqueHostnames = convertCommaSeparatedToArray( overwriteOptions.nonUniqueHostnames || - attr(scriptElement, "non-unique-hostnames") + attr(scriptElement, "non-unique-hostnames"), ); /** endif **/ @@ -553,12 +553,12 @@ /** if ignorednt **/ if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == "1") return warn( - notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt" + notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt", ); /** else **/ if (doNotTrack in nav && nav[doNotTrack] == "1") return warn( - notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt" + notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt", ); /** endif **/ @@ -573,7 +573,7 @@ locationHostname + ". See " + docsUrl + - "/overwrite-domain-name" + "/overwrite-domain-name", ); ///////////////////// @@ -644,7 +644,7 @@ hiddenStart = now(); } else msHidden += now() - hiddenStart; }, - falseVar + falseVar, ); /** endif **/ @@ -660,15 +660,15 @@ body[offsetHeight] || 0, documentElement[clientHeight] || 0, documentElement[scrollHeight] || 0, - documentElement[offsetHeight] || 0 + documentElement[offsetHeight] || 0, ); return Math.min( 100, Math.round( (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) / height / - 5 - ) * 5 + 5, + ) * 5, ); } catch (error) { warn(error); @@ -683,7 +683,7 @@ function () { if (scrolled < position()) scrolled = position(); }, - falseVar + falseVar, ); }); /** endif **/ @@ -737,7 +737,7 @@ isPushState, deleteSourceInfo, sameSite, - metadata + metadata, ) { if (isPushState) sendOnLeave("" + payload.page_id, trueVar); if (collectDataOnLeave) payload.page_id = uuid(); @@ -782,7 +782,7 @@ page.viewport_height = Math.max( documentElement[clientHeight] || 0, - window.innerHeight || 0 + window.innerHeight || 0, ) || null; } /** endif **/ @@ -853,7 +853,7 @@ isPushState, isPushState || userNavigated || !collectMetricByString("r"), // r = referrers sameSite, - metadata + metadata, ); }; @@ -920,7 +920,7 @@ function () { pageview(1); }, - falseVar + falseVar, ); addEventListenerFunc( @@ -928,7 +928,7 @@ function () { pageview(1); }, - falseVar + falseVar, ); } /** endif **/ @@ -941,7 +941,7 @@ function () { pageview(1); }, - falseVar + falseVar, ); } /** endif **/ @@ -988,7 +988,7 @@ if (validTypes.indexOf(typeof eventOutput) < 0) { warnInFunction( eventFunctionName, - event + " returns no string: " + eventOutput + event + " returns no string: " + eventOutput, ); return callback(); } @@ -1022,7 +1022,7 @@ metadata: stringify(metadata), /** endif **/ }), - callback + callback, ); } }; @@ -1065,5 +1065,5 @@ "{{baseUrl}}", "{{apiUrlPrefix}}", "{{scriptName}}", - "{{namespace}}" + "{{namespace}}", ); diff --git a/test/helpers/get-browsers.js b/test/helpers/get-browsers.js index fba8d423..2cc449f7 100644 --- a/test/helpers/get-browsers.js +++ b/test/helpers/get-browsers.js @@ -38,10 +38,10 @@ module.exports = async () => { browser_main_version: version(item.browser_version), })) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1 + version(left.browser_version) > version(right.browser_version) ? -1 : 1, ) .slice(0, 2), - ["os", "browser_main_version"] + ["os", "browser_main_version"], ); const chrome = makeUnique( @@ -54,18 +54,18 @@ module.exports = async () => { ); }) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1 + version(left.browser_version) > version(right.browser_version) ? -1 : 1, ), - ["os", "os_version"] + ["os", "os_version"], ); const ios = makeUnique( all .filter(({ browser }) => browser === "iphone") .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1 + version(left.browser_version) > version(right.browser_version) ? -1 : 1, ), - ["os", "os_version"] + ["os", "os_version"], ); const android = makeUnique( @@ -76,9 +76,9 @@ module.exports = async () => { os_main_version: parseInt(item.os_version.split(".")[0], 10), })) .sort((left, right) => - version(left.os_version) > version(right.os_version) ? -1 : 1 + version(left.os_version) > version(right.os_version) ? -1 : 1, ), - ["os", "os_main_version"] + ["os", "os_main_version"], ); const safari = makeUnique( @@ -96,10 +96,10 @@ module.exports = async () => { browser_main_version: version(item.browser_version), })) .sort((left, right) => - left.browser_main_version > right.browser_main_version ? -1 : 1 + left.browser_main_version > right.browser_main_version ? -1 : 1, ) .slice(0, 4), - ["os", "browser_main_version"] + ["os", "browser_main_version"], ).slice(0, 5); const firefox = makeUnique( @@ -112,9 +112,9 @@ module.exports = async () => { ); }) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1 + version(left.browser_version) > version(right.browser_version) ? -1 : 1, ), - ["os"] + ["os"], ); const opera = makeUnique( @@ -128,9 +128,9 @@ module.exports = async () => { ); }) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1 + version(left.browser_version) > version(right.browser_version) ? -1 : 1, ), - ["os"] + ["os"], ); const ipads = makeUnique( @@ -139,9 +139,9 @@ module.exports = async () => { return browser === "ipad"; }) .sort((left, right) => - version(left.os_version) > version(right.os_version) ? -1 : 1 + version(left.os_version) > version(right.os_version) ? -1 : 1, ), - ["os_version"] + ["os_version"], ); const browsers = [ diff --git a/test/helpers/index.js b/test/helpers/index.js index 25544d7c..66d8b727 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -27,7 +27,7 @@ module.exports.makeUnique = (array = [], keys = []) => { return array.reduce((list, item) => { const has = list.find((listItem) => - keys.every((key) => listItem[key] === item[key]) + keys.every((key) => listItem[key] === item[key]), ); if (!has) list.push(item); return list; @@ -92,7 +92,7 @@ module.exports.navigate = async ({ browser, os, name, driver, commands }) => { `${amount || 1}x`, typeof exceeded === "number" ? `(found request in ${exceeded}ms)` - : `(exceeded timeout)` + : `(exceeded timeout)`, ); } else if (script) { log(`script (${name})`, `${localhost}/?${searchParams}`); diff --git a/test/helpers/server.js b/test/helpers/server.js index 18ef4dfe..cf4353bc 100644 --- a/test/helpers/server.js +++ b/test/helpers/server.js @@ -66,7 +66,7 @@ const route = async (req, res) => { Simple Analytics Test

Path: ${pathname}

- ` + `, ); return res.end(); } diff --git a/test/index.js b/test/index.js index 8bafc945..fc705c9f 100644 --- a/test/index.js +++ b/test/index.js @@ -144,7 +144,7 @@ const log = (...messages) => DEBUG && console.log(" => Test:", ...messages); if (!BROWSERSTACK_USERNAME || !BROWSERSTACK_ACCESS_KEY) { console.error( - "BROWSERSTACK_USERNAME nor BROWSERSTACK_ACCESS_KEY are not defined." + "BROWSERSTACK_USERNAME nor BROWSERSTACK_ACCESS_KEY are not defined.", ); process.exit(1); } @@ -213,7 +213,7 @@ const getDeviceName = ({ const suiteInstance = Mocha.Suite.create( mochaInstance.suite, - "Public Script Test Suite" + "Public Script Test Suite", ); if (CI) @@ -223,16 +223,16 @@ const getDeviceName = ({ async function () { expect( browsers, - "Should have more than 20 browsers" + "Should have more than 20 browsers", ).to.have.lengthOf.at.least(20); - } - ) + }, + ), ); suiteInstance.addTest( new Mocha.Test(`Test Node.js environment`, async function () { expect(process.version, "Should use Node.js 16.16").to.match(/^v16\.16/); - }) + }), ); const appendBrowserData = (browser) => { @@ -409,7 +409,7 @@ const getDeviceName = ({ const testName = `Testing ${browser.name} (${index + 1}/${total})`; const nextBrowser = browsers[index + 1]; suiteInstance.addTest( - new Mocha.Test(testName, () => test(browser, nextBrowser)) + new Mocha.Test(testName, () => test(browser, nextBrowser)), ); } diff --git a/test/test-beacon.js b/test/test-beacon.js index b9aefce1..b47a98de 100644 --- a/test/test-beacon.js +++ b/test/test-beacon.js @@ -9,48 +9,48 @@ module.exports = async () => { expect( beaconRequests, - "There are not enough beacon requests found" + "There are not enough beacon requests found", ).to.have.lengthOf(2); expect( beaconRequests[0].pathname, - "First beacon request should be send via GIF" + "First beacon request should be send via GIF", ).to.equal("/simple.gif"); expect( beaconRequests[1].pathname, - "Second beacon request should be send via /append" + "Second beacon request should be send via /append", ).to.equal("/append"); beaconRequests.map((request) => { expect( request, - "There are no page view requests with body found" + "There are no page view requests with body found", ).to.have.property("body"); expect( request.body, - "All required keys should be present" + "All required keys should be present", ).to.include.all.keys(["duration", "scrolled", "original_id", "type"]); expect( UUIDvalidate(request.body.original_id, 4), - "original_id should be a valid UUIDv4" + "original_id should be a valid UUIDv4", ).to.be.true; expect( parseInt(request.body.scrolled, 10), - "Scrolled should be close to 35 percent" + "Scrolled should be close to 35 percent", ).to.be.closeTo(35, 5); expect( parseInt(request.body.duration, 10), - "Duration should be a valid number" + "Duration should be a valid number", ).to.be.a("number"); expect( parseInt(request.body.duration, 10), - "Duration should be close to 0 or 1 second" + "Duration should be close to 0 or 1 second", ).to.be.closeTo(2, 2); }); }; diff --git a/test/test-events.js b/test/test-events.js index 04e633d2..734dd018 100644 --- a/test/test-events.js +++ b/test/test-events.js @@ -10,31 +10,31 @@ module.exports = async ({ os, browser }) => { expect(requests, "There should be two event requests").to.have.lengthOf(3); expect(requests[0].body.event, "Event should be 'event_123'").to.equal( - "event_123" + "event_123", ); expect(requests[1].body.event, "Event should be 'functionoutput'").to.equal( - "functionoutput" + "functionoutput", ); expect(requests[2].body.metadata, "Event should have metadata").to.contain( - '","bool":false,"int":20301,"string":"hi\'/301%20uas@#*0"}' + '","bool":false,"int":20301,"string":"hi\'/301%20uas@#*0"}', ); expect( new Date(JSON.parse(requests[2].body.metadata).date), - "Event should have a date in the last 5 minutes" + "Event should have a date in the last 5 minutes", ).to.greaterThan(new Date(Date.now() - 300000)); requests.map((request) => { expect( request, - "There are no event requests with body found" + "There are no event requests with body found", ).to.have.property("body"); expect( request.body, - "All required keys should be present" + "All required keys should be present", ).to.include.all.keys([ "version", "hostname", @@ -47,34 +47,34 @@ module.exports = async ({ os, browser }) => { expect( UUIDvalidate(request.body.id, 4), - "event id should be a valid UUIDv4" + "event id should be a valid UUIDv4", ).to.be.true; expect( UUIDvalidate(request.body.session_id, 4), - "session_id should be a valid UUIDv4" + "session_id should be a valid UUIDv4", ).to.be.true; expect( UUIDvalidate(request.body.page_id, 4), - "page_id should be a valid UUIDv4" + "page_id should be a valid UUIDv4", ).to.be.true; if (os === "ios" || browser === "safari") { expect( request.body.hostname, - "Hostname should be bs-local.com on OS X Safari" + "Hostname should be bs-local.com on OS X Safari", ).to.equal("bs-local.com:3000"); } else { expect( request.body.hostname, - "Hostname should be localhost on non iOS" + "Hostname should be localhost on non iOS", ).to.equal("localhost:3000"); } expect( parseInt(request.body.version, 10), - "Version should be a valid number" + "Version should be a valid number", ).to.be.a("number"); }); }; diff --git a/test/test-no-pushstate.js b/test/test-no-pushstate.js index 0dda1a39..503a7209 100644 --- a/test/test-no-pushstate.js +++ b/test/test-no-pushstate.js @@ -11,28 +11,28 @@ module.exports = async () => { expect( pageViewRequests, - "There are not enough page views requests found" + "There are not enough page views requests found", ).to.have.lengthOf(2); expect( pageViewRequests[0].body.unique, - "The first visit should be unique" + "The first visit should be unique", ).to.equal("true"); expect( pageViewRequests[1].body.unique, - "The second visit should not be unique" + "The second visit should not be unique", ).to.equal("false"); pageViewRequests.map((request) => { expect( request, - "There are no page view requests with body found" + "There are no page view requests with body found", ).to.have.property("body"); expect( request.body, - "All required keys should be present" + "All required keys should be present", ).to.include.all.keys([ "hostname", "https", @@ -53,7 +53,7 @@ module.exports = async () => { expect( parseInt(request.body.version, 10), - "Version should be a valid number" + "Version should be a valid number", ).to.be.a("number"); // We replace "https:" with "http:" string on CI diff --git a/test/test-one-beacon.js b/test/test-one-beacon.js index 03d6ee9b..ff7cbaf8 100644 --- a/test/test-one-beacon.js +++ b/test/test-one-beacon.js @@ -9,24 +9,24 @@ module.exports = async () => { expect( beaconRequests, - "There should be 1 beacon type request" + "There should be 1 beacon type request", ).to.have.lengthOf(1); const request = beaconRequests[0]; expect( request.pathname, - "First beacon request should be send via GIF" + "First beacon request should be send via GIF", ).to.equal("/simple.gif"); expect( request, - "There are no beacon requests with body found" + "There are no beacon requests with body found", ).to.have.property("body"); expect( request.body, - "All required keys should be present" + "All required keys should be present", ).to.include.all.keys([ "hostname", "duration", @@ -37,21 +37,21 @@ module.exports = async () => { expect( UUIDvalidate(request.body.original_id, 4), - "original_id should be a valid UUIDv4" + "original_id should be a valid UUIDv4", ).to.be.true; expect( parseInt(request.body.scrolled, 10), - "Scrolled should be close to 35 percent" + "Scrolled should be close to 35 percent", ).to.be.closeTo(35, 5); expect( parseInt(request.body.duration, 10), - "Duration should be a valid number" + "Duration should be a valid number", ).to.be.a("number"); expect( parseInt(request.body.version, 10), - "Version should be a valid number" + "Version should be a valid number", ).to.be.a("number"); }; diff --git a/test/test-pushstate.js b/test/test-pushstate.js index bd3781b5..62e9540f 100644 --- a/test/test-pushstate.js +++ b/test/test-pushstate.js @@ -11,23 +11,23 @@ module.exports = async () => { expect( pageViewRequests, - "There are not enough page views requests found" + "There are not enough page views requests found", ).to.have.lengthOf(2); expect([true, "true"], "The first visit should be unique").to.include( - pageViewRequests[0].body.unique + pageViewRequests[0].body.unique, ); expect([false, "false"], "The second visit should not be unique").to.include( - pageViewRequests[1].body.unique + pageViewRequests[1].body.unique, ); expect(pageViewRequests[0].body.query, "Query should exist").to.equal( - "project=project_x&utm_source=utm_source&medium=medium&ref=ref" + "project=project_x&utm_source=utm_source&medium=medium&ref=ref", ); expect(pageViewRequests[1].body.query, "Query should not exist").to.equal( - "project=project_x" + "project=project_x", ); // Seconds page referrer should be the first page (ending with /) @@ -36,12 +36,12 @@ module.exports = async () => { pageViewRequests.map((request) => { expect( request, - "There are no page view requests with body found" + "There are no page view requests with body found", ).to.have.property("body"); expect( request.body, - "All required keys should be present" + "All required keys should be present", ).to.include.all.keys([ "hostname", "https", @@ -63,7 +63,7 @@ module.exports = async () => { expect( parseInt(request.body.version, 10), - "Version should be a valid number" + "Version should be a valid number", ).to.be.a("number"); // We replace "https:" with "http:" string on CI From bcfe7971cdf780922143cf3dd8916bc74242eb71 Mon Sep 17 00:00:00 2001 From: Adriaan van Rossum <1079135+adriaanvanrossum@users.noreply.github.com> Date: Thu, 25 Jun 2026 12:18:12 +0200 Subject: [PATCH 4/6] Empty commit to trigger GitHub actions again with Claude From 7953a7b0762a92062f594e7eb98fe57594ff20e6 Mon Sep 17 00:00:00 2001 From: Adriaan van Rossum <1079135+adriaanvanrossum@users.noreply.github.com> Date: Thu, 25 Jun 2026 12:40:11 +0200 Subject: [PATCH 5/6] Fix es5 prettier commit --- .github/workflows/browserstack.yml | 22 +++++++------ .prettierrc.json | 3 ++ src/auto-events.js | 2 +- src/default.js | 52 +++++++++++++++--------------- 4 files changed, 43 insertions(+), 36 deletions(-) create mode 100644 .prettierrc.json diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml index 2a9d738f..57a02a11 100644 --- a/.github/workflows/browserstack.yml +++ b/.github/workflows/browserstack.yml @@ -35,15 +35,6 @@ jobs: ref: ${{ github.head_ref }} set-safe-directory: "/github/workspace" - - name: Prettier Action on PR - uses: creyD/prettier_action@v4.3 - with: - prettier_options: "--write {**/*,*}.{js,hbs,html,json,md,yml,css,scss} !.github/workflows/**/* !dist/**/*" - commit_message: "Run prettier via GitHub Action" - file_pattern: "." - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: @@ -52,6 +43,19 @@ jobs: - name: Run npm ci run: sudo npm ci + - name: Prettier check (report only, no writes or commits) + if: always() + run: | + { + echo "## Prettier formatting report" + echo "" + echo "CI does not write or commit formatting changes. Run \`npx prettier --write .\` locally to apply anything listed below." + echo "" + echo '```' + npx prettier --check . 2>&1 || true + echo '```' + } >> "$GITHUB_STEP_SUMMARY" + - name: Run npm test with BrowserStack Local run: npm run build && node ./test/index.js env: diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..757fd64c --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,3 @@ +{ + "trailingComma": "es5" +} diff --git a/src/auto-events.js b/src/auto-events.js index f6813bbf..0a982f75 100644 --- a/src/auto-events.js +++ b/src/auto-events.js @@ -159,7 +159,7 @@ /^https?:\/\//i.test(link.href) && new RegExp( "\\.(" + (optionsLink.downloadsExtensions || []).join("|") + ")$", - "i", + "i" ).test(link.pathname) ) { collect = "download"; diff --git a/src/default.js b/src/default.js index da412b2a..df8de671 100644 --- a/src/default.js +++ b/src/default.js @@ -8,7 +8,7 @@ version, defaultNamespace, sendError, - warn, + warn ) { try { ///////////////////// @@ -152,7 +152,7 @@ /** if ignoremetrics **/ // Customers can skip data points var ignoreMetrics = convertCommaSeparatedToArray( - overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics"), + overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics") ); /** endif **/ @@ -213,7 +213,7 @@ try { return assign( metadata, - metadataCollectorFunction.call(window, assign(metadata, data)), + metadataCollectorFunction.call(window, assign(metadata, data)) ); } catch (error) { warnInFunction("metadata", error); @@ -284,7 +284,7 @@ ignorePage === path || new RegExp( "^" + filterRegex(ignorePage).replace(/\\\*/gi, "(.*)") + "$", - "i", + "i" ).test(path) ) return trueVar; @@ -374,7 +374,7 @@ path: loc.pathname, }), undefinedVar, - trueVar, + trueVar ); }; @@ -387,7 +387,7 @@ sendError(event.message); } }, - falseVar, + falseVar ); /** endif **/ @@ -438,14 +438,14 @@ /** if ignorepages **/ // Customers can ignore certain pages var ignorePages = convertCommaSeparatedToArray( - overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages"), + overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages") ); /** endif **/ /** if allowparams **/ // Customers can allow params var allowParams = convertCommaSeparatedToArray( - overwriteOptions.allowParams || attr(scriptElement, "allow-params"), + overwriteOptions.allowParams || attr(scriptElement, "allow-params") ); /** endif **/ @@ -453,7 +453,7 @@ // Customers can allow params var nonUniqueHostnames = convertCommaSeparatedToArray( overwriteOptions.nonUniqueHostnames || - attr(scriptElement, "non-unique-hostnames"), + attr(scriptElement, "non-unique-hostnames") ); /** endif **/ @@ -553,12 +553,12 @@ /** if ignorednt **/ if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == "1") return warn( - notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt", + notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt" ); /** else **/ if (doNotTrack in nav && nav[doNotTrack] == "1") return warn( - notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt", + notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt" ); /** endif **/ @@ -573,7 +573,7 @@ locationHostname + ". See " + docsUrl + - "/overwrite-domain-name", + "/overwrite-domain-name" ); ///////////////////// @@ -644,7 +644,7 @@ hiddenStart = now(); } else msHidden += now() - hiddenStart; }, - falseVar, + falseVar ); /** endif **/ @@ -660,15 +660,15 @@ body[offsetHeight] || 0, documentElement[clientHeight] || 0, documentElement[scrollHeight] || 0, - documentElement[offsetHeight] || 0, + documentElement[offsetHeight] || 0 ); return Math.min( 100, Math.round( (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) / height / - 5, - ) * 5, + 5 + ) * 5 ); } catch (error) { warn(error); @@ -683,7 +683,7 @@ function () { if (scrolled < position()) scrolled = position(); }, - falseVar, + falseVar ); }); /** endif **/ @@ -737,7 +737,7 @@ isPushState, deleteSourceInfo, sameSite, - metadata, + metadata ) { if (isPushState) sendOnLeave("" + payload.page_id, trueVar); if (collectDataOnLeave) payload.page_id = uuid(); @@ -782,7 +782,7 @@ page.viewport_height = Math.max( documentElement[clientHeight] || 0, - window.innerHeight || 0, + window.innerHeight || 0 ) || null; } /** endif **/ @@ -853,7 +853,7 @@ isPushState, isPushState || userNavigated || !collectMetricByString("r"), // r = referrers sameSite, - metadata, + metadata ); }; @@ -920,7 +920,7 @@ function () { pageview(1); }, - falseVar, + falseVar ); addEventListenerFunc( @@ -928,7 +928,7 @@ function () { pageview(1); }, - falseVar, + falseVar ); } /** endif **/ @@ -941,7 +941,7 @@ function () { pageview(1); }, - falseVar, + falseVar ); } /** endif **/ @@ -988,7 +988,7 @@ if (validTypes.indexOf(typeof eventOutput) < 0) { warnInFunction( eventFunctionName, - event + " returns no string: " + eventOutput, + event + " returns no string: " + eventOutput ); return callback(); } @@ -1022,7 +1022,7 @@ metadata: stringify(metadata), /** endif **/ }), - callback, + callback ); } }; @@ -1065,5 +1065,5 @@ "{{baseUrl}}", "{{apiUrlPrefix}}", "{{scriptName}}", - "{{namespace}}", + "{{namespace}}" ); From 3716185bd907654faae3aae941de7ede0ff0c53e Mon Sep 17 00:00:00 2001 From: Adriaan van Rossum <1079135+adriaanvanrossum@users.noreply.github.com> Date: Thu, 25 Jun 2026 12:42:04 +0200 Subject: [PATCH 6/6] Run npx prettier --write . --- compile.js | 20 ++++++++++---------- playground/callback.html | 2 +- playground/events.html | 4 ++-- test/helpers/get-browsers.js | 32 ++++++++++++++++---------------- test/helpers/index.js | 4 ++-- test/helpers/server.js | 2 +- test/index.js | 14 +++++++------- test/test-beacon.js | 18 +++++++++--------- test/test-events.js | 24 ++++++++++++------------ test/test-no-pushstate.js | 12 ++++++------ test/test-one-beacon.js | 16 ++++++++-------- test/test-pushstate.js | 16 ++++++++-------- 12 files changed, 82 insertions(+), 82 deletions(-) diff --git a/compile.js b/compile.js index 343e22de..52f4bbf1 100644 --- a/compile.js +++ b/compile.js @@ -30,21 +30,21 @@ const fillTemplate = (template, { overwriteOptions = null } = {}) => { return template .replace( /\{\{\s?nginxHost\s?\}\}/gi, - '', + '' ) .replace( /\{\{\s?nginxProxyHost\s?\}\}/gi, - '', + '' ) .replace( /\\?"\{\{\s?overwriteOptions\s?\}\}\\?"/gi, overwriteOptions ? JSON.stringify(overwriteOptions).replace(/:"([^"]+)"/gi, ":$1") - : "{}", + : "{}" ) .replace( /"\{\{\s?cloudFlareCustomDomain\s?\}\}"/gi, - 'INSTALL_OPTIONS.custom_domain || "queue.simpleanalyticscdn.com"', + 'INSTALL_OPTIONS.custom_domain || "queue.simpleanalyticscdn.com"' ); }; @@ -284,7 +284,7 @@ const files = templates.reduce((list, template) => { if (template.variables.sri) { list.push( { ...template, variables: { ...template.variables, sri: true } }, - { ...template, variables: { ...template.variables, sri: false } }, + { ...template, variables: { ...template.variables, sri: false } } ); } else { list.push(template); @@ -346,7 +346,7 @@ for (const file of files) { filename: originalFileName, url: `${finalFileName}.map`, }, - }, + } ) : { code: prepend + rawCode, @@ -374,7 +374,7 @@ for (const file of files) { RED, `[${name}][ERROR] ${input .split("/") - .pop()} ${description} at line ${lineNumber} position ${index}`, + .pop()} ${description} at line ${lineNumber} position ${index}` ); continue; } @@ -402,7 +402,7 @@ for (const file of files) { let write = code.replace( /sourceMappingURL=latest\.js\.map/gi, - `sourceMappingURL=${cdnFileName}.map`, + `sourceMappingURL=${cdnFileName}.map` ); fs.writeFileSync(versionFile, write); @@ -410,7 +410,7 @@ for (const file of files) { if (compiledMap) { let writeCompiled = compiledMap.replace( /latest\.source\.js/gi, - cdnFileName, + cdnFileName ); fs.writeFileSync(`${versionFile}.map`, writeCompiled); @@ -438,7 +438,7 @@ for (const file of files) { console.log( ` ${name.toLowerCase()} ${fill1}Compiled ${sourceName} ${fill2} ${bytesZeroFilled} bytes ${ variables.sri ? " (SRI)" : "" - }`, + }` ); } diff --git a/playground/callback.html b/playground/callback.html index 523f214b..9f1bdfdb 100644 --- a/playground/callback.html +++ b/playground/callback.html @@ -254,7 +254,7 @@

Automated events

}); const callbackMetadataLink = document.querySelector( - "[data-metadata-callback]", + "[data-metadata-callback]" ); callbackMetadataLink.addEventListener("click", (event) => { event.preventDefault(); diff --git a/playground/events.html b/playground/events.html index 6e6336a3..2e8fe67c 100644 --- a/playground/events.html +++ b/playground/events.html @@ -33,9 +33,9 @@ }, () => { console.info( - "Simple Analytics auto events: collected before_script_load", + "Simple Analytics auto events: collected before_script_load" ); - }, + } ); diff --git a/test/helpers/get-browsers.js b/test/helpers/get-browsers.js index 2cc449f7..fba8d423 100644 --- a/test/helpers/get-browsers.js +++ b/test/helpers/get-browsers.js @@ -38,10 +38,10 @@ module.exports = async () => { browser_main_version: version(item.browser_version), })) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1, + version(left.browser_version) > version(right.browser_version) ? -1 : 1 ) .slice(0, 2), - ["os", "browser_main_version"], + ["os", "browser_main_version"] ); const chrome = makeUnique( @@ -54,18 +54,18 @@ module.exports = async () => { ); }) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1, + version(left.browser_version) > version(right.browser_version) ? -1 : 1 ), - ["os", "os_version"], + ["os", "os_version"] ); const ios = makeUnique( all .filter(({ browser }) => browser === "iphone") .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1, + version(left.browser_version) > version(right.browser_version) ? -1 : 1 ), - ["os", "os_version"], + ["os", "os_version"] ); const android = makeUnique( @@ -76,9 +76,9 @@ module.exports = async () => { os_main_version: parseInt(item.os_version.split(".")[0], 10), })) .sort((left, right) => - version(left.os_version) > version(right.os_version) ? -1 : 1, + version(left.os_version) > version(right.os_version) ? -1 : 1 ), - ["os", "os_main_version"], + ["os", "os_main_version"] ); const safari = makeUnique( @@ -96,10 +96,10 @@ module.exports = async () => { browser_main_version: version(item.browser_version), })) .sort((left, right) => - left.browser_main_version > right.browser_main_version ? -1 : 1, + left.browser_main_version > right.browser_main_version ? -1 : 1 ) .slice(0, 4), - ["os", "browser_main_version"], + ["os", "browser_main_version"] ).slice(0, 5); const firefox = makeUnique( @@ -112,9 +112,9 @@ module.exports = async () => { ); }) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1, + version(left.browser_version) > version(right.browser_version) ? -1 : 1 ), - ["os"], + ["os"] ); const opera = makeUnique( @@ -128,9 +128,9 @@ module.exports = async () => { ); }) .sort((left, right) => - version(left.browser_version) > version(right.browser_version) ? -1 : 1, + version(left.browser_version) > version(right.browser_version) ? -1 : 1 ), - ["os"], + ["os"] ); const ipads = makeUnique( @@ -139,9 +139,9 @@ module.exports = async () => { return browser === "ipad"; }) .sort((left, right) => - version(left.os_version) > version(right.os_version) ? -1 : 1, + version(left.os_version) > version(right.os_version) ? -1 : 1 ), - ["os_version"], + ["os_version"] ); const browsers = [ diff --git a/test/helpers/index.js b/test/helpers/index.js index 66d8b727..25544d7c 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -27,7 +27,7 @@ module.exports.makeUnique = (array = [], keys = []) => { return array.reduce((list, item) => { const has = list.find((listItem) => - keys.every((key) => listItem[key] === item[key]), + keys.every((key) => listItem[key] === item[key]) ); if (!has) list.push(item); return list; @@ -92,7 +92,7 @@ module.exports.navigate = async ({ browser, os, name, driver, commands }) => { `${amount || 1}x`, typeof exceeded === "number" ? `(found request in ${exceeded}ms)` - : `(exceeded timeout)`, + : `(exceeded timeout)` ); } else if (script) { log(`script (${name})`, `${localhost}/?${searchParams}`); diff --git a/test/helpers/server.js b/test/helpers/server.js index cf4353bc..18ef4dfe 100644 --- a/test/helpers/server.js +++ b/test/helpers/server.js @@ -66,7 +66,7 @@ const route = async (req, res) => { Simple Analytics Test

Path: ${pathname}

- `, + ` ); return res.end(); } diff --git a/test/index.js b/test/index.js index fc705c9f..8bafc945 100644 --- a/test/index.js +++ b/test/index.js @@ -144,7 +144,7 @@ const log = (...messages) => DEBUG && console.log(" => Test:", ...messages); if (!BROWSERSTACK_USERNAME || !BROWSERSTACK_ACCESS_KEY) { console.error( - "BROWSERSTACK_USERNAME nor BROWSERSTACK_ACCESS_KEY are not defined.", + "BROWSERSTACK_USERNAME nor BROWSERSTACK_ACCESS_KEY are not defined." ); process.exit(1); } @@ -213,7 +213,7 @@ const getDeviceName = ({ const suiteInstance = Mocha.Suite.create( mochaInstance.suite, - "Public Script Test Suite", + "Public Script Test Suite" ); if (CI) @@ -223,16 +223,16 @@ const getDeviceName = ({ async function () { expect( browsers, - "Should have more than 20 browsers", + "Should have more than 20 browsers" ).to.have.lengthOf.at.least(20); - }, - ), + } + ) ); suiteInstance.addTest( new Mocha.Test(`Test Node.js environment`, async function () { expect(process.version, "Should use Node.js 16.16").to.match(/^v16\.16/); - }), + }) ); const appendBrowserData = (browser) => { @@ -409,7 +409,7 @@ const getDeviceName = ({ const testName = `Testing ${browser.name} (${index + 1}/${total})`; const nextBrowser = browsers[index + 1]; suiteInstance.addTest( - new Mocha.Test(testName, () => test(browser, nextBrowser)), + new Mocha.Test(testName, () => test(browser, nextBrowser)) ); } diff --git a/test/test-beacon.js b/test/test-beacon.js index b47a98de..b9aefce1 100644 --- a/test/test-beacon.js +++ b/test/test-beacon.js @@ -9,48 +9,48 @@ module.exports = async () => { expect( beaconRequests, - "There are not enough beacon requests found", + "There are not enough beacon requests found" ).to.have.lengthOf(2); expect( beaconRequests[0].pathname, - "First beacon request should be send via GIF", + "First beacon request should be send via GIF" ).to.equal("/simple.gif"); expect( beaconRequests[1].pathname, - "Second beacon request should be send via /append", + "Second beacon request should be send via /append" ).to.equal("/append"); beaconRequests.map((request) => { expect( request, - "There are no page view requests with body found", + "There are no page view requests with body found" ).to.have.property("body"); expect( request.body, - "All required keys should be present", + "All required keys should be present" ).to.include.all.keys(["duration", "scrolled", "original_id", "type"]); expect( UUIDvalidate(request.body.original_id, 4), - "original_id should be a valid UUIDv4", + "original_id should be a valid UUIDv4" ).to.be.true; expect( parseInt(request.body.scrolled, 10), - "Scrolled should be close to 35 percent", + "Scrolled should be close to 35 percent" ).to.be.closeTo(35, 5); expect( parseInt(request.body.duration, 10), - "Duration should be a valid number", + "Duration should be a valid number" ).to.be.a("number"); expect( parseInt(request.body.duration, 10), - "Duration should be close to 0 or 1 second", + "Duration should be close to 0 or 1 second" ).to.be.closeTo(2, 2); }); }; diff --git a/test/test-events.js b/test/test-events.js index 734dd018..04e633d2 100644 --- a/test/test-events.js +++ b/test/test-events.js @@ -10,31 +10,31 @@ module.exports = async ({ os, browser }) => { expect(requests, "There should be two event requests").to.have.lengthOf(3); expect(requests[0].body.event, "Event should be 'event_123'").to.equal( - "event_123", + "event_123" ); expect(requests[1].body.event, "Event should be 'functionoutput'").to.equal( - "functionoutput", + "functionoutput" ); expect(requests[2].body.metadata, "Event should have metadata").to.contain( - '","bool":false,"int":20301,"string":"hi\'/301%20uas@#*0"}', + '","bool":false,"int":20301,"string":"hi\'/301%20uas@#*0"}' ); expect( new Date(JSON.parse(requests[2].body.metadata).date), - "Event should have a date in the last 5 minutes", + "Event should have a date in the last 5 minutes" ).to.greaterThan(new Date(Date.now() - 300000)); requests.map((request) => { expect( request, - "There are no event requests with body found", + "There are no event requests with body found" ).to.have.property("body"); expect( request.body, - "All required keys should be present", + "All required keys should be present" ).to.include.all.keys([ "version", "hostname", @@ -47,34 +47,34 @@ module.exports = async ({ os, browser }) => { expect( UUIDvalidate(request.body.id, 4), - "event id should be a valid UUIDv4", + "event id should be a valid UUIDv4" ).to.be.true; expect( UUIDvalidate(request.body.session_id, 4), - "session_id should be a valid UUIDv4", + "session_id should be a valid UUIDv4" ).to.be.true; expect( UUIDvalidate(request.body.page_id, 4), - "page_id should be a valid UUIDv4", + "page_id should be a valid UUIDv4" ).to.be.true; if (os === "ios" || browser === "safari") { expect( request.body.hostname, - "Hostname should be bs-local.com on OS X Safari", + "Hostname should be bs-local.com on OS X Safari" ).to.equal("bs-local.com:3000"); } else { expect( request.body.hostname, - "Hostname should be localhost on non iOS", + "Hostname should be localhost on non iOS" ).to.equal("localhost:3000"); } expect( parseInt(request.body.version, 10), - "Version should be a valid number", + "Version should be a valid number" ).to.be.a("number"); }); }; diff --git a/test/test-no-pushstate.js b/test/test-no-pushstate.js index 503a7209..0dda1a39 100644 --- a/test/test-no-pushstate.js +++ b/test/test-no-pushstate.js @@ -11,28 +11,28 @@ module.exports = async () => { expect( pageViewRequests, - "There are not enough page views requests found", + "There are not enough page views requests found" ).to.have.lengthOf(2); expect( pageViewRequests[0].body.unique, - "The first visit should be unique", + "The first visit should be unique" ).to.equal("true"); expect( pageViewRequests[1].body.unique, - "The second visit should not be unique", + "The second visit should not be unique" ).to.equal("false"); pageViewRequests.map((request) => { expect( request, - "There are no page view requests with body found", + "There are no page view requests with body found" ).to.have.property("body"); expect( request.body, - "All required keys should be present", + "All required keys should be present" ).to.include.all.keys([ "hostname", "https", @@ -53,7 +53,7 @@ module.exports = async () => { expect( parseInt(request.body.version, 10), - "Version should be a valid number", + "Version should be a valid number" ).to.be.a("number"); // We replace "https:" with "http:" string on CI diff --git a/test/test-one-beacon.js b/test/test-one-beacon.js index ff7cbaf8..03d6ee9b 100644 --- a/test/test-one-beacon.js +++ b/test/test-one-beacon.js @@ -9,24 +9,24 @@ module.exports = async () => { expect( beaconRequests, - "There should be 1 beacon type request", + "There should be 1 beacon type request" ).to.have.lengthOf(1); const request = beaconRequests[0]; expect( request.pathname, - "First beacon request should be send via GIF", + "First beacon request should be send via GIF" ).to.equal("/simple.gif"); expect( request, - "There are no beacon requests with body found", + "There are no beacon requests with body found" ).to.have.property("body"); expect( request.body, - "All required keys should be present", + "All required keys should be present" ).to.include.all.keys([ "hostname", "duration", @@ -37,21 +37,21 @@ module.exports = async () => { expect( UUIDvalidate(request.body.original_id, 4), - "original_id should be a valid UUIDv4", + "original_id should be a valid UUIDv4" ).to.be.true; expect( parseInt(request.body.scrolled, 10), - "Scrolled should be close to 35 percent", + "Scrolled should be close to 35 percent" ).to.be.closeTo(35, 5); expect( parseInt(request.body.duration, 10), - "Duration should be a valid number", + "Duration should be a valid number" ).to.be.a("number"); expect( parseInt(request.body.version, 10), - "Version should be a valid number", + "Version should be a valid number" ).to.be.a("number"); }; diff --git a/test/test-pushstate.js b/test/test-pushstate.js index 62e9540f..bd3781b5 100644 --- a/test/test-pushstate.js +++ b/test/test-pushstate.js @@ -11,23 +11,23 @@ module.exports = async () => { expect( pageViewRequests, - "There are not enough page views requests found", + "There are not enough page views requests found" ).to.have.lengthOf(2); expect([true, "true"], "The first visit should be unique").to.include( - pageViewRequests[0].body.unique, + pageViewRequests[0].body.unique ); expect([false, "false"], "The second visit should not be unique").to.include( - pageViewRequests[1].body.unique, + pageViewRequests[1].body.unique ); expect(pageViewRequests[0].body.query, "Query should exist").to.equal( - "project=project_x&utm_source=utm_source&medium=medium&ref=ref", + "project=project_x&utm_source=utm_source&medium=medium&ref=ref" ); expect(pageViewRequests[1].body.query, "Query should not exist").to.equal( - "project=project_x", + "project=project_x" ); // Seconds page referrer should be the first page (ending with /) @@ -36,12 +36,12 @@ module.exports = async () => { pageViewRequests.map((request) => { expect( request, - "There are no page view requests with body found", + "There are no page view requests with body found" ).to.have.property("body"); expect( request.body, - "All required keys should be present", + "All required keys should be present" ).to.include.all.keys([ "hostname", "https", @@ -63,7 +63,7 @@ module.exports = async () => { expect( parseInt(request.body.version, 10), - "Version should be a valid number", + "Version should be a valid number" ).to.be.a("number"); // We replace "https:" with "http:" string on CI