diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..ddb3f37 --- /dev/null +++ b/.cursorrules @@ -0,0 +1,2 @@ +- Check AGENTS.md for instructions specifically for AI +- Check README.md for instructions diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..992c6d6 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,24 @@ +module.exports = { + env: { + browser: true, + commonjs: true, + es6: true, + node: true, + }, + extends: "eslint:recommended", + ignorePatterns: ["dist/"], + globals: { + Atomics: "readonly", + SharedArrayBuffer: "readonly", + }, + parserOptions: { + ecmaVersion: 2020, + }, + overrides: [ + { + files: ["test/**/*.js"], + env: { mocha: true }, + }, + ], + rules: {}, +}; diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml index 659668c..91651ce 100644 --- a/.github/workflows/browserstack.yml +++ b/.github/workflows/browserstack.yml @@ -54,6 +54,9 @@ jobs: - name: Test BrowserStack matrix selection run: pnpm run test:matrix + - name: Run unit tests + run: pnpm run build && pnpm run test:unit && pnpm run test:deploy + - name: Prettier check (report only, no writes or commits) if: always() run: | diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b785a1b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,23 @@ +# Agent instructions + +Before working here, read the shared [Simple Analytics instructions](https://github.com/simpleanalytics/ide-config/blob/main/AGENTS.md) through the approved GitHub access method. Apply them alongside applicable parent and nested instructions; more specific instructions take precedence. + +## Tracker changes + +1. **Minimize shipped bytes.** Keep changes small and reuse existing helpers and variables. Measure minified and gzip byte differences for affected scripts against the target branch using the same build and compression settings. Test proposed optimizations: extracting repeated strings can increase gzip size. + +2. **Preserve existing installations.** Unless the user explicitly accepts a behavior change, preserve existing settings and integrations. Check affected combinations against the [customer documentation](https://docs.simpleanalytics.com/), including manual pageviews, query handling, attribution, namespaces, ignored metrics, metadata, and automatic events. Report concrete before/after effects on customer data, event names, and counts, separately from additions that leave existing installations unchanged. + +3. **Prefer simple implementations.** Add fallbacks, polling, abstractions, or compatibility layers only for a demonstrated requirement. Respect explicitly accepted tradeoffs, especially for unused beta helpers, rather than adding speculative compatibility machinery. + +4. **Preserve website behavior.** Tracking must respect cancelled actions, existing handlers, form validation, submitter settings, modified clicks, new tabs, and downloads. Let the browser or website own navigation and submission; send tracking without forcing either action. + +5. **Keep collection deliberate.** Honor collection settings and opt-outs. Distinguish query-parameter names from values when checking what is sent. Keep form field values out of automatic form tracking, sanitize automatically reported URLs, and keep extra diagnostic requests such as 404 confirmation opt-in. Make changes to collection defaults explicit for review. + +6. **Preserve browser and build compatibility.** Keep visitor-facing output ES5-compatible and respect feature boundaries such as event-free `light.js`. Build affected scripts from source and commit their generated distributions. Review source and build inputs first, using relevant generated output to verify those changes. Keep previously published pinned versions and their SRI bytes unchanged unless explicitly requested. + +## Validation and review + +7. **Verify affected behavior locally.** Use the Node and pnpm versions declared by the repository configuration and the commands available in `package.json`; see `README.md` for setup. For script changes, rebuild before focused before/after payload and browser-interaction checks. Prefer the offline suites in `test/unit/` for local runs. Follow the shared testing policy and ensure committed tests run with declared dependencies. Leave the full BrowserStack matrix to CI unless explicitly requested, and report local verification separately from remote CI. + +8. **Keep PRs easy to review.** Prefer one logical change per PR. Group related fixes under one issue, state dependencies and merge order, and branch from and target the integration branch requested by the user. Keep unrelated test-infrastructure repairs separate from tracker behavior changes. diff --git a/README.md b/README.md index 1ca708c..4151c02 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ As our public scripts are very important in our mission to privacy we decided to ## Contribute -If you want to contribute, you probabaly want to contribute to our [`/src/default.js`](src/default.js) or [`/src/auto-events.js`](src/auto-events.js) files. These files compile into a few versions of our script by [`compile.js`](compile.js). They end up on [our CDN](https://scripts.simpleanalyticscdn.com/latest.js), custom domains, and [the Cloudflare app](https://www.cloudflare.com/apps/simpleanalytics). +If you want to contribute, you probabaly want to contribute to our [`/src/default.js`](src/default.js) or [`/src/auto-events.js`](src/auto-events.js) files. These files compile into a few versions of our script by [`compile.js`](compile.js). They end up on [our CDN](https://scripts.simpleanalyticscdn.com/latest.js) and custom domains. In `default.js` you see some weird syntax in the comments. For example, `/** if ignorepages **/` _\[some code\]_ `/** endif **/`. These comments are converted to handlebars like this: `{{#if ignorepages }}` _\[some code\]_ `{{/if}}`. In this case, [`ignorepages` is a variable](https://github.com/simpleanalytics/scripts/blob/3874b44ce5f1b0b8a7d50fb512fdcf5285a0138f/minify.js#L66) used in `minify.js` that takes care of what functionality to show in what script. Our main script is the `latest.js` script which includes all features. We also have a `light.js` script that obviously doesn't. diff --git a/compile.js b/compile.js index 52f4bbf..2774627 100644 --- a/compile.js +++ b/compile.js @@ -3,12 +3,13 @@ const UglifyJS = require("uglify-js"); const fs = require("fs"); const esprima = require("esprima"); const path = require("path"); +const acorn = require("acorn"); const GREEN = "\x1b[32m%s\x1b[0m"; const YELLOW = "\x1b[33m%s\x1b[0m"; const RED = "\x1b[31m%s\x1b[0m"; -const VERSION = 11; +const VERSION = 12; Handlebars.registerHelper("or", function (param1, param2) { return param1 || param2; @@ -24,7 +25,7 @@ const MINIFY_OPTIONS = { nameCache: null, }; -const fillTemplate = (template, { overwriteOptions = null } = {}) => { +const fillTemplate = (template) => { if (!template) throw new Error("Parsing of the JavaScript failed, please use ES5 only."); return template @@ -35,16 +36,6 @@ const fillTemplate = (template, { overwriteOptions = null } = {}) => { .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"' ); }; @@ -77,7 +68,6 @@ const DEFAULTS = { nonuniquehostnames: true, ignoremetrics: true, dev: false, - skipnonwindow: false, }; const LIGHT = { @@ -156,36 +146,6 @@ const templates = [ apiUrlPrefix: "queue.", }, }, - { - type: "js", - input: `${__dirname}/src/default.js`, - output: `cloudflare.js`, - variables: { - ...DEFAULTS, - skipnonwindow: true, - minify: false, - version: VERSION, - scriptName: `cloudflare_${VERSION}`, - sri: false, - baseUrl: "{{cloudFlareCustomDomain}}", - overwriteOptions: { - hostname: "INSTALL_OPTIONS.hostname", - collectDnt: - "typeof INSTALL_OPTIONS.collect_dnt === 'boolean' ? INSTALL_OPTIONS.collect_dnt : null", - mode: "INSTALL_OPTIONS.hash_mode ? 'hash' : 'normal'", - strictUtm: - "INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.strict_utm", - allowParams: - "INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.allow_url_parameters", - nonUniqueHostnames: - "INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.non_unique_hostnames", - ignorePages: - "INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.ignore_pages", - namespace: - "INSTALL_OPTIONS.overwrite_namespace && INSTALL_OPTIONS.namespace", - }, - }, - }, { type: "js", input: `${__dirname}/src/default.js`, @@ -308,10 +268,7 @@ for (const file of files) { const finalFileName = output.split("/").pop(); const template = Handlebars.compile(contents); - const rawCode = template({ - ...variables, - overwriteOptions: "{{overwriteOptions}}", - }); + const rawCode = template(variables); const date = new Date().toISOString().slice(0, 10); const hash = require("crypto") @@ -320,7 +277,7 @@ for (const file of files) { .digest("hex") .slice(0, 4); - const prepend = `/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; ${date}; ${hash}${ + const prepend = `/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; ${date}; ${hash}${ variables.sri ? `; SRI-version` : "" }${variables.version ? `; v${variables.version}` : ""}) */\n`; @@ -358,7 +315,32 @@ for (const file of files) { for (const warning of warnings || []) console.warn(YELLOW, `[${name}] ${warning}`); - const code = fillTemplate(codeTemplate, variables); + try { + acorn.parse(rawCode, { ecmaVersion: 5 }); + } catch (error) { + // console.log("acorn", error); + + // error object: + // pos: 147, + // loc: Position { line: 12, column: 0 }, + // raisedAt: 148 + + // Find part of the code that is causing the error + const lines = rawCode.split("\n"); + const line = error.loc.line; + const column = error.loc.column; + const start = Math.max(0, line - 3); + const end = Math.min(lines.length, line + 3); + const codeSnippet = lines.slice(start, end).join("\n"); + const sentence = lines[error.loc.line - 1]; + + // console.log({ codeSnippet, line: lines[error.loc.line - 1] }); + + throw new Error( + `${error.message} at line ${sentence} position ${column}: ${codeSnippet}` + ); + } + const code = fillTemplate(codeTemplate); const validate = template({ ...variables, @@ -385,7 +367,7 @@ for (const file of files) { fs.mkdirSync(path.dirname(latestFile), { recursive: true }); } - const compiledMap = map ? fillTemplate(map, variables) : null; + const compiledMap = map ? fillTemplate(map) : null; const isCustom = /^custom\//.test(output); if (variables.version && variables.sri) { diff --git a/deploy.mts b/deploy.mts index b595327..956fb90 100644 --- a/deploy.mts +++ b/deploy.mts @@ -71,8 +71,8 @@ const CDN_PUBLIC_ROOT = "https://scripts.simpleanalyticscdn.com"; const CDN_STORAGE_ROOT = "https://storage.bunnycdn.com/sa-cdn"; const CDN_PURGE_URL = "https://api.bunny.net/purge?url=https://simpleanalyticscdn.b-cdn.net/*"; -const HEADER_PATTERN = - /^\/\* Simple Analytics - Privacy friendly analytics \(docs\.simpleanalytics\.com\/[^;]+; \d{4}-\d{2}-\d{2}; [0-9a-f]{4}(?:; SRI-version)?(?:; v\d+)?\) \*\/$/; +export const HEADER_PATTERN = + /^\/\* Simple Analytics - Privacy(?: friendly|-first) analytics \(docs\.simpleanalytics\.com\/[^;]+; \d{4}-\d{2}-\d{2}; [0-9a-f]{4}(?:; SRI-version)?(?:; v\d+)?\) \*\/$/; const ansi = { bold: (value: string) => color("1", value), diff --git a/dist/latest/auto-events.js b/dist/latest/auto-events.js index c55140e..cd391b6 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; 2026-08-17; 5dd7; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 99ad; v12) */ -function r(t,e){var a,o=!1;p.downloads&&/^https?:\/\//i.test(t.href)&&new RegExp("\\.("+(p.downloadsExtensions||[]).join("|")+")$","i").test(t.pathname)?o="download":p.outbound&&/^https?:\/\//i.test(t.href)&&t.hostname!==m.location.hostname?o="outbound":p.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(){saAutomatedLink(this,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 (\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 () {\n saAutomatedLink(this, 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","saAutomatedLink","this","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","element","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState","target"],"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 \"phones\",\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 phones: collectTypes.indexOf(\"phones\") > -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 var saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\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 || type === \"phone\") {\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 case \"phone\": {\n var hrefPhone = element.getAttribute(\"href\");\n event = (hrefPhone.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.phone = event;\n break;\n }\n }\n }\n if (useTitle) event = theTitle;\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, function () {}, true);\n\n log(\"collected \" + clean);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n window.saAutomatedLink = saAutomatedLink;\n\n function collectLink(link) {\n if (link.hasAttribute(\"data-simple-event\")) return;\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 // Collect telephone clicks\n } else if (optionsLink.phones && /^tel:/i.test(link.href)) {\n collect = \"phone\";\n }\n\n if (!collect) return;\n\n link.addEventListener(\"click\", function () {\n saAutomatedLink(this, collect);\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 collectLink(link);\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":["onDOMContentLoaded","a","document","getElementsByTagName","i","length","link","getAttribute","collect","hasAttribute","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","phones","addEventListener","saAutomatedLink","this","collectLink","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","element","theTitle","metadata","undefined","url","useTitle","event","pop","email","phone","clean","replace","readyState","target"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/cloudflare.js b/dist/latest/cloudflare.js deleted file mode 100644 index adc0447..0000000 --- a/dist/latest/cloudflare.js +++ /dev/null @@ -1,943 +0,0 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-08-17; 6b9f; v11) */ -/* eslint-env browser */ - -(function ( - window, - overwriteOptions, - baseUrl, - apiUrlPrefix, - version, - defaultNamespace, - sendError, - warn -) { - try { - ///////////////////// - // PREDEFINED VARIABLES FOR BETTER MINIFICATION - // - - // This seems like a lot of repetition, but it makes our script available for - // multple destination which prevents us to need multiple scripts. The minified - // version stays small. - var undefinedVar = undefined; - var trueVar = true; - var falseVar = false; - var trueText = "true"; - var https = "https:"; - var pageviewText = "pageview"; - var eventText = "event"; - var errorText = "error"; - var slash = "/"; - var protocol = https + "//"; - var con = window.console; - var doNotTrack = "doNotTrack"; - var nav = window.navigator; - var loc = window.location; - var locationHostname = loc.host; - var doc = window.document; - var userAgent = nav.userAgent; - var notSending = "Not sending request "; - var notSendingWhen = notSending + "when "; - var fetchedHighEntropyValues = falseVar; - var encodeURIComponentFunc = encodeURIComponent; - var decodeURIComponentFunc = decodeURIComponent; - var stringify = JSON.stringify; - var thousand = 1000; - var addEventListenerFunc = window.addEventListener; - var fullApiUrl = protocol + apiUrlPrefix + baseUrl; - var documentElement = doc.documentElement || {}; - var language = "language"; - var Height = "Height"; - var Width = "Width"; - var scroll = "scroll"; - var uaData = nav.userAgentData; - var scrollHeight = scroll + Height; - var offsetHeight = "offset" + Height; - var clientHeight = "client" + Height; - var clientWidth = "client" + Width; - var pagehide = "pagehide"; - var platformText = "platform"; - var platformVersionText = "platformVersion"; - var docsUrl = "https://docs.simpleanalytics.com"; - var pages = 0; - var isBotAgent = - /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent); - var screen = window.screen; - - // Skip server side rendered pages on Cloudflare - if (typeof window == "" + undefinedVar) return; - - // Find the script element where options can be set on - var scriptElement = - doc.currentScript || doc.querySelector('script[src*="' + baseUrl + '"]'); - - ///////////////////// - // HELPER FUNCTIONS - // - - // A simple log function so the user knows why a request is not being send - warn = function () { - // 1. Convert args to a normal array - var args = [].slice.call(arguments); - - // 2. Prepend log prefix - args.unshift("Simple Analytics:"); - - // 3. Pass along arguments to console.warn - // Function.prototype.apply.call is needed for Internet Explorer - return Function.prototype.apply.call(con.warn, con, args); - }; - - var warnInFunction = function (name, error) { - warn("Error in your " + name + " function:", error); - }; - - var hasProp = function (obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); - }; - - var isString = function (string) { - return typeof string == "string"; - }; - - var filterRegex = function (item) { - return item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - }; - - var attr = function (scriptElement, attribute) { - return scriptElement && scriptElement.getAttribute("data-" + attribute); - }; - - var convertCommaSeparatedToArray = function (csv) { - return Array.isArray(csv) - ? csv - : isString(csv) && csv.length - ? csv.split(/, ?/) - : []; - }; - - var isObject = function (object) { - return object && object.constructor === Object; - }; - - var assign = function () { - var to = {}; - var arg = arguments; - for (var index = 0; index < arg.length; index++) { - var nextSource = arg[index]; - if (isObject(nextSource)) { - for (var nextKey in nextSource) { - if (hasProp(nextSource, nextKey)) { - to[nextKey] = nextSource[nextKey]; - } - } - } - } - return to; - }; - - var settings = window.sa_settings; - var logSettings = settings || Object.keys(overwriteOptions).length; - - // Merge overwriteOptions with sa_settings - overwriteOptions = assign(overwriteOptions, settings); - - if (logSettings) warn("Settings", overwriteOptions); - - // Customers can skip data points - var ignoreMetrics = convertCommaSeparatedToArray( - overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics") - ); - - var collectMetricByString = function (metricAbbreviation) { - // Can't use Array.find() here because we need to support IE9 - return ( - ignoreMetrics.filter(function (item) { - return new RegExp("^" + metricAbbreviation).test(item); - }).length === 0 - ); - }; - - var now = Date.now; - - var uuid = function () { - var cryptoObject = window.crypto || window.msCrypto; - var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11; - var uuidRegex = /[018]/g; - - try { - return emptyUUID.replace(uuidRegex, function (c) { - return ( - c ^ - (cryptoObject.getRandomValues(new Uint8Array(1))[0] & - (15 >> (c / 4))) - ).toString(16); - }); - } catch (error) { - return emptyUUID.replace(uuidRegex, function (c) { - var r = (Math.random() * 16) | 0, - v = c < 2 ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); - } - }; - - var isFunction = function (func) { - return typeof func == "function"; - }; - - // Define namespace for the library - var namespaceText = "namespace"; - var namespace = - overwriteOptions[namespaceText] || - attr(scriptElement, namespaceText) || - defaultNamespace; - - var metadataObject = window[namespace + "_metadata"]; - var appendMetadata = function (metadata, data) { - if (isObject(metadataObject)) metadata = assign(metadata, metadataObject); - var metadataCollectorFunction = window[metadataCollector]; - if (!isFunction(metadataCollectorFunction)) return metadata; - try { - return assign( - metadata, - metadataCollectorFunction.call(window, assign(metadata, data)) - ); - } catch (error) { - warnInFunction("metadata", error); - } - }; - - var isBoolean = function (value) { - return !!value === value; - }; - - // By default we allow source, medium in the URLs. With strictUtm enabled - // we only allow it with the utm_ prefix: utm_source, utm_medium, ... - var strictUtm = - overwriteOptions.strictUtm || - attr(scriptElement, "strict-utm") == trueText; - - var getQueryParams = function (ignoreSource) { - return ( - loc.search - .slice(1) - .split("&") - .filter(function (keyValue) { - var ignore = ignoreSource || !collectMetricByString("ut"); - - var paramsRegexList = allowParams.map(filterRegex).join("|"); - var regex = ignore - ? "^(" + paramsRegexList + ")=" - : "^((utm_)" + - (strictUtm ? "" : "?") + - "(source|medium|content|term|campaign)" + - (strictUtm ? "" : "|ref") + - "|" + - paramsRegexList + - ")="; - if (ignore && !allowParams.length) return falseVar; - - // The prefix "utm_" is optional with "strictUtm" disabled - // "ref" is only collected when "strictUtm" is disabled - return new RegExp(regex).test(keyValue); - }) - .join("&") || undefinedVar - ); - }; - - // Ignore pages specified in data-ignore-pages - var shouldIgnore = function (path) { - for (var i in ignorePages) { - var ignorePageRaw = ignorePages[i]; - if (!ignorePageRaw) continue; - - // Prepend a slash when it's missing - var ignorePage = - ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw; - - if ( - ignorePage === path || - new RegExp( - "^" + filterRegex(ignorePage).replace(/\\\*/gi, "(.*)") + "$", - "i" - ).test(path) - ) - return trueVar; - } - return falseVar; - }; - - ///////////////////// - // Warn when using script twice - // - - // Only load our script once, customers can still send multiple page views - // with the sa_pageview function if they turn off auto collect. - var loadedVariable = namespace + "_loaded"; - if (window[loadedVariable] == trueVar) return warn(notSending + "twice"); - window.sa_event_loaded = trueVar; - window[loadedVariable] = trueVar; - - ///////////////////// - // SEND DATA VIA OUR PIXEL - // - - // Send data via image - var sendData = function (data, callback, onlyThisData) { - data = onlyThisData ? data : assign(payload, page, data); - - if (nav.brave && !onlyThisData) data.brave = trueVar; - if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar; - - - var image = new Image(); - if (callback) { - image.onerror = callback; - image.onload = callback; - } - image.src = - fullApiUrl + - "/simple.gif?" + - Object.keys(data) - .filter(function (key) { - return data[key] != undefinedVar; - }) - .map(function (key) { - return ( - encodeURIComponentFunc(key) + - "=" + - encodeURIComponentFunc(data[key]) - ); - }) - .join("&") + - "&time=" + - Date.now(); - }; - - // Customers can overwrite their hostname, here we check for that - var overwrittenHostname = - overwriteOptions.hostname || attr(scriptElement, "hostname"); - var definedHostname = overwrittenHostname || locationHostname; - - var basePayload = { - version: version, - hostname: definedHostname, - }; - - ///////////////////// - // ERROR FUNCTIONS - // - - // Send errors - // no var because it's scoped outside of the try/catch - sendError = function (errorOrMessage) { - errorOrMessage = errorOrMessage.stack - ? errorOrMessage + " " + errorOrMessage.stack - : errorOrMessage; - warn(errorOrMessage); - sendData( - assign(basePayload, { - type: errorText, - error: errorOrMessage, - path: loc.pathname, - }), - undefinedVar, - trueVar - ); - }; - - // We listen for the error events and only send errors that are - // from our script (checked by filename) to our server. - addEventListenerFunc( - errorText, - function (event) { - if (event.filename && event.filename.indexOf(baseUrl) > -1) { - sendError(event.message); - } - }, - falseVar - ); - - ///////////////////// - // INITIALIZE VALUES - // - - var start = now(); - - var scrolled = 0; - - ///////////////////// - // GET SETTINGS - // - - // Script mode, this can be hash mode for example - var mode = overwriteOptions.mode || attr(scriptElement, "mode"); - - // Should we record Do Not Track visits? - var collectDnt = isBoolean(overwriteOptions.collectDnt) - ? overwriteOptions.collectDnt - : attr(scriptElement, "ignore-dnt") == trueText || - attr(scriptElement, "skip-dnt") == trueText || - attr(scriptElement, "collect-dnt") == trueText; - - // Some customers want to collect page views manually - var autoCollect = !( - attr(scriptElement, "auto-collect") == "false" || - overwriteOptions.autoCollect === falseVar - ); - - // Event function name - var eventFunctionName = - overwriteOptions.saGlobal || - attr(scriptElement, "sa-global") || - namespace + "_" + eventText; - - // Customers can ignore certain pages - var ignorePages = convertCommaSeparatedToArray( - overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages") - ); - - // Customers can allow params - var allowParams = convertCommaSeparatedToArray( - overwriteOptions.allowParams || attr(scriptElement, "allow-params") - ); - - // Customers can allow params - var nonUniqueHostnames = convertCommaSeparatedToArray( - overwriteOptions.nonUniqueHostnames || - attr(scriptElement, "non-unique-hostnames") - ); - - // Customers can overwrite certain values - var pathOverwriter = - overwriteOptions.pathOverwriter || attr(scriptElement, "path-overwriter"); - - // Customers can add metadata to events and pageviews via a function - var metadataCollector = - overwriteOptions.metadataCollector || - attr(scriptElement, "metadata-collector"); - - // This code could error on (incomplete) implementations, that's why we use try...catch - var timezone; - try { - // c = countries - timezone = collectMetricByString("c") - ? Intl.DateTimeFormat().resolvedOptions().timeZone - : undefinedVar; - } catch (error) { - warn(error); - } - - ///////////////////// - // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS - // - - var bot = - nav.webdriver || - window.__nightmare || - window.callPhantom || - window._phantom || - window.phantom || - window.__polypane || - window._bot || - isBotAgent || - Math.random() == Math.random(); - - // t = timeonpage, scro = scrolled - var collectDataOnLeave = - collectMetricByString("t") || collectMetricByString("scro"); - - if (bot) basePayload.bot = trueVar; - - var payload = assign(basePayload, { - // us = useragent - ua: collectMetricByString("us") ? userAgent : undefinedVar, - - https: loc.protocol == https, - timezone: timezone, - page_id: collectDataOnLeave ? uuid() : undefinedVar, - - // se = sessions - session_id: collectMetricByString("se") ? uuid() : undefinedVar, - }); - - payload.sri = falseVar; - - // Use User-Agent Client Hints for better privacy - // https://web.dev/user-agent-client-hints/ - if (uaData) { - payload.mobile = uaData.mobile; - payload.brands = stringify(uaData.brands); - } - - ///////////////////// - // ADD WARNINGS - // - - - // Warn when no document.doctype is defined (this breaks some documentElement dimensions) - if (!doc.doctype) warn("Add DOCTYPE html for accurate dimensions"); - - // When a customer overwrites the hostname, we need to know what the original - // hostname was to hide that domain from referrer traffic - if (definedHostname !== locationHostname) - payload.hostname_original = locationHostname; - - // Don't track when Do Not Track is set to true - if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == "1") - return warn( - notSendingWhen + doNotTrack + " is enabled. See " + docsUrl + "/dnt" - ); - - // Warn when sending from localhost and not having a hostname set - if ( - (locationHostname.indexOf(".") == -1 || - /^[0-9.:]+$/.test(locationHostname)) && - !overwrittenHostname - ) - warn( - "Set hostname on " + - locationHostname + - ". See " + - docsUrl + - "/overwrite-domain-name" - ); - - ///////////////////// - // SETUP INITIAL VARIABLES - // - - var page = {}; - var lastSendPath; - - var getReferrer = function () { - return ( - (doc.referrer || "") - .replace(locationHostname, definedHostname) - .replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/, "$4") - .replace(/^([^/]+)$/, "$1") || undefinedVar - ); - }; - - // We don't want to end up with sensitive data so we clean the referrer URL - var referrer = getReferrer(); - - ///////////////////// - // TIME ON PAGE AND SCROLLED LOGIC - // - - // We don't put msHidden in if duration block, because it's used outside of that functionality - var msHidden = 0; - - var sendOnLeave = function (id, push) { - if (!collectDataOnLeave) return; - - var append = assign(basePayload, { - type: "append", - original_id: push ? id : payload.page_id, - }); - - // t = timeonpage - if (collectMetricByString("t")) { - append.duration = Math.round((now() - start - msHidden) / thousand); - } - msHidden = 0; - start = now(); - - // scro = scrolled - if (collectMetricByString("scro")) { - append.scrolled = Math.max(0, scrolled, position()); - } - - if (push || !nav.sendBeacon) { - // sendData will assign payload to request - sendData(append, undefinedVar, trueVar); - } else { - nav.sendBeacon(fullApiUrl + "/append", stringify(append)); - } - }; - - var hiddenStart; - addEventListenerFunc( - "visibilitychange", - function () { - if (doc.hidden) { - if (!("on" + pagehide in window)) sendOnLeave(); - hiddenStart = now(); - } else msHidden += now() - hiddenStart; - }, - falseVar - ); - - addEventListenerFunc(pagehide, sendOnLeave, falseVar); - - var body = doc.body || {}; - var position = function () { - try { - var documentClientHeight = documentElement[clientHeight] || 0; - var height = Math.max( - body[scrollHeight] || 0, - body[offsetHeight] || 0, - documentElement[clientHeight] || 0, - documentElement[scrollHeight] || 0, - documentElement[offsetHeight] || 0 - ); - return Math.min( - 100, - Math.round( - (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) / - height / - 5 - ) * 5 - ); - } catch (error) { - warn(error); - return 0; - } - }; - - addEventListenerFunc("load", function () { - scrolled = position(); - addEventListenerFunc( - scroll, - function () { - if (scrolled < position()) scrolled = position(); - }, - falseVar - ); - }); - - ///////////////////// - // ACTUAL PAGE VIEW LOGIC - // - - var getPath = function (overwrite) { - var path = ""; - - // decodeURIComponent can fail when having invalid characters - // https://github.com/simpleanalytics/roadmap/issues/462 - try { - path = overwrite || decodeURIComponentFunc(loc.pathname); - } catch (error) { - warn(error); - } - - var pathOverwriterFunction = window[pathOverwriter]; - if (isFunction(pathOverwriterFunction)) { - try { - path = pathOverwriterFunction.call(window, { path: path }) || path; - } catch (error) { - warnInFunction("path", error); - } - } - - // Ignore pages specified in data-ignore-pages - if (shouldIgnore(path)) { - warn(notSendingWhen + "ignoring " + path); - return; - } - - // Add hash to path when script is put in to hash mode - if (mode == "hash" && loc.hash) path += loc.hash.split("?")[0]; - - return path; - }; - - var previousReferrer; - - // Send page view and append data to it - var sendPageView = function ( - isPushState, - deleteSourceInfo, - sameSite, - metadata - ) { - if (isPushState) sendOnLeave("" + payload.page_id, trueVar); - if (collectDataOnLeave) payload.page_id = uuid(); - - var currentPage = definedHostname + getPath(); - - sendData({ - id: payload.page_id, - type: pageviewText, - referrer: !deleteSourceInfo || sameSite ? referrer : null, - query: getQueryParams(deleteSourceInfo), - - metadata: stringify(metadata), - }); - - previousReferrer = referrer; - referrer = currentPage; - - pages++; - }; - - var sameSite, userNavigated; - - var pageview = function (isPushState, pathOverwrite, metadata) { - // Obfuscate personal data in URL by dropping the search and hash - var path = getPath(pathOverwrite); - - // Don't send the last path again (this could happen when pushState is used to change the path hash or search) - if (!path || lastSendPath == path) return; - - lastSendPath = path; - page.path = path; - - // v = viewportsizes - if (collectMetricByString("v")) { - page.viewport_width = - Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) || - null; - page.viewport_height = - Math.max( - documentElement[clientHeight] || 0, - window.innerHeight || 0 - ) || null; - } - - // l = language - if (collectMetricByString("l")) { - if (nav[language]) page[language] = nav[language]; - } - - // sc = screensizes - if (screen && collectMetricByString("sc")) { - page.screen_width = screen.width; - page.screen_height = screen.height; - } - - // If a user does refresh we need to delete the referrer because otherwise it count double - var perf = window.performance; - var navigationText = "navigation"; - - // Check if back, forward or reload buttons are being used in modern browsers - var performaceEntryType; - try { - performaceEntryType = perf.getEntriesByType(navigationText)[0].type; - } catch (error) { - warn(error); - } - - userNavigated = performaceEntryType - ? ["reload", "back_forward"].indexOf(performaceEntryType) > -1 - : // Check if back, forward or reload buttons are being use in older browsers - // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD - perf && - perf[navigationText] && - [1, 2].indexOf(perf[navigationText].type) > -1; - - // Check if referrer is the same as current real hostname (not the defined hostname!) - var currentReferrerHostname = referrer - ? referrer.split(slash)[0] - : undefinedVar; - sameSite = referrer - ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 || - currentReferrerHostname == locationHostname - : falseVar; - - // We set unique variable based on pushstate or back navigation, if no match we check the referrer - page.unique = isPushState || userNavigated ? falseVar : !sameSite; - - metadata = appendMetadata(metadata, { - type: pageviewText, - path: page.path, - }); - - var triggerSendPageView = function () { - fetchedHighEntropyValues = trueVar; - sendPageView( - isPushState, - isPushState || userNavigated || !collectMetricByString("r"), // r = referrers - sameSite, - metadata - ); - }; - - if (!fetchedHighEntropyValues) { - // Request platform information if this is available - try { - if (uaData && isFunction(uaData.getHighEntropyValues)) { - uaData - .getHighEntropyValues([platformText, platformVersionText]) - .then(function (highEntropyValues) { - payload.os_name = highEntropyValues[platformText]; - payload.os_version = highEntropyValues[platformVersionText]; - triggerSendPageView(); - }) - .catch(triggerSendPageView); - } else { - triggerSendPageView(); - } - } catch (e) { - triggerSendPageView(); - } - } else { - triggerSendPageView(); - } - }; - - ///////////////////// - // AUTOMATED PAGE VIEW COLLECTION - // - - var his = window.history; - var hisPushState = his ? his.pushState : undefinedVar; - var dis = window.dispatchEvent; - var pushStateText = "pushState"; - - // Overwrite history pushState function to - // allow listening on the pushState event - if (autoCollect && hisPushState && Event && dis) { - var stateListener = function (type) { - var orig = his[type]; - return function () { - var arg = arguments; - var rv = orig.apply(this, arg); - var event; - if (isFunction(Event)) { - event = new Event(type); - } else { - // Fix for IE - // https://github.com/simpleanalytics/scripts/issues/8 - event = doc.createEvent("Event"); - event.initEvent(type, trueVar, trueVar); - } - event.arguments = arg; - dis(event); - return rv; - }; - }; - - his.pushState = stateListener(pushStateText); - - addEventListenerFunc( - pushStateText, - function () { - pageview(1); - }, - falseVar - ); - - addEventListenerFunc( - "popstate", - function () { - pageview(1); - }, - falseVar - ); - } - - // When in hash mode, we record a pageview based on the onhashchange function - if (autoCollect && mode == "hash" && "onhashchange" in window) { - addEventListenerFunc( - "hashchange", - function () { - pageview(1); - }, - falseVar - ); - } - - if (autoCollect) pageview(); - else { - window.sa_pageview = function (path, metadata) { - pageview(0, path, metadata); - }; - } - - ///////////////////// - // EVENTS - // - - var validTypes = ["string", "number"]; - - var sendEvent = function (event, metadata, callbackRaw) { - if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata; - - var eventIsFunction = isFunction(event); - var callback = isFunction(callbackRaw) ? callbackRaw : function () {}; - var eventType = typeof event; - - if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) { - warnInFunction(eventFunctionName, eventText + " can't be " + eventType); - return callback(); - } - - try { - if (eventIsFunction) { - var eventOutput = event(); - if (validTypes.indexOf(typeof eventOutput) < 0) { - warnInFunction( - eventFunctionName, - event + " returns no string: " + eventOutput - ); - return callback(); - } - event = eventOutput; - } - } catch (error) { - warnInFunction(eventFunctionName, error); - return callback(); - } - - event = ("" + event).replace(/[^a-z0-9]+/gi, "_").replace(/(^_|_$)/g, ""); - - var eventParams = { type: eventText, event: event }; - var firstPage = !userNavigated && pages < 2; - - metadata = appendMetadata(metadata, eventParams); - - if (event) { - sendData( - assign(eventParams, { - id: uuid(), - query: getQueryParams(!firstPage), - referrer: - (firstPage || sameSite) && collectMetricByString("r") - ? previousReferrer - : null, - - metadata: stringify(metadata), - }), - callback - ); - } - }; - - var defaultEventFunc = function (event, metadata, callback) { - sendEvent(event, metadata, callback); - }; - - // Set default function if user didn't define a function - if (!window[eventFunctionName]) - window[eventFunctionName] = defaultEventFunc; - - var eventFunc = window[eventFunctionName]; - - // Read queue of the user defined function - var queue = eventFunc && eventFunc.q ? eventFunc.q : []; - - // Overwrite user defined function - window[eventFunctionName] = defaultEventFunc; - - // Post events from the queue of the user defined function - for (var event in queue) { - if (hasProp(queue, event)) { - Array.isArray(queue[event]) - ? sendEvent.apply(null, queue[event]) - : sendEvent(queue[event]); - } - } - } catch (e) { - sendError(e); - } -})( - window, - {"hostname":INSTALL_OPTIONS.hostname,"collectDnt":typeof INSTALL_OPTIONS.collect_dnt === 'boolean' ? INSTALL_OPTIONS.collect_dnt : null,"mode":INSTALL_OPTIONS.hash_mode ? 'hash' : 'normal',"strictUtm":INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.strict_utm,"allowParams":INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.allow_url_parameters,"nonUniqueHostnames":INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.non_unique_hostnames,"ignorePages":INSTALL_OPTIONS.advanced_settings_toggle && INSTALL_OPTIONS.ignore_pages,"namespace":INSTALL_OPTIONS.overwrite_namespace && INSTALL_OPTIONS.namespace}, - INSTALL_OPTIONS.custom_domain || "queue.simpleanalyticscdn.com", - "", - "cloudflare_11", - "sa" -); diff --git a/dist/latest/custom/app.js b/dist/latest/custom/app.js index bd85d87..1f3a204 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; 2026-08-17; 2eca; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 65b4; v12) */ -!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"); +!function(v,e,n,m){var r,a,t;if(v)try{var g=undefined,y=!0,_=!1,i="true",o="https:",w="pageview",l="event",c="error",s=v.console,u="doNotTrack",b=v.navigator,f=v.location,x=f.host,p=v.document,d=b.userAgent,h="Not sending request ",E=h+"when ",O=_,M=encodeURIComponent,S=decodeURIComponent,k=JSON.stringify,A=v.addEventListener,q="https://"+e,C=p.documentElement||{},D="language",$="Height",H="scroll",R=b.userAgentData,j=H+$,L="offset"+$,N="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(d)&&!/(cubot)/i.test(d),F=v.screen,z=p.currentScript||p.querySelector('script[src*="'+e+'"]');m=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(s.warn,s,t)};var W=function(t,e){m("Error in your "+t+" function:",e)},G=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},J=function(t){return"string"==typeof t},X=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},Y=function(t,e){return t&&t.getAttribute("data-"+e)},Z=function(t){return Array.isArray(t)?t:J(t)&&t.length?t.split(/, ?/):[]},K=function(t){return t&&t.constructor===Object},Q=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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=v[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=v[qt];if(!ct(r))return qt&&m(qt+" not found, set window."+qt),t;try{return Q(t,r.call(v,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,pt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0"); //# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/dist/latest/custom/app.js.map b/dist/latest/custom/app.js.map index fd21da9..a8d8242 100644 --- a/dist/latest/custom/app.js.map +++ b/dist/latest/custom/app.js.map @@ -1 +1 @@ -{"version":3,"file":"app.source.js","sources":["app.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n overwriteOptions,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings || Object.keys(overwriteOptions).length;\n\n // Merge overwriteOptions with sa_settings\n overwriteOptions = assign(overwriteOptions, settings);\n\n if (logSettings) warn(\"Settings\", overwriteOptions);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n overwriteOptions.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var metadataObject = window[namespace + \"_metadata\"];\n var appendMetadata = function (metadata, data) {\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) return metadata;\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(overwriteOptions.collectDnt)\n ? overwriteOptions.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n overwriteOptions.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n overwriteOptions.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n overwriteOptions.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n overwriteOptions.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n overwriteOptions.nonUniqueHostnames ||\n attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n overwriteOptions.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n overwriteOptions.metadataCollector ||\n attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n window.phantom ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n metadata: stringify(metadata),\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // We set unique variable based on pushstate or back navigation, if no match we check the referrer\n page.unique = isPushState || userNavigated ? falseVar : !sameSite;\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n else {\n window.sa_pageview = function (path, metadata) {\n pageview(0, path, metadata);\n };\n }\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback) {\n sendEvent(event, metadata, callback);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n } catch (e) {\n sendError(e);\n }\n})(\n window,\n {},\n \"\",\n \"\",\n \"custom_app_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","sendError","warn","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","settings","sa_settings","logSettings","keys","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","metadataObject","appendMetadata","metadata","data","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","search","keyValue","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","src","key","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","type","path","pathname","event","filename","indexOf","message","timezone","start","scrolled","mode","collectDnt","value","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","webdriver","__nightmare","callPhantom","_phantom","phantom","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","i","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","orig","rv","this","createEvent","initEvent","sa_pageview","validTypes","sendEvent","callbackRaw","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","q"],"mappings":";;CAEA,SACEA,EACAC,EACAC,EAIAC,EACAC,GAEA,IAQE,IAAIC,EAAeC,UACfC,GAAU,EACVC,GAAW,EACXC,EAAW,OACXC,EAAQ,SACRC,EAAe,WACfC,EAAY,QACZC,EAAY,QAGZC,EAAMd,EAAOe,QACbC,EAAa,aACbC,EAAMjB,EAAOkB,UACbC,EAAMnB,EAAOoB,SACbC,EAAmBF,EAAIG,KACvBC,EAAMvB,EAAOwB,SACbC,EAAYR,EAAIQ,UAChBC,EAAa,uBACbC,EAAiBD,EAAa,QAC9BE,EAA2BpB,EAC3BqB,EAAyBC,mBACzBC,EAAyBC,mBACzBC,EAAYC,KAAKD,UAEjBE,EAAuBnC,EAAOoC,iBAC9BC,EAhBW3B,WAgB4BR,EACvCoC,EAAkBf,EAAIe,iBAAmB,GACzCC,EAAW,WACXC,EAAS,SAETC,EAAS,SACTC,EAASzB,EAAI0B,cACbC,EAAeH,EAASD,EACxBK,EAAe,SAAWL,EAC1BM,EAAe,SAAWN,EAE1BO,EAAW,WACXC,EAAe,WACfC,EAAsB,kBACtBC,EAAU,mCACVC,EAAQ,EACRC,EACF,sBAAsBC,KAAK5B,KAAe,WAAW4B,KAAK5B,GACxD6B,EAAStD,EAAOsD,OAIhBC,EACFhC,EAAIiC,eAAiBjC,EAAIkC,cAAc,gBAAkBvD,EAAU,MAOrEE,EAAO,WAEL,IAAIsD,EAAO,GAAGC,MAAMC,KAAKC,WAOzB,OAJAH,EAAKI,QAAQ,qBAINC,SAASC,UAAUC,MAAML,KAAK9C,EAAIV,KAAMU,EAAK4C,IAGtD,IAAIQ,EAAiB,SAAUC,EAAMC,GACnChE,EAAK,iBAAmB+D,EAAO,aAAcC,IAG3CC,EAAU,SAAUC,EAAKC,GAC3B,OAAOC,OAAOR,UAAUS,eAAeb,KAAKU,EAAKC,IAO/CG,EAAc,SAAUC,GAC1B,OAAOA,EAAKC,QAAQ,sBAAuB,SAGzCC,EAAO,SAAUtB,EAAeuB,GAClC,OAAOvB,GAAiBA,EAAcwB,aAAa,QAAUD,IAG3DE,EAA+B,SAAUC,GAC3C,OAAOC,MAAMC,QAAQF,GACjBA,EAboB,iBAcXA,GAAQA,EAAIG,OACnBH,EAAII,MAAM,OACV,IAGJC,EAAW,SAAUC,GACvB,OAAOA,GAAUA,EAAOC,cAAgBhB,QAGtCiB,EAAS,WAGX,IAFA,IAAIC,EAAK,GACLC,EAAM9B,UACD+B,EAAQ,EAAGA,EAAQD,EAAIP,OAAQQ,IAAS,CAC/C,IAAIC,EAAaF,EAAIC,GACrB,GAAIN,EAASO,GACX,IAAK,IAAIC,KAAWD,EACdxB,EAAQwB,EAAYC,KACtBJ,EAAGI,GAAWD,EAAWC,IAKjC,OAAOJ,GAGLK,EAAW/F,EAAOgG,YAClBC,EAAcF,GAAYvB,OAAO0B,KAAKjG,GAAkBmF,OAG5DnF,EAAmBwF,EAAOxF,EAAkB8F,GAExCE,GAAa7F,EAAK,WAAYH,GAGlC,IAAIkG,EAAgBnB,EAClB/E,EAAiBkG,eAAiBtB,EAAKtB,EAAe,mBAGpD6C,GAAwB,SAAUC,GAEpC,OAGgB,IAFdF,EAAcG,OAAO,SAAU3B,GAC7B,OAAO,IAAI4B,OAAO,IAAMF,GAAoBhD,KAAKsB,KAChDS,QAIHoB,GAAMC,KAAKD,IAEXE,GAAO,WACT,IAAIC,EAAe3G,EAAO4G,QAAU5G,EAAO6G,SACvCC,EAAY,CAAC,MAAQ,KAAO,KAAO,KAAO,KAC1CC,EAAY,SAEhB,IACE,OAAOD,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,OACEA,EACCL,EAAaM,gBAAgB,IAAIC,WAAW,IAAI,GAC9C,IAAOF,EAAI,GACdG,SAAS,MAEb,MAAO/C,GACP,OAAO0C,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,IAAII,EAAqB,GAAhBC,KAAKC,SAAiB,EAE/B,OADMN,EAAI,EAAII,EAAS,EAAJA,EAAW,GACrBD,SAAS,QAKpBI,GAAa,SAAUC,GACzB,MAAsB,mBAARA,GAIZC,GAAgB,YAChBC,GACFzH,EAAiBwH,KACjB5C,EAAKtB,EAAekE,KA6uBxB,KA1uBME,GAAiB3H,EAAO0H,GAAY,aACpCE,GAAiB,SAAUC,EAAUC,GACnCxC,EAASqC,MAAiBE,EAAWpC,EAAOoC,EAAUF,KAC1D,IAAII,EAA4B/H,EAAOgI,IACvC,IAAKT,GAAWQ,GAA4B,OAAOF,EACnD,IACE,OAAOpC,EACLoC,EACAE,EAA0BnE,KAAK5D,EAAQyF,EAAOoC,EAAUC,KAE1D,MAAO1D,GACPF,EAAe,WAAYE,KAU3B6D,GACFhI,EAAiBgI,WACjBpD,EAAKtB,EAAe,eAAiB9C,EAEnCyH,GAAiB,SAAUC,GAC7B,OACEhH,EAAIiH,OACDzE,MAAM,GACN0B,MAAM,KACNiB,OAAO,SAAU+B,GAChB,IAAIC,EAASH,IAAiB/B,GAAsB,MAEhDmC,EAAkBC,GAAYC,IAAI/D,GAAagE,KAAK,KACpDC,EAAQL,EACR,KAAOC,EAAkB,KACzB,YACCN,GAAY,GAAK,KAClB,yCACCA,GAAY,GAAK,QAClB,IACAM,EACA,KACJ,OAAID,IAAWE,GAAYpD,OAAe5E,EAInC,IAAI+F,OAAOoC,GAAOtF,KAAKgF,KAE/BK,KAAK,MAAQrI,GAgChBuI,GAAiBlB,GAAY,UACjC,GAAI1H,EAAO4I,KAAmBrI,EAAS,OAAOH,EAAKsB,EAAa,SAChE1B,EAAO6I,gBAAkBtI,EACzBP,EAAO4I,IAAkBrI,EAOzB,IAAIuI,GAAW,SAAUhB,EAAMiB,EAAUC,GACvClB,EAAOkB,EAAelB,EAAOrC,EAAOwD,GAASC,GAAMpB,GAE/C7G,EAAIkI,QAAUH,IAAclB,EAAKqB,MAAQ5I,GACzCU,EAAImI,qBAAuBJ,IAAclB,EAAKuB,KAAO9I,GAGzD,IAAI+I,EAAQ,IAAIC,MACZR,IACFO,EAAME,QAAUT,EAChBO,EAAMG,OAASV,GAEjBO,EAAMI,IACJrH,EACA,eACAmC,OAAO0B,KAAK4B,GACTxB,OAAO,SAAUqD,GAChB,OAAO7B,EAAK6B,IAAQtJ,IAErBoI,IAAI,SAAUkB,GACb,OACE9H,EAAuB8H,GACvB,IACA9H,EAAuBiG,EAAK6B,MAG/BjB,KAAK,KACR,SACAjC,KAAKD,OAILoD,GACF3J,EAAiB4J,UAAYhF,EAAKtB,EAAe,YAC/CuG,GAAkBF,IAAuBvI,EAEzC0I,GAAc,CAChBC,QAymBJ,gBAxmBIH,SAAUC,IASZ3J,EAAY,SAAU8J,GACpBA,EAAiBA,EAAeC,MAC5BD,EAAiB,IAAMA,EAAeC,MACtCD,EACJ7J,EAAK6J,GACLnB,GACErD,EAAOsE,GAAa,CAClBI,KAAMtJ,EACNuD,MAAO6F,EACPG,KAAMjJ,EAAIkJ,WAEZhK,EACAE,IAMJ4B,EACEtB,EACA,SAAUyJ,GACJA,EAAMC,WAA+C,EAAnCD,EAAMC,SAASC,QAAQtK,IAC3CC,EAAUmK,EAAMG,UAGpBjK,GAOF,IAwDIkK,GAxDAC,GAAQnE,KAERoE,GAAW,EAOXC,GAAO5K,EAAiB4K,MAAQhG,EAAKtB,EAAe,QAGpDuH,MAvKsBC,GAuKC9K,EAAiB6K,cAtKvBC,GAuKjB9K,EAAiB6K,WACjBjG,EAAKtB,EAAe,eAAiB9C,GACrCoE,EAAKtB,EAAe,aAAe9C,GACnCoE,EAAKtB,EAAe,gBAAkB9C,EAGtCuK,KACqC,SAAvCnG,EAAKtB,EAAe,iBACpBtD,EAAiB+K,cAAgBxK,GAI/ByK,GACFhL,EAAiBiL,UACjBrG,EAAKtB,EAAe,cACpBmE,GAAY,IAAM9G,EAGhBuK,GAAcnG,EAChB/E,EAAiBkL,aAAetG,EAAKtB,EAAe,iBAIlDiF,GAAcxD,EAChB/E,EAAiBuI,aAAe3D,EAAKtB,EAAe,iBAIlD6H,GAAqBpG,EACvB/E,EAAiBmL,oBACfvG,EAAKtB,EAAe,yBAIpB8H,GACFpL,EAAiBoL,gBAAkBxG,EAAKtB,EAAe,mBAGrDyE,GACF/H,EAAiB+H,mBACjBnD,EAAKtB,EAAe,sBAItB,IAEEmH,GAAWtE,GAAsB,KAC7BkF,KAAKC,iBAAiBC,kBAAkBC,SACxCpL,EACJ,MAAO+D,IACPhE,EAAKgE,IAOP,IAAIsH,GACFzK,EAAI0K,WACJ3L,EAAO4L,aACP5L,EAAO6L,aACP7L,EAAO8L,UACP9L,EAAO+L,SACP/L,EAAOgM,YACPhM,EAAOiM,MACP7I,GACAiE,KAAKC,UAAYD,KAAKC,SAGpB4E,GACF9F,GAAsB,MAAQA,GAAsB,QAElDsF,KAAK3B,GAAY2B,IAAMnL,GAE3B,IAAI0I,GAAUxD,EAAOsE,GAAa,CAEhCoC,GAAI/F,GAAsB,MAAQ3E,EAAYpB,EAE9CK,MAAOS,EAAIiL,UAAY1L,EACvBgK,SAAUA,GACV2B,QAASH,GAAqBxF,KAASrG,EAGvCiM,WAAYlG,GAAsB,MAAQM,KAASrG,IA0BrD,GAvBA4I,GAAQsD,IAAM/L,EAIVkC,IACFuG,GAAQuD,OAAS9J,EAAO8J,OACxBvD,GAAQwD,OAASxK,EAAUS,EAAO+J,SAS/BlL,EAAImL,SAAStM,EAAK,4CAInB0J,KAAoBzI,IACtB4H,GAAQ0D,kBAAoBtL,IAGzByJ,IAAc9J,KAAcC,GAA0B,KAAnBA,EAAID,GAC1C,OAAOZ,EACLuB,EAAiBX,EAAa,oBAAsBkC,EAAU,SAK7B,GAAlC7B,EAAiBmJ,QAAQ,OACxB,aAAanH,KAAKhC,IACnBuI,IAEDxJ,EACE,mBACEiB,EACA,SACA6B,EACA,0BAON,IACI0J,GAiDAC,GAlDA3D,GAAO,GAaP4D,IARCvL,EAAIuL,UAAY,IACdlI,QAAQvD,EAAkByI,IAC1BlF,QAAQ,sDAAuD,MAC/DA,QAAQ,YAAa,OAASvE,EAYjC0M,GAAW,EAEXC,GAAc,SAAUC,EAAIC,GAC9B,IAEIC,EAFCjB,KAEDiB,EAAS1H,EAAOsE,GAAa,CAC/BI,KAAM,SACNiD,YAAaF,EAAOD,EAAKhE,GAAQoD,UAI/BjG,GAAsB,OACxB+G,EAAOE,SAAWhG,KAAKiG,OAAO9G,KAAQmE,GAAQoC,IAhfnC,MAkfbA,GAAW,EACXpC,GAAQnE,KAGJJ,GAAsB,UACxB+G,EAAOvC,SAAWvD,KAAKkG,IAAI,EAAG3C,GAAU4C,OAGtCN,IAASjM,EAAIwM,WAEf3E,GAASqE,EAAQ9M,EAAcE,GAE/BU,EAAIwM,WAAWpL,EAAa,UAAWJ,EAAUkL,MAKrDhL,EACE,mBACA,WACMZ,EAAImM,QACA,KAAO3K,KAAY/C,GAASgN,KAClCH,GAAcrG,MACTuG,IAAYvG,KAAQqG,IAE7BrM,GAGF2B,EAAqBY,EAAUiK,GAAaxM,GAE5C,IAAImN,GAAOpM,EAAIoM,MAAQ,GACnBH,GAAW,WACb,IACE,IAAII,EAAuBtL,EAAgBQ,IAAiB,EACxD+K,EAASxG,KAAKkG,IAChBI,GAAK/K,IAAiB,EACtB+K,GAAK9K,IAAiB,EACtBP,EAAgBQ,IAAiB,EACjCR,EAAgBM,IAAiB,EACjCN,EAAgBO,IAAiB,GAEnC,OAAOwE,KAAKyG,IACV,IAKI,EAJJzG,KAAKiG,MACF,MAAQhL,EAAgByL,WAAa,GAAKH,GACzCC,EACA,IAGN,MAAOzJ,IAEP,OADAhE,EAAKgE,IACE,IAIXjC,EAAqB,OAAQ,WAC3ByI,GAAW4C,KACXrL,EACEM,EACA,WACMmI,GAAW4C,OAAY5C,GAAW4C,OAExChN,KAQJ,IAgCIwN,GA6BAC,GAAUC,GA7DVC,GAAU,SAAUC,GACtB,IAAIhE,EAAO,GAIX,IACEA,EAAOgE,GAAarM,EAAuBZ,EAAIkJ,UAC/C,MAAOjG,IACPhE,EAAKgE,IAGP,IAAIiK,EAAyBrO,EAAOqL,IACpC,GAAI9D,GAAW8G,GACb,IACEjE,EAAOiE,EAAuBzK,KAAK5D,EAAQ,CAAEoK,KAAMA,KAAWA,EAC9D,MAAOhG,IACPF,EAAe,OAAQE,IAK3B,IAlYiB,SAAUgG,GAC3B,IAAK,IAAIkE,KAAKnD,GAAa,CACzB,IAAIoD,EAAgBpD,GAAYmD,GAChC,GAAKC,EAAL,CAGA,IAAIC,EAhOI,KAiOND,EAAc,GAAcA,EAjOtB,IAiO8CA,EAEtD,GACEC,IAAepE,GACf,IAAI7D,OACF,IAAM7B,EAAY8J,GAAY5J,QAAQ,SAAU,QAAU,IAC1D,KACAvB,KAAK+G,GAEP,OAAO7J,GAEX,OAAOC,EAgXHiO,CAAarE,GAQjB,MAFY,QAARS,IAAkB1J,EAAIuN,OAAMtE,GAAQjJ,EAAIuN,KAAKrJ,MAAM,KAAK,IAErD+E,EAPLhK,EAAKuB,EAAiB,YAAcyI,IAyCpCuE,GAAW,SAAUC,EAAaC,EAAehH,GAEnD,IAAIuC,EAAO+D,GAAQU,GAGnB,GAAKzE,GAAQwC,IAAgBxC,EAA7B,CAEAwC,GAAexC,EACflB,GAAKkB,KAAOA,EAGRhE,GAAsB,OACxB8C,GAAK4F,eACHzH,KAAKkG,IAAIjL,EAA2B,aAAK,EAAGtC,EAAO+O,YAAc,IACjE,KACF7F,GAAK8F,gBACH3H,KAAKkG,IACHjL,EAAgBQ,IAAiB,EACjC9C,EAAOiP,aAAe,IACnB,MAIL7I,GAAsB,MACpBnF,EAAIsB,KAAW2G,GAAK3G,GAAYtB,EAAIsB,IAItCe,GAAU8C,GAAsB,QAClC8C,GAAKgG,aAAe5L,EAAO6L,MAC3BjG,GAAKkG,cAAgB9L,EAAOuK,QAI9B,IAIIwB,EAJAC,EAAOtP,EAAOuP,YACdC,EAAiB,aAIrB,IACEH,EAAsBC,EAAKG,iBAAiBD,GAAgB,GAAGrF,KAC/D,MAAO/F,IACPhE,EAAKgE,IAGP8J,GAAgBmB,GAC+C,EAA3D,CAAC,SAAU,gBAAgB7E,QAAQ6E,GAGnCC,GACAA,EAAKE,KACwC,EAA7C,CAAC,EAAG,GAAGhF,QAAQ8E,EAAKE,GAAgBrF,MAGxC,IAAIuF,EAA0B5C,GAC1BA,GAASzH,MA7rBH,KA6rBgB,GACtBhF,EACJ4N,GAAWnB,IACgD,EAAvD1B,GAAmBZ,QAAQkF,IAC3BA,GAA2BrO,EAC3Bb,EAGJ0I,GAAKyG,OAASf,GAAeV,GAAgB1N,GAAYyN,GAEzDpG,EAAWD,GAAeC,EAAU,CAClCsC,KAAMxJ,EACNyJ,KAAMlB,GAAKkB,OAGb,IAAIwF,EAAsB,WACxBhO,EAA2BrB,EAnGZ,SACjBqO,EACAiB,EACA5B,EACApG,GAEI+G,GAAa5B,GAAY,GAAK/D,GAAQoD,QAAS9L,GAC/C2L,KAAoBjD,GAAQoD,QAAU3F,MAE1C,IAAIoJ,EAAchG,GAAkBqE,KAEpCrF,GAAS,CACPmE,GAAIhE,GAAQoD,QACZlC,KAAMxJ,EACNmM,UAAW+C,GAAoB5B,EAAWnB,GAAW,KACrDiD,MAAO7H,GAAe2H,GAEtBhI,SAAU5F,EAAU4F,KAGtBmG,GAAmBlB,GACnBA,GAAWgD,EAEX3M,IA6EE6M,CACEpB,EACAA,GAAeV,KAAkB9H,GAAsB,KACvD6H,GACApG,IAIJ,GAAKjG,EAmBHgO,SAjBA,IACMlN,GAAU6E,GAAW7E,EAAOuN,sBAC9BvN,EACGuN,qBAAqB,CAACjN,EAAcC,IACpCiN,KAAK,SAAUC,GACdlH,GAAQmH,QAAUD,EAAkBnN,GACpCiG,GAAQoH,WAAaF,EAAkBlN,GACvC2M,MAEDU,SAAMV,GAETA,IAEF,MAAOW,GACPX,OAWFY,GAAMxQ,EAAOyQ,QACbC,GAAeF,GAAMA,GAAIG,UAAYtQ,EACrCuQ,GAAM5Q,EAAO6Q,cACbC,GAAgB,YAIhB9F,IAAe0F,IAAgBK,OAASH,KAqB1CJ,GAAIG,WAnBEK,GAAOR,GADiBrG,GAoBA2G,IAlBrB,WACL,IAEIxG,EAFA3E,EAAM9B,UACNoN,EAAKD,GAAK/M,MAAMiN,KAAMvL,GAY1B,OAVI4B,GAAWwJ,OACbzG,EAAQ,IAAIyG,MAAM5G,KAIlBG,EAAQ/I,EAAI4P,YAAY,UAClBC,UAAUjH,GAAM5J,EAASA,GAEjC+J,EAAMzG,UAAY8B,EAClBiL,GAAItG,GACG2G,IAMX9O,EACE2O,GACA,WACEnC,GAAS,IAEXnO,GAGF2B,EACE,WACA,WACEwM,GAAS,IAEXnO,IAKAwK,IAAuB,QAARH,IAAkB,iBAAkB7K,GACrDmC,EACE,aACA,WACEwM,GAAS,IAEXnO,GAIAwK,GAAa2D,KAEf3O,EAAOqR,YAAc,SAAUjH,EAAMvC,GACnC8G,GAAS,EAAGvE,EAAMvC,IAQtB,IAAIyJ,GAAa,CAAC,SAAU,UAExBC,GAAY,SAAUjH,EAAOzC,EAAU2J,IACpCA,GAAejK,GAAWM,KAAW2J,EAAc3J,GAExD,IAAI4J,EAAkBlK,GAAW+C,GAC7BvB,EAAWxB,GAAWiK,GAAeA,EAAc,aACnDE,SAAmBpH,EAEvB,GAAIgH,GAAW9G,QAAQkH,GAAa,IAAMD,EAExC,OADAvN,EAAe+G,GAAmBrK,EAAY,aAAe8Q,GACtD3I,IAGT,IACE,GAAI0I,EAAiB,CACnB,IAAIE,EAAcrH,IAClB,GAAIgH,GAAW9G,eAAemH,GAAe,EAK3C,OAJAzN,EACE+G,GACAX,EAAQ,uBAAyBqH,GAE5B5I,IAETuB,EAAQqH,GAEV,MAAOvN,IAEP,OADAF,EAAe+G,GAAmB7G,IAC3B2E,IAGTuB,GAAS,GAAKA,GAAO1F,QAAQ,eAAgB,KAAKA,QAAQ,WAAY,IAEtE,IAAIgN,EAAc,CAAEzH,KAAMvJ,EAAW0J,MAAOA,GACxCuH,GAAa3D,IAAiB/K,EAAQ,EAE1C0E,EAAWD,GAAeC,EAAU+J,GAEhCtH,GACFxB,GACErD,EAAOmM,EAAa,CAClB3E,GAAIvG,KACJqJ,MAAO7H,IAAgB2J,GACvB/E,UACG+E,GAAa5D,KAAa7H,GAAsB,KAC7C4H,GACA,KAENnG,SAAU5F,EAAU4F,KAEtBkB,IAKF+I,GAAmB,SAAUxH,EAAOzC,EAAUkB,GAChDwI,GAAUjH,EAAOzC,EAAUkB,IAIxB/I,EAAOiL,MACVjL,EAAOiL,IAAqB6G,IAE9B,IAAIC,GAAY/R,EAAOiL,IAGnB+G,GAAQD,IAAaA,GAAUE,EAAIF,GAAUE,EAAI,GAMrD,IAAK,IAAI3H,MAHTtK,EAAOiL,IAAqB6G,GAGVE,GACZ3N,EAAQ2N,GAAO1H,MACjBpF,MAAMC,QAAQ6M,GAAM1H,KAChBiH,GAAUtN,MAAM,KAAM+N,GAAM1H,KAC5BiH,GAAUS,GAAM1H,MAGxB,MAAOiG,IACPpQ,EAAUoQ,IA7IY,IAAUpG,GACxB6G,GAvkBkBjG,GA7M9B,CAm6BE/K,OACA,uBACA"} \ No newline at end of file +{"version":3,"file":"app.source.js","sources":["app.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_app_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/custom/auto-events.js b/dist/latest/custom/auto-events.js index c55140e..cd391b6 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; 2026-08-17; 5dd7; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 99ad; v12) */ -function r(t,e){var a,o=!1;p.downloads&&/^https?:\/\//i.test(t.href)&&new RegExp("\\.("+(p.downloadsExtensions||[]).join("|")+")$","i").test(t.pathname)?o="download":p.outbound&&/^https?:\/\//i.test(t.href)&&t.hostname!==m.location.hostname?o="outbound":p.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(){saAutomatedLink(this,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 (\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 () {\n saAutomatedLink(this, 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","saAutomatedLink","this","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","element","sent","callback","theTitle","metadata","undefined","url","useTitle","event","pop","email","clean","replace","setTimeout","readyState","target"],"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 \"phones\",\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 phones: collectTypes.indexOf(\"phones\") > -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 var saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\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 || type === \"phone\") {\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 case \"phone\": {\n var hrefPhone = element.getAttribute(\"href\");\n event = (hrefPhone.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.phone = event;\n break;\n }\n }\n }\n if (useTitle) event = theTitle;\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, function () {}, true);\n\n log(\"collected \" + clean);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n window.saAutomatedLink = saAutomatedLink;\n\n function collectLink(link) {\n if (link.hasAttribute(\"data-simple-event\")) return;\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 // Collect telephone clicks\n } else if (optionsLink.phones && /^tel:/i.test(link.href)) {\n collect = \"phone\";\n }\n\n if (!collect) return;\n\n link.addEventListener(\"click\", function () {\n saAutomatedLink(this, collect);\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 collectLink(link);\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":["onDOMContentLoaded","a","document","getElementsByTagName","i","length","link","getAttribute","collect","hasAttribute","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","phones","addEventListener","saAutomatedLink","this","collectLink","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","element","theTitle","metadata","undefined","url","useTitle","event","pop","email","phone","clean","replace","readyState","target"],"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 5d67ac6..692d04a 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; 2026-08-17; 4949; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 1c39; v12) */ -!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"); +!function(v,e,n,m){var r,a,t;if(v)try{var g=undefined,y=!0,_=!1,i="true",o="https:",w="pageview",l="event",c="error",s=v.console,u="doNotTrack",b=v.navigator,f=v.location,x=f.host,d=v.document,p=b.userAgent,h="Not sending request ",E=h+"when ",O=_,M=encodeURIComponent,S=decodeURIComponent,k=JSON.stringify,A=v.addEventListener,q="https://"+e,C=d.documentElement||{},D="language",$="Height",H="scroll",R=b.userAgentData,j=H+$,L="offset"+$,N="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(p)&&!/(cubot)/i.test(p),F=v.screen,z=d.currentScript||d.querySelector('script[src*="'+e+'"]');m=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(s.warn,s,t)};var W=function(t,e){m("Error in your "+t+" function:",e)},G=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},J=function(t){return"string"==typeof t},X=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},Y=function(t,e){return t&&t.getAttribute("data-"+e)},Z=function(t){return Array.isArray(t)?t:J(t)&&t.length?t.split(/, ?/):[]},K=function(t){return t&&t.constructor===Object},Q=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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=v[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=v[qt];if(!ct(r))return qt&&m(qt+" not found, set window."+qt),t;try{return Q(t,r.call(v,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,dt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0"); //# sourceMappingURL=e.js.map \ No newline at end of file diff --git a/dist/latest/custom/e.js.map b/dist/latest/custom/e.js.map index 01cf5d9..325699b 100644 --- a/dist/latest/custom/e.js.map +++ b/dist/latest/custom/e.js.map @@ -1 +1 @@ -{"version":3,"file":"e.source.js","sources":["e.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n overwriteOptions,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings || Object.keys(overwriteOptions).length;\n\n // Merge overwriteOptions with sa_settings\n overwriteOptions = assign(overwriteOptions, settings);\n\n if (logSettings) warn(\"Settings\", overwriteOptions);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n overwriteOptions.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var metadataObject = window[namespace + \"_metadata\"];\n var appendMetadata = function (metadata, data) {\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) return metadata;\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(overwriteOptions.collectDnt)\n ? overwriteOptions.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n overwriteOptions.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n overwriteOptions.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n overwriteOptions.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n overwriteOptions.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n overwriteOptions.nonUniqueHostnames ||\n attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n overwriteOptions.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n overwriteOptions.metadataCollector ||\n attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n window.phantom ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n metadata: stringify(metadata),\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // We set unique variable based on pushstate or back navigation, if no match we check the referrer\n page.unique = isPushState || userNavigated ? falseVar : !sameSite;\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n else {\n window.sa_pageview = function (path, metadata) {\n pageview(0, path, metadata);\n };\n }\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback) {\n sendEvent(event, metadata, callback);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n } catch (e) {\n sendError(e);\n }\n})(\n window,\n {},\n \"\",\n \"\",\n \"custom_events_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","sendError","warn","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","settings","sa_settings","logSettings","keys","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","metadataObject","appendMetadata","metadata","data","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","search","keyValue","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","src","key","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","type","path","pathname","event","filename","indexOf","message","timezone","start","scrolled","mode","collectDnt","value","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","webdriver","__nightmare","callPhantom","_phantom","phantom","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","i","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","orig","rv","this","createEvent","initEvent","sa_pageview","validTypes","sendEvent","callbackRaw","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","q"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"e.source.js","sources":["e.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_events_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/custom/latest.dev.js b/dist/latest/custom/latest.dev.js index 883ddcd..579c9a8 100644 --- a/dist/latest/custom/latest.dev.js +++ b/dist/latest/custom/latest.dev.js @@ -1,9 +1,8 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-08-17; 1bd9; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 5f47; v12) */ /* eslint-env browser */ (function ( window, - overwriteOptions, baseUrl, apiUrlPrefix, version, @@ -11,6 +10,9 @@ sendError, warn ) { + // Only initialize in a browser. + if (!window) return; + try { ///////////////////// // PREDEFINED VARIABLES FOR BETTER MINIFICATION @@ -64,7 +66,6 @@ /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent); var screen = window.screen; - // Find the script element where options can be set on var scriptElement = doc.currentScript || doc.querySelector('script[src*="' + baseUrl + '"]'); @@ -135,16 +136,14 @@ }; var settings = window.sa_settings; - var logSettings = settings || Object.keys(overwriteOptions).length; - - // Merge overwriteOptions with sa_settings - overwriteOptions = assign(overwriteOptions, settings); + var logSettings = settings; + settings = assign(settings); - if (logSettings) warn("Settings", overwriteOptions); + if (logSettings) warn("Settings", settings); // Customers can skip data points var ignoreMetrics = convertCommaSeparatedToArray( - overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics") + settings.ignoreMetrics || attr(scriptElement, "ignore-metrics") ); var collectMetricByString = function (metricAbbreviation) { @@ -187,15 +186,21 @@ // Define namespace for the library var namespaceText = "namespace"; var namespace = - overwriteOptions[namespaceText] || + settings[namespaceText] || attr(scriptElement, namespaceText) || defaultNamespace; - var metadataObject = window[namespace + "_metadata"]; var appendMetadata = function (metadata, data) { + var metadataObject = window[namespace + "_metadata"]; if (isObject(metadataObject)) metadata = assign(metadata, metadataObject); var metadataCollectorFunction = window[metadataCollector]; - if (!isFunction(metadataCollectorFunction)) return metadata; + if (!isFunction(metadataCollectorFunction)) { + if (metadataCollector) + warn( + metadataCollector + " not found, set window." + metadataCollector + ); + return metadata; + } try { return assign( metadata, @@ -213,35 +218,42 @@ // By default we allow source, medium in the URLs. With strictUtm enabled // we only allow it with the utm_ prefix: utm_source, utm_medium, ... var strictUtm = - overwriteOptions.strictUtm || - attr(scriptElement, "strict-utm") == trueText; - - var getQueryParams = function (ignoreSource) { - return ( - loc.search - .slice(1) - .split("&") - .filter(function (keyValue) { - var ignore = ignoreSource || !collectMetricByString("ut"); - - var paramsRegexList = allowParams.map(filterRegex).join("|"); - var regex = ignore - ? "^(" + paramsRegexList + ")=" - : "^((utm_)" + - (strictUtm ? "" : "?") + - "(source|medium|content|term|campaign)" + - (strictUtm ? "" : "|ref") + - "|" + - paramsRegexList + - ")="; - if (ignore && !allowParams.length) return falseVar; - - // The prefix "utm_" is optional with "strictUtm" disabled - // "ref" is only collected when "strictUtm" is disabled - return new RegExp(regex).test(keyValue); - }) - .join("&") || undefinedVar - ); + settings.strictUtm || attr(scriptElement, "strict-utm") == trueText; + + var k; + + var getQueryParams = function (ignoreSource, overwriteSearch) { + k = !ignoreSource && collectMetricByString("q") ? "" : falseVar; + var q = (overwriteSearch || loc.search) + .slice(1) + .split("&") + .filter(function (keyValue) { + var i = keyValue.indexOf("="); + if (k !== falseVar && i > 0 && keyValue.slice(i + 1)) + k += (k ? "," : "") + keyValue.slice(0, i); + + var ignore = ignoreSource || !collectMetricByString("ut"); + + var paramsRegexList = allowParams.map(filterRegex).join("|"); + var regex = ignore + ? "^(" + paramsRegexList + ")=" + : "^((utm_)" + + (strictUtm ? "" : "?") + + "(source|medium|content|term|campaign)" + + (strictUtm ? "" : "|ref") + + "|" + + paramsRegexList + + ")="; + if (ignore && !allowParams.length) return falseVar; + + // The prefix "utm_" is optional with "strictUtm" disabled + // "ref" is only collected when "strictUtm" is disabled + return new RegExp(regex, "i").test(keyValue); + }) + .join("&"); + + k = k || undefinedVar; + return q || undefinedVar; }; // Ignore pages specified in data-ignore-pages @@ -282,7 +294,7 @@ // // Send data via image - var sendData = function (data, callback, onlyThisData) { + var sendData = function (data, callback, onlyThisData, keepalive) { data = onlyThisData ? data : assign(payload, page, data); if (nav.brave && !onlyThisData) data.brave = trueVar; @@ -295,7 +307,7 @@ image.onerror = callback; image.onload = callback; } - image.src = + var imageUrl = fullApiUrl + "/simple.gif?" + Object.keys(data) @@ -312,11 +324,28 @@ .join("&") + "&time=" + Date.now(); + + // Events must survive navigation without taking over links or forms. + if (keepalive && window.fetch) { + try { + window + .fetch(imageUrl, { + keepalive: trueVar, + mode: "no-cors", + credentials: "omit", + }) + .catch(function () { + image.src = imageUrl; + }); + return; + } catch (error) {} + } + image.src = imageUrl; }; // Customers can overwrite their hostname, here we check for that var overwrittenHostname = - overwriteOptions.hostname || attr(scriptElement, "hostname"); + settings.hostname || attr(scriptElement, "hostname"); var definedHostname = overwrittenHostname || locationHostname; var basePayload = { @@ -371,11 +400,11 @@ // // Script mode, this can be hash mode for example - var mode = overwriteOptions.mode || attr(scriptElement, "mode"); + var mode = settings.mode || attr(scriptElement, "mode"); // Should we record Do Not Track visits? - var collectDnt = isBoolean(overwriteOptions.collectDnt) - ? overwriteOptions.collectDnt + var collectDnt = isBoolean(settings.collectDnt) + ? settings.collectDnt : attr(scriptElement, "ignore-dnt") == trueText || attr(scriptElement, "skip-dnt") == trueText || attr(scriptElement, "collect-dnt") == trueText; @@ -383,39 +412,37 @@ // Some customers want to collect page views manually var autoCollect = !( attr(scriptElement, "auto-collect") == "false" || - overwriteOptions.autoCollect === falseVar + settings.autoCollect === falseVar ); // Event function name var eventFunctionName = - overwriteOptions.saGlobal || + settings.saGlobal || attr(scriptElement, "sa-global") || namespace + "_" + eventText; // Customers can ignore certain pages var ignorePages = convertCommaSeparatedToArray( - overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages") + settings.ignorePages || attr(scriptElement, "ignore-pages") ); // Customers can allow params var allowParams = convertCommaSeparatedToArray( - overwriteOptions.allowParams || attr(scriptElement, "allow-params") + settings.allowParams || attr(scriptElement, "allow-params") ); // Customers can allow params var nonUniqueHostnames = convertCommaSeparatedToArray( - overwriteOptions.nonUniqueHostnames || - attr(scriptElement, "non-unique-hostnames") + settings.nonUniqueHostnames || attr(scriptElement, "non-unique-hostnames") ); // Customers can overwrite certain values var pathOverwriter = - overwriteOptions.pathOverwriter || attr(scriptElement, "path-overwriter"); + settings.pathOverwriter || attr(scriptElement, "path-overwriter"); // Customers can add metadata to events and pageviews via a function var metadataCollector = - overwriteOptions.metadataCollector || - attr(scriptElement, "metadata-collector"); + settings.metadataCollector || attr(scriptElement, "metadata-collector"); // This code could error on (incomplete) implementations, that's why we use try...catch var timezone; @@ -432,12 +459,13 @@ // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS // + var phantom = window.phantom; var bot = nav.webdriver || window.__nightmare || window.callPhantom || window._phantom || - window.phantom || + (phantom && !phantom.solana) || window.__polypane || window._bot || isBotAgent || @@ -511,9 +539,17 @@ var page = {}; var lastSendPath; - var getReferrer = function () { + var getReferrer = function (raw) { + // Customers can overwrite their referrer, here we check for that + var referrer = + settings.referrer || + attr(scriptElement, "referrer") || + doc.referrer || + ""; + + if (raw) return referrer; return ( - (doc.referrer || "") + referrer .replace(locationHostname, definedHostname) .replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/, "$4") .replace(/^([^/]+)$/, "$1") || undefinedVar @@ -554,7 +590,12 @@ // sendData will assign payload to request sendData(append, undefinedVar, trueVar); } else { - nav.sendBeacon(fullApiUrl + "/append", stringify(append)); + try { + nav.sendBeacon.bind(nav)(fullApiUrl + "/append", stringify(append)); + } catch (e) { + // Fallback for browsers throwing "Illegal invocation" when the URL is invalid + sendData(append, undefinedVar, trueVar); + } } }; @@ -651,21 +692,28 @@ isPushState, deleteSourceInfo, sameSite, - metadata + search, + metadata, + callback ) { if (isPushState) sendOnLeave("" + payload.page_id, trueVar); if (collectDataOnLeave) payload.page_id = uuid(); var currentPage = definedHostname + getPath(); + var query = getQueryParams(deleteSourceInfo, search); - sendData({ - id: payload.page_id, - type: pageviewText, - referrer: !deleteSourceInfo || sameSite ? referrer : null, - query: getQueryParams(deleteSourceInfo), - - metadata: stringify(metadata), - }); + sendData( + { + id: payload.page_id, + type: pageviewText, + referrer: !deleteSourceInfo || sameSite ? referrer : null, + query: query, + k: k, + + metadata: stringify(metadata), + }, + callback + ); previousReferrer = referrer; referrer = currentPage; @@ -675,14 +723,29 @@ var sameSite, userNavigated; - var pageview = function (isPushState, pathOverwrite, metadata) { + var pageview = function ( + isPushState, + pathOverwrite, + metadata, + callbackRaw + ) { + if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata; + var callback = isFunction(callbackRaw) ? callbackRaw : function () {}; + var querySearch = ""; + if (isString(pathOverwrite) && pathOverwrite.indexOf("?") > -1) { + // keep query from manual path + var parts = pathOverwrite.split("?"); + pathOverwrite = parts.shift(); + querySearch = "?" + parts.join("?"); + } // Obfuscate personal data in URL by dropping the search and hash var path = getPath(pathOverwrite); // Don't send the last path again (this could happen when pushState is used to change the path hash or search) - if (!path || lastSendPath == path) return; + var pathKey = path + querySearch; + if (!path || lastSendPath == pathKey) return; - lastSendPath = path; + lastSendPath = pathKey; page.path = path; // v = viewportsizes @@ -737,8 +800,11 @@ currentReferrerHostname == locationHostname : falseVar; - // We set unique variable based on pushstate or back navigation, if no match we check the referrer - page.unique = isPushState || userNavigated ? falseVar : !sameSite; + // Only the first pageview can use a Cloudflare referrer as a unique arrival. + page.unique = + isPushState || userNavigated + ? falseVar + : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar))); metadata = appendMetadata(metadata, { type: pageviewText, @@ -747,11 +813,15 @@ var triggerSendPageView = function () { fetchedHighEntropyValues = trueVar; + var delSrc = + isPushState || userNavigated || !collectMetricByString("r"); sendPageView( isPushState, - isPushState || userNavigated || !collectMetricByString("r"), // r = referrers + delSrc, // r = referrers sameSite, - metadata + querySearch, + metadata, + callback ); }; @@ -841,11 +911,14 @@ } if (autoCollect) pageview(); - else { - window.sa_pageview = function (path, metadata) { - pageview(0, path, metadata); - }; - } + + var manualPageview = function (path, metadata, callback) { + pageview(0, path, metadata, callback); + }; + window[namespace + "_" + pageviewText] = manualPageview; + var defaultPageview = defaultNamespace + "_" + pageviewText; + if (!window[defaultPageview]) window[defaultPageview] = manualPageview; + ///////////////////// // EVENTS @@ -853,7 +926,7 @@ var validTypes = ["string", "number"]; - var sendEvent = function (event, metadata, callbackRaw) { + var sendEvent = function (event, metadata, callbackRaw, keepalive) { if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata; var eventIsFunction = isFunction(event); @@ -901,13 +974,15 @@ metadata: stringify(metadata), }), - callback + callback, + undefinedVar, + keepalive ); } }; - var defaultEventFunc = function (event, metadata, callback) { - sendEvent(event, metadata, callback); + var defaultEventFunc = function (event, metadata, callback, keepalive) { + sendEvent(event, metadata, callback, keepalive); }; // Set default function if user didn't define a function @@ -930,14 +1005,78 @@ : sendEvent(queue[event]); } } + + var inlineEvent = function (event) { + var element = event.target; + while ( + element && + element !== doc && + (!element.getAttribute || attr(element, "simple-event") === null) + ) + element = element.parentNode; + + if (!element || element === doc) return; + var isForm = element.tagName === "FORM"; + var name = attr(element, "simple-event"); + if (!name || isForm !== (event.type === "submit")) return; + + var metadata = { tag: element.tagName.toLowerCase() }; + var attributes = element.attributes; + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + if (attribute.name.indexOf("data-simple-event-") === 0) + metadata[attribute.name.slice(18).replace(/-/g, "_")] = + attribute.value; + } + if (isForm) { + var button = event.submitter; + metadata.button_text = button + ? (button.textContent || button.value || "") + .replace(/\s+/g, " ") + .trim() + .slice(0, 200) + : ""; + } + sendEvent(name, metadata, undefinedVar, trueVar); + }; + + doc.addEventListener("click", inlineEvent, falseVar); + doc.addEventListener("submit", inlineEvent, falseVar); + + // 404 confirmation adds a request, so existing installs must opt in. + if ( + settings.detect404 === trueVar || + attr(scriptElement, "detect-404") == trueText + ) { + var detect404 = function () { + if ( + !/\b404\b/.test(doc.title + " " + (doc.body && doc.body.textContent)) + ) + return; + try { + var request = new window.XMLHttpRequest(); + request.open("HEAD", loc.href, trueVar); + request.onload = function () { + if (request.status === 404) + sendEvent("page_404", { + url: loc.protocol + "//" + definedHostname + loc.pathname, + status: 404, + }); + }; + request.send(); + } catch (error) {} + }; + if (doc.readyState === "loading") + doc.addEventListener("DOMContentLoaded", detect404, falseVar); + else detect404(); + } } catch (e) { sendError(e); } })( - window, - {}, + typeof window != "undefined" && window, "", "", - "custom_latest_dev_11", + "custom_latest_dev_12", "sa" ); diff --git a/dist/latest/custom/latest.js b/dist/latest/custom/latest.js index ad661a7..186abf9 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; 2026-08-17; 4015; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 79e7; v12) */ -!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"); +!function(v,e,n,m){var r,a,t;if(v)try{var g=undefined,y=!0,_=!1,i="true",o="https:",w="pageview",l="event",c="error",s=v.console,u="doNotTrack",b=v.navigator,f=v.location,x=f.host,d=v.document,p=b.userAgent,h="Not sending request ",E=h+"when ",O=_,M=encodeURIComponent,S=decodeURIComponent,k=JSON.stringify,A=v.addEventListener,q="https://"+e,C=d.documentElement||{},D="language",$="Height",H="scroll",R=b.userAgentData,j=H+$,L="offset"+$,N="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(p)&&!/(cubot)/i.test(p),F=v.screen,z=d.currentScript||d.querySelector('script[src*="'+e+'"]');m=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(s.warn,s,t)};var W=function(t,e){m("Error in your "+t+" function:",e)},G=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},J=function(t){return"string"==typeof t},X=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},Y=function(t,e){return t&&t.getAttribute("data-"+e)},Z=function(t){return Array.isArray(t)?t:J(t)&&t.length?t.split(/, ?/):[]},K=function(t){return t&&t.constructor===Object},Q=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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=v[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=v[qt];if(!ct(r))return qt&&m(qt+" not found, set window."+qt),t;try{return Q(t,r.call(v,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,dt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0"); //# sourceMappingURL=latest.js.map \ No newline at end of file diff --git a/dist/latest/custom/latest.js.map b/dist/latest/custom/latest.js.map index d0be19b..e8fd11c 100644 --- a/dist/latest/custom/latest.js.map +++ b/dist/latest/custom/latest.js.map @@ -1 +1 @@ -{"version":3,"file":"latest.source.js","sources":["latest.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n overwriteOptions,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings || Object.keys(overwriteOptions).length;\n\n // Merge overwriteOptions with sa_settings\n overwriteOptions = assign(overwriteOptions, settings);\n\n if (logSettings) warn(\"Settings\", overwriteOptions);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n overwriteOptions.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var metadataObject = window[namespace + \"_metadata\"];\n var appendMetadata = function (metadata, data) {\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) return metadata;\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(overwriteOptions.collectDnt)\n ? overwriteOptions.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n overwriteOptions.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n overwriteOptions.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n overwriteOptions.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n overwriteOptions.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n overwriteOptions.nonUniqueHostnames ||\n attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n overwriteOptions.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n overwriteOptions.metadataCollector ||\n attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n window.phantom ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n metadata: stringify(metadata),\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // We set unique variable based on pushstate or back navigation, if no match we check the referrer\n page.unique = isPushState || userNavigated ? falseVar : !sameSite;\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n else {\n window.sa_pageview = function (path, metadata) {\n pageview(0, path, metadata);\n };\n }\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback) {\n sendEvent(event, metadata, callback);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n } catch (e) {\n sendError(e);\n }\n})(\n window,\n {},\n \"\",\n \"\",\n \"custom_latest_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","sendError","warn","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","settings","sa_settings","logSettings","keys","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","metadataObject","appendMetadata","metadata","data","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","search","keyValue","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","src","key","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","type","path","pathname","event","filename","indexOf","message","timezone","start","scrolled","mode","collectDnt","value","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","webdriver","__nightmare","callPhantom","_phantom","phantom","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","i","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","orig","rv","this","createEvent","initEvent","sa_pageview","validTypes","sendEvent","callbackRaw","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","q"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"latest.source.js","sources":["latest.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_latest_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/custom/light.js b/dist/latest/custom/light.js index 4c6f493..a2ddf85 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; 2026-08-17; 98d5; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 5075; v12) */ -!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,{},""); +!function(f,e,m){if(f)try{var u=undefined,t="https:",n=f.console,r="doNotTrack",g=f.navigator,p=f.location,h=p.host,i=f.document,a=g.userAgent,o="Not sending request ",v=!1,c=encodeURIComponent,s=decodeURIComponent,d=JSON.stringify,l=f.addEventListener,y="https://"+e,_=(i.documentElement,"language"),w=g.userAgentData,b="platform",O="platformVersion",S="https://docs.simpleanalytics.com",j=/(bot|spider|crawl)/i.test(a)&&!/(cubot)/i.test(a),k=i.currentScript||i.querySelector('script[src*="'+e+'"]');m=function(){var e=[].slice.call(arguments);return e.unshift("Simple Analytics:"),Function.prototype.apply.call(n.warn,n,e)};var x=function(e){return"string"==typeof e},E=function(e,t){return e&&e.getAttribute("data-"+t)},A=function(){for(var e,t,n,r={},i=arguments,a=0;a>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=function(e){return"function"==typeof e},N="namespace",R=q[N]||E(k,N)||"sa",U=q.strictUtm||"true"==E(k,"strict-utm"),V=R+"_loaded";if(1==f[V])return m(o+"twice");f.sa_event_loaded=!0,f[V]=!0;var B,C=function(t,e,n,r){t=n?t:A(z,L,t),g.brave&&!n&&(t.brave=!0),g._duckduckgoloader_&&!n&&(t.duck=!0);var i=new Image,a=y+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=u}).map(function(e){return c(e)+"="+c(t[e])}).join("&")+"&time="+Date.now();i.src=a},H=q.hostname||E(k,"hostname"),T=H||h,F={version:"custom_light_12",hostname:T};q.mode||E(k,"mode");try{B=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(W){m(W)}j&&(F.bot=!0);var z=A(F,{ua:a,https:p.protocol==t,timezone:B,page_id:D(),session_id:D()});if(z.sri=!1,w&&(z.mobile=w.mobile,z.brands=d(w.brands)),T!==h&&(z.hostname_original=h),r in g&&"1"==g[r])return m("Not sending request when "+r+" is enabled. See "+S+"/dnt");-1!=h.indexOf(".")&&!/^[0-9.:]+$/.test(h)||H||m("Set hostname on "+h+". See "+S+"/overwrite-domain-name");var J,L={},M=(q.referrer||E(k,"referrer")||i.referrer||"").replace(h,T).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||u,P=function(e,t){var n=A(F,{type:"append",original_id:t?e:z.page_id});if(t||!g.sendBeacon)C(n,0,!0);else try{g.sendBeacon.bind(g)(y+"/append",d(n))}catch(r){C(n,0,!0)}};l("pagehide",P,!1);var Z,G,K=function(e){var t="";try{t=e||s(p.pathname)}catch(W){m(W)}return t},Q=function(e,t,n,r,i,a){e&&P(""+z.page_id,!0),z.page_id=D();var o,c=T+K(),s=(o=t,(r||p.search).slice(1).split("&").filter(function(e){return!o&&new RegExp("^((utm_)"+(U?"":"?")+"(source|medium|content|term|campaign)"+(U?"":"|ref")+")=","i").test(e)}).join("&")||u);C({id:z.page_id,type:"pageview",referrer:!t||n?M:null,query:s}),M=c,0};!function(e,t,n,r){!r&&I(n)&&(r=n);I(r);var i,a="";x(t)&&-1"); //# sourceMappingURL=light.js.map \ No newline at end of file diff --git a/dist/latest/custom/light.js.map b/dist/latest/custom/light.js.map index 146d92d..9e9d78e 100644 --- a/dist/latest/custom/light.js.map +++ b/dist/latest/custom/light.js.map @@ -1 +1 @@ -{"version":3,"file":"light.source.js","sources":["light.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n overwriteOptions,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings || Object.keys(overwriteOptions).length;\n\n // Merge overwriteOptions with sa_settings\n overwriteOptions = assign(overwriteOptions, settings);\n\n if (logSettings) warn(\"Settings\", overwriteOptions);\n\n\n var collectMetricByString = function (metricAbbreviation) {\n return true;\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n if (ignore) return falseVar;\n var regex =\n \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \")=\";\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n\n\n\n\n\n\n\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot = isBotAgent;\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n\n\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n sameSite = referrer\n ? referrer.split(slash)[0] == locationHostname\n : falseVar;\n\n\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n\n\n pageview();\n\n } catch (e) {\n warn(e);\n }\n})(\n window,\n {},\n \"\",\n \"\",\n \"custom_light_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","warn","undefinedVar","undefined","https","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","language","documentElement","uaData","userAgentData","platformText","platformVersionText","docsUrl","isBotAgent","test","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","attr","attribute","getAttribute","assign","obj","prop","object","to","arg","index","length","nextSource","constructor","Object","nextKey","hasOwnProperty","settings","sa_settings","logSettings","keys","Date","now","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","replace","c","getRandomValues","Uint8Array","toString","error","r","Math","random","namespaceText","namespace","strictUtm","loadedVariable","sa_event_loaded","timezone","sendData","data","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","Image","src","filter","key","map","join","overwrittenHostname","hostname","definedHostname","basePayload","version","mode","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","ua","protocol","page_id","session_id","sri","mobile","brands","hostname_original","indexOf","lastSendPath","referrer","sendOnLeave","id","push","append","type","original_id","sendBeacon","sameSite","userNavigated","getPath","overwrite","path","pathname","sendPageView","isPushState","deleteSourceInfo","metadata","ignoreSource","currentPage","query","search","split","keyValue","RegExp","pages","pathOverwrite","performaceEntryType","perf","performance","navigationText","getEntriesByType","triggerSendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","pageview"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"light.source.js","sources":["light.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n\n var collectMetricByString = function (metricAbbreviation) {\n // eslint-disable-next-line no-unreachable\n return true;\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n if (ignore) return falseVar;\n // eslint-disable-next-line no-redeclare\n var regex =\n \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \")=\";\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n return q || undefinedVar;\n };\n\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n\n\n\n\n\n\n\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n // eslint-disable-next-line no-redeclare\n var bot = isBotAgent;\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n\n\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n sameSite = referrer\n ? referrer.split(slash)[0] == locationHostname\n : falseVar;\n\n\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n\n\n pageview();\n\n } catch (e) {\n warn(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_light_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","warn","undefinedVar","undefined","https","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","language","documentElement","uaData","userAgentData","platformText","platformVersionText","docsUrl","isBotAgent","test","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","isString","string","attr","attribute","getAttribute","assign","obj","prop","object","to","arg","index","length","nextSource","constructor","Object","nextKey","hasOwnProperty","logSettings","settings","sa_settings","Date","now","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","replace","c","getRandomValues","Uint8Array","toString","error","r","Math","random","isFunction","func","namespaceText","namespace","strictUtm","loadedVariable","sa_event_loaded","timezone","sendData","data","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","imageUrl","keys","filter","key","map","join","src","overwrittenHostname","hostname","definedHostname","basePayload","version","mode","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","ua","protocol","page_id","session_id","sri","mobile","brands","hostname_original","indexOf","lastSendPath","referrer","sendOnLeave","id","push","append","type","original_id","sendBeacon","bind","e","sameSite","userNavigated","getPath","overwrite","path","pathname","sendPageView","isPushState","deleteSourceInfo","search","metadata","ignoreSource","currentPage","query","split","keyValue","RegExp","pages","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","performaceEntryType","perf","performance","navigationText","getEntriesByType","triggerSendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","pageview"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/custom/proxy.js b/dist/latest/custom/proxy.js index 6794058..b88a2a7 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; 2026-08-17; 9e79; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 8624; v12) */ -!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"); +!function(v,e,n,m){var r,a,t;if(v)try{var g=undefined,y=!0,_=!1,i="true",o="https:",w="pageview",l="event",c="error",s=v.console,u="doNotTrack",b=v.navigator,f=v.location,x=f.host,p=v.document,d=b.userAgent,h="Not sending request ",E=h+"when ",O=_,M=encodeURIComponent,S=decodeURIComponent,k=JSON.stringify,A=v.addEventListener,q="https://"+e,C=p.documentElement||{},D="language",$="Height",H="scroll",R=b.userAgentData,j=H+$,L="offset"+$,N="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(d)&&!/(cubot)/i.test(d),F=v.screen,z=p.currentScript||p.querySelector('script[src*="'+e+'"]');m=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(s.warn,s,t)};var W=function(t,e){m("Error in your "+t+" function:",e)},G=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},J=function(t){return"string"==typeof t},X=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},Y=function(t,e){return t&&t.getAttribute("data-"+e)},Z=function(t){return Array.isArray(t)?t:J(t)&&t.length?t.split(/, ?/):[]},K=function(t){return t&&t.constructor===Object},Q=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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=v[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=v[qt];if(!ct(r))return qt&&m(qt+" not found, set window."+qt),t;try{return Q(t,r.call(v,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,pt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0"); //# sourceMappingURL=proxy.js.map \ No newline at end of file diff --git a/dist/latest/custom/proxy.js.map b/dist/latest/custom/proxy.js.map index 0f4461e..0778ab9 100644 --- a/dist/latest/custom/proxy.js.map +++ b/dist/latest/custom/proxy.js.map @@ -1 +1 @@ -{"version":3,"file":"proxy.source.js","sources":["proxy.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n overwriteOptions,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings || Object.keys(overwriteOptions).length;\n\n // Merge overwriteOptions with sa_settings\n overwriteOptions = assign(overwriteOptions, settings);\n\n if (logSettings) warn(\"Settings\", overwriteOptions);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n overwriteOptions.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var metadataObject = window[namespace + \"_metadata\"];\n var appendMetadata = function (metadata, data) {\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) return metadata;\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(overwriteOptions.collectDnt)\n ? overwriteOptions.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n overwriteOptions.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n overwriteOptions.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n overwriteOptions.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n overwriteOptions.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n overwriteOptions.nonUniqueHostnames ||\n attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n overwriteOptions.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n overwriteOptions.metadataCollector ||\n attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n window.phantom ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n metadata: stringify(metadata),\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // We set unique variable based on pushstate or back navigation, if no match we check the referrer\n page.unique = isPushState || userNavigated ? falseVar : !sameSite;\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n else {\n window.sa_pageview = function (path, metadata) {\n pageview(0, path, metadata);\n };\n }\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback) {\n sendEvent(event, metadata, callback);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n } catch (e) {\n sendError(e);\n }\n})(\n window,\n {},\n \"\",\n \"\",\n \"custom_proxy_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","sendError","warn","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","settings","sa_settings","logSettings","keys","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","metadataObject","appendMetadata","metadata","data","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","search","keyValue","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","src","key","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","type","path","pathname","event","filename","indexOf","message","timezone","start","scrolled","mode","collectDnt","value","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","webdriver","__nightmare","callPhantom","_phantom","phantom","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","i","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","orig","rv","this","createEvent","initEvent","sa_pageview","validTypes","sendEvent","callbackRaw","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","q"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"proxy.source.js","sources":["proxy.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_proxy_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":";;CAEA,SACEA,EACAC,EAIAC,EACAC,GAk1BwB,IAAUC,EACxBC,EAxoBkBC,EAxM5B,GAAKN,EAEL,IAQE,IAAIO,EAAeC,UACfC,GAAU,EACVC,GAAW,EACXC,EAAW,OACXC,EAAQ,SACRC,EAAe,WACfC,EAAY,QACZC,EAAY,QAGZC,EAAMhB,EAAOiB,QACbC,EAAa,aACbC,EAAMnB,EAAOoB,UACbC,EAAMrB,EAAOsB,SACbC,EAAmBF,EAAIG,KACvBC,EAAMzB,EAAO0B,SACbC,EAAYR,EAAIQ,UAChBC,EAAa,uBACbC,EAAiBD,EAAa,QAC9BE,EAA2BpB,EAC3BqB,EAAyBC,mBACzBC,EAAyBC,mBACzBC,EAAYC,KAAKD,UAEjBE,EAAuBrC,EAAOsC,iBAC9BC,EAhBW3B,WAgB4BX,EACvCuC,EAAkBf,EAAIe,iBAAmB,GACzCC,EAAW,WACXC,EAAS,SAETC,EAAS,SACTC,EAASzB,EAAI0B,cACbC,EAAeH,EAASD,EACxBK,EAAe,SAAWL,EAC1BM,EAAe,SAAWN,EAE1BO,EAAW,WACXC,EAAe,WACfC,EAAsB,kBACtBC,EAAU,mCACVC,EAAQ,EACRC,EACF,sBAAsBC,KAAK5B,KAAe,WAAW4B,KAAK5B,GACxD6B,EAASxD,EAAOwD,OAGhBC,EACFhC,EAAIiC,eAAiBjC,EAAIkC,cAAc,gBAAkB1D,EAAU,MAOrEE,EAAO,WAEL,IAAIyD,EAAO,GAAGC,MAAMC,KAAKC,WAOzB,OAJAH,EAAKI,QAAQ,qBAINC,SAASC,UAAUC,MAAML,KAAK9C,EAAIb,KAAMa,EAAK4C,IAGtD,IAAIQ,EAAiB,SAAUC,EAAMC,GACnCnE,EAAK,iBAAmBkE,EAAO,aAAcC,IAG3CC,EAAU,SAAUC,EAAKC,GAC3B,OAAOC,OAAOR,UAAUS,eAAeb,KAAKU,EAAKC,IAG/CG,EAAW,SAAUC,GACvB,MAAwB,iBAAVA,GAGZC,EAAc,SAAUC,GAC1B,OAAOA,EAAKC,QAAQ,sBAAuB,SAGzCC,EAAO,SAAUxB,EAAeyB,GAClC,OAAOzB,GAAiBA,EAAc0B,aAAa,QAAUD,IAG3DE,EAA+B,SAAUC,GAC3C,OAAOC,MAAMC,QAAQF,GACjBA,EACAT,EAASS,IAAQA,EAAIG,OACnBH,EAAII,MAAM,OACV,IAGJC,EAAW,SAAUC,GACvB,OAAOA,GAAUA,EAAOC,cAAgBlB,QAGtCmB,EAAS,WAGX,IAFA,IAAIC,EAAK,GACLC,EAAMhC,UACDiC,EAAQ,EAAGA,EAAQD,EAAIP,OAAQQ,IAAS,CAC/C,IAAIC,EAAaF,EAAIC,GACrB,GAAIN,EAASO,GACX,IAAK,IAAIC,KAAWD,EACd1B,EAAQ0B,EAAYC,KACtBJ,EAAGI,GAAWD,EAAWC,IAKjC,OAAOJ,GAILK,GADAC,GAAWpG,EAAOqG,YAEtBD,GAAWP,EAAOO,IAEdD,IAAahG,EAAK,WAAYiG,IAGlC,IA8EIE,GA9EAC,GAAgBnB,EAClBgB,GAASG,eAAiBtB,EAAKxB,EAAe,mBAG5C+C,GAAwB,SAAUC,GAEpC,OAGgB,IAFdF,GAAcG,OAAO,SAAU3B,GAC7B,OAAO,IAAI4B,OAAO,IAAMF,GAAoBlD,KAAKwB,KAChDS,QAIHoB,GAAMC,KAAKD,IAEXE,GAAO,WACT,IAAIC,EAAe/G,EAAOgH,QAAUhH,EAAOiH,SACvCC,EAAY,CAAC,MAAQ,KAAO,KAAO,KAAO,KAC1CC,EAAY,SAEhB,IACE,OAAOD,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,OACEA,EACCL,EAAaM,gBAAgB,IAAIC,WAAW,IAAI,GAC9C,IAAOF,EAAI,GACdG,SAAS,MAEb,MAAOjD,GACP,OAAO4C,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,IAAII,EAAqB,GAAhBC,KAAKC,SAAiB,EAE/B,OADMN,EAAI,EAAII,EAAS,EAAJA,EAAW,GACrBD,SAAS,QAKpBI,GAAa,SAAUC,GACzB,MAAsB,mBAARA,GAIZC,GAAgB,YAChBC,GACF1B,GAASyB,KACT5C,EAAKxB,EAAeoE,KAy3BxB,KAt3BME,GAAiB,SAAUC,EAAUC,GACvC,IAAIC,EAAiBlI,EAAO8H,GAAY,aACpCpC,EAASwC,KAAiBF,EAAWnC,EAAOmC,EAAUE,IAC1D,IAAIC,EAA4BnI,EAAOoI,IACvC,IAAKT,GAAWQ,GAKd,OAJIC,IACFjI,EACEiI,GAAoB,0BAA4BA,IAE7CJ,EAET,IACE,OAAOnC,EACLmC,EACAG,EAA0BrE,KAAK9D,EAAQ6F,EAAOmC,EAAUC,KAE1D,MAAO3D,GACPF,EAAe,WAAYE,KAU3B+D,GACFjC,GAASiC,WAAapD,EAAKxB,EAAe,eAAiB9C,EAIzD2H,GAAiB,SAAUC,EAAcC,GAC3ClC,IAAKiC,GAAgB/B,GAAsB,KAAO,GAAK9F,EACvD,IAAI+H,GAAKD,GAAmBnH,EAAIqH,QAC7B7E,MAAM,GACN4B,MAAM,KACNiB,OAAO,SAAUiC,GAChB,IAAIC,EAAID,EAASE,QAAQ,KACrBvC,KAAM5F,GAAgB,EAAJkI,GAASD,EAAS9E,MAAM+E,EAAI,KAChDtC,KAAMA,GAAI,IAAM,IAAMqC,EAAS9E,MAAM,EAAG+E,IAE1C,IAAIE,EAASP,IAAiB/B,GAAsB,MAEhDuC,EAAkBC,GAAYC,IAAInE,GAAaoE,KAAK,KACpDC,EAAQL,EACR,KAAOC,EAAkB,KACzB,YACCV,GAAY,GAAK,KAClB,yCACCA,GAAY,GAAK,QAClB,IACAU,EACA,KACJ,OAAID,IAAWE,GAAYxD,OAAe9E,EAInC,IAAIiG,OAAOwC,EAAO,KAAK5F,KAAKoF,KAEpCO,KAAK,KAGR,OADA5C,GAAIA,IAAK/F,EACFkI,GAAKlI,GA+BV6I,GAAiBtB,GAAY,UACjC,GAAI9H,EAAOoJ,KAAmB3I,EAAS,OAAON,EAAKyB,EAAa,SAChE5B,EAAOqJ,gBAAkB5I,EACzBT,EAAOoJ,IAAkB3I,EAOzB,IAAI6I,GAAW,SAAUrB,EAAMsB,EAAUC,EAAcC,GACrDxB,EAAOuB,EAAevB,EAAOpC,EAAO6D,GAASC,GAAM1B,GAE/C9G,EAAIyI,QAAUJ,IAAcvB,EAAK2B,MAAQnJ,GACzCU,EAAI0I,qBAAuBL,IAAcvB,EAAK6B,KAAOrJ,GAGzD,IAAIsJ,EAAQ,IAAIC,MACZT,IACFQ,EAAME,QAAUV,EAChBQ,EAAMG,OAASX,GAEjB,IAAIY,EACF5H,EACA,eACAmC,OAAO0F,KAAKnC,GACTvB,OAAO,SAAU2D,GAChB,OAAOpC,EAAKoC,IAAQ9J,IAErB0I,IAAI,SAAUoB,GACb,OACEtI,EAAuBsI,GACvB,IACAtI,EAAuBkG,EAAKoC,MAG/BnB,KAAK,KACR,SACArC,KAAKD,MAGP,GAAI6C,GAAazJ,EAAOsK,MACtB,IAUE,YATAtK,EACGsK,MAAMH,EAAU,CACfV,UAAWhJ,EACX8J,KAAM,UACNC,YAAa,SAEdC,SAAM,WACLV,EAAMW,IAAMP,IAGhB,MAAO7F,IAEXyF,EAAMW,IAAMP,GAIVQ,GACFvE,GAASwE,UAAY3F,EAAKxB,EAAe,YACvCoH,GAAkBF,IAAuBpJ,EAEzCuJ,GAAc,CAChBC,QAutBJ,kBAttBIH,SAAUC,IASZ3K,EAAY,SAAU8K,GACpBA,EAAiBA,EAAeC,MAC5BD,EAAiB,IAAMA,EAAeC,MACtCD,EACJ7K,EAAK6K,GACL1B,GACEzD,EAAOiF,GAAa,CAClB1K,KAAMW,EACNuD,MAAO0G,EACPE,KAAM7J,EAAI8J,WAEZ5K,EACAE,IAMJ4B,EACEtB,EACA,SAAUqK,GACJA,EAAMC,WAA+C,EAAnCD,EAAMC,SAASxC,QAAQ5I,IAC3CC,EAAUkL,EAAME,UAGpB5K,GAOF,IAsDI6K,GAtDAC,GAAQ5E,KAER6E,GAAW,EAOXlB,GAAOnE,GAASmE,MAAQtF,EAAKxB,EAAe,QAG5CiI,MA/LsBpL,EA+LC8F,GAASsF,cA9LfpL,EA+LjB8F,GAASsF,WACTzG,EAAKxB,EAAe,eAAiB9C,GACrCsE,EAAKxB,EAAe,aAAe9C,GACnCsE,EAAKxB,EAAe,gBAAkB9C,EAGtCgL,KACqC,SAAvC1G,EAAKxB,EAAe,iBACpB2C,GAASuF,cAAgBjL,GAIvBkL,GACFxF,GAASyF,UACT5G,EAAKxB,EAAe,cACpBqE,GAAY,IAAMhH,EAGhBgL,GAAc1G,EAChBgB,GAAS0F,aAAe7G,EAAKxB,EAAe,iBAI1CuF,GAAc5D,EAChBgB,GAAS4C,aAAe/D,EAAKxB,EAAe,iBAI1CsI,GAAqB3G,EACvBgB,GAAS2F,oBAAsB9G,EAAKxB,EAAe,yBAIjDuI,GACF5F,GAAS4F,gBAAkB/G,EAAKxB,EAAe,mBAG7C2E,GACFhC,GAASgC,mBAAqBnD,EAAKxB,EAAe,sBAIpD,IAEE8H,GAAW/E,GAAsB,KAC7ByF,KAAKC,iBAAiBC,kBAAkBC,SACxC7L,EACJ,MAAO+D,IACPnE,EAAKmE,IAOP,IAAI+H,GAAUrM,EAAOqM,QACjBC,GACFnL,EAAIoL,WACJvM,EAAOwM,aACPxM,EAAOyM,aACPzM,EAAO0M,UACNL,KAAYA,GAAQM,QACrB3M,EAAO4M,YACP5M,EAAO6M,MACPvJ,GACAmE,KAAKC,UAAYD,KAAKC,SAGpBoF,GACFtG,GAAsB,MAAQA,GAAsB,QAElD8F,KAAKxB,GAAYwB,IAAM7L,GAE3B,IAAIiJ,GAAU7D,EAAOiF,GAAa,CAEhCiC,GAAIvG,GAAsB,MAAQ7E,EAAYpB,EAE9CK,MAAOS,EAAI2L,UAAYpM,EACvB2K,SAAUA,GACV0B,QAASH,GAAqBhG,KAASvG,EAGvC2M,WAAY1G,GAAsB,MAAQM,KAASvG,IA0BrD,GAvBAmJ,GAAQyD,IAAMzM,EAIVkC,IACF8G,GAAQ0D,OAASxK,EAAOwK,OACxB1D,GAAQ2D,OAASlL,EAAUS,EAAOyK,SAS/B5L,EAAI6L,SAASnN,EAAK,4CAInB0K,KAAoBtJ,IACtBmI,GAAQ6D,kBAAoBhM,IAGzBmK,IAAcxK,KAAcC,GAA0B,KAAnBA,EAAID,GAC1C,OAAOf,EACL0B,EAAiBX,EAAa,oBAAsBkC,EAAU,SAK7B,GAAlC7B,EAAiBsH,QAAQ,OACxB,aAAatF,KAAKhC,IACnBoJ,IAEDxK,EACE,mBACEoB,EACA,SACA6B,EACA,0BAON,IACIoK,GA8DAC,GA/DA9D,GAAO,GAGP+D,GAAc,SAAUC,GAE1B,IAAIC,EACFxH,GAASwH,UACT3I,EAAKxB,EAAe,aACpBhC,EAAImM,UACJ,GAEF,OAAID,EAAYC,EAEdA,EACG5I,QAAQzD,EAAkBsJ,IAC1B7F,QAAQ,sDAAuD,MAC/DA,QAAQ,YAAa,OAASzE,GAKjCqN,GAAWF,KAOXG,GAAW,EAEXC,GAAc,SAAUC,EAAIC,GAC9B,GAAKlB,GAAL,CAEA,IAAImB,EAASpI,EAAOiF,GAAa,CAC/B1K,KAAM,SACN8N,YAAaF,EAAOD,EAAKrE,GAAQuD,UAenC,GAXIzG,GAAsB,OACxByH,EAAOE,SAAW1G,KAAK2G,OAAOxH,KAAQ4E,GAAQqC,IAlhBnC,MAohBbA,GAAW,EACXrC,GAAQ5E,KAGJJ,GAAsB,UACxByH,EAAOxC,SAAWhE,KAAK4G,IAAI,EAAG5C,GAAU6C,OAGtCN,IAAS7M,EAAIoN,WAEfjF,GAAS2E,EAAQ1N,EAAcE,QAE/B,IACEU,EAAIoN,WAAWC,KAAKrN,EAApBA,CAAyBoB,EAAa,UAAWJ,EAAU8L,IAC3D,MAAOQ,GAEPnF,GAAS2E,EAAQ1N,EAAcE,MAMrC4B,EACE,mBACA,WACMZ,EAAIiN,QACA,KAAOzL,KAAYjD,GAAS8N,KAClCL,GAAc7G,MACTiH,IAAYjH,KAAQ6G,IAE7B/M,GAGF2B,EAAqBY,EAAU6K,GAAapN,GAE5C,IAAIiO,GAAOlN,EAAIkN,MAAQ,GACnBL,GAAW,WACb,IACE,IAAIM,EAAuBpM,EAAgBQ,IAAiB,EACxD6L,EAASpH,KAAK4G,IAChBM,GAAK7L,IAAiB,EACtB6L,GAAK5L,IAAiB,EACtBP,EAAgBQ,IAAiB,EACjCR,EAAgBM,IAAiB,EACjCN,EAAgBO,IAAiB,GAEnC,OAAO0E,KAAKqH,IACV,IAKI,EAJJrH,KAAK2G,MACF,MAAQ5L,EAAgBuM,WAAa,GAAKH,GACzCC,EACA,IAGN,MAAOvK,IAEP,OADAnE,EAAKmE,IACE,IAIXjC,EAAqB,OAAQ,WAC3BoJ,GAAW6C,KACXjM,EACEM,EACA,WACM8I,GAAW6C,OAAY7C,GAAW6C,OAExC5N,KAQJ,IAgCIsO,GAoCAC,GAAUC,GApEVC,GAAU,SAAUC,GACtB,IAAIlE,EAAO,GAIX,IACEA,EAAOkE,GAAanN,EAAuBZ,EAAI8J,UAC/C,MAAO7G,IACPnE,EAAKmE,IAGP,IAAI+K,EAAyBrP,EAAOgM,IACpC,GAAIrE,GAAW0H,GACb,IACEnE,EAAOmE,EAAuBvL,KAAK9D,EAAQ,CAAEkL,KAAMA,KAAWA,EAC9D,MAAO5G,IACPF,EAAe,OAAQE,IAK3B,IA/ZiB,SAAU4G,GAC3B,IAAK,IAAItC,KAAKkD,GAAa,CACzB,IAAIwD,EAAgBxD,GAAYlD,GAChC,GAAK0G,EAAL,CAGA,IAAIC,EA1OI,KA2OND,EAAc,GAAcA,EA3OtB,IA2O8CA,EAEtD,GACEC,IAAerE,GACf,IAAIvE,OACF,IAAM7B,EAAYyK,GAAYvK,QAAQ,SAAU,QAAU,IAC1D,KACAzB,KAAK2H,GAEP,OAAOzK,GAEX,OAAOC,EA6YH8O,CAAatE,GAQjB,MAFY,QAARX,IAAkBlJ,EAAIoO,OAAMvE,GAAQ7J,EAAIoO,KAAKhK,MAAM,KAAK,IAErDyF,EAPL/K,EAAK0B,EAAiB,YAAcqJ,IAgDpCwE,GAAW,SACbC,EACAC,EACA5H,EACA6H,IAEKA,GAAelI,GAAWK,KAAW6H,EAAc7H,GACxD,IAIM8H,EAJFvG,EAAW5B,GAAWkI,GAAeA,EAAc,aACnDE,EAAc,GACdnL,EAASgL,KAAgD,EAA9BA,EAAc/G,QAAQ,OAGnD+G,GADIE,EAAQF,EAAcnK,MAAM,MACVuK,QACtBD,EAAc,IAAMD,EAAM5G,KAAK,MAGjC,IAAIgC,EAAOiE,GAAQS,GAGfK,EAAU/E,EAAO6E,EACrB,GAAK7E,GAAQsC,IAAgByC,EAA7B,CAEAzC,GAAeyC,EACftG,GAAKuB,KAAOA,EAGR1E,GAAsB,OACxBmD,GAAKuG,eACHzI,KAAK4G,IAAI7L,EAA2B,aAAK,EAAGxC,EAAOmQ,YAAc,IACjE,KACFxG,GAAKyG,gBACH3I,KAAK4G,IACH7L,EAAgBQ,IAAiB,EACjChD,EAAOqQ,aAAe,IACnB,MAIL7J,GAAsB,MACpBrF,EAAIsB,KAAWkH,GAAKlH,GAAYtB,EAAIsB,IAItCe,GAAUgD,GAAsB,QAClCmD,GAAK2G,aAAe9M,EAAO+M,MAC3B5G,GAAK6G,cAAgBhN,EAAOqL,QAI9B,IAII4B,EAJAC,EAAO1Q,EAAO2Q,YACdC,EAAiB,aAIrB,IACEH,EAAsBC,EAAKG,iBAAiBD,GAAgB,GAAGxQ,KAC/D,MAAOkE,IACPnE,EAAKmE,IAGP4K,GAAgBuB,GAC+C,EAA3D,CAAC,SAAU,gBAAgB5H,QAAQ4H,GAGnCC,GACAA,EAAKE,KACwC,EAA7C,CAAC,EAAG,GAAG/H,QAAQ6H,EAAKE,GAAgBxQ,MAGxC,IAAI0Q,EAA0BlD,GAC1BA,GAASnI,MA1vBH,KA0vBgB,GACtBlF,EACJ0O,GAAWrB,IACgD,EAAvD7B,GAAmBlD,QAAQiI,IAC3BA,GAA2BvP,EAC3Bb,EAGJiJ,GAAKoH,OACHpB,GAAeT,GACXxO,GACCuO,KAAc5L,GAAS,YAAYE,KAAKmK,GAAYjN,IAE3DuH,EAAWD,GAAeC,EAAU,CAClC5H,KAAMS,EACNqK,KAAMvB,GAAKuB,OAGb,IAAI8F,EAAsB,WACxBlP,EAA2BrB,EAC3B,IAAIwQ,EACFtB,GAAeT,KAAkB1I,GAAsB,MA9H1C,SACjBmJ,EACAuB,EACAjC,EACAvG,EACAV,EACAuB,GAEIoG,GAAa7B,GAAY,GAAKpE,GAAQuD,QAASxM,GAC/CqM,KAAoBpD,GAAQuD,QAAUnG,MAE1C,IAAIqK,EAActG,GAAkBsE,KAChCiC,EAAQ9I,GAAe4I,EAAkBxI,GAE7CY,GACE,CACEyE,GAAIrE,GAAQuD,QACZ7M,KAAMS,EACN+M,UAAWsD,GAAoBjC,EAAWrB,GAAW,KACrDwD,MAAOA,EACP9K,EAAGA,GAEH0B,SAAU7F,EAAU6F,IAEtBuB,GAGFyF,GAAmBpB,GACnBA,GAAWuD,EAEX9N,IAiGEgO,CACE1B,EACAsB,EACAhC,GACAc,EACA/H,EACAuB,IAIJ,GAAKzH,EAmBHkP,SAjBA,IACMpO,GAAU+E,GAAW/E,EAAO0O,sBAC9B1O,EACG0O,qBAAqB,CAACpO,EAAcC,IACpCoO,KAAK,SAAUC,GACd9H,GAAQ+H,QAAUD,EAAkBtO,GACpCwG,GAAQgI,WAAaF,EAAkBrO,GACvC6N,MAEDvG,SAAMuG,GAETA,IAEF,MAAOvC,GACPuC,OAWFW,GAAM3R,EAAO4R,QACbC,GAAeF,GAAMA,GAAIG,UAAYvR,EACrCwR,GAAM/R,EAAOgS,cACbC,GAAgB,YAIhBtG,IAAekG,IAAgBK,OAASH,KAqB1CJ,GAAIG,WAnBEzR,EAAOsR,GADiBvR,EAoBA6R,IAlBrB,WACL,IAEI7G,EAFArF,EAAMhC,UACNoO,EAAK9R,EAAK8D,MAAMiO,KAAMrM,GAY1B,OAVI4B,GAAWuK,OACb9G,EAAQ,IAAI8G,MAAM9R,IAIlBgL,EAAQ3J,EAAI4Q,YAAY,UAClBC,UAAUlS,EAAMK,EAASA,GAEjC2K,EAAMrH,UAAYgC,EAClBgM,GAAI3G,GACG+G,IAMX9P,EACE4P,GACA,WACEvC,GAAS,IAEXhP,GAGF2B,EACE,WACA,WACEqN,GAAS,IAEXhP,IAKAiL,IAAuB,QAARpB,IAAkB,iBAAkBvK,GACrDqC,EACE,aACA,WACEqN,GAAS,IAEXhP,GAIAiL,IAAa+D,KAEjB,IAAI6C,GAAiB,SAAUrH,EAAMlD,EAAUuB,GAC7CmG,GAAS,EAAGxE,EAAMlD,EAAUuB,IAE9BvJ,EAAO8H,GAAY,IAAMjH,GAAgB0R,GACzC,IAAIC,GAAkBC,MAAyB5R,EAC1Cb,EAAOwS,MAAkBxS,EAAOwS,IAAmBD,IAOxD,IAAIG,GAAa,CAAC,SAAU,UAExBC,GAAY,SAAUvH,EAAOpD,EAAU6H,EAAapG,IACjDoG,GAAelI,GAAWK,KAAW6H,EAAc7H,GAExD,IAAI4K,EAAkBjL,GAAWyD,GAC7B7B,EAAW5B,GAAWkI,GAAeA,EAAc,aACnDgD,SAAmBzH,EAEvB,GAAIsH,GAAW7J,QAAQgK,GAAa,IAAMD,EAExC,OADAxO,EAAewH,GAAmB9K,EAAY,aAAe+R,GACtDtJ,IAGT,IACE,GAAIqJ,EAAiB,CACnB,IAAIE,EAAc1H,IAClB,GAAIsH,GAAW7J,eAAeiK,GAAe,EAK3C,OAJA1O,EACEwH,GACAR,EAAQ,uBAAyB0H,GAE5BvJ,IAET6B,EAAQ0H,GAEV,MAAOxO,IAEP,OADAF,EAAewH,GAAmBtH,IAC3BiF,IAGT6B,GAAS,GAAKA,GAAOpG,QAAQ,eAAgB,KAAKA,QAAQ,WAAY,IAEtE,IAAI+N,EAAc,CAAE3S,KAAMU,EAAWsK,MAAOA,GACxC4H,GAAa9D,IAAiB7L,EAAQ,EAE1C2E,EAAWD,GAAeC,EAAU+K,GAEhC3H,GACF9B,GACEzD,EAAOkN,EAAa,CAClBhF,GAAIjH,KACJsK,MAAO9I,IAAgB0K,GACvBpF,UACGoF,GAAa/D,KAAazI,GAAsB,KAC7CwI,GACA,KAENhH,SAAU7F,EAAU6F,KAEtBuB,EACAhJ,EACAkJ,IAKFwJ,GAAmB,SAAU7H,EAAOpD,EAAUuB,EAAUE,GAC1DkJ,GAAUvH,EAAOpD,EAAUuB,EAAUE,IAIlCzJ,EAAO4L,MACV5L,EAAO4L,IAAqBqH,IAE9B,IAAIC,GAAYlT,EAAO4L,IAGnBuH,GAAQD,IAAaA,GAAUzK,EAAIyK,GAAUzK,EAAI,GAMrD,IAAK,IAAI2C,MAHTpL,EAAO4L,IAAqBqH,GAGVE,GACZ5O,EAAQ4O,GAAO/H,MACjB9F,MAAMC,QAAQ4N,GAAM/H,KAChBuH,GAAUxO,MAAM,KAAMgP,GAAM/H,KAC5BuH,GAAUQ,GAAM/H,MAIxB,IA0CMgI,GA1CFC,GAAc,SAAUjI,GAE1B,IADA,IAAIkI,EAAUlI,EAAMmI,OAElBD,GACAA,IAAY7R,KACV6R,EAAQnO,cAAkD,OAAlCF,EAAKqO,EAAS,kBAExCA,EAAUA,EAAQE,WAEpB,GAAKF,GAAWA,IAAY7R,EAA5B,CACA,IAAIgS,EAA6B,SAApBH,EAAQI,QACjBrP,EAAOY,EAAKqO,EAAS,gBACzB,GAAKjP,GAAQoP,IAA2B,WAAfrI,EAAMhL,MAA/B,CAIA,IAFA,IASMuT,EATF3L,EAAW,CAAE4L,IAAKN,EAAQI,QAAQG,eAClCC,EAAaR,EAAQQ,WAChBlL,EAAI,EAAGA,EAAIkL,EAAWtO,OAAQoD,IAAK,CAC1C,IAAI1D,EAAY4O,EAAWlL,GAC0B,IAAjD1D,EAAUb,KAAKwE,QAAQ,wBACzBb,EAAS9C,EAAUb,KAAKR,MAAM,IAAImB,QAAQ,KAAM,MAC9CE,EAAU5E,OAEZmT,IACEE,EAASvI,EAAM2I,UACnB/L,EAASgM,YAAcL,GAClBA,EAAOM,aAAeN,EAAOrT,OAAS,IACpC0E,QAAQ,OAAQ,KAChBkP,OACArQ,MAAM,EAAG,KACZ,IAEN8O,GAAUtO,EAAM2D,EAAUzH,EAAcE,MAG1CgB,EAAIa,iBAAiB,QAAS+Q,GAAa3S,GAC3Ce,EAAIa,iBAAiB,SAAU+Q,GAAa3S,GAI1C0F,GAASgN,YAAc3S,GACvBwE,EAAKxB,EAAe,eAAiB9C,IAEjCyS,GAAY,WACd,GACG,UAAU7P,KAAK9B,EAAI0S,MAAQ,KAAO1S,EAAIkN,MAAQlN,EAAIkN,KAAKsF,cAG1D,IACE,IAAIG,EAAU,IAAIpU,EAAOqU,eACzBD,EAAQE,KAAK,OAAQjT,EAAIkT,KAAM9T,GAC/B2T,EAAQlK,OAAS,WACQ,MAAnBkK,EAAQI,QACV7B,GAAU,WAAY,CACpB8B,IAAKpT,EAAI2L,SAAW,KAAOnC,GAAkBxJ,EAAI8J,SACjDqJ,OAAQ,OAGdJ,EAAQM,OACR,MAAOpQ,OAEY,YAAnB7C,EAAIkT,WACNlT,EAAIa,iBAAiB,mBAAoB8Q,GAAW1S,GACjD0S,MAEP,MAAO3E,IACPvO,EAAUuO,KA5iCd,CA+iCmB,oBAAVzO,QAAyBA,OAChC"} \ No newline at end of file diff --git a/dist/latest/hello.js b/dist/latest/hello.js index ba75a8d..05857b8 100644 --- a/dist/latest/hello.js +++ b/dist/latest/hello.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-08-17; 016a) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 9ce0) */ -!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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=m[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=m[At];if(!ct(r))return At&&v(At+" not found, set window."+At),t;try{return Q(t,r.call(m,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,dt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var metadataObject = window[namespace + \"_metadata\"];\n var appendMetadata = function (metadata, data) {\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) return metadata;\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(overwriteOptions.collectDnt)\n ? overwriteOptions.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n overwriteOptions.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n overwriteOptions.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n overwriteOptions.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n overwriteOptions.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n overwriteOptions.nonUniqueHostnames ||\n attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n overwriteOptions.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n overwriteOptions.metadataCollector ||\n attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n window.phantom ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n metadata: stringify(metadata),\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // We set unique variable based on pushstate or back navigation, if no match we check the referrer\n page.unique = isPushState || userNavigated ? falseVar : !sameSite;\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n else {\n window.sa_pageview = function (path, metadata) {\n pageview(0, path, metadata);\n };\n }\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback) {\n sendEvent(event, metadata, callback);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n } catch (e) {\n sendError(e);\n }\n})(\n window,\n {},\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_hello_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","sendError","warn","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","settings","sa_settings","logSettings","keys","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","metadataObject","appendMetadata","metadata","data","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","search","keyValue","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","src","key","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","type","path","pathname","event","filename","indexOf","message","timezone","start","scrolled","mode","collectDnt","value","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","webdriver","__nightmare","callPhantom","_phantom","phantom","__polypane","_bot","collectDataOnLeave","ua","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","i","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","orig","rv","this","createEvent","initEvent","sa_pageview","validTypes","sendEvent","callbackRaw","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","q"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"hello.source.js","sources":["hello.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_hello_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/latest.dev.js b/dist/latest/latest.dev.js index 93496d6..4568881 100644 --- a/dist/latest/latest.dev.js +++ b/dist/latest/latest.dev.js @@ -1,9 +1,8 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-08-17; 2483; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 1a59; v12) */ /* eslint-env browser */ (function ( window, - overwriteOptions, baseUrl, apiUrlPrefix, version, @@ -11,6 +10,9 @@ sendError, warn ) { + // Only initialize in a browser. + if (!window) return; + try { ///////////////////// // PREDEFINED VARIABLES FOR BETTER MINIFICATION @@ -64,7 +66,6 @@ /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent); var screen = window.screen; - // Find the script element where options can be set on var scriptElement = doc.currentScript || doc.querySelector('script[src*="' + baseUrl + '"]'); @@ -135,16 +136,14 @@ }; var settings = window.sa_settings; - var logSettings = settings || Object.keys(overwriteOptions).length; - - // Merge overwriteOptions with sa_settings - overwriteOptions = assign(overwriteOptions, settings); + var logSettings = settings; + settings = assign(settings); - if (logSettings) warn("Settings", overwriteOptions); + if (logSettings) warn("Settings", settings); // Customers can skip data points var ignoreMetrics = convertCommaSeparatedToArray( - overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics") + settings.ignoreMetrics || attr(scriptElement, "ignore-metrics") ); var collectMetricByString = function (metricAbbreviation) { @@ -187,15 +186,21 @@ // Define namespace for the library var namespaceText = "namespace"; var namespace = - overwriteOptions[namespaceText] || + settings[namespaceText] || attr(scriptElement, namespaceText) || defaultNamespace; - var metadataObject = window[namespace + "_metadata"]; var appendMetadata = function (metadata, data) { + var metadataObject = window[namespace + "_metadata"]; if (isObject(metadataObject)) metadata = assign(metadata, metadataObject); var metadataCollectorFunction = window[metadataCollector]; - if (!isFunction(metadataCollectorFunction)) return metadata; + if (!isFunction(metadataCollectorFunction)) { + if (metadataCollector) + warn( + metadataCollector + " not found, set window." + metadataCollector + ); + return metadata; + } try { return assign( metadata, @@ -213,35 +218,42 @@ // By default we allow source, medium in the URLs. With strictUtm enabled // we only allow it with the utm_ prefix: utm_source, utm_medium, ... var strictUtm = - overwriteOptions.strictUtm || - attr(scriptElement, "strict-utm") == trueText; - - var getQueryParams = function (ignoreSource) { - return ( - loc.search - .slice(1) - .split("&") - .filter(function (keyValue) { - var ignore = ignoreSource || !collectMetricByString("ut"); - - var paramsRegexList = allowParams.map(filterRegex).join("|"); - var regex = ignore - ? "^(" + paramsRegexList + ")=" - : "^((utm_)" + - (strictUtm ? "" : "?") + - "(source|medium|content|term|campaign)" + - (strictUtm ? "" : "|ref") + - "|" + - paramsRegexList + - ")="; - if (ignore && !allowParams.length) return falseVar; - - // The prefix "utm_" is optional with "strictUtm" disabled - // "ref" is only collected when "strictUtm" is disabled - return new RegExp(regex).test(keyValue); - }) - .join("&") || undefinedVar - ); + settings.strictUtm || attr(scriptElement, "strict-utm") == trueText; + + var k; + + var getQueryParams = function (ignoreSource, overwriteSearch) { + k = !ignoreSource && collectMetricByString("q") ? "" : falseVar; + var q = (overwriteSearch || loc.search) + .slice(1) + .split("&") + .filter(function (keyValue) { + var i = keyValue.indexOf("="); + if (k !== falseVar && i > 0 && keyValue.slice(i + 1)) + k += (k ? "," : "") + keyValue.slice(0, i); + + var ignore = ignoreSource || !collectMetricByString("ut"); + + var paramsRegexList = allowParams.map(filterRegex).join("|"); + var regex = ignore + ? "^(" + paramsRegexList + ")=" + : "^((utm_)" + + (strictUtm ? "" : "?") + + "(source|medium|content|term|campaign)" + + (strictUtm ? "" : "|ref") + + "|" + + paramsRegexList + + ")="; + if (ignore && !allowParams.length) return falseVar; + + // The prefix "utm_" is optional with "strictUtm" disabled + // "ref" is only collected when "strictUtm" is disabled + return new RegExp(regex, "i").test(keyValue); + }) + .join("&"); + + k = k || undefinedVar; + return q || undefinedVar; }; // Ignore pages specified in data-ignore-pages @@ -282,7 +294,7 @@ // // Send data via image - var sendData = function (data, callback, onlyThisData) { + var sendData = function (data, callback, onlyThisData, keepalive) { data = onlyThisData ? data : assign(payload, page, data); if (nav.brave && !onlyThisData) data.brave = trueVar; @@ -295,7 +307,7 @@ image.onerror = callback; image.onload = callback; } - image.src = + var imageUrl = fullApiUrl + "/simple.gif?" + Object.keys(data) @@ -312,11 +324,28 @@ .join("&") + "&time=" + Date.now(); + + // Events must survive navigation without taking over links or forms. + if (keepalive && window.fetch) { + try { + window + .fetch(imageUrl, { + keepalive: trueVar, + mode: "no-cors", + credentials: "omit", + }) + .catch(function () { + image.src = imageUrl; + }); + return; + } catch (error) {} + } + image.src = imageUrl; }; // Customers can overwrite their hostname, here we check for that var overwrittenHostname = - overwriteOptions.hostname || attr(scriptElement, "hostname"); + settings.hostname || attr(scriptElement, "hostname"); var definedHostname = overwrittenHostname || locationHostname; var basePayload = { @@ -371,11 +400,11 @@ // // Script mode, this can be hash mode for example - var mode = overwriteOptions.mode || attr(scriptElement, "mode"); + var mode = settings.mode || attr(scriptElement, "mode"); // Should we record Do Not Track visits? - var collectDnt = isBoolean(overwriteOptions.collectDnt) - ? overwriteOptions.collectDnt + var collectDnt = isBoolean(settings.collectDnt) + ? settings.collectDnt : attr(scriptElement, "ignore-dnt") == trueText || attr(scriptElement, "skip-dnt") == trueText || attr(scriptElement, "collect-dnt") == trueText; @@ -383,39 +412,37 @@ // Some customers want to collect page views manually var autoCollect = !( attr(scriptElement, "auto-collect") == "false" || - overwriteOptions.autoCollect === falseVar + settings.autoCollect === falseVar ); // Event function name var eventFunctionName = - overwriteOptions.saGlobal || + settings.saGlobal || attr(scriptElement, "sa-global") || namespace + "_" + eventText; // Customers can ignore certain pages var ignorePages = convertCommaSeparatedToArray( - overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages") + settings.ignorePages || attr(scriptElement, "ignore-pages") ); // Customers can allow params var allowParams = convertCommaSeparatedToArray( - overwriteOptions.allowParams || attr(scriptElement, "allow-params") + settings.allowParams || attr(scriptElement, "allow-params") ); // Customers can allow params var nonUniqueHostnames = convertCommaSeparatedToArray( - overwriteOptions.nonUniqueHostnames || - attr(scriptElement, "non-unique-hostnames") + settings.nonUniqueHostnames || attr(scriptElement, "non-unique-hostnames") ); // Customers can overwrite certain values var pathOverwriter = - overwriteOptions.pathOverwriter || attr(scriptElement, "path-overwriter"); + settings.pathOverwriter || attr(scriptElement, "path-overwriter"); // Customers can add metadata to events and pageviews via a function var metadataCollector = - overwriteOptions.metadataCollector || - attr(scriptElement, "metadata-collector"); + settings.metadataCollector || attr(scriptElement, "metadata-collector"); // This code could error on (incomplete) implementations, that's why we use try...catch var timezone; @@ -432,12 +459,13 @@ // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS // + var phantom = window.phantom; var bot = nav.webdriver || window.__nightmare || window.callPhantom || window._phantom || - window.phantom || + (phantom && !phantom.solana) || window.__polypane || window._bot || isBotAgent || @@ -511,9 +539,17 @@ var page = {}; var lastSendPath; - var getReferrer = function () { + var getReferrer = function (raw) { + // Customers can overwrite their referrer, here we check for that + var referrer = + settings.referrer || + attr(scriptElement, "referrer") || + doc.referrer || + ""; + + if (raw) return referrer; return ( - (doc.referrer || "") + referrer .replace(locationHostname, definedHostname) .replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/, "$4") .replace(/^([^/]+)$/, "$1") || undefinedVar @@ -554,7 +590,12 @@ // sendData will assign payload to request sendData(append, undefinedVar, trueVar); } else { - nav.sendBeacon(fullApiUrl + "/append", stringify(append)); + try { + nav.sendBeacon.bind(nav)(fullApiUrl + "/append", stringify(append)); + } catch (e) { + // Fallback for browsers throwing "Illegal invocation" when the URL is invalid + sendData(append, undefinedVar, trueVar); + } } }; @@ -651,21 +692,28 @@ isPushState, deleteSourceInfo, sameSite, - metadata + search, + metadata, + callback ) { if (isPushState) sendOnLeave("" + payload.page_id, trueVar); if (collectDataOnLeave) payload.page_id = uuid(); var currentPage = definedHostname + getPath(); + var query = getQueryParams(deleteSourceInfo, search); - sendData({ - id: payload.page_id, - type: pageviewText, - referrer: !deleteSourceInfo || sameSite ? referrer : null, - query: getQueryParams(deleteSourceInfo), - - metadata: stringify(metadata), - }); + sendData( + { + id: payload.page_id, + type: pageviewText, + referrer: !deleteSourceInfo || sameSite ? referrer : null, + query: query, + k: k, + + metadata: stringify(metadata), + }, + callback + ); previousReferrer = referrer; referrer = currentPage; @@ -675,14 +723,29 @@ var sameSite, userNavigated; - var pageview = function (isPushState, pathOverwrite, metadata) { + var pageview = function ( + isPushState, + pathOverwrite, + metadata, + callbackRaw + ) { + if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata; + var callback = isFunction(callbackRaw) ? callbackRaw : function () {}; + var querySearch = ""; + if (isString(pathOverwrite) && pathOverwrite.indexOf("?") > -1) { + // keep query from manual path + var parts = pathOverwrite.split("?"); + pathOverwrite = parts.shift(); + querySearch = "?" + parts.join("?"); + } // Obfuscate personal data in URL by dropping the search and hash var path = getPath(pathOverwrite); // Don't send the last path again (this could happen when pushState is used to change the path hash or search) - if (!path || lastSendPath == path) return; + var pathKey = path + querySearch; + if (!path || lastSendPath == pathKey) return; - lastSendPath = path; + lastSendPath = pathKey; page.path = path; // v = viewportsizes @@ -737,8 +800,11 @@ currentReferrerHostname == locationHostname : falseVar; - // We set unique variable based on pushstate or back navigation, if no match we check the referrer - page.unique = isPushState || userNavigated ? falseVar : !sameSite; + // Only the first pageview can use a Cloudflare referrer as a unique arrival. + page.unique = + isPushState || userNavigated + ? falseVar + : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar))); metadata = appendMetadata(metadata, { type: pageviewText, @@ -747,11 +813,15 @@ var triggerSendPageView = function () { fetchedHighEntropyValues = trueVar; + var delSrc = + isPushState || userNavigated || !collectMetricByString("r"); sendPageView( isPushState, - isPushState || userNavigated || !collectMetricByString("r"), // r = referrers + delSrc, // r = referrers sameSite, - metadata + querySearch, + metadata, + callback ); }; @@ -841,11 +911,14 @@ } if (autoCollect) pageview(); - else { - window.sa_pageview = function (path, metadata) { - pageview(0, path, metadata); - }; - } + + var manualPageview = function (path, metadata, callback) { + pageview(0, path, metadata, callback); + }; + window[namespace + "_" + pageviewText] = manualPageview; + var defaultPageview = defaultNamespace + "_" + pageviewText; + if (!window[defaultPageview]) window[defaultPageview] = manualPageview; + ///////////////////// // EVENTS @@ -853,7 +926,7 @@ var validTypes = ["string", "number"]; - var sendEvent = function (event, metadata, callbackRaw) { + var sendEvent = function (event, metadata, callbackRaw, keepalive) { if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata; var eventIsFunction = isFunction(event); @@ -901,13 +974,15 @@ metadata: stringify(metadata), }), - callback + callback, + undefinedVar, + keepalive ); } }; - var defaultEventFunc = function (event, metadata, callback) { - sendEvent(event, metadata, callback); + var defaultEventFunc = function (event, metadata, callback, keepalive) { + sendEvent(event, metadata, callback, keepalive); }; // Set default function if user didn't define a function @@ -930,14 +1005,78 @@ : sendEvent(queue[event]); } } + + var inlineEvent = function (event) { + var element = event.target; + while ( + element && + element !== doc && + (!element.getAttribute || attr(element, "simple-event") === null) + ) + element = element.parentNode; + + if (!element || element === doc) return; + var isForm = element.tagName === "FORM"; + var name = attr(element, "simple-event"); + if (!name || isForm !== (event.type === "submit")) return; + + var metadata = { tag: element.tagName.toLowerCase() }; + var attributes = element.attributes; + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + if (attribute.name.indexOf("data-simple-event-") === 0) + metadata[attribute.name.slice(18).replace(/-/g, "_")] = + attribute.value; + } + if (isForm) { + var button = event.submitter; + metadata.button_text = button + ? (button.textContent || button.value || "") + .replace(/\s+/g, " ") + .trim() + .slice(0, 200) + : ""; + } + sendEvent(name, metadata, undefinedVar, trueVar); + }; + + doc.addEventListener("click", inlineEvent, falseVar); + doc.addEventListener("submit", inlineEvent, falseVar); + + // 404 confirmation adds a request, so existing installs must opt in. + if ( + settings.detect404 === trueVar || + attr(scriptElement, "detect-404") == trueText + ) { + var detect404 = function () { + if ( + !/\b404\b/.test(doc.title + " " + (doc.body && doc.body.textContent)) + ) + return; + try { + var request = new window.XMLHttpRequest(); + request.open("HEAD", loc.href, trueVar); + request.onload = function () { + if (request.status === 404) + sendEvent("page_404", { + url: loc.protocol + "//" + definedHostname + loc.pathname, + status: 404, + }); + }; + request.send(); + } catch (error) {} + }; + if (doc.readyState === "loading") + doc.addEventListener("DOMContentLoaded", detect404, falseVar); + else detect404(); + } } catch (e) { sendError(e); } })( - window, - {}, + typeof window != "undefined" && window, "simpleanalyticscdn.com", "queue.", - "cdn_latest_dev_11", + "cdn_latest_dev_12", "sa" ); diff --git a/dist/latest/latest.js b/dist/latest/latest.js index 555b628..e05ca67 100644 --- a/dist/latest/latest.js +++ b/dist/latest/latest.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-08-17; 3761; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; d320; v12) */ -!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>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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=m[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=m[At];if(!ct(r))return At&&v(At+" not found, set window."+At),t;try{return Q(t,r.call(m,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,dt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var metadataObject = window[namespace + \"_metadata\"];\n var appendMetadata = function (metadata, data) {\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) return metadata;\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(overwriteOptions.collectDnt)\n ? overwriteOptions.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n overwriteOptions.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n overwriteOptions.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n overwriteOptions.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n overwriteOptions.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n overwriteOptions.nonUniqueHostnames ||\n attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n overwriteOptions.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n overwriteOptions.metadataCollector ||\n attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n window.phantom ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n metadata: stringify(metadata),\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // We set unique variable based on pushstate or back navigation, if no match we check the referrer\n page.unique = isPushState || userNavigated ? falseVar : !sameSite;\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n else {\n window.sa_pageview = function (path, metadata) {\n pageview(0, path, metadata);\n };\n }\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback) {\n sendEvent(event, metadata, callback);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n } catch (e) {\n sendError(e);\n }\n})(\n window,\n {},\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_latest_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","sendError","warn","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","settings","sa_settings","logSettings","keys","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","metadataObject","appendMetadata","metadata","data","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","search","keyValue","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","src","key","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","type","path","pathname","event","filename","indexOf","message","timezone","start","scrolled","mode","collectDnt","value","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","webdriver","__nightmare","callPhantom","_phantom","phantom","__polypane","_bot","collectDataOnLeave","ua","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","i","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","orig","rv","this","createEvent","initEvent","sa_pageview","validTypes","sendEvent","callbackRaw","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","q"],"mappings":";;CAEA,SACEA,EACAC,EACAC,EAIAC,EACAC,GAEA,IAQE,IAAIC,EAAeC,UACfC,GAAU,EACVC,GAAW,EACXC,EAAW,OACXC,EAAQ,SACRC,EAAe,WACfC,EAAY,QACZC,EAAY,QAGZC,EAAMd,EAAOe,QACbC,EAAa,aACbC,EAAMjB,EAAOkB,UACbC,EAAMnB,EAAOoB,SACbC,EAAmBF,EAAIG,KACvBC,EAAMvB,EAAOwB,SACbC,EAAYR,EAAIQ,UAChBC,EAAa,uBACbC,EAAiBD,EAAa,QAC9BE,EAA2BpB,EAC3BqB,EAAyBC,mBACzBC,EAAyBC,mBACzBC,EAAYC,KAAKD,UAEjBE,EAAuBnC,EAAOoC,iBAC9BC,EAAaC,iBAA0BpC,EACvCqC,EAAkBhB,EAAIgB,iBAAmB,GACzCC,EAAW,WACXC,EAAS,SAETC,EAAS,SACTC,EAAS1B,EAAI2B,cACbC,EAAeH,EAASD,EACxBK,EAAe,SAAWL,EAC1BM,EAAe,SAAWN,EAE1BO,EAAW,WACXC,EAAe,WACfC,EAAsB,kBACtBC,EAAU,mCACVC,EAAQ,EACRC,EACF,sBAAsBC,KAAK7B,KAAe,WAAW6B,KAAK7B,GACxD8B,EAASvD,EAAOuD,OAIhBC,EACFjC,EAAIkC,eAAiBlC,EAAImC,cAAc,gBAAkBxD,EAAU,MAOrEE,EAAO,WAEL,IAAIuD,EAAO,GAAGC,MAAMC,KAAKC,WAOzB,OAJAH,EAAKI,QAAQ,qBAINC,SAASC,UAAUC,MAAML,KAAK/C,EAAIV,KAAMU,EAAK6C,IAGtD,IAAIQ,EAAiB,SAAUC,EAAMC,GACnCjE,EAAK,iBAAmBgE,EAAO,aAAcC,IAG3CC,EAAU,SAAUC,EAAKC,GAC3B,OAAOC,OAAOR,UAAUS,eAAeb,KAAKU,EAAKC,IAO/CG,EAAc,SAAUC,GAC1B,OAAOA,EAAKC,QAAQ,sBAAuB,SAGzCC,EAAO,SAAUtB,EAAeuB,GAClC,OAAOvB,GAAiBA,EAAcwB,aAAa,QAAUD,IAG3DE,EAA+B,SAAUC,GAC3C,OAAOC,MAAMC,QAAQF,GACjBA,EAboB,iBAcXA,GAAQA,EAAIG,OACnBH,EAAII,MAAM,OACV,IAGJC,EAAW,SAAUC,GACvB,OAAOA,GAAUA,EAAOC,cAAgBhB,QAGtCiB,EAAS,WAGX,IAFA,IAAIC,EAAK,GACLC,EAAM9B,UACD+B,EAAQ,EAAGA,EAAQD,EAAIP,OAAQQ,IAAS,CAC/C,IAAIC,EAAaF,EAAIC,GACrB,GAAIN,EAASO,GACX,IAAK,IAAIC,KAAWD,EACdxB,EAAQwB,EAAYC,KACtBJ,EAAGI,GAAWD,EAAWC,IAKjC,OAAOJ,GAGLK,EAAWhG,EAAOiG,YAClBC,EAAcF,GAAYvB,OAAO0B,KAAKlG,GAAkBoF,OAG5DpF,EAAmByF,EAAOzF,EAAkB+F,GAExCE,GAAa9F,EAAK,WAAYH,GAGlC,IAAImG,EAAgBnB,EAClBhF,EAAiBmG,eAAiBtB,EAAKtB,EAAe,mBAGpD6C,GAAwB,SAAUC,GAEpC,OAGgB,IAFdF,EAAcG,OAAO,SAAU3B,GAC7B,OAAO,IAAI4B,OAAO,IAAMF,GAAoBhD,KAAKsB,KAChDS,QAIHoB,GAAMC,KAAKD,IAEXE,GAAO,WACT,IAAIC,EAAe5G,EAAO6G,QAAU7G,EAAO8G,SACvCC,EAAY,CAAC,MAAQ,KAAO,KAAO,KAAO,KAC1CC,EAAY,SAEhB,IACE,OAAOD,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,OACEA,EACCL,EAAaM,gBAAgB,IAAIC,WAAW,IAAI,GAC9C,IAAOF,EAAI,GACdG,SAAS,MAEb,MAAO/C,GACP,OAAO0C,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,IAAII,EAAqB,GAAhBC,KAAKC,SAAiB,EAE/B,OADMN,EAAI,EAAII,EAAS,EAAJA,EAAW,GACrBD,SAAS,QAKpBI,GAAa,SAAUC,GACzB,MAAsB,mBAARA,GAIZC,GAAgB,YAChBC,GACF1H,EAAiByH,KACjB5C,EAAKtB,EAAekE,KA6uBxB,KA1uBME,GAAiB5H,EAAO2H,GAAY,aACpCE,GAAiB,SAAUC,EAAUC,GACnCxC,EAASqC,MAAiBE,EAAWpC,EAAOoC,EAAUF,KAC1D,IAAII,EAA4BhI,EAAOiI,IACvC,IAAKT,GAAWQ,GAA4B,OAAOF,EACnD,IACE,OAAOpC,EACLoC,EACAE,EAA0BnE,KAAK7D,EAAQ0F,EAAOoC,EAAUC,KAE1D,MAAO1D,GACPF,EAAe,WAAYE,KAU3B6D,GACFjI,EAAiBiI,WACjBpD,EAAKtB,EAAe,eAAiB/C,EAEnC0H,GAAiB,SAAUC,GAC7B,OACEjH,EAAIkH,OACDzE,MAAM,GACN0B,MAAM,KACNiB,OAAO,SAAU+B,GAChB,IAAIC,EAASH,IAAiB/B,GAAsB,MAEhDmC,EAAkBC,GAAYC,IAAI/D,GAAagE,KAAK,KACpDC,EAAQL,EACR,KAAOC,EAAkB,KACzB,YACCN,GAAY,GAAK,KAClB,yCACCA,GAAY,GAAK,QAClB,IACAM,EACA,KACJ,OAAID,IAAWE,GAAYpD,OAAe7E,EAInC,IAAIgG,OAAOoC,GAAOtF,KAAKgF,KAE/BK,KAAK,MAAQtI,GAgChBwI,GAAiBlB,GAAY,UACjC,GAAI3H,EAAO6I,KAAmBtI,EAAS,OAAOH,EAAKsB,EAAa,SAChE1B,EAAO8I,gBAAkBvI,EACzBP,EAAO6I,IAAkBtI,EAOzB,IAAIwI,GAAW,SAAUhB,EAAMiB,EAAUC,GACvClB,EAAOkB,EAAelB,EAAOrC,EAAOwD,GAASC,GAAMpB,GAE/C9G,EAAImI,QAAUH,IAAclB,EAAKqB,MAAQ7I,GACzCU,EAAIoI,qBAAuBJ,IAAclB,EAAKuB,KAAO/I,GAGzD,IAAIgJ,EAAQ,IAAIC,MACZR,IACFO,EAAME,QAAUT,EAChBO,EAAMG,OAASV,GAEjBO,EAAMI,IACJtH,EACA,eACAoC,OAAO0B,KAAK4B,GACTxB,OAAO,SAAUqD,GAChB,OAAO7B,EAAK6B,IAAQvJ,IAErBqI,IAAI,SAAUkB,GACb,OACE/H,EAAuB+H,GACvB,IACA/H,EAAuBkG,EAAK6B,MAG/BjB,KAAK,KACR,SACAjC,KAAKD,OAILoD,GACF5J,EAAiB6J,UAAYhF,EAAKtB,EAAe,YAC/CuG,GAAkBF,IAAuBxI,EAEzC2I,GAAc,CAChBC,QAymBJ,gBAxmBIH,SAAUC,IASZ5J,EAAY,SAAU+J,GACpBA,EAAiBA,EAAeC,MAC5BD,EAAiB,IAAMA,EAAeC,MACtCD,EACJ9J,EAAK8J,GACLnB,GACErD,EAAOsE,GAAa,CAClBI,KAAMvJ,EACNwD,MAAO6F,EACPG,KAAMlJ,EAAImJ,WAEZjK,EACAE,IAMJ4B,EACEtB,EACA,SAAU0J,GACJA,EAAMC,WAA+C,EAAnCD,EAAMC,SAASC,QAAQvK,IAC3CC,EAAUoK,EAAMG,UAGpBlK,GAOF,IAwDImK,GAxDAC,GAAQnE,KAERoE,GAAW,EAOXC,GAAO7K,EAAiB6K,MAAQhG,EAAKtB,EAAe,QAGpDuH,MAvKsBC,GAuKC/K,EAAiB8K,cAtKvBC,GAuKjB/K,EAAiB8K,WACjBjG,EAAKtB,EAAe,eAAiB/C,GACrCqE,EAAKtB,EAAe,aAAe/C,GACnCqE,EAAKtB,EAAe,gBAAkB/C,EAGtCwK,KACqC,SAAvCnG,EAAKtB,EAAe,iBACpBvD,EAAiBgL,cAAgBzK,GAI/B0K,GACFjL,EAAiBkL,UACjBrG,EAAKtB,EAAe,cACpBmE,GAAY,IAAM/G,EAGhBwK,GAAcnG,EAChBhF,EAAiBmL,aAAetG,EAAKtB,EAAe,iBAIlDiF,GAAcxD,EAChBhF,EAAiBwI,aAAe3D,EAAKtB,EAAe,iBAIlD6H,GAAqBpG,EACvBhF,EAAiBoL,oBACfvG,EAAKtB,EAAe,yBAIpB8H,GACFrL,EAAiBqL,gBAAkBxG,EAAKtB,EAAe,mBAGrDyE,GACFhI,EAAiBgI,mBACjBnD,EAAKtB,EAAe,sBAItB,IAEEmH,GAAWtE,GAAsB,KAC7BkF,KAAKC,iBAAiBC,kBAAkBC,SACxCrL,EACJ,MAAOgE,IACPjE,EAAKiE,IAOP,IAAIsH,GACF1K,EAAI2K,WACJ5L,EAAO6L,aACP7L,EAAO8L,aACP9L,EAAO+L,UACP/L,EAAOgM,SACPhM,EAAOiM,YACPjM,EAAOkM,MACP7I,GACAiE,KAAKC,UAAYD,KAAKC,SAGpB4E,GACF9F,GAAsB,MAAQA,GAAsB,QAElDsF,KAAK3B,GAAY2B,IAAMpL,GAE3B,IAAI2I,GAAUxD,EAAOsE,GAAa,CAEhCoC,GAAI/F,GAAsB,MAAQ5E,EAAYpB,EAE9CK,MAAOS,EAAImB,UAAY5B,EACvBiK,SAAUA,GACV0B,QAASF,GAAqBxF,KAAStG,EAGvCiM,WAAYjG,GAAsB,MAAQM,KAAStG,IA0BrD,GAvBA6I,GAAQqD,IAAM/L,EAIVmC,IACFuG,GAAQsD,OAAS7J,EAAO6J,OACxBtD,GAAQuD,OAASxK,EAAUU,EAAO8J,SAS/BlL,EAAImL,SAAStM,EAAK,4CAInB2J,KAAoB1I,IACtB6H,GAAQyD,kBAAoBtL,IAGzB0J,IAAc/J,KAAcC,GAA0B,KAAnBA,EAAID,GAC1C,OAAOZ,EACLuB,EAAiBX,EAAa,oBAAsBmC,EAAU,SAK7B,GAAlC9B,EAAiBoJ,QAAQ,OACxB,aAAanH,KAAKjC,IACnBwI,IAEDzJ,EACE,mBACEiB,EACA,SACA8B,EACA,0BAON,IACIyJ,GAiDAC,GAlDA1D,GAAO,GAaP2D,IARCvL,EAAIuL,UAAY,IACdjI,QAAQxD,EAAkB0I,IAC1BlF,QAAQ,sDAAuD,MAC/DA,QAAQ,YAAa,OAASxE,EAYjC0M,GAAW,EAEXC,GAAc,SAAUC,EAAIC,GAC9B,IAEIC,EAFChB,KAEDgB,EAASzH,EAAOsE,GAAa,CAC/BI,KAAM,SACNgD,YAAaF,EAAOD,EAAK/D,GAAQmD,UAI/BhG,GAAsB,OACxB8G,EAAOE,SAAW/F,KAAKgG,OAAO7G,KAAQmE,GAAQmC,IAhfnC,MAkfbA,GAAW,EACXnC,GAAQnE,KAGJJ,GAAsB,UACxB8G,EAAOtC,SAAWvD,KAAKiG,IAAI,EAAG1C,GAAU2C,OAGtCN,IAASjM,EAAIwM,WAEf1E,GAASoE,EAAQ9M,EAAcE,GAE/BU,EAAIwM,WAAWpL,EAAa,UAAWJ,EAAUkL,MAKrDhL,EACE,mBACA,WACMZ,EAAImM,QACA,KAAO1K,KAAYhD,GAASgN,KAClCH,GAAcpG,MACTsG,IAAYtG,KAAQoG,IAE7BrM,GAGF2B,EAAqBa,EAAUgK,GAAaxM,GAE5C,IAAImN,GAAOpM,EAAIoM,MAAQ,GACnBH,GAAW,WACb,IACE,IAAII,EAAuBrL,EAAgBQ,IAAiB,EACxD8K,EAASvG,KAAKiG,IAChBI,GAAK9K,IAAiB,EACtB8K,GAAK7K,IAAiB,EACtBP,EAAgBQ,IAAiB,EACjCR,EAAgBM,IAAiB,EACjCN,EAAgBO,IAAiB,GAEnC,OAAOwE,KAAKwG,IACV,IAKI,EAJJxG,KAAKgG,MACF,MAAQ/K,EAAgBwL,WAAa,GAAKH,GACzCC,EACA,IAGN,MAAOxJ,IAEP,OADAjE,EAAKiE,IACE,IAIXlC,EAAqB,OAAQ,WAC3B0I,GAAW2C,KACXrL,EACEO,EACA,WACMmI,GAAW2C,OAAY3C,GAAW2C,OAExChN,KAQJ,IAgCIwN,GA6BAC,GAAUC,GA7DVC,GAAU,SAAUC,GACtB,IAAI/D,EAAO,GAIX,IACEA,EAAO+D,GAAarM,EAAuBZ,EAAImJ,UAC/C,MAAOjG,IACPjE,EAAKiE,IAGP,IAAIgK,EAAyBrO,EAAOsL,IACpC,GAAI9D,GAAW6G,GACb,IACEhE,EAAOgE,EAAuBxK,KAAK7D,EAAQ,CAAEqK,KAAMA,KAAWA,EAC9D,MAAOhG,IACPF,EAAe,OAAQE,IAK3B,IAlYiB,SAAUgG,GAC3B,IAAK,IAAIiE,KAAKlD,GAAa,CACzB,IAAImD,EAAgBnD,GAAYkD,GAChC,GAAKC,EAAL,CAGA,IAAIC,EAhOI,KAiOND,EAAc,GAAcA,EAjOtB,IAiO8CA,EAEtD,GACEC,IAAenE,GACf,IAAI7D,OACF,IAAM7B,EAAY6J,GAAY3J,QAAQ,SAAU,QAAU,IAC1D,KACAvB,KAAK+G,GAEP,OAAO9J,GAEX,OAAOC,EAgXHiO,CAAapE,GAQjB,MAFY,QAARS,IAAkB3J,EAAIuN,OAAMrE,GAAQlJ,EAAIuN,KAAKpJ,MAAM,KAAK,IAErD+E,EAPLjK,EAAKuB,EAAiB,YAAc0I,IAyCpCsE,GAAW,SAAUC,EAAaC,EAAe/G,GAEnD,IAAIuC,EAAO8D,GAAQU,GAGnB,GAAKxE,GAAQuC,IAAgBvC,EAA7B,CAEAuC,GAAevC,EACflB,GAAKkB,KAAOA,EAGRhE,GAAsB,OACxB8C,GAAK2F,eACHxH,KAAKiG,IAAIhL,EAA2B,aAAK,EAAGvC,EAAO+O,YAAc,IACjE,KACF5F,GAAK6F,gBACH1H,KAAKiG,IACHhL,EAAgBQ,IAAiB,EACjC/C,EAAOiP,aAAe,IACnB,MAIL5I,GAAsB,MACpBpF,EAAIuB,KAAW2G,GAAK3G,GAAYvB,EAAIuB,IAItCe,GAAU8C,GAAsB,QAClC8C,GAAK+F,aAAe3L,EAAO4L,MAC3BhG,GAAKiG,cAAgB7L,EAAOsK,QAI9B,IAIIwB,EAJAC,EAAOtP,EAAOuP,YACdC,EAAiB,aAIrB,IACEH,EAAsBC,EAAKG,iBAAiBD,GAAgB,GAAGpF,KAC/D,MAAO/F,IACPjE,EAAKiE,IAGP6J,GAAgBmB,GAC+C,EAA3D,CAAC,SAAU,gBAAgB5E,QAAQ4E,GAGnCC,GACAA,EAAKE,KACwC,EAA7C,CAAC,EAAG,GAAG/E,QAAQ6E,EAAKE,GAAgBpF,MAGxC,IAAIsF,EAA0B5C,GAC1BA,GAASxH,MA7rBH,KA6rBgB,GACtBjF,EACJ4N,GAAWnB,IACgD,EAAvDzB,GAAmBZ,QAAQiF,IAC3BA,GAA2BrO,EAC3Bb,EAGJ2I,GAAKwG,OAASf,GAAeV,GAAgB1N,GAAYyN,GAEzDnG,EAAWD,GAAeC,EAAU,CAClCsC,KAAMzJ,EACN0J,KAAMlB,GAAKkB,OAGb,IAAIuF,EAAsB,WACxBhO,EAA2BrB,EAnGZ,SACjBqO,EACAiB,EACA5B,EACAnG,GAEI8G,GAAa5B,GAAY,GAAK9D,GAAQmD,QAAS9L,GAC/C4L,KAAoBjD,GAAQmD,QAAU1F,MAE1C,IAAImJ,EAAc/F,GAAkBoE,KAEpCpF,GAAS,CACPkE,GAAI/D,GAAQmD,QACZjC,KAAMzJ,EACNmM,UAAW+C,GAAoB5B,EAAWnB,GAAW,KACrDiD,MAAO5H,GAAe0H,GAEtB/H,SAAU7F,EAAU6F,KAGtBkG,GAAmBlB,GACnBA,GAAWgD,EAEX1M,IA6EE4M,CACEpB,EACAA,GAAeV,KAAkB7H,GAAsB,KACvD4H,GACAnG,IAIJ,GAAKlG,EAmBHgO,SAjBA,IACMjN,GAAU6E,GAAW7E,EAAOsN,sBAC9BtN,EACGsN,qBAAqB,CAAChN,EAAcC,IACpCgN,KAAK,SAAUC,GACdjH,GAAQkH,QAAUD,EAAkBlN,GACpCiG,GAAQmH,WAAaF,EAAkBjN,GACvC0M,MAEDU,SAAMV,GAETA,IAEF,MAAOW,GACPX,OAWFY,GAAMxQ,EAAOyQ,QACbC,GAAeF,GAAMA,GAAIG,UAAYtQ,EACrCuQ,GAAM5Q,EAAO6Q,cACbC,GAAgB,YAIhB7F,IAAeyF,IAAgBK,OAASH,KAqB1CJ,GAAIG,WAnBEK,GAAOR,GADiBpG,GAoBA0G,IAlBrB,WACL,IAEIvG,EAFA3E,EAAM9B,UACNmN,EAAKD,GAAK9M,MAAMgN,KAAMtL,GAY1B,OAVI4B,GAAWuJ,OACbxG,EAAQ,IAAIwG,MAAM3G,KAIlBG,EAAQhJ,EAAI4P,YAAY,UAClBC,UAAUhH,GAAM7J,EAASA,GAEjCgK,EAAMzG,UAAY8B,EAClBgL,GAAIrG,GACG0G,IAMX9O,EACE2O,GACA,WACEnC,GAAS,IAEXnO,GAGF2B,EACE,WACA,WACEwM,GAAS,IAEXnO,IAKAyK,IAAuB,QAARH,IAAkB,iBAAkB9K,GACrDmC,EACE,aACA,WACEwM,GAAS,IAEXnO,GAIAyK,GAAa0D,KAEf3O,EAAOqR,YAAc,SAAUhH,EAAMvC,GACnC6G,GAAS,EAAGtE,EAAMvC,IAQtB,IAAIwJ,GAAa,CAAC,SAAU,UAExBC,GAAY,SAAUhH,EAAOzC,EAAU0J,IACpCA,GAAehK,GAAWM,KAAW0J,EAAc1J,GAExD,IAAI2J,EAAkBjK,GAAW+C,GAC7BvB,EAAWxB,GAAWgK,GAAeA,EAAc,aACnDE,SAAmBnH,EAEvB,GAAI+G,GAAW7G,QAAQiH,GAAa,IAAMD,EAExC,OADAtN,EAAe+G,GAAmBtK,EAAY,aAAe8Q,GACtD1I,IAGT,IACE,GAAIyI,EAAiB,CACnB,IAAIE,EAAcpH,IAClB,GAAI+G,GAAW7G,eAAekH,GAAe,EAK3C,OAJAxN,EACE+G,GACAX,EAAQ,uBAAyBoH,GAE5B3I,IAETuB,EAAQoH,GAEV,MAAOtN,IAEP,OADAF,EAAe+G,GAAmB7G,IAC3B2E,IAGTuB,GAAS,GAAKA,GAAO1F,QAAQ,eAAgB,KAAKA,QAAQ,WAAY,IAEtE,IAAI+M,EAAc,CAAExH,KAAMxJ,EAAW2J,MAAOA,GACxCsH,GAAa3D,IAAiB9K,EAAQ,EAE1C0E,EAAWD,GAAeC,EAAU8J,GAEhCrH,GACFxB,GACErD,EAAOkM,EAAa,CAClB3E,GAAItG,KACJoJ,MAAO5H,IAAgB0J,GACvB/E,UACG+E,GAAa5D,KAAa5H,GAAsB,KAC7C2H,GACA,KAENlG,SAAU7F,EAAU6F,KAEtBkB,IAKF8I,GAAmB,SAAUvH,EAAOzC,EAAUkB,GAChDuI,GAAUhH,EAAOzC,EAAUkB,IAIxBhJ,EAAOkL,MACVlL,EAAOkL,IAAqB4G,IAE9B,IAAIC,GAAY/R,EAAOkL,IAGnB8G,GAAQD,IAAaA,GAAUE,EAAIF,GAAUE,EAAI,GAMrD,IAAK,IAAI1H,MAHTvK,EAAOkL,IAAqB4G,GAGVE,GACZ1N,EAAQ0N,GAAOzH,MACjBpF,MAAMC,QAAQ4M,GAAMzH,KAChBgH,GAAUrN,MAAM,KAAM8N,GAAMzH,KAC5BgH,GAAUS,GAAMzH,MAGxB,MAAOgG,IACPpQ,EAAUoQ,IA7IY,IAAUnG,GACxB4G,GAvkBkBhG,GA7M9B,CAm6BEhL,OACA,uBACA"} \ No newline at end of file +{"version":3,"file":"latest.source.js","sources":["latest.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_latest_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/latest/light.js b/dist/latest/light.js index 1232534..c4b6498 100644 --- a/dist/latest/light.js +++ b/dist/latest/light.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2026-08-17; 630c; v11) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; b187; v12) */ -!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=!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"); +!function(f,e,m){if(f)try{var u=undefined,t="https:",n=f.console,r="doNotTrack",g=f.navigator,p=f.location,h=p.host,a=f.document,i=g.userAgent,o="Not sending request ",v=!1,c=encodeURIComponent,s=decodeURIComponent,d=JSON.stringify,l=f.addEventListener,y="https://queue."+e,_=(a.documentElement,"language"),w=g.userAgentData,b="platform",O="platformVersion",S="https://docs.simpleanalytics.com",j=/(bot|spider|crawl)/i.test(i)&&!/(cubot)/i.test(i),k=a.currentScript||a.querySelector('script[src*="'+e+'"]');m=function(){var e=[].slice.call(arguments);return e.unshift("Simple Analytics:"),Function.prototype.apply.call(n.warn,n,e)};var E=function(e){return"string"==typeof e},q=function(e,t){return e&&e.getAttribute("data-"+t)},x=function(){for(var e,t,n,r={},a=arguments,i=0;i>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=function(e){return"function"==typeof e},N="namespace",R=$[N]||q(k,N)||"sa",U=$.strictUtm||"true"==q(k,"strict-utm"),V=R+"_loaded";if(1==f[V])return m(o+"twice");f.sa_event_loaded=!0,f[V]=!0;var B,C=function(t,e,n,r){t=n?t:x(z,L,t),g.brave&&!n&&(t.brave=!0),g._duckduckgoloader_&&!n&&(t.duck=!0);var a=new Image,i=y+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=u}).map(function(e){return c(e)+"="+c(t[e])}).join("&")+"&time="+Date.now();a.src=i},T=$.hostname||q(k,"hostname"),F=T||h,H={version:"cdn_light_12",hostname:F};$.mode||q(k,"mode");try{B=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(W){m(W)}j&&(H.bot=!0);var z=x(H,{ua:i,https:p.protocol==t,timezone:B,page_id:D(),session_id:D()});if(z.sri=!1,w&&(z.mobile=w.mobile,z.brands=d(w.brands)),F!==h&&(z.hostname_original=h),r in g&&"1"==g[r])return m("Not sending request when "+r+" is enabled. See "+S+"/dnt");-1!=h.indexOf(".")&&!/^[0-9.:]+$/.test(h)||T||m("Set hostname on "+h+". See "+S+"/overwrite-domain-name");var J,L={},M=($.referrer||q(k,"referrer")||a.referrer||"").replace(h,F).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||u,P=function(e,t){var n=x(H,{type:"append",original_id:t?e:z.page_id});if(t||!g.sendBeacon)C(n,0,!0);else try{g.sendBeacon.bind(g)(y+"/append",d(n))}catch(r){C(n,0,!0)}};l("pagehide",P,!1);var Z,G,K=function(e){var t="";try{t=e||s(p.pathname)}catch(W){m(W)}return t},Q=function(e,t,n,r,a,i){e&&P(""+z.page_id,!0),z.page_id=D();var o,c=F+K(),s=(o=t,(r||p.search).slice(1).split("&").filter(function(e){return!o&&new RegExp("^((utm_)"+(U?"":"?")+"(source|medium|content|term|campaign)"+(U?"":"|ref")+")=","i").test(e)}).join("&")||u);C({id:z.page_id,type:"pageview",referrer:!t||n?M:null,query:s}),M=c,0};!function(e,t,n,r){!r&&I(n)&&(r=n);I(r);var a,i="";E(t)&&-1> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n overwriteOptions[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n overwriteOptions.strictUtm ||\n attr(scriptElement, \"strict-utm\") == trueText;\n\n var getQueryParams = function (ignoreSource) {\n return (\n loc.search\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n if (ignore) return falseVar;\n var regex =\n \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \")=\";\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex).test(keyValue);\n })\n .join(\"&\") || undefinedVar\n );\n };\n\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n image.src =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n overwriteOptions.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = overwriteOptions.mode || attr(scriptElement, \"mode\");\n\n\n\n\n\n\n\n\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var bot = isBotAgent;\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function () {\n return (\n (doc.referrer || \"\")\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n nav.sendBeacon(fullApiUrl + \"/append\", stringify(append));\n }\n };\n\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n\n\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n metadata\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n\n sendData({\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: getQueryParams(deleteSourceInfo),\n\n });\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (isPushState, pathOverwrite, metadata) {\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n if (!path || lastSendPath == path) return;\n\n lastSendPath = path;\n page.path = path;\n\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n sameSite = referrer\n ? referrer.split(slash)[0] == locationHostname\n : falseVar;\n\n\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n sendPageView(\n isPushState,\n isPushState || userNavigated || !collectMetricByString(\"r\"), // r = referrers\n sameSite,\n metadata\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n\n\n pageview();\n\n } catch (e) {\n warn(e);\n }\n})(\n window,\n {},\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_light_11\",\n \"sa\"\n);\n"],"names":["window","overwriteOptions","baseUrl","warn","undefinedVar","undefined","https","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","language","documentElement","uaData","userAgentData","platformText","platformVersionText","docsUrl","isBotAgent","test","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","attr","attribute","getAttribute","assign","obj","prop","object","to","arg","index","length","nextSource","constructor","Object","nextKey","hasOwnProperty","settings","sa_settings","logSettings","keys","Date","now","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","replace","c","getRandomValues","Uint8Array","toString","error","r","Math","random","namespaceText","namespace","strictUtm","loadedVariable","sa_event_loaded","timezone","sendData","data","callback","onlyThisData","payload","page","brave","_duckduckgoloader_","duck","Image","src","filter","key","map","join","overwrittenHostname","hostname","definedHostname","basePayload","version","mode","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","ua","page_id","session_id","sri","mobile","brands","hostname_original","indexOf","lastSendPath","referrer","sendOnLeave","id","push","append","type","original_id","sendBeacon","sameSite","userNavigated","getPath","overwrite","path","pathname","sendPageView","isPushState","deleteSourceInfo","metadata","ignoreSource","currentPage","query","search","split","keyValue","RegExp","pages","pathOverwrite","performaceEntryType","perf","performance","navigationText","getEntriesByType","triggerSendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","e","pageview"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"light.source.js","sources":["light.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n\n var collectMetricByString = function (metricAbbreviation) {\n // eslint-disable-next-line no-unreachable\n return true;\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n if (ignore) return falseVar;\n // eslint-disable-next-line no-redeclare\n var regex =\n \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \")=\";\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n return q || undefinedVar;\n };\n\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n\n\n\n\n\n\n\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n // eslint-disable-next-line no-redeclare\n var bot = isBotAgent;\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = falseVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n\n\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n sameSite = referrer\n ? referrer.split(slash)[0] == locationHostname\n : falseVar;\n\n\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n\n\n pageview();\n\n } catch (e) {\n warn(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_light_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","warn","undefinedVar","undefined","https","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","language","documentElement","uaData","userAgentData","platformText","platformVersionText","docsUrl","isBotAgent","test","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","isString","string","attr","attribute","getAttribute","assign","obj","prop","object","to","arg","index","length","nextSource","constructor","Object","nextKey","hasOwnProperty","logSettings","settings","sa_settings","Date","now","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","replace","c","getRandomValues","Uint8Array","toString","error","r","Math","random","isFunction","func","namespaceText","namespace","strictUtm","loadedVariable","sa_event_loaded","timezone","sendData","data","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","imageUrl","keys","filter","key","map","join","src","overwrittenHostname","hostname","definedHostname","basePayload","version","mode","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","ua","page_id","session_id","sri","mobile","brands","hostname_original","indexOf","lastSendPath","referrer","sendOnLeave","id","push","append","type","original_id","sendBeacon","bind","e","sameSite","userNavigated","getPath","overwrite","path","pathname","sendPageView","isPushState","deleteSourceInfo","search","metadata","ignoreSource","currentPage","query","split","keyValue","RegExp","pages","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","performaceEntryType","perf","performance","navigationText","getEntriesByType","triggerSendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","pageview"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v12/app.js b/dist/v12/app.js new file mode 100644 index 0000000..472fa43 --- /dev/null +++ b/dist/v12/app.js @@ -0,0 +1,4 @@ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 2ba7; SRI-version; v12) */ + +!function(m,e,n,v){var r,a,t;if(m)try{var g=undefined,y=!0,_=!1,i="true",o="https:",w="pageview",l="event",c="error",s=m.console,u="doNotTrack",b=m.navigator,f=m.location,E=f.host,d=m.document,p=b.userAgent,h="Not sending request ",x=h+"when ",O=_,M=encodeURIComponent,S=decodeURIComponent,k=JSON.stringify,q=m.addEventListener,A="https://queue."+e,C=d.documentElement||{},D="language",$="Height",R="scroll",j=b.userAgentData,H=R+$,L="offset"+$,N="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(p)&&!/(cubot)/i.test(p),F=m.screen,z=d.currentScript||d.querySelector('script[src*="'+e+'"]');v=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(s.warn,s,t)};var W=function(t,e){v("Error in your "+t+" function:",e)},G=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},J=function(t){return"string"==typeof t},X=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},Y=function(t,e){return t&&t.getAttribute("data-"+e)},Z=function(t){return Array.isArray(t)?t:J(t)&&t.length?t.split(/, ?/):[]},K=function(t){return t&&t.constructor===Object},Q=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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=m[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=m[At];if(!ct(r))return At&&v(At+" not found, set window."+At),t;try{return Q(t,r.call(m,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,dt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = trueVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_latest_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v12/auto-events.js b/dist/v12/auto-events.js new file mode 100644 index 0000000..b6b0f60 --- /dev/null +++ b/dist/v12/auto-events.js @@ -0,0 +1,4 @@ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 99ad; SRI-version; v12) */ + +function t(){try{for(var e=document.getElementsByTagName("a"),t=0;t -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n phones: collectTypes.indexOf(\"phones\") > -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 var saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\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 || type === \"phone\") {\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 case \"phone\": {\n var hrefPhone = element.getAttribute(\"href\");\n event = (hrefPhone.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.phone = event;\n break;\n }\n }\n }\n if (useTitle) event = theTitle;\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, function () {}, true);\n\n log(\"collected \" + clean);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n window.saAutomatedLink = saAutomatedLink;\n\n function collectLink(link) {\n if (link.hasAttribute(\"data-simple-event\")) return;\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 // Collect telephone clicks\n } else if (optionsLink.phones && /^tel:/i.test(link.href)) {\n collect = \"phone\";\n }\n\n if (!collect) return;\n\n link.addEventListener(\"click\", function () {\n saAutomatedLink(this, collect);\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 collectLink(link);\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":["onDOMContentLoaded","a","document","getElementsByTagName","i","length","link","getAttribute","collect","hasAttribute","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","phones","addEventListener","saAutomatedLink","this","collectLink","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","element","theTitle","metadata","undefined","url","useTitle","event","pop","email","phone","clean","replace","readyState","target"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v12/custom/app.js b/dist/v12/custom/app.js new file mode 100644 index 0000000..e61330e --- /dev/null +++ b/dist/v12/custom/app.js @@ -0,0 +1,4 @@ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; fcc2; SRI-version; v12) */ + +!function(v,e,n,m){var r,a,t;if(v)try{var g=undefined,y=!0,_=!1,i="true",o="https:",w="pageview",l="event",c="error",s=v.console,u="doNotTrack",b=v.navigator,f=v.location,x=f.host,p=v.document,d=b.userAgent,h="Not sending request ",E=h+"when ",O=_,M=encodeURIComponent,S=decodeURIComponent,k=JSON.stringify,A=v.addEventListener,q="https://"+e,C=p.documentElement||{},D="language",$="Height",H="scroll",R=b.userAgentData,j=H+$,L="offset"+$,N="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(d)&&!/(cubot)/i.test(d),F=v.screen,z=p.currentScript||p.querySelector('script[src*="'+e+'"]');m=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(s.warn,s,t)};var W=function(t,e){m("Error in your "+t+" function:",e)},G=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},J=function(t){return"string"==typeof t},X=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},Y=function(t,e){return t&&t.getAttribute("data-"+e)},Z=function(t){return Array.isArray(t)?t:J(t)&&t.length?t.split(/, ?/):[]},K=function(t){return t&&t.constructor===Object},Q=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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=v[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=v[qt];if(!ct(r))return qt&&m(qt+" not found, set window."+qt),t;try{return Q(t,r.call(v,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,pt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0"); +//# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/dist/v12/custom/app.js.map b/dist/v12/custom/app.js.map new file mode 100644 index 0000000..c2da3ef --- /dev/null +++ b/dist/v12/custom/app.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.source.js","sources":["app.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = trueVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_app_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":";;CAEA,SACEA,EACAC,EAIAC,EACAC,GAk1BwB,IAAUC,EACxBC,EAxoBkBC,EAxM5B,GAAKN,EAEL,IAQE,IAAIO,EAAeC,UACfC,GAAU,EACVC,GAAW,EACXC,EAAW,OACXC,EAAQ,SACRC,EAAe,WACfC,EAAY,QACZC,EAAY,QAGZC,EAAMhB,EAAOiB,QACbC,EAAa,aACbC,EAAMnB,EAAOoB,UACbC,EAAMrB,EAAOsB,SACbC,EAAmBF,EAAIG,KACvBC,EAAMzB,EAAO0B,SACbC,EAAYR,EAAIQ,UAChBC,EAAa,uBACbC,EAAiBD,EAAa,QAC9BE,EAA2BpB,EAC3BqB,EAAyBC,mBACzBC,EAAyBC,mBACzBC,EAAYC,KAAKD,UAEjBE,EAAuBrC,EAAOsC,iBAC9BC,EAhBW3B,WAgB4BX,EACvCuC,EAAkBf,EAAIe,iBAAmB,GACzCC,EAAW,WACXC,EAAS,SAETC,EAAS,SACTC,EAASzB,EAAI0B,cACbC,EAAeH,EAASD,EACxBK,EAAe,SAAWL,EAC1BM,EAAe,SAAWN,EAE1BO,EAAW,WACXC,EAAe,WACfC,EAAsB,kBACtBC,EAAU,mCACVC,EAAQ,EACRC,EACF,sBAAsBC,KAAK5B,KAAe,WAAW4B,KAAK5B,GACxD6B,EAASxD,EAAOwD,OAGhBC,EACFhC,EAAIiC,eAAiBjC,EAAIkC,cAAc,gBAAkB1D,EAAU,MAOrEE,EAAO,WAEL,IAAIyD,EAAO,GAAGC,MAAMC,KAAKC,WAOzB,OAJAH,EAAKI,QAAQ,qBAINC,SAASC,UAAUC,MAAML,KAAK9C,EAAIb,KAAMa,EAAK4C,IAGtD,IAAIQ,EAAiB,SAAUC,EAAMC,GACnCnE,EAAK,iBAAmBkE,EAAO,aAAcC,IAG3CC,EAAU,SAAUC,EAAKC,GAC3B,OAAOC,OAAOR,UAAUS,eAAeb,KAAKU,EAAKC,IAG/CG,EAAW,SAAUC,GACvB,MAAwB,iBAAVA,GAGZC,EAAc,SAAUC,GAC1B,OAAOA,EAAKC,QAAQ,sBAAuB,SAGzCC,EAAO,SAAUxB,EAAeyB,GAClC,OAAOzB,GAAiBA,EAAc0B,aAAa,QAAUD,IAG3DE,EAA+B,SAAUC,GAC3C,OAAOC,MAAMC,QAAQF,GACjBA,EACAT,EAASS,IAAQA,EAAIG,OACnBH,EAAII,MAAM,OACV,IAGJC,EAAW,SAAUC,GACvB,OAAOA,GAAUA,EAAOC,cAAgBlB,QAGtCmB,EAAS,WAGX,IAFA,IAAIC,EAAK,GACLC,EAAMhC,UACDiC,EAAQ,EAAGA,EAAQD,EAAIP,OAAQQ,IAAS,CAC/C,IAAIC,EAAaF,EAAIC,GACrB,GAAIN,EAASO,GACX,IAAK,IAAIC,KAAWD,EACd1B,EAAQ0B,EAAYC,KACtBJ,EAAGI,GAAWD,EAAWC,IAKjC,OAAOJ,GAILK,GADAC,GAAWpG,EAAOqG,YAEtBD,GAAWP,EAAOO,IAEdD,IAAahG,EAAK,WAAYiG,IAGlC,IA8EIE,GA9EAC,GAAgBnB,EAClBgB,GAASG,eAAiBtB,EAAKxB,EAAe,mBAG5C+C,GAAwB,SAAUC,GAEpC,OAGgB,IAFdF,GAAcG,OAAO,SAAU3B,GAC7B,OAAO,IAAI4B,OAAO,IAAMF,GAAoBlD,KAAKwB,KAChDS,QAIHoB,GAAMC,KAAKD,IAEXE,GAAO,WACT,IAAIC,EAAe/G,EAAOgH,QAAUhH,EAAOiH,SACvCC,EAAY,CAAC,MAAQ,KAAO,KAAO,KAAO,KAC1CC,EAAY,SAEhB,IACE,OAAOD,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,OACEA,EACCL,EAAaM,gBAAgB,IAAIC,WAAW,IAAI,GAC9C,IAAOF,EAAI,GACdG,SAAS,MAEb,MAAOjD,GACP,OAAO4C,EAAUlC,QAAQmC,EAAW,SAAUC,GAC5C,IAAII,EAAqB,GAAhBC,KAAKC,SAAiB,EAE/B,OADMN,EAAI,EAAII,EAAS,EAAJA,EAAW,GACrBD,SAAS,QAKpBI,GAAa,SAAUC,GACzB,MAAsB,mBAARA,GAIZC,GAAgB,YAChBC,GACF1B,GAASyB,KACT5C,EAAKxB,EAAeoE,KAy3BxB,KAt3BME,GAAiB,SAAUC,EAAUC,GACvC,IAAIC,EAAiBlI,EAAO8H,GAAY,aACpCpC,EAASwC,KAAiBF,EAAWnC,EAAOmC,EAAUE,IAC1D,IAAIC,EAA4BnI,EAAOoI,IACvC,IAAKT,GAAWQ,GAKd,OAJIC,IACFjI,EACEiI,GAAoB,0BAA4BA,IAE7CJ,EAET,IACE,OAAOnC,EACLmC,EACAG,EAA0BrE,KAAK9D,EAAQ6F,EAAOmC,EAAUC,KAE1D,MAAO3D,GACPF,EAAe,WAAYE,KAU3B+D,GACFjC,GAASiC,WAAapD,EAAKxB,EAAe,eAAiB9C,EAIzD2H,GAAiB,SAAUC,EAAcC,GAC3ClC,IAAKiC,GAAgB/B,GAAsB,KAAO,GAAK9F,EACvD,IAAI+H,GAAKD,GAAmBnH,EAAIqH,QAC7B7E,MAAM,GACN4B,MAAM,KACNiB,OAAO,SAAUiC,GAChB,IAAIC,EAAID,EAASE,QAAQ,KACrBvC,KAAM5F,GAAgB,EAAJkI,GAASD,EAAS9E,MAAM+E,EAAI,KAChDtC,KAAMA,GAAI,IAAM,IAAMqC,EAAS9E,MAAM,EAAG+E,IAE1C,IAAIE,EAASP,IAAiB/B,GAAsB,MAEhDuC,EAAkBC,GAAYC,IAAInE,GAAaoE,KAAK,KACpDC,EAAQL,EACR,KAAOC,EAAkB,KACzB,YACCV,GAAY,GAAK,KAClB,yCACCA,GAAY,GAAK,QAClB,IACAU,EACA,KACJ,OAAID,IAAWE,GAAYxD,OAAe9E,EAInC,IAAIiG,OAAOwC,EAAO,KAAK5F,KAAKoF,KAEpCO,KAAK,KAGR,OADA5C,GAAIA,IAAK/F,EACFkI,GAAKlI,GA+BV6I,GAAiBtB,GAAY,UACjC,GAAI9H,EAAOoJ,KAAmB3I,EAAS,OAAON,EAAKyB,EAAa,SAChE5B,EAAOqJ,gBAAkB5I,EACzBT,EAAOoJ,IAAkB3I,EAOzB,IAAI6I,GAAW,SAAUrB,EAAMsB,EAAUC,EAAcC,GACrDxB,EAAOuB,EAAevB,EAAOpC,EAAO6D,GAASC,GAAM1B,GAE/C9G,EAAIyI,QAAUJ,IAAcvB,EAAK2B,MAAQnJ,GACzCU,EAAI0I,qBAAuBL,IAAcvB,EAAK6B,KAAOrJ,GAGzD,IAAIsJ,EAAQ,IAAIC,MACZT,IACFQ,EAAME,QAAUV,EAChBQ,EAAMG,OAASX,GAEjB,IAAIY,EACF5H,EACA,eACAmC,OAAO0F,KAAKnC,GACTvB,OAAO,SAAU2D,GAChB,OAAOpC,EAAKoC,IAAQ9J,IAErB0I,IAAI,SAAUoB,GACb,OACEtI,EAAuBsI,GACvB,IACAtI,EAAuBkG,EAAKoC,MAG/BnB,KAAK,KACR,SACArC,KAAKD,MAGP,GAAI6C,GAAazJ,EAAOsK,MACtB,IAUE,YATAtK,EACGsK,MAAMH,EAAU,CACfV,UAAWhJ,EACX8J,KAAM,UACNC,YAAa,SAEdC,SAAM,WACLV,EAAMW,IAAMP,IAGhB,MAAO7F,IAEXyF,EAAMW,IAAMP,GAIVQ,GACFvE,GAASwE,UAAY3F,EAAKxB,EAAe,YACvCoH,GAAkBF,IAAuBpJ,EAEzCuJ,GAAc,CAChBC,QAutBJ,gBAttBIH,SAAUC,IASZ3K,EAAY,SAAU8K,GACpBA,EAAiBA,EAAeC,MAC5BD,EAAiB,IAAMA,EAAeC,MACtCD,EACJ7K,EAAK6K,GACL1B,GACEzD,EAAOiF,GAAa,CAClB1K,KAAMW,EACNuD,MAAO0G,EACPE,KAAM7J,EAAI8J,WAEZ5K,EACAE,IAMJ4B,EACEtB,EACA,SAAUqK,GACJA,EAAMC,WAA+C,EAAnCD,EAAMC,SAASxC,QAAQ5I,IAC3CC,EAAUkL,EAAME,UAGpB5K,GAOF,IAsDI6K,GAtDAC,GAAQ5E,KAER6E,GAAW,EAOXlB,GAAOnE,GAASmE,MAAQtF,EAAKxB,EAAe,QAG5CiI,MA/LsBpL,EA+LC8F,GAASsF,cA9LfpL,EA+LjB8F,GAASsF,WACTzG,EAAKxB,EAAe,eAAiB9C,GACrCsE,EAAKxB,EAAe,aAAe9C,GACnCsE,EAAKxB,EAAe,gBAAkB9C,EAGtCgL,KACqC,SAAvC1G,EAAKxB,EAAe,iBACpB2C,GAASuF,cAAgBjL,GAIvBkL,GACFxF,GAASyF,UACT5G,EAAKxB,EAAe,cACpBqE,GAAY,IAAMhH,EAGhBgL,GAAc1G,EAChBgB,GAAS0F,aAAe7G,EAAKxB,EAAe,iBAI1CuF,GAAc5D,EAChBgB,GAAS4C,aAAe/D,EAAKxB,EAAe,iBAI1CsI,GAAqB3G,EACvBgB,GAAS2F,oBAAsB9G,EAAKxB,EAAe,yBAIjDuI,GACF5F,GAAS4F,gBAAkB/G,EAAKxB,EAAe,mBAG7C2E,GACFhC,GAASgC,mBAAqBnD,EAAKxB,EAAe,sBAIpD,IAEE8H,GAAW/E,GAAsB,KAC7ByF,KAAKC,iBAAiBC,kBAAkBC,SACxC7L,EACJ,MAAO+D,IACPnE,EAAKmE,IAOP,IAAI+H,GAAUrM,EAAOqM,QACjBC,GACFnL,EAAIoL,WACJvM,EAAOwM,aACPxM,EAAOyM,aACPzM,EAAO0M,UACNL,KAAYA,GAAQM,QACrB3M,EAAO4M,YACP5M,EAAO6M,MACPvJ,GACAmE,KAAKC,UAAYD,KAAKC,SAGpBoF,GACFtG,GAAsB,MAAQA,GAAsB,QAElD8F,KAAKxB,GAAYwB,IAAM7L,GAE3B,IAAIiJ,GAAU7D,EAAOiF,GAAa,CAEhCiC,GAAIvG,GAAsB,MAAQ7E,EAAYpB,EAE9CK,MAAOS,EAAI2L,UAAYpM,EACvB2K,SAAUA,GACV0B,QAASH,GAAqBhG,KAASvG,EAGvC2M,WAAY1G,GAAsB,MAAQM,KAASvG,IA0BrD,GAvBAmJ,GAAQyD,IAAM1M,EAIVmC,IACF8G,GAAQ0D,OAASxK,EAAOwK,OACxB1D,GAAQ2D,OAASlL,EAAUS,EAAOyK,SAS/B5L,EAAI6L,SAASnN,EAAK,4CAInB0K,KAAoBtJ,IACtBmI,GAAQ6D,kBAAoBhM,IAGzBmK,IAAcxK,KAAcC,GAA0B,KAAnBA,EAAID,GAC1C,OAAOf,EACL0B,EAAiBX,EAAa,oBAAsBkC,EAAU,SAK7B,GAAlC7B,EAAiBsH,QAAQ,OACxB,aAAatF,KAAKhC,IACnBoJ,IAEDxK,EACE,mBACEoB,EACA,SACA6B,EACA,0BAON,IACIoK,GA8DAC,GA/DA9D,GAAO,GAGP+D,GAAc,SAAUC,GAE1B,IAAIC,EACFxH,GAASwH,UACT3I,EAAKxB,EAAe,aACpBhC,EAAImM,UACJ,GAEF,OAAID,EAAYC,EAEdA,EACG5I,QAAQzD,EAAkBsJ,IAC1B7F,QAAQ,sDAAuD,MAC/DA,QAAQ,YAAa,OAASzE,GAKjCqN,GAAWF,KAOXG,GAAW,EAEXC,GAAc,SAAUC,EAAIC,GAC9B,GAAKlB,GAAL,CAEA,IAAImB,EAASpI,EAAOiF,GAAa,CAC/B1K,KAAM,SACN8N,YAAaF,EAAOD,EAAKrE,GAAQuD,UAenC,GAXIzG,GAAsB,OACxByH,EAAOE,SAAW1G,KAAK2G,OAAOxH,KAAQ4E,GAAQqC,IAlhBnC,MAohBbA,GAAW,EACXrC,GAAQ5E,KAGJJ,GAAsB,UACxByH,EAAOxC,SAAWhE,KAAK4G,IAAI,EAAG5C,GAAU6C,OAGtCN,IAAS7M,EAAIoN,WAEfjF,GAAS2E,EAAQ1N,EAAcE,QAE/B,IACEU,EAAIoN,WAAWC,KAAKrN,EAApBA,CAAyBoB,EAAa,UAAWJ,EAAU8L,IAC3D,MAAOQ,GAEPnF,GAAS2E,EAAQ1N,EAAcE,MAMrC4B,EACE,mBACA,WACMZ,EAAIiN,QACA,KAAOzL,KAAYjD,GAAS8N,KAClCL,GAAc7G,MACTiH,IAAYjH,KAAQ6G,IAE7B/M,GAGF2B,EAAqBY,EAAU6K,GAAapN,GAE5C,IAAIiO,GAAOlN,EAAIkN,MAAQ,GACnBL,GAAW,WACb,IACE,IAAIM,EAAuBpM,EAAgBQ,IAAiB,EACxD6L,EAASpH,KAAK4G,IAChBM,GAAK7L,IAAiB,EACtB6L,GAAK5L,IAAiB,EACtBP,EAAgBQ,IAAiB,EACjCR,EAAgBM,IAAiB,EACjCN,EAAgBO,IAAiB,GAEnC,OAAO0E,KAAKqH,IACV,IAKI,EAJJrH,KAAK2G,MACF,MAAQ5L,EAAgBuM,WAAa,GAAKH,GACzCC,EACA,IAGN,MAAOvK,IAEP,OADAnE,EAAKmE,IACE,IAIXjC,EAAqB,OAAQ,WAC3BoJ,GAAW6C,KACXjM,EACEM,EACA,WACM8I,GAAW6C,OAAY7C,GAAW6C,OAExC5N,KAQJ,IAgCIsO,GAoCAC,GAAUC,GApEVC,GAAU,SAAUC,GACtB,IAAIlE,EAAO,GAIX,IACEA,EAAOkE,GAAanN,EAAuBZ,EAAI8J,UAC/C,MAAO7G,IACPnE,EAAKmE,IAGP,IAAI+K,EAAyBrP,EAAOgM,IACpC,GAAIrE,GAAW0H,GACb,IACEnE,EAAOmE,EAAuBvL,KAAK9D,EAAQ,CAAEkL,KAAMA,KAAWA,EAC9D,MAAO5G,IACPF,EAAe,OAAQE,IAK3B,IA/ZiB,SAAU4G,GAC3B,IAAK,IAAItC,KAAKkD,GAAa,CACzB,IAAIwD,EAAgBxD,GAAYlD,GAChC,GAAK0G,EAAL,CAGA,IAAIC,EA1OI,KA2OND,EAAc,GAAcA,EA3OtB,IA2O8CA,EAEtD,GACEC,IAAerE,GACf,IAAIvE,OACF,IAAM7B,EAAYyK,GAAYvK,QAAQ,SAAU,QAAU,IAC1D,KACAzB,KAAK2H,GAEP,OAAOzK,GAEX,OAAOC,EA6YH8O,CAAatE,GAQjB,MAFY,QAARX,IAAkBlJ,EAAIoO,OAAMvE,GAAQ7J,EAAIoO,KAAKhK,MAAM,KAAK,IAErDyF,EAPL/K,EAAK0B,EAAiB,YAAcqJ,IAgDpCwE,GAAW,SACbC,EACAC,EACA5H,EACA6H,IAEKA,GAAelI,GAAWK,KAAW6H,EAAc7H,GACxD,IAIM8H,EAJFvG,EAAW5B,GAAWkI,GAAeA,EAAc,aACnDE,EAAc,GACdnL,EAASgL,KAAgD,EAA9BA,EAAc/G,QAAQ,OAGnD+G,GADIE,EAAQF,EAAcnK,MAAM,MACVuK,QACtBD,EAAc,IAAMD,EAAM5G,KAAK,MAGjC,IAAIgC,EAAOiE,GAAQS,GAGfK,EAAU/E,EAAO6E,EACrB,GAAK7E,GAAQsC,IAAgByC,EAA7B,CAEAzC,GAAeyC,EACftG,GAAKuB,KAAOA,EAGR1E,GAAsB,OACxBmD,GAAKuG,eACHzI,KAAK4G,IAAI7L,EAA2B,aAAK,EAAGxC,EAAOmQ,YAAc,IACjE,KACFxG,GAAKyG,gBACH3I,KAAK4G,IACH7L,EAAgBQ,IAAiB,EACjChD,EAAOqQ,aAAe,IACnB,MAIL7J,GAAsB,MACpBrF,EAAIsB,KAAWkH,GAAKlH,GAAYtB,EAAIsB,IAItCe,GAAUgD,GAAsB,QAClCmD,GAAK2G,aAAe9M,EAAO+M,MAC3B5G,GAAK6G,cAAgBhN,EAAOqL,QAI9B,IAII4B,EAJAC,EAAO1Q,EAAO2Q,YACdC,EAAiB,aAIrB,IACEH,EAAsBC,EAAKG,iBAAiBD,GAAgB,GAAGxQ,KAC/D,MAAOkE,IACPnE,EAAKmE,IAGP4K,GAAgBuB,GAC+C,EAA3D,CAAC,SAAU,gBAAgB5H,QAAQ4H,GAGnCC,GACAA,EAAKE,KACwC,EAA7C,CAAC,EAAG,GAAG/H,QAAQ6H,EAAKE,GAAgBxQ,MAGxC,IAAI0Q,EAA0BlD,GAC1BA,GAASnI,MA1vBH,KA0vBgB,GACtBlF,EACJ0O,GAAWrB,IACgD,EAAvD7B,GAAmBlD,QAAQiI,IAC3BA,GAA2BvP,EAC3Bb,EAGJiJ,GAAKoH,OACHpB,GAAeT,GACXxO,GACCuO,KAAc5L,GAAS,YAAYE,KAAKmK,GAAYjN,IAE3DuH,EAAWD,GAAeC,EAAU,CAClC5H,KAAMS,EACNqK,KAAMvB,GAAKuB,OAGb,IAAI8F,EAAsB,WACxBlP,EAA2BrB,EAC3B,IAAIwQ,EACFtB,GAAeT,KAAkB1I,GAAsB,MA9H1C,SACjBmJ,EACAuB,EACAjC,EACAvG,EACAV,EACAuB,GAEIoG,GAAa7B,GAAY,GAAKpE,GAAQuD,QAASxM,GAC/CqM,KAAoBpD,GAAQuD,QAAUnG,MAE1C,IAAIqK,EAActG,GAAkBsE,KAChCiC,EAAQ9I,GAAe4I,EAAkBxI,GAE7CY,GACE,CACEyE,GAAIrE,GAAQuD,QACZ7M,KAAMS,EACN+M,UAAWsD,GAAoBjC,EAAWrB,GAAW,KACrDwD,MAAOA,EACP9K,EAAGA,GAEH0B,SAAU7F,EAAU6F,IAEtBuB,GAGFyF,GAAmBpB,GACnBA,GAAWuD,EAEX9N,IAiGEgO,CACE1B,EACAsB,EACAhC,GACAc,EACA/H,EACAuB,IAIJ,GAAKzH,EAmBHkP,SAjBA,IACMpO,GAAU+E,GAAW/E,EAAO0O,sBAC9B1O,EACG0O,qBAAqB,CAACpO,EAAcC,IACpCoO,KAAK,SAAUC,GACd9H,GAAQ+H,QAAUD,EAAkBtO,GACpCwG,GAAQgI,WAAaF,EAAkBrO,GACvC6N,MAEDvG,SAAMuG,GAETA,IAEF,MAAOvC,GACPuC,OAWFW,GAAM3R,EAAO4R,QACbC,GAAeF,GAAMA,GAAIG,UAAYvR,EACrCwR,GAAM/R,EAAOgS,cACbC,GAAgB,YAIhBtG,IAAekG,IAAgBK,OAASH,KAqB1CJ,GAAIG,WAnBEzR,EAAOsR,GADiBvR,EAoBA6R,IAlBrB,WACL,IAEI7G,EAFArF,EAAMhC,UACNoO,EAAK9R,EAAK8D,MAAMiO,KAAMrM,GAY1B,OAVI4B,GAAWuK,OACb9G,EAAQ,IAAI8G,MAAM9R,IAIlBgL,EAAQ3J,EAAI4Q,YAAY,UAClBC,UAAUlS,EAAMK,EAASA,GAEjC2K,EAAMrH,UAAYgC,EAClBgM,GAAI3G,GACG+G,IAMX9P,EACE4P,GACA,WACEvC,GAAS,IAEXhP,GAGF2B,EACE,WACA,WACEqN,GAAS,IAEXhP,IAKAiL,IAAuB,QAARpB,IAAkB,iBAAkBvK,GACrDqC,EACE,aACA,WACEqN,GAAS,IAEXhP,GAIAiL,IAAa+D,KAEjB,IAAI6C,GAAiB,SAAUrH,EAAMlD,EAAUuB,GAC7CmG,GAAS,EAAGxE,EAAMlD,EAAUuB,IAE9BvJ,EAAO8H,GAAY,IAAMjH,GAAgB0R,GACzC,IAAIC,GAAkBC,MAAyB5R,EAC1Cb,EAAOwS,MAAkBxS,EAAOwS,IAAmBD,IAOxD,IAAIG,GAAa,CAAC,SAAU,UAExBC,GAAY,SAAUvH,EAAOpD,EAAU6H,EAAapG,IACjDoG,GAAelI,GAAWK,KAAW6H,EAAc7H,GAExD,IAAI4K,EAAkBjL,GAAWyD,GAC7B7B,EAAW5B,GAAWkI,GAAeA,EAAc,aACnDgD,SAAmBzH,EAEvB,GAAIsH,GAAW7J,QAAQgK,GAAa,IAAMD,EAExC,OADAxO,EAAewH,GAAmB9K,EAAY,aAAe+R,GACtDtJ,IAGT,IACE,GAAIqJ,EAAiB,CACnB,IAAIE,EAAc1H,IAClB,GAAIsH,GAAW7J,eAAeiK,GAAe,EAK3C,OAJA1O,EACEwH,GACAR,EAAQ,uBAAyB0H,GAE5BvJ,IAET6B,EAAQ0H,GAEV,MAAOxO,IAEP,OADAF,EAAewH,GAAmBtH,IAC3BiF,IAGT6B,GAAS,GAAKA,GAAOpG,QAAQ,eAAgB,KAAKA,QAAQ,WAAY,IAEtE,IAAI+N,EAAc,CAAE3S,KAAMU,EAAWsK,MAAOA,GACxC4H,GAAa9D,IAAiB7L,EAAQ,EAE1C2E,EAAWD,GAAeC,EAAU+K,GAEhC3H,GACF9B,GACEzD,EAAOkN,EAAa,CAClBhF,GAAIjH,KACJsK,MAAO9I,IAAgB0K,GACvBpF,UACGoF,GAAa/D,KAAazI,GAAsB,KAC7CwI,GACA,KAENhH,SAAU7F,EAAU6F,KAEtBuB,EACAhJ,EACAkJ,IAKFwJ,GAAmB,SAAU7H,EAAOpD,EAAUuB,EAAUE,GAC1DkJ,GAAUvH,EAAOpD,EAAUuB,EAAUE,IAIlCzJ,EAAO4L,MACV5L,EAAO4L,IAAqBqH,IAE9B,IAAIC,GAAYlT,EAAO4L,IAGnBuH,GAAQD,IAAaA,GAAUzK,EAAIyK,GAAUzK,EAAI,GAMrD,IAAK,IAAI2C,MAHTpL,EAAO4L,IAAqBqH,GAGVE,GACZ5O,EAAQ4O,GAAO/H,MACjB9F,MAAMC,QAAQ4N,GAAM/H,KAChBuH,GAAUxO,MAAM,KAAMgP,GAAM/H,KAC5BuH,GAAUQ,GAAM/H,MAIxB,IA0CMgI,GA1CFC,GAAc,SAAUjI,GAE1B,IADA,IAAIkI,EAAUlI,EAAMmI,OAElBD,GACAA,IAAY7R,KACV6R,EAAQnO,cAAkD,OAAlCF,EAAKqO,EAAS,kBAExCA,EAAUA,EAAQE,WAEpB,GAAKF,GAAWA,IAAY7R,EAA5B,CACA,IAAIgS,EAA6B,SAApBH,EAAQI,QACjBrP,EAAOY,EAAKqO,EAAS,gBACzB,GAAKjP,GAAQoP,IAA2B,WAAfrI,EAAMhL,MAA/B,CAIA,IAFA,IASMuT,EATF3L,EAAW,CAAE4L,IAAKN,EAAQI,QAAQG,eAClCC,EAAaR,EAAQQ,WAChBlL,EAAI,EAAGA,EAAIkL,EAAWtO,OAAQoD,IAAK,CAC1C,IAAI1D,EAAY4O,EAAWlL,GAC0B,IAAjD1D,EAAUb,KAAKwE,QAAQ,wBACzBb,EAAS9C,EAAUb,KAAKR,MAAM,IAAImB,QAAQ,KAAM,MAC9CE,EAAU5E,OAEZmT,IACEE,EAASvI,EAAM2I,UACnB/L,EAASgM,YAAcL,GAClBA,EAAOM,aAAeN,EAAOrT,OAAS,IACpC0E,QAAQ,OAAQ,KAChBkP,OACArQ,MAAM,EAAG,KACZ,IAEN8O,GAAUtO,EAAM2D,EAAUzH,EAAcE,MAG1CgB,EAAIa,iBAAiB,QAAS+Q,GAAa3S,GAC3Ce,EAAIa,iBAAiB,SAAU+Q,GAAa3S,GAI1C0F,GAASgN,YAAc3S,GACvBwE,EAAKxB,EAAe,eAAiB9C,IAEjCyS,GAAY,WACd,GACG,UAAU7P,KAAK9B,EAAI0S,MAAQ,KAAO1S,EAAIkN,MAAQlN,EAAIkN,KAAKsF,cAG1D,IACE,IAAIG,EAAU,IAAIpU,EAAOqU,eACzBD,EAAQE,KAAK,OAAQjT,EAAIkT,KAAM9T,GAC/B2T,EAAQlK,OAAS,WACQ,MAAnBkK,EAAQI,QACV7B,GAAU,WAAY,CACpB8B,IAAKpT,EAAI2L,SAAW,KAAOnC,GAAkBxJ,EAAI8J,SACjDqJ,OAAQ,OAGdJ,EAAQM,OACR,MAAOpQ,OAEY,YAAnB7C,EAAIkT,WACNlT,EAAIa,iBAAiB,mBAAoB8Q,GAAW1S,GACjD0S,MAEP,MAAO3E,IACPvO,EAAUuO,KA5iCd,CA+iCmB,oBAAVzO,QAAyBA,OAChC"} \ No newline at end of file diff --git a/dist/v12/custom/auto-events.js b/dist/v12/custom/auto-events.js new file mode 100644 index 0000000..b6b0f60 --- /dev/null +++ b/dist/v12/custom/auto-events.js @@ -0,0 +1,4 @@ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; 99ad; SRI-version; v12) */ + +function t(){try{for(var e=document.getElementsByTagName("a"),t=0;t -1,\n emails: collectTypes.indexOf(\"emails\") > -1,\n downloads: collectTypes.indexOf(\"downloads\") > -1,\n phones: collectTypes.indexOf(\"phones\") > -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 var saAutomatedLink = function saAutomatedLink(element, type) {\n try {\n if (!element) return log(\"no element found\");\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 || type === \"phone\") {\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 case \"phone\": {\n var hrefPhone = element.getAttribute(\"href\");\n event = (hrefPhone.split(\":\")[1] || \"\").split(\"?\")[0];\n metadata.phone = event;\n break;\n }\n }\n }\n if (useTitle) event = theTitle;\n\n var clean =\n type +\n \"_\" +\n event.replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_+|_+$)/g, \"\");\n\n window[saGlobal](clean, metadata, function () {}, true);\n\n log(\"collected \" + clean);\n } else {\n log(saGlobal + \" is not defined\", \"warn\");\n }\n } catch (error) {\n log(error.message, \"warn\");\n }\n };\n\n window.saAutomatedLink = saAutomatedLink;\n\n function collectLink(link) {\n if (link.hasAttribute(\"data-simple-event\")) return;\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 // Collect telephone clicks\n } else if (optionsLink.phones && /^tel:/i.test(link.href)) {\n collect = \"phone\";\n }\n\n if (!collect) return;\n\n link.addEventListener(\"click\", function () {\n saAutomatedLink(this, collect);\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 collectLink(link);\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":["onDOMContentLoaded","a","document","getElementsByTagName","i","length","link","getAttribute","collect","hasAttribute","optionsLink","downloads","test","href","RegExp","downloadsExtensions","join","pathname","outbound","hostname","window","location","emails","phones","addEventListener","saAutomatedLink","this","collectLink","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","element","theTitle","metadata","undefined","url","useTitle","event","pop","email","phone","clean","replace","readyState","target"],"mappings":";;AAwLE,SAASA,IACP,IAIE,IAHA,IAAIC,EAAIC,SAASC,qBAAqB,KAG7BC,EAAI,EAAGA,EAAIH,EAAEI,OAAQD,IAAK,CACjC,IAAIE,EAAOL,EAAEG,GACFE,EAAKC,aAAa,SA9CnC,SAAqBD,GACnB,IACIE,EADAF,EAAKG,aAAa,uBAClBD,GAAU,EAIZE,EAAYC,WACZ,gBAAgBC,KAAKN,EAAKO,OAC1B,IAAIC,OACF,QAAUJ,EAAYK,qBAAuB,IAAIC,KAAK,KAAO,KAC7D,KACAJ,KAAKN,EAAKW,UAEZT,EAAU,WAIVE,EAAYQ,UACZ,gBAAgBN,KAAKN,EAAKO,OAC1BP,EAAKa,WAAaC,EAAOC,SAASF,SAElCX,EAAU,WAGDE,EAAYY,QAAU,YAAYV,KAAKN,EAAKO,MACrDL,EAAU,QAGDE,EAAYa,QAAU,SAASX,KAAKN,EAAKO,QAClDL,EAAU,SAGPA,GAELF,EAAKkB,iBAAiB,QAAS,WAC7BC,EAAgBC,KAAMlB,MAgBpBmB,CAAYrB,IAEd,MAAOsB,GACPC,EAAID,EAAME,QAAS,SAvMzB,IAA4BV,EAItBS,EAKAE,EAEAC,EAGAC,EAqBAC,EAMAC,EAEAC,EA0BAC,EAGA3B,EAKAe,OA3EkB,KAFIL,EAkNzBA,UA9MGS,EAAM,SAAUC,EAASQ,GAC3B,IAAIC,EAAkB,SAATD,EAAkBE,QAAQC,KAAOD,QAAQE,KACtD,OAAOH,GAAUA,EAAO,gCAAiCT,IAGvDC,EAAMX,EAAOlB,SAEb8B,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,YACA,WAEEZ,EAAWF,EAAQ,WAAY,QAAQ,GAEvCG,EAAU,CAEZlB,UAA8C,EAApCgB,EAAaqB,QAAQ,YAC/BjC,QAA0C,EAAlCY,EAAaqB,QAAQ,UAC7B5C,WAAgD,EAArCuB,EAAaqB,QAAQ,aAChChC,QAA0C,EAAlCW,EAAaqB,QAAQ,UAE7BxC,oBAAqBkB,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,KAFvBvB,EAAc0B,IAGhBP,EAAI,2CAA4C,QAE9CJ,EAAkB,SAASA,EAAgBkC,EAASrB,GACtD,IACE,IAAKqB,EAAS,OAAO9B,EAAI,oBAEzB,GAAIT,EAAOiB,IAAajB,EAAOiB,EAAW,WAAY,CACpD,IAWMuB,EAXFzC,EAAWwC,EAAQxC,SACnBF,EAAW0C,EAAQ1C,SAGnB4C,EAAW,CACbL,MAAOG,EAAQpD,aAAa,UAAYuD,WAEtCC,EAAMJ,EAAQ9C,MAAQiD,UAEtBE,GAAW,EAMf,GALItD,EAAY8C,OAASG,EAAQlD,aAAa,WAE5B,KADZmD,EAAWD,EAAQpD,aAAa,SAAS6C,UACzBY,GAAW,KAG5BA,GAAqB,UAAT1B,EACf,OAAQA,GACN,IAAK,WACH2B,EAAQ9C,GAAYT,EAAY+C,gBAAkBxC,EAAW,IAC7D4C,EAASE,IAAMA,EACf,MAEF,IAAK,WACHE,EAAQvD,EAAYgD,iBAChBvC,EAAWF,EACXA,EAASgC,MAAM,KAAKiB,MACxBL,EAASE,IAAMA,EACf,MAEF,IAAK,QACH,IACAE,GADWN,EAAQpD,aAAa,QAClB0C,MAAM,KAAK,IAAM,IAAIA,MAAM,KAAK,GAC9CY,EAASM,MAAQF,EACjB,MAEF,IAAK,QAEHA,GADgBN,EAAQpD,aAAa,QAClB0C,MAAM,KAAK,IAAM,IAAIA,MAAM,KAAK,GACnDY,EAASO,MAAQH,EAKnBD,IAAUC,EAAQL,GAEtB,IAAIS,EACF/B,EACA,IACA2B,EAAMK,QAAQ,eAAgB,KAAKA,QAAQ,aAAc,IAE3DlD,EAAOiB,GAAUgC,EAAOR,EAAU,cAAgB,GAElDhC,EAAI,aAAewC,QAEnBxC,EAAIQ,EAAW,kBAAmB,QAEpC,MAAOT,GACPC,EAAID,EAAME,QAAS,UAIvBV,EAAOK,gBAAkBA,EA4DF,UAAnBM,EAAIwC,YAA6C,aAAnBxC,EAAIwC,WACpCvE,IAEAE,SAASsB,iBAAiB,mBAAoB,SAAUyC,GACtB,aAA5BA,EAAMO,OAAOD,YAA2BvE"} \ No newline at end of file diff --git a/dist/v12/custom/light.js b/dist/v12/custom/light.js new file mode 100644 index 0000000..51ab72b --- /dev/null +++ b/dist/v12/custom/light.js @@ -0,0 +1,4 @@ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; edd8; SRI-version; v12) */ + +!function(f,e,m){if(f)try{var u=undefined,t="https:",n=f.console,r="doNotTrack",g=f.navigator,p=f.location,h=p.host,i=f.document,a=g.userAgent,o="Not sending request ",v=!1,c=encodeURIComponent,s=decodeURIComponent,d=JSON.stringify,l=f.addEventListener,y="https://"+e,_=(i.documentElement,"language"),w=g.userAgentData,b="platform",O="platformVersion",S="https://docs.simpleanalytics.com",j=/(bot|spider|crawl)/i.test(a)&&!/(cubot)/i.test(a),k=i.currentScript||i.querySelector('script[src*="'+e+'"]');m=function(){var e=[].slice.call(arguments);return e.unshift("Simple Analytics:"),Function.prototype.apply.call(n.warn,n,e)};var x=function(e){return"string"==typeof e},E=function(e,t){return e&&e.getAttribute("data-"+t)},A=function(){for(var e,t,n,r={},i=arguments,a=0;a>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=function(e){return"function"==typeof e},N="namespace",R=q[N]||E(k,N)||"sa",U=q.strictUtm||"true"==E(k,"strict-utm"),V=R+"_loaded";if(1==f[V])return m(o+"twice");f.sa_event_loaded=!0,f[V]=!0;var B,C=function(t,e,n,r){t=n?t:A(z,L,t),g.brave&&!n&&(t.brave=!0),g._duckduckgoloader_&&!n&&(t.duck=!0);var i=new Image,a=y+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=u}).map(function(e){return c(e)+"="+c(t[e])}).join("&")+"&time="+Date.now();i.src=a},H=q.hostname||E(k,"hostname"),T=H||h,F={version:"custom_light_12",hostname:T};q.mode||E(k,"mode");try{B=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(W){m(W)}j&&(F.bot=!0);var z=A(F,{ua:a,https:p.protocol==t,timezone:B,page_id:D(),session_id:D()});if(z.sri=!0,w&&(z.mobile=w.mobile,z.brands=d(w.brands)),T!==h&&(z.hostname_original=h),r in g&&"1"==g[r])return m("Not sending request when "+r+" is enabled. See "+S+"/dnt");-1!=h.indexOf(".")&&!/^[0-9.:]+$/.test(h)||H||m("Set hostname on "+h+". See "+S+"/overwrite-domain-name");var J,L={},M=(q.referrer||E(k,"referrer")||i.referrer||"").replace(h,T).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||u,P=function(e,t){var n=A(F,{type:"append",original_id:t?e:z.page_id});if(t||!g.sendBeacon)C(n,0,!0);else try{g.sendBeacon.bind(g)(y+"/append",d(n))}catch(r){C(n,0,!0)}};l("pagehide",P,!1);var Z,G,K=function(e){var t="";try{t=e||s(p.pathname)}catch(W){m(W)}return t},Q=function(e,t,n,r,i,a){e&&P(""+z.page_id,!0),z.page_id=D();var o,c=T+K(),s=(o=t,(r||p.search).slice(1).split("&").filter(function(e){return!o&&new RegExp("^((utm_)"+(U?"":"?")+"(source|medium|content|term|campaign)"+(U?"":"|ref")+")=","i").test(e)}).join("&")||u);C({id:z.page_id,type:"pageview",referrer:!t||n?M:null,query:s}),M=c,0};!function(e,t,n,r){!r&&I(n)&&(r=n);I(r);var i,a="";x(t)&&-1"); +//# sourceMappingURL=light.js.map \ No newline at end of file diff --git a/dist/v12/custom/light.js.map b/dist/v12/custom/light.js.map new file mode 100644 index 0000000..97df90a --- /dev/null +++ b/dist/v12/custom/light.js.map @@ -0,0 +1 @@ +{"version":3,"file":"light.source.js","sources":["light.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n\n var collectMetricByString = function (metricAbbreviation) {\n // eslint-disable-next-line no-unreachable\n return true;\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n if (ignore) return falseVar;\n // eslint-disable-next-line no-redeclare\n var regex =\n \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \")=\";\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n return q || undefinedVar;\n };\n\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n\n\n\n\n\n\n\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n // eslint-disable-next-line no-redeclare\n var bot = isBotAgent;\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = trueVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n\n\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n sameSite = referrer\n ? referrer.split(slash)[0] == locationHostname\n : falseVar;\n\n\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n\n\n pageview();\n\n } catch (e) {\n warn(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_light_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","warn","undefinedVar","undefined","https","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","language","documentElement","uaData","userAgentData","platformText","platformVersionText","docsUrl","isBotAgent","test","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","isString","string","attr","attribute","getAttribute","assign","obj","prop","object","to","arg","index","length","nextSource","constructor","Object","nextKey","hasOwnProperty","logSettings","settings","sa_settings","Date","now","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","replace","c","getRandomValues","Uint8Array","toString","error","r","Math","random","isFunction","func","namespaceText","namespace","strictUtm","loadedVariable","sa_event_loaded","timezone","sendData","data","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","imageUrl","keys","filter","key","map","join","src","overwrittenHostname","hostname","definedHostname","basePayload","version","mode","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","ua","protocol","page_id","session_id","sri","mobile","brands","hostname_original","indexOf","lastSendPath","referrer","sendOnLeave","id","push","append","type","original_id","sendBeacon","bind","e","sameSite","userNavigated","getPath","overwrite","path","pathname","sendPageView","isPushState","deleteSourceInfo","search","metadata","ignoreSource","currentPage","query","split","keyValue","RegExp","pages","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","performaceEntryType","perf","performance","navigationText","getEntriesByType","triggerSendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","pageview"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v12/custom/proxy.js b/dist/v12/custom/proxy.js new file mode 100644 index 0000000..5cab442 --- /dev/null +++ b/dist/v12/custom/proxy.js @@ -0,0 +1,4 @@ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; a36f; SRI-version; v12) */ + +!function(v,e,n,m){var r,a,t;if(v)try{var g=undefined,y=!0,_=!1,i="true",o="https:",w="pageview",l="event",c="error",s=v.console,u="doNotTrack",b=v.navigator,f=v.location,x=f.host,p=v.document,d=b.userAgent,h="Not sending request ",E=h+"when ",O=_,M=encodeURIComponent,S=decodeURIComponent,k=JSON.stringify,A=v.addEventListener,q="https://"+e,C=p.documentElement||{},D="language",$="Height",H="scroll",R=b.userAgentData,j=H+$,L="offset"+$,N="client"+$,P="pagehide",T="platform",U="platformVersion",I="https://docs.simpleanalytics.com",V=0,B=/(bot|spider|crawl)/i.test(d)&&!/(cubot)/i.test(d),F=v.screen,z=p.currentScript||p.querySelector('script[src*="'+e+'"]');m=function(){var t=[].slice.call(arguments);return t.unshift("Simple Analytics:"),Function.prototype.apply.call(s.warn,s,t)};var W=function(t,e){m("Error in your "+t+" function:",e)},G=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},J=function(t){return"string"==typeof t},X=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},Y=function(t,e){return t&&t.getAttribute("data-"+e)},Z=function(t){return Array.isArray(t)?t:J(t)&&t.length?t.split(/, ?/):[]},K=function(t){return t&&t.constructor===Object},Q=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)})}},ct=function(t){return"function"==typeof t},st="namespace",ut=et[st]||Y(z,st)||"sa",lt=function(t,e){var n=v[ut+"_metadata"];K(n)&&(t=Q(t,n));var r=v[qt];if(!ct(r))return qt&&m(qt+" not found, set window."+qt),t;try{return Q(t,r.call(v,Q(t,e)))}catch(a){W("metadata",a)}},ft=et.strictUtm||Y(z,"strict-utm")==i,pt=function(i,t){nt=!i&&at("q")?"":_;var e=(t||f.search).slice(1).split("&").filter(function(t){var e=t.indexOf("=");nt!==_&&0"); +//# sourceMappingURL=proxy.js.map \ No newline at end of file diff --git a/dist/v12/custom/proxy.js.map b/dist/v12/custom/proxy.js.map new file mode 100644 index 0000000..db13d56 --- /dev/null +++ b/dist/v12/custom/proxy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy.source.js","sources":["proxy.source.js"],"sourcesContent":["/* eslint-env browser */\n\n(function (\n window,\n baseUrl,\n apiUrlPrefix,\n version,\n defaultNamespace,\n sendError,\n warn\n) {\n // Only initialize in a browser.\n if (!window) return;\n\n try {\n /////////////////////\n // PREDEFINED VARIABLES FOR BETTER MINIFICATION\n //\n\n // This seems like a lot of repetition, but it makes our script available for\n // multple destination which prevents us to need multiple scripts. The minified\n // version stays small.\n var undefinedVar = undefined;\n var trueVar = true;\n var falseVar = false;\n var trueText = \"true\";\n var https = \"https:\";\n var pageviewText = \"pageview\";\n var eventText = \"event\";\n var errorText = \"error\";\n var slash = \"/\";\n var protocol = https + \"//\";\n var con = window.console;\n var doNotTrack = \"doNotTrack\";\n var nav = window.navigator;\n var loc = window.location;\n var locationHostname = loc.host;\n var doc = window.document;\n var userAgent = nav.userAgent;\n var notSending = \"Not sending request \";\n var notSendingWhen = notSending + \"when \";\n var fetchedHighEntropyValues = falseVar;\n var encodeURIComponentFunc = encodeURIComponent;\n var decodeURIComponentFunc = decodeURIComponent;\n var stringify = JSON.stringify;\n var thousand = 1000;\n var addEventListenerFunc = window.addEventListener;\n var fullApiUrl = protocol + apiUrlPrefix + baseUrl;\n var documentElement = doc.documentElement || {};\n var language = \"language\";\n var Height = \"Height\";\n var Width = \"Width\";\n var scroll = \"scroll\";\n var uaData = nav.userAgentData;\n var scrollHeight = scroll + Height;\n var offsetHeight = \"offset\" + Height;\n var clientHeight = \"client\" + Height;\n var clientWidth = \"client\" + Width;\n var pagehide = \"pagehide\";\n var platformText = \"platform\";\n var platformVersionText = \"platformVersion\";\n var docsUrl = \"https://docs.simpleanalytics.com\";\n var pages = 0;\n var isBotAgent =\n /(bot|spider|crawl)/i.test(userAgent) && !/(cubot)/i.test(userAgent);\n var screen = window.screen;\n\n // Find the script element where options can be set on\n var scriptElement =\n doc.currentScript || doc.querySelector('script[src*=\"' + baseUrl + '\"]');\n\n /////////////////////\n // HELPER FUNCTIONS\n //\n\n // A simple log function so the user knows why a request is not being send\n warn = function () {\n // 1. Convert args to a normal array\n var args = [].slice.call(arguments);\n\n // 2. Prepend log prefix\n args.unshift(\"Simple Analytics:\");\n\n // 3. Pass along arguments to console.warn\n // Function.prototype.apply.call is needed for Internet Explorer\n return Function.prototype.apply.call(con.warn, con, args);\n };\n\n var warnInFunction = function (name, error) {\n warn(\"Error in your \" + name + \" function:\", error);\n };\n\n var hasProp = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n\n var isString = function (string) {\n return typeof string == \"string\";\n };\n\n var filterRegex = function (item) {\n return item.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n };\n\n var attr = function (scriptElement, attribute) {\n return scriptElement && scriptElement.getAttribute(\"data-\" + attribute);\n };\n\n var convertCommaSeparatedToArray = function (csv) {\n return Array.isArray(csv)\n ? csv\n : isString(csv) && csv.length\n ? csv.split(/, ?/)\n : [];\n };\n\n var isObject = function (object) {\n return object && object.constructor === Object;\n };\n\n var assign = function () {\n var to = {};\n var arg = arguments;\n for (var index = 0; index < arg.length; index++) {\n var nextSource = arg[index];\n if (isObject(nextSource)) {\n for (var nextKey in nextSource) {\n if (hasProp(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n\n var settings = window.sa_settings;\n var logSettings = settings;\n settings = assign(settings);\n\n if (logSettings) warn(\"Settings\", settings);\n\n // Customers can skip data points\n var ignoreMetrics = convertCommaSeparatedToArray(\n settings.ignoreMetrics || attr(scriptElement, \"ignore-metrics\")\n );\n\n var collectMetricByString = function (metricAbbreviation) {\n // Can't use Array.find() here because we need to support IE9\n return (\n ignoreMetrics.filter(function (item) {\n return new RegExp(\"^\" + metricAbbreviation).test(item);\n }).length === 0\n );\n };\n\n var now = Date.now;\n\n var uuid = function () {\n var cryptoObject = window.crypto || window.msCrypto;\n var emptyUUID = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;\n var uuidRegex = /[018]/g;\n\n try {\n return emptyUUID.replace(uuidRegex, function (c) {\n return (\n c ^\n (cryptoObject.getRandomValues(new Uint8Array(1))[0] &\n (15 >> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n var appendMetadata = function (metadata, data) {\n var metadataObject = window[namespace + \"_metadata\"];\n if (isObject(metadataObject)) metadata = assign(metadata, metadataObject);\n var metadataCollectorFunction = window[metadataCollector];\n if (!isFunction(metadataCollectorFunction)) {\n if (metadataCollector)\n warn(\n metadataCollector + \" not found, set window.\" + metadataCollector\n );\n return metadata;\n }\n try {\n return assign(\n metadata,\n metadataCollectorFunction.call(window, assign(metadata, data))\n );\n } catch (error) {\n warnInFunction(\"metadata\", error);\n }\n };\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n var k;\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n k = !ignoreSource && collectMetricByString(\"q\") ? \"\" : falseVar;\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n var i = keyValue.indexOf(\"=\");\n if (k !== falseVar && i > 0 && keyValue.slice(i + 1))\n k += (k ? \",\" : \"\") + keyValue.slice(0, i);\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n var paramsRegexList = allowParams.map(filterRegex).join(\"|\");\n var regex = ignore\n ? \"^(\" + paramsRegexList + \")=\"\n : \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \"|\" +\n paramsRegexList +\n \")=\";\n if (ignore && !allowParams.length) return falseVar;\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n k = k || undefinedVar;\n return q || undefinedVar;\n };\n\n // Ignore pages specified in data-ignore-pages\n var shouldIgnore = function (path) {\n for (var i in ignorePages) {\n var ignorePageRaw = ignorePages[i];\n if (!ignorePageRaw) continue;\n\n // Prepend a slash when it's missing\n var ignorePage =\n ignorePageRaw[0] == slash ? ignorePageRaw : slash + ignorePageRaw;\n\n if (\n ignorePage === path ||\n new RegExp(\n \"^\" + filterRegex(ignorePage).replace(/\\\\\\*/gi, \"(.*)\") + \"$\",\n \"i\"\n ).test(path)\n )\n return trueVar;\n }\n return falseVar;\n };\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n if (callback) {\n image.onerror = callback;\n image.onload = callback;\n }\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n // Events must survive navigation without taking over links or forms.\n if (keepalive && window.fetch) {\n try {\n window\n .fetch(imageUrl, {\n keepalive: trueVar,\n mode: \"no-cors\",\n credentials: \"omit\",\n })\n .catch(function () {\n image.src = imageUrl;\n });\n return;\n } catch (error) {}\n }\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n /////////////////////\n // ERROR FUNCTIONS\n //\n\n // Send errors\n // no var because it's scoped outside of the try/catch\n sendError = function (errorOrMessage) {\n errorOrMessage = errorOrMessage.stack\n ? errorOrMessage + \" \" + errorOrMessage.stack\n : errorOrMessage;\n warn(errorOrMessage);\n sendData(\n assign(basePayload, {\n type: errorText,\n error: errorOrMessage,\n path: loc.pathname,\n }),\n undefinedVar,\n trueVar\n );\n };\n\n // We listen for the error events and only send errors that are\n // from our script (checked by filename) to our server.\n addEventListenerFunc(\n errorText,\n function (event) {\n if (event.filename && event.filename.indexOf(baseUrl) > -1) {\n sendError(event.message);\n }\n },\n falseVar\n );\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n var start = now();\n\n var scrolled = 0;\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n // Should we record Do Not Track visits?\n var collectDnt = isBoolean(settings.collectDnt)\n ? settings.collectDnt\n : attr(scriptElement, \"ignore-dnt\") == trueText ||\n attr(scriptElement, \"skip-dnt\") == trueText ||\n attr(scriptElement, \"collect-dnt\") == trueText;\n\n // Some customers want to collect page views manually\n var autoCollect = !(\n attr(scriptElement, \"auto-collect\") == \"false\" ||\n settings.autoCollect === falseVar\n );\n\n // Event function name\n var eventFunctionName =\n settings.saGlobal ||\n attr(scriptElement, \"sa-global\") ||\n namespace + \"_\" + eventText;\n\n // Customers can ignore certain pages\n var ignorePages = convertCommaSeparatedToArray(\n settings.ignorePages || attr(scriptElement, \"ignore-pages\")\n );\n\n // Customers can allow params\n var allowParams = convertCommaSeparatedToArray(\n settings.allowParams || attr(scriptElement, \"allow-params\")\n );\n\n // Customers can allow params\n var nonUniqueHostnames = convertCommaSeparatedToArray(\n settings.nonUniqueHostnames || attr(scriptElement, \"non-unique-hostnames\")\n );\n\n // Customers can overwrite certain values\n var pathOverwriter =\n settings.pathOverwriter || attr(scriptElement, \"path-overwriter\");\n\n // Customers can add metadata to events and pageviews via a function\n var metadataCollector =\n settings.metadataCollector || attr(scriptElement, \"metadata-collector\");\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n var phantom = window.phantom;\n var bot =\n nav.webdriver ||\n window.__nightmare ||\n window.callPhantom ||\n window._phantom ||\n (phantom && !phantom.solana) ||\n window.__polypane ||\n window._bot ||\n isBotAgent ||\n Math.random() == Math.random();\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = trueVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n // Warn when no document.doctype is defined (this breaks some documentElement dimensions)\n if (!doc.doctype) warn(\"Add DOCTYPE html for accurate dimensions\");\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (!collectDnt && doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n if (raw) return referrer;\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n // t = timeonpage\n if (collectMetricByString(\"t\")) {\n append.duration = Math.round((now() - start - msHidden) / thousand);\n }\n msHidden = 0;\n start = now();\n\n // scro = scrolled\n if (collectMetricByString(\"scro\")) {\n append.scrolled = Math.max(0, scrolled, position());\n }\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n var hiddenStart;\n addEventListenerFunc(\n \"visibilitychange\",\n function () {\n if (doc.hidden) {\n if (!(\"on\" + pagehide in window)) sendOnLeave();\n hiddenStart = now();\n } else msHidden += now() - hiddenStart;\n },\n falseVar\n );\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n var body = doc.body || {};\n var position = function () {\n try {\n var documentClientHeight = documentElement[clientHeight] || 0;\n var height = Math.max(\n body[scrollHeight] || 0,\n body[offsetHeight] || 0,\n documentElement[clientHeight] || 0,\n documentElement[scrollHeight] || 0,\n documentElement[offsetHeight] || 0\n );\n return Math.min(\n 100,\n Math.round(\n (100 * ((documentElement.scrollTop || 0) + documentClientHeight)) /\n height /\n 5\n ) * 5\n );\n } catch (error) {\n warn(error);\n return 0;\n }\n };\n\n addEventListenerFunc(\"load\", function () {\n scrolled = position();\n addEventListenerFunc(\n scroll,\n function () {\n if (scrolled < position()) scrolled = position();\n },\n falseVar\n );\n });\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n var pathOverwriterFunction = window[pathOverwriter];\n if (isFunction(pathOverwriterFunction)) {\n try {\n path = pathOverwriterFunction.call(window, { path: path }) || path;\n } catch (error) {\n warnInFunction(\"path\", error);\n }\n }\n\n // Ignore pages specified in data-ignore-pages\n if (shouldIgnore(path)) {\n warn(notSendingWhen + \"ignoring \" + path);\n return;\n }\n\n // Add hash to path when script is put in to hash mode\n if (mode == \"hash\" && loc.hash) path += loc.hash.split(\"?\")[0];\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n k: k,\n\n metadata: stringify(metadata),\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n // v = viewportsizes\n if (collectMetricByString(\"v\")) {\n page.viewport_width =\n Math.max(documentElement[clientWidth] || 0, window.innerWidth || 0) ||\n null;\n page.viewport_height =\n Math.max(\n documentElement[clientHeight] || 0,\n window.innerHeight || 0\n ) || null;\n }\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n // sc = screensizes\n if (screen && collectMetricByString(\"sc\")) {\n page.screen_width = screen.width;\n page.screen_height = screen.height;\n }\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n var currentReferrerHostname = referrer\n ? referrer.split(slash)[0]\n : undefinedVar;\n sameSite = referrer\n ? nonUniqueHostnames.indexOf(currentReferrerHostname) > -1 ||\n currentReferrerHostname == locationHostname\n : falseVar;\n\n // Only the first pageview can use a Cloudflare referrer as a unique arrival.\n page.unique =\n isPushState || userNavigated\n ? falseVar\n : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar)));\n\n metadata = appendMetadata(metadata, {\n type: pageviewText,\n path: page.path,\n });\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n /////////////////////\n // AUTOMATED PAGE VIEW COLLECTION\n //\n\n var his = window.history;\n var hisPushState = his ? his.pushState : undefinedVar;\n var dis = window.dispatchEvent;\n var pushStateText = \"pushState\";\n\n // Overwrite history pushState function to\n // allow listening on the pushState event\n if (autoCollect && hisPushState && Event && dis) {\n var stateListener = function (type) {\n var orig = his[type];\n return function () {\n var arg = arguments;\n var rv = orig.apply(this, arg);\n var event;\n if (isFunction(Event)) {\n event = new Event(type);\n } else {\n // Fix for IE\n // https://github.com/simpleanalytics/scripts/issues/8\n event = doc.createEvent(\"Event\");\n event.initEvent(type, trueVar, trueVar);\n }\n event.arguments = arg;\n dis(event);\n return rv;\n };\n };\n\n his.pushState = stateListener(pushStateText);\n\n addEventListenerFunc(\n pushStateText,\n function () {\n pageview(1);\n },\n falseVar\n );\n\n addEventListenerFunc(\n \"popstate\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n // When in hash mode, we record a pageview based on the onhashchange function\n if (autoCollect && mode == \"hash\" && \"onhashchange\" in window) {\n addEventListenerFunc(\n \"hashchange\",\n function () {\n pageview(1);\n },\n falseVar\n );\n }\n\n if (autoCollect) pageview();\n\n var manualPageview = function (path, metadata, callback) {\n pageview(0, path, metadata, callback);\n };\n window[namespace + \"_\" + pageviewText] = manualPageview;\n var defaultPageview = defaultNamespace + \"_\" + pageviewText;\n if (!window[defaultPageview]) window[defaultPageview] = manualPageview;\n\n\n /////////////////////\n // EVENTS\n //\n\n var validTypes = [\"string\", \"number\"];\n\n var sendEvent = function (event, metadata, callbackRaw, keepalive) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n\n var eventIsFunction = isFunction(event);\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var eventType = typeof event;\n\n if (validTypes.indexOf(eventType) < 0 && !eventIsFunction) {\n warnInFunction(eventFunctionName, eventText + \" can't be \" + eventType);\n return callback();\n }\n\n try {\n if (eventIsFunction) {\n var eventOutput = event();\n if (validTypes.indexOf(typeof eventOutput) < 0) {\n warnInFunction(\n eventFunctionName,\n event + \" returns no string: \" + eventOutput\n );\n return callback();\n }\n event = eventOutput;\n }\n } catch (error) {\n warnInFunction(eventFunctionName, error);\n return callback();\n }\n\n event = (\"\" + event).replace(/[^a-z0-9]+/gi, \"_\").replace(/(^_|_$)/g, \"\");\n\n var eventParams = { type: eventText, event: event };\n var firstPage = !userNavigated && pages < 2;\n\n metadata = appendMetadata(metadata, eventParams);\n\n if (event) {\n sendData(\n assign(eventParams, {\n id: uuid(),\n query: getQueryParams(!firstPage),\n referrer:\n (firstPage || sameSite) && collectMetricByString(\"r\")\n ? previousReferrer\n : null,\n\n metadata: stringify(metadata),\n }),\n callback,\n undefinedVar,\n keepalive\n );\n }\n };\n\n var defaultEventFunc = function (event, metadata, callback, keepalive) {\n sendEvent(event, metadata, callback, keepalive);\n };\n\n // Set default function if user didn't define a function\n if (!window[eventFunctionName])\n window[eventFunctionName] = defaultEventFunc;\n\n var eventFunc = window[eventFunctionName];\n\n // Read queue of the user defined function\n var queue = eventFunc && eventFunc.q ? eventFunc.q : [];\n\n // Overwrite user defined function\n window[eventFunctionName] = defaultEventFunc;\n\n // Post events from the queue of the user defined function\n for (var event in queue) {\n if (hasProp(queue, event)) {\n Array.isArray(queue[event])\n ? sendEvent.apply(null, queue[event])\n : sendEvent(queue[event]);\n }\n }\n\n var inlineEvent = function (event) {\n var element = event.target;\n while (\n element &&\n element !== doc &&\n (!element.getAttribute || attr(element, \"simple-event\") === null)\n )\n element = element.parentNode;\n\n if (!element || element === doc) return;\n var isForm = element.tagName === \"FORM\";\n var name = attr(element, \"simple-event\");\n if (!name || isForm !== (event.type === \"submit\")) return;\n\n var metadata = { tag: element.tagName.toLowerCase() };\n var attributes = element.attributes;\n for (var i = 0; i < attributes.length; i++) {\n var attribute = attributes[i];\n if (attribute.name.indexOf(\"data-simple-event-\") === 0)\n metadata[attribute.name.slice(18).replace(/-/g, \"_\")] =\n attribute.value;\n }\n if (isForm) {\n var button = event.submitter;\n metadata.button_text = button\n ? (button.textContent || button.value || \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200)\n : \"\";\n }\n sendEvent(name, metadata, undefinedVar, trueVar);\n };\n\n doc.addEventListener(\"click\", inlineEvent, falseVar);\n doc.addEventListener(\"submit\", inlineEvent, falseVar);\n\n // 404 confirmation adds a request, so existing installs must opt in.\n if (\n settings.detect404 === trueVar ||\n attr(scriptElement, \"detect-404\") == trueText\n ) {\n var detect404 = function () {\n if (\n !/\\b404\\b/.test(doc.title + \" \" + (doc.body && doc.body.textContent))\n )\n return;\n try {\n var request = new window.XMLHttpRequest();\n request.open(\"HEAD\", loc.href, trueVar);\n request.onload = function () {\n if (request.status === 404)\n sendEvent(\"page_404\", {\n url: loc.protocol + \"//\" + definedHostname + loc.pathname,\n status: 404,\n });\n };\n request.send();\n } catch (error) {}\n };\n if (doc.readyState === \"loading\")\n doc.addEventListener(\"DOMContentLoaded\", detect404, falseVar);\n else detect404();\n }\n } catch (e) {\n sendError(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"\",\n \"\",\n \"custom_proxy_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","sendError","warn","type","orig","value","undefinedVar","undefined","trueVar","falseVar","trueText","https","pageviewText","eventText","errorText","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","notSendingWhen","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","documentElement","language","Height","scroll","uaData","userAgentData","scrollHeight","offsetHeight","clientHeight","pagehide","platformText","platformVersionText","docsUrl","pages","isBotAgent","test","screen","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","warnInFunction","name","error","hasProp","obj","prop","Object","hasOwnProperty","isString","string","filterRegex","item","replace","attr","attribute","getAttribute","convertCommaSeparatedToArray","csv","Array","isArray","length","split","isObject","object","constructor","assign","to","arg","index","nextSource","nextKey","logSettings","settings","sa_settings","k","ignoreMetrics","collectMetricByString","metricAbbreviation","filter","RegExp","now","Date","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","c","getRandomValues","Uint8Array","toString","r","Math","random","isFunction","func","namespaceText","namespace","appendMetadata","metadata","data","metadataObject","metadataCollectorFunction","metadataCollector","strictUtm","getQueryParams","ignoreSource","overwriteSearch","q","search","keyValue","i","indexOf","ignore","paramsRegexList","allowParams","map","join","regex","loadedVariable","sa_event_loaded","sendData","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","onerror","onload","imageUrl","keys","key","fetch","mode","credentials","catch","src","overwrittenHostname","hostname","definedHostname","basePayload","version","errorOrMessage","stack","path","pathname","event","filename","message","timezone","start","scrolled","collectDnt","autoCollect","eventFunctionName","saGlobal","ignorePages","nonUniqueHostnames","pathOverwriter","Intl","DateTimeFormat","resolvedOptions","timeZone","phantom","bot","webdriver","__nightmare","callPhantom","_phantom","solana","__polypane","_bot","collectDataOnLeave","ua","protocol","page_id","session_id","sri","mobile","brands","doctype","hostname_original","lastSendPath","hiddenStart","getReferrer","raw","referrer","msHidden","sendOnLeave","id","push","append","original_id","duration","round","max","position","sendBeacon","bind","e","hidden","body","documentClientHeight","height","min","scrollTop","previousReferrer","sameSite","userNavigated","getPath","overwrite","pathOverwriterFunction","ignorePageRaw","ignorePage","shouldIgnore","hash","pageview","isPushState","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","viewport_width","innerWidth","viewport_height","innerHeight","screen_width","width","screen_height","performaceEntryType","perf","performance","navigationText","getEntriesByType","currentReferrerHostname","unique","triggerSendPageView","delSrc","deleteSourceInfo","currentPage","query","sendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","his","history","hisPushState","pushState","dis","dispatchEvent","pushStateText","Event","rv","this","createEvent","initEvent","manualPageview","defaultPageview","defaultNamespace","validTypes","sendEvent","eventIsFunction","eventType","eventOutput","eventParams","firstPage","defaultEventFunc","eventFunc","queue","detect404","inlineEvent","element","target","parentNode","isForm","tagName","button","tag","toLowerCase","attributes","submitter","button_text","textContent","trim","title","request","XMLHttpRequest","open","href","status","url","send","readyState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v12/light.js b/dist/v12/light.js new file mode 100644 index 0000000..b24ba6e --- /dev/null +++ b/dist/v12/light.js @@ -0,0 +1,4 @@ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; d74a; SRI-version; v12) */ + +!function(f,e,m){if(f)try{var u=undefined,t="https:",n=f.console,r="doNotTrack",g=f.navigator,p=f.location,h=p.host,a=f.document,i=g.userAgent,o="Not sending request ",v=!1,c=encodeURIComponent,s=decodeURIComponent,d=JSON.stringify,l=f.addEventListener,y="https://queue."+e,_=(a.documentElement,"language"),w=g.userAgentData,b="platform",O="platformVersion",S="https://docs.simpleanalytics.com",j=/(bot|spider|crawl)/i.test(i)&&!/(cubot)/i.test(i),k=a.currentScript||a.querySelector('script[src*="'+e+'"]');m=function(){var e=[].slice.call(arguments);return e.unshift("Simple Analytics:"),Function.prototype.apply.call(n.warn,n,e)};var E=function(e){return"string"==typeof e},q=function(e,t){return e&&e.getAttribute("data-"+t)},x=function(){for(var e,t,n,r={},a=arguments,i=0;i>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=function(e){return"function"==typeof e},N="namespace",R=$[N]||q(k,N)||"sa",U=$.strictUtm||"true"==q(k,"strict-utm"),V=R+"_loaded";if(1==f[V])return m(o+"twice");f.sa_event_loaded=!0,f[V]=!0;var B,C=function(t,e,n,r){t=n?t:x(z,L,t),g.brave&&!n&&(t.brave=!0),g._duckduckgoloader_&&!n&&(t.duck=!0);var a=new Image,i=y+"/simple.gif?"+Object.keys(t).filter(function(e){return t[e]!=u}).map(function(e){return c(e)+"="+c(t[e])}).join("&")+"&time="+Date.now();a.src=i},T=$.hostname||q(k,"hostname"),F=T||h,H={version:"cdn_light_12",hostname:F};$.mode||q(k,"mode");try{B=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(W){m(W)}j&&(H.bot=!0);var z=x(H,{ua:i,https:p.protocol==t,timezone:B,page_id:D(),session_id:D()});if(z.sri=!0,w&&(z.mobile=w.mobile,z.brands=d(w.brands)),F!==h&&(z.hostname_original=h),r in g&&"1"==g[r])return m("Not sending request when "+r+" is enabled. See "+S+"/dnt");-1!=h.indexOf(".")&&!/^[0-9.:]+$/.test(h)||T||m("Set hostname on "+h+". See "+S+"/overwrite-domain-name");var J,L={},M=($.referrer||q(k,"referrer")||a.referrer||"").replace(h,F).replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/,"$4").replace(/^([^/]+)$/,"$1")||u,P=function(e,t){var n=x(H,{type:"append",original_id:t?e:z.page_id});if(t||!g.sendBeacon)C(n,0,!0);else try{g.sendBeacon.bind(g)(y+"/append",d(n))}catch(r){C(n,0,!0)}};l("pagehide",P,!1);var Z,G,K=function(e){var t="";try{t=e||s(p.pathname)}catch(W){m(W)}return t},Q=function(e,t,n,r,a,i){e&&P(""+z.page_id,!0),z.page_id=D();var o,c=F+K(),s=(o=t,(r||p.search).slice(1).split("&").filter(function(e){return!o&&new RegExp("^((utm_)"+(U?"":"?")+"(source|medium|content|term|campaign)"+(U?"":"|ref")+")=","i").test(e)}).join("&")||u);C({id:z.page_id,type:"pageview",referrer:!t||n?M:null,query:s}),M=c,0};!function(e,t,n,r){!r&&I(n)&&(r=n);I(r);var a,i="";E(t)&&-1> (c / 4)))\n ).toString(16);\n });\n } catch (error) {\n return emptyUUID.replace(uuidRegex, function (c) {\n var r = (Math.random() * 16) | 0,\n v = c < 2 ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n };\n\n var isFunction = function (func) {\n return typeof func == \"function\";\n };\n\n // Define namespace for the library\n var namespaceText = \"namespace\";\n var namespace =\n settings[namespaceText] ||\n attr(scriptElement, namespaceText) ||\n defaultNamespace;\n\n\n var isBoolean = function (value) {\n return !!value === value;\n };\n\n // By default we allow source, medium in the URLs. With strictUtm enabled\n // we only allow it with the utm_ prefix: utm_source, utm_medium, ...\n var strictUtm =\n settings.strictUtm || attr(scriptElement, \"strict-utm\") == trueText;\n\n\n var getQueryParams = function (ignoreSource, overwriteSearch) {\n var q = (overwriteSearch || loc.search)\n .slice(1)\n .split(\"&\")\n .filter(function (keyValue) {\n\n var ignore = ignoreSource || !collectMetricByString(\"ut\");\n\n if (ignore) return falseVar;\n // eslint-disable-next-line no-redeclare\n var regex =\n \"^((utm_)\" +\n (strictUtm ? \"\" : \"?\") +\n \"(source|medium|content|term|campaign)\" +\n (strictUtm ? \"\" : \"|ref\") +\n \")=\";\n\n // The prefix \"utm_\" is optional with \"strictUtm\" disabled\n // \"ref\" is only collected when \"strictUtm\" is disabled\n return new RegExp(regex, \"i\").test(keyValue);\n })\n .join(\"&\");\n\n return q || undefinedVar;\n };\n\n\n /////////////////////\n // Warn when using script twice\n //\n\n // Only load our script once, customers can still send multiple page views\n // with the sa_pageview function if they turn off auto collect.\n var loadedVariable = namespace + \"_loaded\";\n if (window[loadedVariable] == trueVar) return warn(notSending + \"twice\");\n window.sa_event_loaded = trueVar;\n window[loadedVariable] = trueVar;\n\n /////////////////////\n // SEND DATA VIA OUR PIXEL\n //\n\n // Send data via image\n var sendData = function (data, callback, onlyThisData, keepalive) {\n data = onlyThisData ? data : assign(payload, page, data);\n\n if (nav.brave && !onlyThisData) data.brave = trueVar;\n if (nav._duckduckgoloader_ && !onlyThisData) data.duck = trueVar;\n\n\n var image = new Image();\n var imageUrl =\n fullApiUrl +\n \"/simple.gif?\" +\n Object.keys(data)\n .filter(function (key) {\n return data[key] != undefinedVar;\n })\n .map(function (key) {\n return (\n encodeURIComponentFunc(key) +\n \"=\" +\n encodeURIComponentFunc(data[key])\n );\n })\n .join(\"&\") +\n \"&time=\" +\n Date.now();\n\n image.src = imageUrl;\n };\n\n // Customers can overwrite their hostname, here we check for that\n var overwrittenHostname =\n settings.hostname || attr(scriptElement, \"hostname\");\n var definedHostname = overwrittenHostname || locationHostname;\n\n var basePayload = {\n version: version,\n hostname: definedHostname,\n };\n\n\n /////////////////////\n // INITIALIZE VALUES\n //\n\n\n\n /////////////////////\n // GET SETTINGS\n //\n\n // Script mode, this can be hash mode for example\n var mode = settings.mode || attr(scriptElement, \"mode\");\n\n\n\n\n\n\n\n\n\n // This code could error on (incomplete) implementations, that's why we use try...catch\n var timezone;\n try {\n // c = countries\n timezone = collectMetricByString(\"c\")\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefinedVar;\n } catch (error) {\n warn(error);\n }\n\n /////////////////////\n // PAYLOAD FOR BOTH PAGE VIEWS AND EVENTS\n //\n\n // eslint-disable-next-line no-redeclare\n var bot = isBotAgent;\n\n // t = timeonpage, scro = scrolled\n var collectDataOnLeave =\n collectMetricByString(\"t\") || collectMetricByString(\"scro\");\n\n if (bot) basePayload.bot = trueVar;\n\n var payload = assign(basePayload, {\n // us = useragent\n ua: collectMetricByString(\"us\") ? userAgent : undefinedVar,\n\n https: loc.protocol == https,\n timezone: timezone,\n page_id: collectDataOnLeave ? uuid() : undefinedVar,\n\n // se = sessions\n session_id: collectMetricByString(\"se\") ? uuid() : undefinedVar,\n });\n\n payload.sri = trueVar;\n\n // Use User-Agent Client Hints for better privacy\n // https://web.dev/user-agent-client-hints/\n if (uaData) {\n payload.mobile = uaData.mobile;\n payload.brands = stringify(uaData.brands);\n }\n\n /////////////////////\n // ADD WARNINGS\n //\n\n\n\n // When a customer overwrites the hostname, we need to know what the original\n // hostname was to hide that domain from referrer traffic\n if (definedHostname !== locationHostname)\n payload.hostname_original = locationHostname;\n\n // Don't track when Do Not Track is set to true\n if (doNotTrack in nav && nav[doNotTrack] == \"1\")\n return warn(\n notSendingWhen + doNotTrack + \" is enabled. See \" + docsUrl + \"/dnt\"\n );\n\n // Warn when sending from localhost and not having a hostname set\n if (\n (locationHostname.indexOf(\".\") == -1 ||\n /^[0-9.:]+$/.test(locationHostname)) &&\n !overwrittenHostname\n )\n warn(\n \"Set hostname on \" +\n locationHostname +\n \". See \" +\n docsUrl +\n \"/overwrite-domain-name\"\n );\n\n /////////////////////\n // SETUP INITIAL VARIABLES\n //\n\n var page = {};\n var lastSendPath;\n\n var getReferrer = function (raw) {\n // Customers can overwrite their referrer, here we check for that\n var referrer =\n settings.referrer ||\n attr(scriptElement, \"referrer\") ||\n doc.referrer ||\n \"\";\n\n return (\n referrer\n .replace(locationHostname, definedHostname)\n .replace(/^https?:\\/\\/((m|l|w{2,3}([0-9]+)?)\\.)?([^?#]+)(.*)$/, \"$4\")\n .replace(/^([^/]+)$/, \"$1\") || undefinedVar\n );\n };\n\n // We don't want to end up with sensitive data so we clean the referrer URL\n var referrer = getReferrer();\n\n /////////////////////\n // TIME ON PAGE AND SCROLLED LOGIC\n //\n\n // We don't put msHidden in if duration block, because it's used outside of that functionality\n var msHidden = 0;\n\n var sendOnLeave = function (id, push) {\n if (!collectDataOnLeave) return;\n\n var append = assign(basePayload, {\n type: \"append\",\n original_id: push ? id : payload.page_id,\n });\n\n\n\n if (push || !nav.sendBeacon) {\n // sendData will assign payload to request\n sendData(append, undefinedVar, trueVar);\n } else {\n try {\n nav.sendBeacon.bind(nav)(fullApiUrl + \"/append\", stringify(append));\n } catch (e) {\n // Fallback for browsers throwing \"Illegal invocation\" when the URL is invalid\n sendData(append, undefinedVar, trueVar);\n }\n }\n };\n\n\n addEventListenerFunc(pagehide, sendOnLeave, falseVar);\n\n\n /////////////////////\n // ACTUAL PAGE VIEW LOGIC\n //\n\n var getPath = function (overwrite) {\n var path = \"\";\n\n // decodeURIComponent can fail when having invalid characters\n // https://github.com/simpleanalytics/roadmap/issues/462\n try {\n path = overwrite || decodeURIComponentFunc(loc.pathname);\n } catch (error) {\n warn(error);\n }\n\n\n\n\n return path;\n };\n\n var previousReferrer;\n\n // Send page view and append data to it\n var sendPageView = function (\n isPushState,\n deleteSourceInfo,\n sameSite,\n search,\n metadata,\n callback\n ) {\n if (isPushState) sendOnLeave(\"\" + payload.page_id, trueVar);\n if (collectDataOnLeave) payload.page_id = uuid();\n\n var currentPage = definedHostname + getPath();\n var query = getQueryParams(deleteSourceInfo, search);\n\n sendData(\n {\n id: payload.page_id,\n type: pageviewText,\n referrer: !deleteSourceInfo || sameSite ? referrer : null,\n query: query,\n\n },\n callback\n );\n\n previousReferrer = referrer;\n referrer = currentPage;\n\n pages++;\n };\n\n var sameSite, userNavigated;\n\n var pageview = function (\n isPushState,\n pathOverwrite,\n metadata,\n callbackRaw\n ) {\n if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata;\n var callback = isFunction(callbackRaw) ? callbackRaw : function () {};\n var querySearch = \"\";\n if (isString(pathOverwrite) && pathOverwrite.indexOf(\"?\") > -1) {\n // keep query from manual path\n var parts = pathOverwrite.split(\"?\");\n pathOverwrite = parts.shift();\n querySearch = \"?\" + parts.join(\"?\");\n }\n // Obfuscate personal data in URL by dropping the search and hash\n var path = getPath(pathOverwrite);\n\n // Don't send the last path again (this could happen when pushState is used to change the path hash or search)\n var pathKey = path + querySearch;\n if (!path || lastSendPath == pathKey) return;\n\n lastSendPath = pathKey;\n page.path = path;\n\n\n // l = language\n if (collectMetricByString(\"l\")) {\n if (nav[language]) page[language] = nav[language];\n }\n\n\n // If a user does refresh we need to delete the referrer because otherwise it count double\n var perf = window.performance;\n var navigationText = \"navigation\";\n\n // Check if back, forward or reload buttons are being used in modern browsers\n var performaceEntryType;\n try {\n performaceEntryType = perf.getEntriesByType(navigationText)[0].type;\n } catch (error) {\n warn(error);\n }\n\n userNavigated = performaceEntryType\n ? [\"reload\", \"back_forward\"].indexOf(performaceEntryType) > -1\n : // Check if back, forward or reload buttons are being use in older browsers\n // 1: TYPE_RELOAD, 2: TYPE_BACK_FORWARD\n perf &&\n perf[navigationText] &&\n [1, 2].indexOf(perf[navigationText].type) > -1;\n\n // Check if referrer is the same as current real hostname (not the defined hostname!)\n sameSite = referrer\n ? referrer.split(slash)[0] == locationHostname\n : falseVar;\n\n\n\n var triggerSendPageView = function () {\n fetchedHighEntropyValues = trueVar;\n var delSrc =\n isPushState || userNavigated || !collectMetricByString(\"r\");\n sendPageView(\n isPushState,\n delSrc, // r = referrers\n sameSite,\n querySearch,\n metadata,\n callback\n );\n };\n\n if (!fetchedHighEntropyValues) {\n // Request platform information if this is available\n try {\n if (uaData && isFunction(uaData.getHighEntropyValues)) {\n uaData\n .getHighEntropyValues([platformText, platformVersionText])\n .then(function (highEntropyValues) {\n payload.os_name = highEntropyValues[platformText];\n payload.os_version = highEntropyValues[platformVersionText];\n triggerSendPageView();\n })\n .catch(triggerSendPageView);\n } else {\n triggerSendPageView();\n }\n } catch (e) {\n triggerSendPageView();\n }\n } else {\n triggerSendPageView();\n }\n };\n\n\n\n pageview();\n\n } catch (e) {\n warn(e);\n }\n})(\n typeof window != \"undefined\" && window,\n \"simpleanalyticscdn.com\",\n \"queue.\",\n \"cdn_light_12\",\n \"sa\"\n);\n"],"names":["window","baseUrl","warn","undefinedVar","undefined","https","con","console","doNotTrack","nav","navigator","loc","location","locationHostname","host","doc","document","userAgent","notSending","fetchedHighEntropyValues","encodeURIComponentFunc","encodeURIComponent","decodeURIComponentFunc","decodeURIComponent","stringify","JSON","addEventListenerFunc","addEventListener","fullApiUrl","protocol","language","documentElement","uaData","userAgentData","platformText","platformVersionText","docsUrl","isBotAgent","test","scriptElement","currentScript","querySelector","args","slice","call","arguments","unshift","Function","prototype","apply","isString","string","attr","attribute","getAttribute","assign","obj","prop","object","to","arg","index","length","nextSource","constructor","Object","nextKey","hasOwnProperty","logSettings","settings","sa_settings","Date","now","uuid","cryptoObject","crypto","msCrypto","emptyUUID","uuidRegex","replace","c","getRandomValues","Uint8Array","toString","error","r","Math","random","isFunction","func","namespaceText","namespace","strictUtm","loadedVariable","sa_event_loaded","timezone","sendData","data","callback","onlyThisData","keepalive","payload","page","brave","_duckduckgoloader_","duck","image","Image","imageUrl","keys","filter","key","map","join","src","overwrittenHostname","hostname","definedHostname","basePayload","version","mode","Intl","DateTimeFormat","resolvedOptions","timeZone","bot","ua","page_id","session_id","sri","mobile","brands","hostname_original","indexOf","lastSendPath","referrer","sendOnLeave","id","push","append","type","original_id","sendBeacon","bind","e","sameSite","userNavigated","getPath","overwrite","path","pathname","sendPageView","isPushState","deleteSourceInfo","search","metadata","ignoreSource","currentPage","query","split","keyValue","RegExp","pages","pathOverwrite","callbackRaw","parts","querySearch","shift","pathKey","performaceEntryType","perf","performance","navigationText","getEntriesByType","triggerSendPageView","getHighEntropyValues","then","highEntropyValues","os_name","os_version","catch","pageview"],"mappings":"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"} \ No newline at end of file diff --git a/package.json b/package.json index 5405eb6..41f384b 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "deploy": "node --env-file-if-exists=.env deploy.mts", "pretest": "pnpm run build:testing", "test": "node -r dotenv/config ./test/index.js", + "test:unit": "mocha \"test/unit/*.test.js\" --exit", "test:matrix": "mocha test/helpers/get-browsers.test.js", "test:deploy": "node --test test/deploy.test.mts", "posttest": "pnpm run build", @@ -38,12 +39,14 @@ }, "devDependencies": { "@types/node": "24.13.3", + "acorn": "^8.18.0", "browserstack-local": "^1.5.1", "chai": "^4.2.0", "dotenv": "^8.2.0", "eslint": "^6.7.2", "esprima": "^4.0.1", - "handlebars": "^4.7.6", + "handlebars": "^4.7.10", + "jsdom": "26.1.0", "mocha": "^6.2.3", "nodemon": "^1.19.4", "request": "^2.88.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd32086..e24287c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,6 +15,9 @@ importers: '@types/node': specifier: 24.13.3 version: 24.13.3 + acorn: + specifier: ^8.18.0 + version: 8.18.0 browserstack-local: specifier: ^1.5.1 version: 1.5.1(supports-color@5.5.0) @@ -31,8 +34,11 @@ importers: specifier: ^4.0.1 version: 4.0.1 handlebars: - specifier: ^4.7.6 - version: 4.7.6 + specifier: ^4.7.10 + version: 4.7.10 + jsdom: + specifier: 26.1.0 + version: 26.1.0(supports-color@5.5.0) mocha: specifier: ^6.2.3 version: 6.2.3 @@ -57,6 +63,9 @@ importers: packages: + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@babel/code-frame@7.5.5': resolution: {integrity: sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==} @@ -71,6 +80,34 @@ packages: resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==} engines: {node: '>= 20.12.0'} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} @@ -213,10 +250,19 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + ajv@6.10.2: resolution: {integrity: sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==} @@ -448,10 +494,18 @@ packages: resolution: {integrity: sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg==} engines: {node: '>=4'} + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -482,6 +536,9 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + decode-uri-component@0.2.0: resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==} engines: {node: '>=0.10'} @@ -548,6 +605,10 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + es-abstract@1.17.6: resolution: {integrity: sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==} engines: {node: '>= 0.4'} @@ -771,8 +832,8 @@ packages: resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} engines: {node: '>=4.x'} - handlebars@4.7.6: - resolution: {integrity: sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==} + handlebars@4.7.10: + resolution: {integrity: sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==} engines: {node: '>=0.4.7'} hasBin: true @@ -817,6 +878,14 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + http-signature@1.2.0: resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} engines: {node: '>=0.8', npm: '>=1.3.7'} @@ -825,10 +894,18 @@ packages: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + ignore-by-default@1.0.1: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} @@ -969,6 +1046,9 @@ packages: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@2.1.0: resolution: {integrity: sha512-NECAi6wp6CgMesHuVUEK8JwjCvm/tvnn5pCbB42JOHp3mgUizN0nagXu4HEqQZBkieGEQ+jVcMKWqoVd6CDbLQ==} @@ -1029,6 +1109,15 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -1090,6 +1179,9 @@ packages: resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} engines: {node: '>=0.10.0'} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} @@ -1130,6 +1222,9 @@ packages: minimist@1.2.5: resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + mixin-deep@1.3.2: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} engines: {node: '>=0.10.0'} @@ -1170,8 +1265,8 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - neo-async@2.6.1: - resolution: {integrity: sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==} + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} @@ -1200,6 +1295,9 @@ packages: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} + nwsapi@2.2.28: + resolution: {integrity: sha512-IlVB7OS7qrOsVYlpnFIkETjMwT9jwvmocJmmM+GZU/PAB3uGi9Ezd7vcWhWBUnSc0ya4ppmQITOyP1ez9gg8cg==} + oauth-sign@0.9.0: resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} @@ -1272,6 +1370,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + pascalcase@0.1.1: resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} engines: {node: '>=0.10.0'} @@ -1347,6 +1448,10 @@ packages: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + qs@6.5.2: resolution: {integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==} engines: {node: '>=0.6'} @@ -1431,6 +1536,9 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + run-async@2.3.0: resolution: {integrity: sha512-Fx+QT3fGtS0jk8OvKyKgAB2YHPsrmqBRcMeTC5AZ+lp4vzXKPPrFSY3iLdgvjA3HVBkIvJeM6J80LRjx8bQwhA==} engines: {node: '>=0.12.0'} @@ -1448,6 +1556,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + selenium-webdriver@4.3.1: resolution: {integrity: sha512-TjH/ls1WKRQoFEHcqtn6UtwcLnA3yvx08v9cSSFYvyhp8hJWRtbe9ae2I8uXPisEZ2EaGKKoxBZ4EHv0BJM15g==} engines: {node: '>= 10.15.0'} @@ -1595,6 +1707,9 @@ packages: resolution: {integrity: sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==} engines: {node: '>=6'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + table@5.4.6: resolution: {integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==} engines: {node: '>=6.0.0'} @@ -1617,6 +1732,13 @@ packages: resolution: {integrity: sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==} engines: {node: '>=0.10.0'} + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -1645,6 +1767,14 @@ packages: resolution: {integrity: sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==} engines: {node: '>=0.8'} + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + tslib@1.10.0: resolution: {integrity: sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==} @@ -1739,6 +1869,27 @@ packages: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + which-module@2.0.0: resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} @@ -1774,6 +1925,18 @@ packages: resolution: {integrity: sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==} engines: {node: '>=4'} + ws@8.22.0: + resolution: {integrity: sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.8.1: resolution: {integrity: sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==} engines: {node: '>=10.0.0'} @@ -1790,6 +1953,13 @@ packages: resolution: {integrity: sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==} engines: {node: '>=4'} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@4.0.0: resolution: {integrity: sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==} @@ -1808,6 +1978,14 @@ packages: snapshots: + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + '@babel/code-frame@7.5.5': dependencies: '@babel/highlight': 7.5.0 @@ -1830,6 +2008,26 @@ snapshots: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + '@types/keyv@3.1.4': dependencies: '@types/node': 24.13.3 @@ -1910,12 +2108,16 @@ snapshots: acorn@7.1.1: {} + acorn@8.18.0: {} + agent-base@6.0.2(supports-color@5.5.0): dependencies: debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color + agent-base@7.1.4: {} + ajv@6.10.2: dependencies: fast-deep-equal: 2.0.1 @@ -2185,10 +2387,20 @@ snapshots: crypto-random-string@1.0.0: {} + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + dashdash@1.14.1: dependencies: assert-plus: 1.0.0 + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + debug@2.6.9(supports-color@5.5.0): dependencies: ms: 2.0.0 @@ -2215,6 +2427,8 @@ snapshots: decamelize@1.2.0: {} + decimal.js@10.6.0: {} + decode-uri-component@0.2.0: {} deep-eql@3.0.1: @@ -2269,6 +2483,8 @@ snapshots: emoji-regex@8.0.0: {} + entities@6.0.1: {} + es-abstract@1.17.6: dependencies: es-to-primitive: 1.2.1 @@ -2573,10 +2789,10 @@ snapshots: growl@1.10.5: {} - handlebars@4.7.6: + handlebars@4.7.10: dependencies: - minimist: 1.2.5 - neo-async: 2.6.1 + minimist: 1.2.8 + neo-async: 2.6.2 source-map: 0.6.1 wordwrap: 1.0.0 optionalDependencies: @@ -2618,6 +2834,17 @@ snapshots: he@1.2.0: {} + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + http-proxy-agent@7.0.2(supports-color@5.5.0): + dependencies: + agent-base: 7.1.4 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + http-signature@1.2.0: dependencies: assert-plus: 1.0.0 @@ -2631,10 +2858,21 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@7.0.6(supports-color@5.5.0): + dependencies: + agent-base: 7.1.4 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + ignore-by-default@1.0.1: {} ignore@4.0.6: {} @@ -2760,6 +2998,8 @@ snapshots: dependencies: isobject: 3.0.1 + is-potential-custom-element-name@1.0.1: {} + is-promise@2.1.0: {} is-redirect@1.0.0: {} @@ -2803,6 +3043,33 @@ snapshots: jsbn@0.1.1: {} + jsdom@26.1.0(supports-color@5.5.0): + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2(supports-color@5.5.0) + https-proxy-agent: 7.0.6(supports-color@5.5.0) + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.28 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.22.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + json-schema-traverse@0.4.1: {} json-schema@0.2.3: {} @@ -2863,6 +3130,8 @@ snapshots: lowercase-keys@1.0.1: {} + lru-cache@10.4.3: {} + lru-cache@4.1.5: dependencies: pseudomap: 1.0.2 @@ -2912,6 +3181,8 @@ snapshots: minimist@1.2.5: {} + minimist@1.2.8: {} + mixin-deep@1.3.2: dependencies: for-in: 1.0.2 @@ -2980,7 +3251,7 @@ snapshots: natural-compare@1.4.0: {} - neo-async@2.6.1: {} + neo-async@2.6.2: {} nice-try@1.0.5: {} @@ -3016,6 +3287,8 @@ snapshots: dependencies: path-key: 2.0.1 + nwsapi@2.2.28: {} + oauth-sign@0.9.0: {} object-copy@0.1.0: @@ -3092,6 +3365,10 @@ snapshots: dependencies: callsites: 3.1.0 + parse5@7.3.0: + dependencies: + entities: 6.0.1 + pascalcase@0.1.1: {} path-dirname@1.0.2: {} @@ -3138,6 +3415,8 @@ snapshots: punycode@2.1.1: {} + punycode@2.3.1: {} + qs@6.5.2: {} rc@1.2.8: @@ -3237,6 +3516,8 @@ snapshots: dependencies: glob: 7.1.6 + rrweb-cssom@0.8.0: {} + run-async@2.3.0: dependencies: is-promise: 2.1.0 @@ -3253,6 +3534,10 @@ snapshots: safer-buffer@2.1.2: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + selenium-webdriver@4.3.1: dependencies: jszip: 3.10.0 @@ -3422,6 +3707,8 @@ snapshots: dependencies: has-flag: 3.0.0 + symbol-tree@3.2.4: {} + table@5.4.6: dependencies: ajv: 6.10.2 @@ -3443,6 +3730,12 @@ snapshots: timed-out@4.0.1: {} + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -3476,6 +3769,14 @@ snapshots: psl: 1.7.0 punycode: 1.4.1 + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + tslib@1.10.0: {} tunnel-agent@0.6.0: @@ -3586,6 +3887,23 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@7.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + which-module@2.0.0: {} which@1.3.1: @@ -3622,10 +3940,16 @@ snapshots: dependencies: mkdirp: 0.5.5 + ws@8.22.0: {} + ws@8.8.1: {} xdg-basedir@3.0.0: {} + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + y18n@4.0.0: {} yallist@2.1.2: {} diff --git a/src/auto-events.js b/src/auto-events.js index b115315..56a8874 100644 --- a/src/auto-events.js +++ b/src/auto-events.js @@ -37,6 +37,7 @@ "outbound", "emails", "downloads", + "phones", ]); var fullUrls = setting("fullUrls", "bool", false); @@ -45,6 +46,7 @@ outbound: collectTypes.indexOf("outbound") > -1, emails: collectTypes.indexOf("emails") > -1, downloads: collectTypes.indexOf("downloads") > -1, + phones: collectTypes.indexOf("phones") > -1, // Downloads: enter file extensions you want to collect downloadsExtensions: setting("extensions", "array", [ "pdf", @@ -73,20 +75,9 @@ if (typeof optionsLink === "undefined") log("options object not found, please specify", "warn"); - window.saAutomatedLink = function saAutomatedLink(element, type) { + var saAutomatedLink = function saAutomatedLink(element, type) { try { if (!element) return log("no element found"); - var sent = false; - - var callback = function () { - if ( - !sent && - (!element.hasAttribute("target") || - element.getAttribute("target") === "_self") - ) - document.location = element.getAttribute("href"); - sent = true; - }; if (window[saGlobal] && window[saGlobal + "_loaded"]) { var hostname = element.hostname; @@ -104,9 +95,7 @@ if (theTitle != "") useTitle = true; } - if (useTitle) { - event = theTitle; - } else { + if (!useTitle || type === "phone") { switch (type) { case "outbound": { event = hostname + (optionsLink.outboundFullUrl ? pathname : ""); @@ -126,31 +115,36 @@ metadata.email = event; break; } + case "phone": { + var hrefPhone = element.getAttribute("href"); + event = (hrefPhone.split(":")[1] || "").split("?")[0]; + metadata.phone = event; + break; + } } } + if (useTitle) event = theTitle; var clean = type + "_" + event.replace(/[^a-z0-9]+/gi, "_").replace(/(^_+|_+$)/g, ""); - window[saGlobal](clean, metadata, callback); + window[saGlobal](clean, metadata, function () {}, true); log("collected " + clean); - - return type === "email" - ? callback() - : window.setTimeout(callback, 5000); } else { log(saGlobal + " is not defined", "warn"); - return callback(); } } catch (error) { log(error.message, "warn"); } }; - function collectLink(link, onclick) { + window.saAutomatedLink = saAutomatedLink; + + function collectLink(link) { + if (link.hasAttribute("data-simple-event")) return; var collect = false; // Collect download clicks @@ -175,25 +169,17 @@ // Collect email clicks } else if (optionsLink.emails && /^mailto:/i.test(link.href)) { collect = "email"; + + // Collect telephone clicks + } else if (optionsLink.phones && /^tel:/i.test(link.href)) { + collect = "phone"; } if (!collect) return; - if (onclick) { - var onClickAttribute = "saAutomatedLink(this, '" + collect + "');"; - - if ( - !link.hasAttribute("target") || - link.getAttribute("target") === "_self" - ) - onClickAttribute += " return false;"; - - link.setAttribute("onclick", onClickAttribute); - } else { - link.addEventListener("click", function () { - saAutomatedLink(this, collect); - }); - } + link.addEventListener("click", function () { + saAutomatedLink(this, collect); + }); } function onDOMContentLoaded() { @@ -208,12 +194,7 @@ // Skip links that don't have an href if (!href) continue; - // We don't want to overwrite website behaviour so we check for the onclick attribute - if (!link.getAttribute("onclick") && !/^mailto:/.test(href)) { - collectLink(link, true); - } else { - collectLink(link, false); - } + collectLink(link); } } catch (error) { log(error.message, "warn"); diff --git a/src/default.js b/src/default.js index df8de67..b07d46b 100644 --- a/src/default.js +++ b/src/default.js @@ -2,7 +2,6 @@ (function ( window, - overwriteOptions, baseUrl, apiUrlPrefix, version, @@ -10,6 +9,9 @@ sendError, warn ) { + // Only initialize in a browser. + if (!window) return; + try { ///////////////////// // PREDEFINED VARIABLES FOR BETTER MINIFICATION @@ -67,11 +69,6 @@ var screen = window.screen; /** endif **/ - /** if skipnonwindow **/ - // Skip server side rendered pages on Cloudflare - if (typeof window == "" + undefinedVar) return; - /** endif **/ - // Find the script element where options can be set on var scriptElement = doc.currentScript || doc.querySelector('script[src*="' + baseUrl + '"]'); @@ -142,17 +139,15 @@ }; var settings = window.sa_settings; - var logSettings = settings || Object.keys(overwriteOptions).length; + var logSettings = settings; + settings = assign(settings); - // Merge overwriteOptions with sa_settings - overwriteOptions = assign(overwriteOptions, settings); - - if (logSettings) warn("Settings", overwriteOptions); + if (logSettings) warn("Settings", settings); /** if ignoremetrics **/ // Customers can skip data points var ignoreMetrics = convertCommaSeparatedToArray( - overwriteOptions.ignoreMetrics || attr(scriptElement, "ignore-metrics") + settings.ignoreMetrics || attr(scriptElement, "ignore-metrics") ); /** endif **/ @@ -165,6 +160,7 @@ }).length === 0 ); /** else **/ + // eslint-disable-next-line no-unreachable return true; /** endif **/ }; @@ -200,16 +196,22 @@ // Define namespace for the library var namespaceText = "namespace"; var namespace = - overwriteOptions[namespaceText] || + settings[namespaceText] || attr(scriptElement, namespaceText) || defaultNamespace; /** if metadata **/ - var metadataObject = window[namespace + "_metadata"]; var appendMetadata = function (metadata, data) { + var metadataObject = window[namespace + "_metadata"]; if (isObject(metadataObject)) metadata = assign(metadata, metadataObject); var metadataCollectorFunction = window[metadataCollector]; - if (!isFunction(metadataCollectorFunction)) return metadata; + if (!isFunction(metadataCollectorFunction)) { + if (metadataCollector) + warn( + metadataCollector + " not found, set window." + metadataCollector + ); + return metadata; + } try { return assign( metadata, @@ -228,45 +230,61 @@ // By default we allow source, medium in the URLs. With strictUtm enabled // we only allow it with the utm_ prefix: utm_source, utm_medium, ... var strictUtm = - overwriteOptions.strictUtm || - attr(scriptElement, "strict-utm") == trueText; + settings.strictUtm || attr(scriptElement, "strict-utm") == trueText; - var getQueryParams = function (ignoreSource) { - return ( - loc.search - .slice(1) - .split("&") - .filter(function (keyValue) { - var ignore = ignoreSource || !collectMetricByString("ut"); - - /** if allowparams **/ - var paramsRegexList = allowParams.map(filterRegex).join("|"); - var regex = ignore - ? "^(" + paramsRegexList + ")=" - : "^((utm_)" + - (strictUtm ? "" : "?") + - "(source|medium|content|term|campaign)" + - (strictUtm ? "" : "|ref") + - "|" + - paramsRegexList + - ")="; - if (ignore && !allowParams.length) return falseVar; - /** else **/ - if (ignore) return falseVar; - var regex = - "^((utm_)" + + /** if ignoremetrics **/ + var k; + /** endif **/ + + var getQueryParams = function (ignoreSource, overwriteSearch) { + /** if ignoremetrics **/ + k = !ignoreSource && collectMetricByString("q") ? "" : falseVar; + /** endif **/ + var q = (overwriteSearch || loc.search) + .slice(1) + .split("&") + .filter(function (keyValue) { + /** if ignoremetrics **/ + var i = keyValue.indexOf("="); + if (k !== falseVar && i > 0 && keyValue.slice(i + 1)) + k += (k ? "," : "") + keyValue.slice(0, i); + /** endif **/ + + var ignore = ignoreSource || !collectMetricByString("ut"); + + /** if allowparams **/ + var paramsRegexList = allowParams.map(filterRegex).join("|"); + var regex = ignore + ? "^(" + paramsRegexList + ")=" + : "^((utm_)" + (strictUtm ? "" : "?") + "(source|medium|content|term|campaign)" + (strictUtm ? "" : "|ref") + + "|" + + paramsRegexList + ")="; - /** endif **/ + if (ignore && !allowParams.length) return falseVar; + /** else **/ + if (ignore) return falseVar; + // eslint-disable-next-line no-redeclare + var regex = + "^((utm_)" + + (strictUtm ? "" : "?") + + "(source|medium|content|term|campaign)" + + (strictUtm ? "" : "|ref") + + ")="; + /** endif **/ + + // The prefix "utm_" is optional with "strictUtm" disabled + // "ref" is only collected when "strictUtm" is disabled + return new RegExp(regex, "i").test(keyValue); + }) + .join("&"); - // The prefix "utm_" is optional with "strictUtm" disabled - // "ref" is only collected when "strictUtm" is disabled - return new RegExp(regex).test(keyValue); - }) - .join("&") || undefinedVar - ); + /** if ignoremetrics **/ + k = k || undefinedVar; + /** endif **/ + return q || undefinedVar; }; /** if ignorepages **/ @@ -309,7 +327,7 @@ // // Send data via image - var sendData = function (data, callback, onlyThisData) { + var sendData = function (data, callback, onlyThisData, keepalive) { data = onlyThisData ? data : assign(payload, page, data); if (nav.brave && !onlyThisData) data.brave = trueVar; @@ -326,7 +344,7 @@ image.onload = callback; } /** endif **/ - image.src = + var imageUrl = fullApiUrl + "/simple.gif?" + Object.keys(data) @@ -343,11 +361,30 @@ .join("&") + "&time=" + Date.now(); + + /** if events **/ + // Events must survive navigation without taking over links or forms. + if (keepalive && window.fetch) { + try { + window + .fetch(imageUrl, { + keepalive: trueVar, + mode: "no-cors", + credentials: "omit", + }) + .catch(function () { + image.src = imageUrl; + }); + return; + } catch (error) {} + } + /** endif **/ + image.src = imageUrl; }; // Customers can overwrite their hostname, here we check for that var overwrittenHostname = - overwriteOptions.hostname || attr(scriptElement, "hostname"); + settings.hostname || attr(scriptElement, "hostname"); var definedHostname = overwrittenHostname || locationHostname; var basePayload = { @@ -408,12 +445,12 @@ // // Script mode, this can be hash mode for example - var mode = overwriteOptions.mode || attr(scriptElement, "mode"); + var mode = settings.mode || attr(scriptElement, "mode"); /** if ignorednt **/ // Should we record Do Not Track visits? - var collectDnt = isBoolean(overwriteOptions.collectDnt) - ? overwriteOptions.collectDnt + var collectDnt = isBoolean(settings.collectDnt) + ? settings.collectDnt : attr(scriptElement, "ignore-dnt") == trueText || attr(scriptElement, "skip-dnt") == trueText || attr(scriptElement, "collect-dnt") == trueText; @@ -423,14 +460,14 @@ // Some customers want to collect page views manually var autoCollect = !( attr(scriptElement, "auto-collect") == "false" || - overwriteOptions.autoCollect === falseVar + settings.autoCollect === falseVar ); /** endif **/ /** if events **/ // Event function name var eventFunctionName = - overwriteOptions.saGlobal || + settings.saGlobal || attr(scriptElement, "sa-global") || namespace + "_" + eventText; /** endif **/ @@ -438,36 +475,34 @@ /** if ignorepages **/ // Customers can ignore certain pages var ignorePages = convertCommaSeparatedToArray( - overwriteOptions.ignorePages || attr(scriptElement, "ignore-pages") + settings.ignorePages || attr(scriptElement, "ignore-pages") ); /** endif **/ /** if allowparams **/ // Customers can allow params var allowParams = convertCommaSeparatedToArray( - overwriteOptions.allowParams || attr(scriptElement, "allow-params") + settings.allowParams || attr(scriptElement, "allow-params") ); /** endif **/ /** if nonuniquehostnames **/ // Customers can allow params var nonUniqueHostnames = convertCommaSeparatedToArray( - overwriteOptions.nonUniqueHostnames || - attr(scriptElement, "non-unique-hostnames") + settings.nonUniqueHostnames || attr(scriptElement, "non-unique-hostnames") ); /** endif **/ /** if pathoverwriter **/ // Customers can overwrite certain values var pathOverwriter = - overwriteOptions.pathOverwriter || attr(scriptElement, "path-overwriter"); + settings.pathOverwriter || attr(scriptElement, "path-overwriter"); /** endif **/ /** if metadata **/ // Customers can add metadata to events and pageviews via a function var metadataCollector = - overwriteOptions.metadataCollector || - attr(scriptElement, "metadata-collector"); + settings.metadataCollector || attr(scriptElement, "metadata-collector"); /** endif **/ // This code could error on (incomplete) implementations, that's why we use try...catch @@ -486,17 +521,19 @@ // /** if botdetection **/ + var phantom = window.phantom; var bot = nav.webdriver || window.__nightmare || window.callPhantom || window._phantom || - window.phantom || + (phantom && !phantom.solana) || window.__polypane || window._bot || isBotAgent || Math.random() == Math.random(); /** else **/ + // eslint-disable-next-line no-redeclare var bot = isBotAgent; /** endif **/ @@ -583,9 +620,19 @@ var page = {}; var lastSendPath; - var getReferrer = function () { + var getReferrer = function (raw) { + // Customers can overwrite their referrer, here we check for that + var referrer = + settings.referrer || + attr(scriptElement, "referrer") || + doc.referrer || + ""; + + /** if uniques **/ + if (raw) return referrer; + /** endif **/ return ( - (doc.referrer || "") + referrer .replace(locationHostname, definedHostname) .replace(/^https?:\/\/((m|l|w{2,3}([0-9]+)?)\.)?([^?#]+)(.*)$/, "$4") .replace(/^([^/]+)$/, "$1") || undefinedVar @@ -630,7 +677,12 @@ // sendData will assign payload to request sendData(append, undefinedVar, trueVar); } else { - nav.sendBeacon(fullApiUrl + "/append", stringify(append)); + try { + nav.sendBeacon.bind(nav)(fullApiUrl + "/append", stringify(append)); + } catch (e) { + // Fallback for browsers throwing "Illegal invocation" when the URL is invalid + sendData(append, undefinedVar, trueVar); + } } }; @@ -737,23 +789,32 @@ isPushState, deleteSourceInfo, sameSite, - metadata + search, + metadata, + callback ) { if (isPushState) sendOnLeave("" + payload.page_id, trueVar); if (collectDataOnLeave) payload.page_id = uuid(); var currentPage = definedHostname + getPath(); + var query = getQueryParams(deleteSourceInfo, search); - sendData({ - id: payload.page_id, - type: pageviewText, - referrer: !deleteSourceInfo || sameSite ? referrer : null, - query: getQueryParams(deleteSourceInfo), - - /** if metadata **/ - metadata: stringify(metadata), - /** endif **/ - }); + sendData( + { + id: payload.page_id, + type: pageviewText, + referrer: !deleteSourceInfo || sameSite ? referrer : null, + query: query, + /** if ignoremetrics **/ + k: k, + /** endif **/ + + /** if metadata **/ + metadata: stringify(metadata), + /** endif **/ + }, + callback + ); previousReferrer = referrer; referrer = currentPage; @@ -763,14 +824,29 @@ var sameSite, userNavigated; - var pageview = function (isPushState, pathOverwrite, metadata) { + var pageview = function ( + isPushState, + pathOverwrite, + metadata, + callbackRaw + ) { + if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata; + var callback = isFunction(callbackRaw) ? callbackRaw : function () {}; + var querySearch = ""; + if (isString(pathOverwrite) && pathOverwrite.indexOf("?") > -1) { + // keep query from manual path + var parts = pathOverwrite.split("?"); + pathOverwrite = parts.shift(); + querySearch = "?" + parts.join("?"); + } // Obfuscate personal data in URL by dropping the search and hash var path = getPath(pathOverwrite); // Don't send the last path again (this could happen when pushState is used to change the path hash or search) - if (!path || lastSendPath == path) return; + var pathKey = path + querySearch; + if (!path || lastSendPath == pathKey) return; - lastSendPath = path; + lastSendPath = pathKey; page.path = path; /** if screen **/ @@ -836,8 +912,11 @@ /** endif **/ /** if uniques **/ - // We set unique variable based on pushstate or back navigation, if no match we check the referrer - page.unique = isPushState || userNavigated ? falseVar : !sameSite; + // Only the first pageview can use a Cloudflare referrer as a unique arrival. + page.unique = + isPushState || userNavigated + ? falseVar + : !sameSite || (!pages && /[?&]__cf_/.test(getReferrer(trueVar))); /** endif **/ /** if metadata **/ @@ -849,11 +928,15 @@ var triggerSendPageView = function () { fetchedHighEntropyValues = trueVar; + var delSrc = + isPushState || userNavigated || !collectMetricByString("r"); sendPageView( isPushState, - isPushState || userNavigated || !collectMetricByString("r"), // r = referrers + delSrc, // r = referrers sameSite, - metadata + querySearch, + metadata, + callback ); }; @@ -948,17 +1031,20 @@ /** if (or spa hash) **/ if (autoCollect) pageview(); - else { - /** if metadata **/ - window.sa_pageview = function (path, metadata) { - pageview(0, path, metadata); - }; - /** else **/ - window.sa_pageview = function (path) { - pageview(0, path); - }; - /** endif **/ - } + + /** if metadata **/ + var manualPageview = function (path, metadata, callback) { + pageview(0, path, metadata, callback); + }; + /** else **/ + var manualPageview = function (path, callback) { + pageview(0, path, undefinedVar, callback); + }; + /** endif **/ + window[namespace + "_" + pageviewText] = manualPageview; + var defaultPageview = defaultNamespace + "_" + pageviewText; + if (!window[defaultPageview]) window[defaultPageview] = manualPageview; + /** else **/ pageview(); /** endif **/ @@ -970,7 +1056,7 @@ var validTypes = ["string", "number"]; - var sendEvent = function (event, metadata, callbackRaw) { + var sendEvent = function (event, metadata, callbackRaw, keepalive) { if (!callbackRaw && isFunction(metadata)) callbackRaw = metadata; var eventIsFunction = isFunction(event); @@ -1022,13 +1108,15 @@ metadata: stringify(metadata), /** endif **/ }), - callback + callback, + undefinedVar, + keepalive ); } }; - var defaultEventFunc = function (event, metadata, callback) { - sendEvent(event, metadata, callback); + var defaultEventFunc = function (event, metadata, callback, keepalive) { + sendEvent(event, metadata, callback, keepalive); }; // Set default function if user didn't define a function @@ -1051,6 +1139,71 @@ : sendEvent(queue[event]); } } + + var inlineEvent = function (event) { + var element = event.target; + while ( + element && + element !== doc && + (!element.getAttribute || attr(element, "simple-event") === null) + ) + element = element.parentNode; + + if (!element || element === doc) return; + var isForm = element.tagName === "FORM"; + var name = attr(element, "simple-event"); + if (!name || isForm !== (event.type === "submit")) return; + + var metadata = { tag: element.tagName.toLowerCase() }; + var attributes = element.attributes; + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + if (attribute.name.indexOf("data-simple-event-") === 0) + metadata[attribute.name.slice(18).replace(/-/g, "_")] = + attribute.value; + } + if (isForm) { + var button = event.submitter; + metadata.button_text = button + ? (button.textContent || button.value || "") + .replace(/\s+/g, " ") + .trim() + .slice(0, 200) + : ""; + } + sendEvent(name, metadata, undefinedVar, trueVar); + }; + + doc.addEventListener("click", inlineEvent, falseVar); + doc.addEventListener("submit", inlineEvent, falseVar); + + // 404 confirmation adds a request, so existing installs must opt in. + if ( + settings.detect404 === trueVar || + attr(scriptElement, "detect-404") == trueText + ) { + var detect404 = function () { + if ( + !/\b404\b/.test(doc.title + " " + (doc.body && doc.body.textContent)) + ) + return; + try { + var request = new window.XMLHttpRequest(); + request.open("HEAD", loc.href, trueVar); + request.onload = function () { + if (request.status === 404) + sendEvent("page_404", { + url: loc.protocol + "//" + definedHostname + loc.pathname, + status: 404, + }); + }; + request.send(); + } catch (error) {} + }; + if (doc.readyState === "loading") + doc.addEventListener("DOMContentLoaded", detect404, falseVar); + else detect404(); + } /** endif **/ } catch (e) { /** if errorhandling **/ @@ -1060,8 +1213,7 @@ /** endif **/ } })( - window, - "{{overwriteOptions}}", + typeof window != "undefined" && window, "{{baseUrl}}", "{{apiUrlPrefix}}", "{{scriptName}}", diff --git a/test/deploy.test.mts b/test/deploy.test.mts index 3ae7408..317db1c 100644 --- a/test/deploy.test.mts +++ b/test/deploy.test.mts @@ -1,10 +1,12 @@ import assert from "node:assert/strict"; +import { readFile, readdir } from "node:fs/promises"; import { describe, it } from "node:test"; import { classifyContent, createManifest, firstLine, + HEADER_PATTERN, latestVersionFromNames, repositoryPolicy, summarize, @@ -13,6 +15,52 @@ import { type PreviewFile, } from "../deploy.mts"; +describe("deployment headers", () => { + it("accepts every generated JavaScript header in the current manifest", async () => { + const version = latestVersionFromNames( + await readdir(new URL("../dist", import.meta.url)) + ); + assert.ok(version !== undefined, "dist has no versioned SRI directory"); + assert.match( + firstLine( + await readFile(new URL("../dist/latest/latest.js", import.meta.url)) + ), + new RegExp(`; v${version}\\) \\*/$`), + "SRI directory version must match dist/latest/latest.js" + ); + const files = createManifest( + { + destinations: ["cdn", "custom"], + scripts: ["default", "auto-events"], + variants: ["latest", "sri", "light", "proxy"], + }, + version + ); + for (const file of files.filter((file) => file.kind === "javascript")) { + const content = await readFile( + new URL("../" + file.localPath, import.meta.url) + ); + assert.match(firstLine(content), HEADER_PATTERN, file.localPath); + } + }); + + it("keeps accepting legacy headers", () => { + assert.match( + "/* Simple Analytics - Privacy friendly analytics (docs.simpleanalytics.com/script; 2024-01-01; abcd; SRI-version; v11) */", + HEADER_PATTERN + ); + }); + + it("rejects malformed or unrelated headers", () => { + for (const header of [ + "/* unrelated script */", + "/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2026-10-15; not-a-hash; v12) */", + ]) { + assert.doesNotMatch(header, HEADER_PATTERN); + } + }); +}); + describe("deployment manifest", () => { it("maps latest and its legacy companions to both destinations", () => { const files = createManifest({ diff --git a/test/helpers/get-exit-code.js b/test/helpers/get-exit-code.js new file mode 100644 index 0000000..3303d9a --- /dev/null +++ b/test/helpers/get-exit-code.js @@ -0,0 +1,2 @@ +module.exports = ({ stopOnFail, amountFailures }) => + stopOnFail && amountFailures > 0 ? 1 : 0; diff --git a/test/helpers/index.js b/test/helpers/index.js index 25544d7..0d3c176 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -1,5 +1,4 @@ const crypto = require("crypto"); -const { networkInterfaces: getNetworkInterfaces } = require("os"); const { DEBUG, SERVER_PORT } = require("../constants"); const { promisify } = require("util"); const { By, Key } = require("selenium-webdriver"); diff --git a/test/helpers/server.js b/test/helpers/server.js index 18ef4df..2c2d012 100644 --- a/test/helpers/server.js +++ b/test/helpers/server.js @@ -1,7 +1,7 @@ const url = require("url"); const http = require("http"); const { readFileSync } = require("fs"); -const { SERVER_PORT, DEBUG, CI } = require("../constants"); +const { SERVER_PORT, DEBUG } = require("../constants"); const { getJSONBody } = require("./request"); const log = (...messages) => diff --git a/test/unit/auto-events.test.js b/test/unit/auto-events.test.js new file mode 100644 index 0000000..0a3492e --- /dev/null +++ b/test/unit/auto-events.test.js @@ -0,0 +1,134 @@ +const { expect } = require("chai"); +const { createDOM } = require("./helpers/dom-auto-events"); +const { readFileSync } = require("fs"); +const { runInNewContext } = require("vm"); + +function setupDOM() { + const events = []; + const dom = createDOM({ + beforeRun(vm) { + vm.sa_event = function (name, metadata, cb) { + events.push({ name, metadata }); + if (typeof cb === "function") cb(); + }; + vm.sa_event_loaded = true; + }, + }); + dom.events = events; + return dom; +} + +describe("auto-events", function () { + it("keeps phone metadata when the title names the event", function () { + const dom = setupDOM(); + const link = dom.window.document.createElement("a"); + link.href = "tel:+31201234567?extension=42"; + link.title = "Call sales"; + + dom.window.saAutomatedLink(link, "phone"); + + expect(dom.events).to.deep.equal([ + { + name: "phone_Call_sales", + metadata: { title: "Call sales", phone: "+31201234567" }, + }, + ]); + dom.window.close(); + }); + + it("collects phone clicks by default without overriding cancelled navigation", function () { + const events = []; + const navigations = []; + let click; + const link = { + href: "tel:+31201234567", + getAttribute(name) { + return name === "href" ? this.href : null; + }, + hasAttribute() { + return false; + }, + addEventListener(type, listener) { + click = listener; + }, + }; + const document = { + readyState: "complete", + currentScript: { dataset: {} }, + getElementsByTagName: () => [link], + set location(value) { + navigations.push(value); + }, + }; + const window = { + document, + location: { hostname: "example.com" }, + sa_event_loaded: true, + sa_event(name, metadata, callback) { + events.push({ name, metadata }); + callback(); + }, + }; + runInNewContext(readFileSync("dist/latest/auto-events.js", "utf8"), { + window, + document, + console, + }); + click.call(link, { defaultPrevented: true }); + expect(events).to.deep.equal([ + { + name: "phone_31201234567", + metadata: { title: undefined, phone: "+31201234567" }, + }, + ]); + expect(navigations).to.deep.equal([]); + }); + + it("tracks outbound link clicks", function (done) { + const dom = setupDOM(); + const link = dom.window.document.createElement("a"); + link.href = "https://example.org/path"; + link.target = "_blank"; + dom.window.document.body.appendChild(link); + + dom.window.saAutomatedLink(link, "outbound"); + + setTimeout(() => { + expect(dom.events[0]).to.deep.include({ name: "outbound_example_org" }); + expect(dom.events[0].metadata).to.include({ url: link.href }); + done(); + }, 0); + }); + + it("tracks download link clicks", function (done) { + const dom = setupDOM(); + const link = dom.window.document.createElement("a"); + link.href = "https://example.com/file.pdf"; + link.target = "_blank"; + dom.window.document.body.appendChild(link); + + dom.window.saAutomatedLink(link, "download"); + + setTimeout(() => { + expect(dom.events[0]).to.deep.include({ name: "download_file_pdf" }); + expect(dom.events[0].metadata).to.include({ url: link.href }); + done(); + }, 0); + }); + + it("tracks email link clicks", function (done) { + const dom = setupDOM(); + const link = dom.window.document.createElement("a"); + link.href = "mailto:test@example.com"; + link.target = "_blank"; + dom.window.document.body.appendChild(link); + + dom.window.saAutomatedLink(link, "email"); + + setTimeout(() => { + expect(dom.events[0]).to.deep.include({ name: "email_test_example_com" }); + expect(dom.events[0].metadata).to.include({ email: "test@example.com" }); + done(); + }, 0); + }); +}); diff --git a/test/unit/get-exit-code.test.js b/test/unit/get-exit-code.test.js new file mode 100644 index 0000000..2f850ab --- /dev/null +++ b/test/unit/get-exit-code.test.js @@ -0,0 +1,13 @@ +const { expect } = require("chai"); +const getExitCode = require("../helpers/get-exit-code"); + +describe("get exit code", function () { + it("returns a numeric exit code for passing and failing runs", function () { + expect(getExitCode({ stopOnFail: true, amountFailures: 0 })).to.equal(0); + expect(getExitCode({ stopOnFail: true, amountFailures: 1 })).to.equal(1); + }); + + it("returns zero when stopping on failures is disabled", function () { + expect(getExitCode({ stopOnFail: false, amountFailures: 1 })).to.equal(0); + }); +}); diff --git a/test/unit/helpers/dom-auto-events.js b/test/unit/helpers/dom-auto-events.js new file mode 100644 index 0000000..eaf7ccc --- /dev/null +++ b/test/unit/helpers/dom-auto-events.js @@ -0,0 +1,78 @@ +const { JSDOM } = require("jsdom"); +const { readFileSync } = require("fs"); +const vm = require("vm"); + +const SCRIPT_PATH = "dist/latest/auto-events.js"; + +/** + * @typedef {"navigate" | "reload" | "back_forward" | "prerender"} NavigationType + */ + +/** @type {Record} */ +const NAVIGATION_TYPES = { + navigate: { name: "navigate", code: 0 }, + reload: { name: "reload", code: 1 }, + back_forward: { name: "back_forward", code: 2 }, + prerender: { name: "prerender", code: 255 }, +}; + +function createDOM(options = {}) { + const { + url = "https://example.com/", + navigationType = "navigate", + settings, + beforeRun, + } = options; + const dom = new JSDOM("", { + url, + runScripts: "outside-only", + pretendToBeVisual: true, + }); + + if (settings) { + vm.runInContext( + `window.sa_settings = ${JSON.stringify(settings)}`, + dom.getInternalVMContext() + ); + } + + if (typeof beforeRun === "function") beforeRun(dom.getInternalVMContext()); + + const sent = []; + dom.window.Image = function () { + return { + set src(value) { + sent.push({ type: "image", url: value }); + }, + }; + }; + dom.window.navigator.sendBeacon = function (url, data) { + sent.push({ type: "beacon", url, data }); + return true; + }; + + Object.defineProperty(dom.window, "performance", { + writable: true, + value: { + getEntriesByType: function (type) { + if (type === "navigation") { + return [{ type: NAVIGATION_TYPES[navigationType].name }]; + } + return []; + }, + navigation: { type: NAVIGATION_TYPES[navigationType].code }, + }, + }); + + const script = readFileSync(SCRIPT_PATH, "utf8"); + vm.runInContext(script, dom.getInternalVMContext()); + + dom.sent = sent; + return dom; +} + +module.exports = { + createDOM, + SCRIPT_PATH, + NAVIGATION_TYPES, +}; diff --git a/test/unit/helpers/dom.js b/test/unit/helpers/dom.js new file mode 100644 index 0000000..b0f2bae --- /dev/null +++ b/test/unit/helpers/dom.js @@ -0,0 +1,78 @@ +const { JSDOM } = require("jsdom"); +const { readFileSync } = require("fs"); +const vm = require("vm"); + +const SCRIPT_PATH = "dist/latest/latest.dev.js"; + +/** + * @typedef {"navigate" | "reload" | "back_forward" | "prerender"} NavigationType + */ + +/** @type {Record} */ +const NAVIGATION_TYPES = { + navigate: { name: "navigate", code: 0 }, + reload: { name: "reload", code: 1 }, + back_forward: { name: "back_forward", code: 2 }, + prerender: { name: "prerender", code: 255 }, +}; + +function createDOM(options = {}) { + const { + url = "https://example.com/", + navigationType = "navigate", + settings, + beforeRun, + } = options; + const dom = new JSDOM("", { + url, + runScripts: "outside-only", + pretendToBeVisual: true, + }); + + if (settings) { + vm.runInContext( + `window.sa_settings = ${JSON.stringify(settings)}`, + dom.getInternalVMContext() + ); + } + + if (typeof beforeRun === "function") beforeRun(dom.getInternalVMContext()); + + const sent = []; + dom.window.Image = function () { + return { + set src(value) { + sent.push({ type: "image", url: value }); + }, + }; + }; + dom.window.navigator.sendBeacon = function (url, data) { + sent.push({ type: "beacon", url, data }); + return true; + }; + + Object.defineProperty(dom.window, "performance", { + writable: true, + value: { + getEntriesByType: function (type) { + if (type === "navigation") { + return [{ type: NAVIGATION_TYPES[navigationType].name }]; + } + return []; + }, + navigation: { type: NAVIGATION_TYPES[navigationType].code }, + }, + }); + + const script = readFileSync(SCRIPT_PATH, "utf8"); + vm.runInContext(script, dom.getInternalVMContext()); + + dom.sent = sent; + return dom; +} + +module.exports = { + createDOM, + SCRIPT_PATH, + NAVIGATION_TYPES, +}; diff --git a/test/unit/helpers/index.js b/test/unit/helpers/index.js new file mode 100644 index 0000000..385a060 --- /dev/null +++ b/test/unit/helpers/index.js @@ -0,0 +1 @@ +module.exports = require("./dom"); diff --git a/test/unit/ignore-pages.test.js b/test/unit/ignore-pages.test.js new file mode 100644 index 0000000..df7b538 --- /dev/null +++ b/test/unit/ignore-pages.test.js @@ -0,0 +1,26 @@ +const { expect } = require("chai"); +const { createDOM } = require("./helpers/dom"); + +describe("ignore pages", function () { + it("does not send a request for ignored paths", function (done) { + const dom = createDOM({ + settings: { autoCollect: false, ignorePages: "/ignore" }, + }); + + dom.window.sa_pageview("/ignore"); + dom.window.sa_pageview("/allowed"); + + setTimeout(() => { + const ignoreReq = dom.sent.find( + (r) => r.type === "image" && /path=%2Fignore/.test(r.url) + ); + const allowedReq = dom.sent.find( + (r) => r.type === "image" && /path=%2Fallowed/.test(r.url) + ); + + expect(ignoreReq, "request for ignored path").to.not.exist; + expect(allowedReq, "request for allowed path").to.exist; + done(); + }, 10); + }); +}); diff --git a/test/unit/inline-events.test.js b/test/unit/inline-events.test.js new file mode 100644 index 0000000..dbf5923 --- /dev/null +++ b/test/unit/inline-events.test.js @@ -0,0 +1,316 @@ +const { expect } = require("chai"); +const { runInContext } = require("vm"); +const { createDOM } = require("./helpers/dom"); + +describe("inline events", function () { + const windows = []; + const setup = (options = {}) => { + const dom = createDOM({ settings: { autoCollect: false }, ...options }); + windows.push(dom.window); + return dom; + }; + const events = (dom) => + dom.sent + .filter( + (request) => new URL(request.url).searchParams.get("type") === "event" + ) + .map((request) => { + const params = new URL(request.url).searchParams; + return { + name: params.get("event"), + metadata: JSON.parse(params.get("metadata")), + }; + }); + const click = (dom, element, options = {}) => { + const event = new dom.window.MouseEvent("click", { + bubbles: true, + cancelable: true, + ...options, + }); + element.dispatchEvent(event); + return event; + }; + const submit = (dom, form, button) => { + const event = new dom.window.SubmitEvent("submit", { + bubbles: true, + cancelable: true, + submitter: button, + }); + form.dispatchEvent(event); + return event; + }; + + afterEach(() => windows.splice(0).forEach((window) => window.close())); + + it("tracks nested clicks and new elements with current metadata", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + ''; + const button = dom.window.document.querySelector("button"); + click(dom, button.firstChild); + button.setAttribute("data-simple-event", "upgrade"); + button.setAttribute("data-simple-event-plan-name", "enterprise"); + click(dom, button); + expect(events(dom)).to.deep.equal([ + { name: "choose", metadata: { tag: "button", plan_name: "pro" } }, + { name: "upgrade", metadata: { tag: "button", plan_name: "enterprise" } }, + ]); + }); + + it("leaves link behavior and modified clicks untouched", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + 'Download'; + const link = dom.window.document.querySelector("a"); + const event = click(dom, link, { ctrlKey: true }); + expect(event.defaultPrevented).to.equal(false); + expect(link.getAttribute("target")).to.equal("_blank"); + expect(link.hasAttribute("download")).to.equal(true); + expect(link.hasAttribute("onclick")).to.equal(false); + expect(events(dom)).to.have.length(1); + }); + + it("tracks SPA clicks without undoing cancellation, and ignores untagged elements", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + ''; + const buttons = dom.window.document.querySelectorAll("button"); + buttons[0].addEventListener("click", (event) => event.preventDefault()); + expect(click(dom, buttons[0]).defaultPrevented).to.equal(true); + click(dom, buttons[1]); + expect(events(dom)).to.have.length(1); + expect(events(dom)[0].name).to.equal("cancelled"); + }); + + it("uses the actual submitter and lets the browser submit the form", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + '
'; + const form = dom.window.document.querySelector("form"); + const button = dom.window.document.querySelector("button"); + click(dom, form.querySelector("input")); + const event = submit(dom, form, button); + expect(event.defaultPrevented).to.equal(false); + expect(button.getAttribute("formaction")).to.equal("/other"); + expect(events(dom)).to.deep.equal([ + { name: "signup", metadata: { tag: "form", button_text: "Join" } }, + ]); + }); + + it("tracks SPA form submissions without submitting the form itself", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + '
'; + const form = dom.window.document.querySelector("form"); + form.addEventListener("submit", (event) => event.preventDefault()); + let submits = 0; + form.submit = () => submits++; + expect(submit(dom, form, form.firstChild).defaultPrevented).to.equal(true); + expect(events(dom)).to.have.length(1); + expect(submits).to.equal(0); + }); + + it("does not disable built-in events when the beta helper is installed", function () { + const dom = setup({ + beforeRun(context) { + context.document.head.innerHTML = + ''; + }, + }); + dom.window.document.body.innerHTML = + ''; + click(dom, dom.window.document.querySelector("button")); + expect(events(dom)).to.have.length(1); + }); + + it("uses the button label, trims it, and limits its length", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + '
'; + const form = dom.window.document.querySelector("form"); + const button = form.firstChild; + submit(dom, form, button); + expect(events(dom)[0].metadata.button_text).to.equal("Save changes"); + button.textContent = "x".repeat(5000); + submit(dom, form, button); + expect(events(dom)[1].metadata.button_text).to.equal("x".repeat(200)); + }); + + it("keeps submit labels stable when button markup is reformatted", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + '
'; + const form = dom.window.document.querySelector("form"); + const button = form.firstChild; + submit(dom, form, button); + button.innerHTML = + "\n \n Save\n changes\n"; + submit(dom, form, button); + expect( + events(dom).map((event) => event.metadata.button_text) + ).to.deep.equal(["Save changes", "Save changes"]); + }); + + it("uses submit input labels and leaves missing submitter text empty", function () { + const dom = setup(); + dom.window.document.body.innerHTML = + '
'; + const form = dom.window.document.querySelector("form"); + submit(dom, form, form.lastChild); + expect(events(dom)[0].metadata.button_text).to.equal("Join"); + form.firstChild.focus(); + submit(dom, form); + expect(events(dom)[1].metadata.button_text).to.equal(""); + }); + + it("uses a keepalive GET for inline events", function () { + const requests = []; + const dom = setup(); + dom.window.fetch = (url, options) => { + requests.push({ url, options }); + return Promise.resolve(); + }; + dom.window.document.body.innerHTML = + ''; + click(dom, dom.window.document.querySelector("button")); + expect(requests).to.have.length(1); + expect(new URL(requests[0].url).searchParams.get("event")).to.equal( + "choose" + ); + expect(requests[0].options).to.include({ + keepalive: true, + mode: "no-cors", + credentials: "omit", + }); + expect(requests[0].options.method).to.equal(undefined); + expect(events(dom)).to.have.length(0); + }); + + it("falls back to the image when fetch fails", async function () { + const dom = setup(); + dom.window.fetch = () => Promise.reject(new Error("blocked")); + dom.window.document.body.innerHTML = + ''; + click(dom, dom.window.document.querySelector("button")); + await Promise.resolve(); + expect(events(dom)).to.have.length(1); + }); + + it("falls back when fetch throws synchronously", function () { + const dom = setup(); + dom.window.fetch = () => { + throw new Error("unsupported"); + }; + dom.window.document.body.innerHTML = + ''; + click(dom, dom.window.document.querySelector("button")); + expect(events(dom)).to.have.length(1); + }); + + it("uses the tracker namespace and global metadata", function () { + const dom = setup({ + settings: { autoCollect: false, namespace: "other" }, + beforeRun(context) { + runInContext('window.other_metadata = { source: "global" };', context); + }, + }); + dom.window.document.body.innerHTML = + ''; + click(dom, dom.window.document.querySelector("button")); + expect(events(dom)[0].metadata).to.include({ + source: "global", + tag: "button", + }); + }); + + it("only confirms 404s when opted in, and strips query strings and fragments", function () { + const requests = []; + const options = { + url: "https://example.test/missing?secret=private#fragment", + beforeRun(context) { + context.document.body.innerHTML = "Page 404 not found"; + context.XMLHttpRequest = function () { + this.open = (method, url) => requests.push({ method, url }); + this.send = () => { + this.status = 404; + this.onload(); + }; + }; + }, + }; + const off = setup(options); + off.window.document.dispatchEvent(new off.window.Event("DOMContentLoaded")); + expect(requests).to.have.length(0); + const on = setup({ + ...options, + settings: { autoCollect: false, detect404: true }, + }); + on.window.document.dispatchEvent(new on.window.Event("DOMContentLoaded")); + expect(requests).to.have.length(1); + expect(requests[0].method).to.equal("HEAD"); + expect(events(on)).to.deep.equal([ + { + name: "page_404", + metadata: { url: "https://example.test/missing", status: 404 }, + }, + ]); + }); + + it("supports the 404 script attribute after DOMContentLoaded", function () { + const dom = setup({ + beforeRun(context) { + context.document.head.innerHTML = + ''; + context.document.body.innerHTML = "Page 404 not found"; + Object.defineProperty(context.document, "readyState", { + value: "complete", + }); + context.XMLHttpRequest = function () { + this.open = () => {}; + this.send = () => { + this.status = 404; + this.onload(); + }; + }; + }, + }); + expect(events(dom)).to.have.length(1); + expect(events(dom)[0].name).to.equal("page_404"); + }); + + it("does not report a successful HEAD response as a 404", function () { + const dom = setup({ + settings: { autoCollect: false, detect404: true }, + beforeRun(context) { + context.document.body.innerHTML = "An article about 404 errors"; + context.XMLHttpRequest = function () { + this.open = () => {}; + this.send = () => { + this.status = 200; + this.onload(); + }; + }; + }, + }); + dom.window.document.dispatchEvent(new dom.window.Event("DOMContentLoaded")); + expect(events(dom)).to.have.length(0); + }); + + it("does not issue HEAD requests for 404 in HTML attributes", function () { + let requests = 0; + const dom = setup({ + settings: { autoCollect: false, detect404: true }, + beforeRun(context) { + context.document.head.innerHTML = + ''; + context.document.body.innerHTML = + '
A normal page
'; + context.XMLHttpRequest = function () { + requests++; + }; + }, + }); + dom.window.document.dispatchEvent(new dom.window.Event("DOMContentLoaded")); + expect(requests).to.equal(0); + }); +}); diff --git a/test/unit/metadata-attr.test.js b/test/unit/metadata-attr.test.js new file mode 100644 index 0000000..5b473bd --- /dev/null +++ b/test/unit/metadata-attr.test.js @@ -0,0 +1,33 @@ +const { expect } = require("chai"); +const { createDOM } = require("./helpers/dom"); + +describe("metadata via data attribute", function () { + it("uses data-metadata-collector attribute", function (done) { + const dom = createDOM({ + settings: { autoCollect: false }, + beforeRun(vmContext) { + const { runInContext } = require("vm"); + runInContext( + "window.collector = function(data){ return { fromAttr: true, path: data.path }; };" + + "Object.defineProperty(document, 'currentScript', {get: function(){ return { getAttribute: function(name){ return name === 'data-metadata-collector' ? 'collector' : null; } }; }});", + vmContext + ); + }, + }); + + dom.window.sa_pageview("/attr"); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fattr/.test(r.url) + ); + expect(req, "pageview request").to.exist; + const url = new URL(req.url); + const meta = JSON.parse( + decodeURIComponent(url.searchParams.get("metadata")) + ); + expect(meta).to.include({ fromAttr: true }); + done(); + }, 10); + }); +}); diff --git a/test/unit/metadata.test.js b/test/unit/metadata.test.js new file mode 100644 index 0000000..b5270b6 --- /dev/null +++ b/test/unit/metadata.test.js @@ -0,0 +1,85 @@ +const { expect } = require("chai"); +const { createDOM } = require("./helpers/dom"); + +describe("metadata", function () { + it("collects metadata from global object and collector", function (done) { + const dom = createDOM({ + settings: { autoCollect: false, metadataCollector: "collector" }, + beforeRun(vmContext) { + const { runInContext } = require("vm"); + runInContext( + "window.sa_metadata = { fromGlobal: true };" + + "window.collector = function(data){ return { fromCollector: true, path: data.path }; };", + vmContext + ); + }, + }); + + const { runInContext } = require("vm"); + runInContext( + "window.manualMeta = { manual: true };", + dom.getInternalVMContext() + ); + dom.window.sa_pageview("/meta", dom.window.manualMeta); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fmeta/.test(r.url) + ); + expect(req, "pageview request").to.exist; + const url = new URL(req.url); + const meta = JSON.parse( + decodeURIComponent(url.searchParams.get("metadata")) + ); + expect(meta).to.include({ + manual: true, + fromGlobal: true, + fromCollector: true, + }); + done(); + }, 10); + }); + + it("reloads global metadata on each call", function (done) { + const dom = createDOM({ settings: { autoCollect: false } }); + const { runInContext } = require("vm"); + + runInContext( + "window.sa_metadata = { first: true };", + dom.getInternalVMContext() + ); + + dom.window.sa_pageview("/first"); + + setTimeout(() => { + let req = dom.sent.find( + (r) => r.type === "image" && /path=%2Ffirst/.test(r.url) + ); + expect(req, "first pageview request").to.exist; + let url = new URL(req.url); + let meta = JSON.parse( + decodeURIComponent(url.searchParams.get("metadata")) + ); + expect(meta).to.include({ first: true }); + + runInContext( + "window.sa_metadata = { second: true };", + dom.getInternalVMContext() + ); + + dom.window.sa_pageview("/second"); + + setTimeout(() => { + req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fsecond/.test(r.url) + ); + expect(req, "second pageview request").to.exist; + url = new URL(req.url); + meta = JSON.parse(decodeURIComponent(url.searchParams.get("metadata"))); + expect(meta).to.include({ second: true }); + expect(meta).to.not.have.property("first"); + done(); + }, 10); + }, 10); + }); +}); diff --git a/test/unit/pageview-callback.test.js b/test/unit/pageview-callback.test.js new file mode 100644 index 0000000..6929b31 --- /dev/null +++ b/test/unit/pageview-callback.test.js @@ -0,0 +1,34 @@ +const { expect } = require("chai"); +const { createDOM } = require("./helpers/dom"); + +describe("pageview callback", function () { + it("executes callback after sending a pageview", function (done) { + const dom = createDOM({ settings: { autoCollect: false } }); + + const sent = dom.sent; + dom.window.Image = function () { + return { + onload: null, + onerror: null, + set src(value) { + sent.push({ type: "image", url: value }); + if (this.onload) this.onload(); + }, + }; + }; + + let called = false; + dom.window.sa_pageview("/callback", function () { + called = true; + }); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fcallback/.test(r.url) + ); + expect(req, "pageview request").to.exist; + expect(called, "callback called").to.be.true; + done(); + }, 10); + }); +}); diff --git a/test/unit/pageview-query.test.js b/test/unit/pageview-query.test.js new file mode 100644 index 0000000..b4378b9 --- /dev/null +++ b/test/unit/pageview-query.test.js @@ -0,0 +1,147 @@ +const { expect } = require("chai"); +const { createDOM } = require("./helpers/dom"); + +describe("pageview query", function () { + it("keeps accepting numeric manual paths and path-overwriter results", function () { + const dom = createDOM({ settings: { autoCollect: false } }); + dom.window.sa_pageview(123); + expect(new URL(dom.sent[0].url).searchParams.get("path")).to.equal("123"); + dom.window.close(); + + const rewritten = createDOM({ + settings: { autoCollect: false, pathOverwriter: "rewrite" }, + beforeRun(context) { + context.rewrite = () => 456; + }, + }); + rewritten.window.sa_pageview("/product?product-id=1"); + expect(new URL(rewritten.sent[0].url).searchParams.get("path")).to.equal( + "456" + ); + rewritten.window.close(); + }); + + it("keeps ignore-pages active for manual query paths", function () { + const dom = createDOM({ + settings: { autoCollect: false, ignorePages: "/product" }, + }); + dom.window.sa_pageview("/product?product-id=1"); + expect(dom.sent).to.deep.equal([]); + dom.window.close(); + }); + + it("keeps the hash route when stripping a manual query", function () { + const dom = createDOM({ + url: "https://example.com/#/deep", + settings: { autoCollect: false, mode: "hash" }, + }); + dom.window.sa_pageview("/product?product-id=1"); + const url = new URL(dom.sent[0].url); + expect(url.searchParams.get("path")).to.equal("/product#/deep"); + dom.window.close(); + }); + + it("keeps manual pageviews that differ only in their query", function () { + const dom = createDOM({ settings: { autoCollect: false } }); + dom.window.sa_pageview("/product?product-id=1"); + dom.window.sa_pageview("/product?product-id=2"); + dom.window.sa_pageview("/product?product-id=2"); + const paths = dom.sent + .filter((request) => request.type === "image") + .map((request) => new URL(request.url).searchParams.get("path")); + expect(paths).to.deep.equal(["/product", "/product"]); + dom.window.close(); + }); + + it("passes manual paths without the query to the path overwriter", function () { + const paths = []; + const dom = createDOM({ + settings: { autoCollect: false, pathOverwriter: "rewrite" }, + beforeRun(context) { + context.rewrite = ({ path }) => { + paths.push(path); + return path === "/product" ? "/rewritten" : path; + }; + }, + }); + dom.window.sa_pageview("/product?product-id=1"); + expect(paths[0]).to.equal("/product"); + const url = new URL(dom.sent[0].url); + expect(url.searchParams.get("path")).to.equal("/rewritten"); + dom.window.close(); + }); + + it("sends query params from manual path", function (done) { + const dom = createDOM({ + settings: { autoCollect: false, allowParams: "foo" }, + }); + + dom.window.sa_pageview("/manual?foo=bar"); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fmanual/.test(r.url) + ); + expect(req, "pageview request").to.exist; + const url = new URL(req.url); + expect(url.searchParams.get("query")).to.equal("foo=bar"); + done(); + }, 10); + }); + + it("matches allowed params case insensitively", function (done) { + const dom = createDOM({ + settings: { autoCollect: false, allowParams: "foo" }, + }); + + dom.window.sa_pageview("/manual?FOO=bar"); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fmanual/.test(r.url) + ); + expect(req, "pageview request").to.exist; + const url = new URL(req.url); + expect(url.searchParams.get("query")).to.equal("FOO=bar"); + done(); + }, 10); + }); + + it("sends non-empty parameter names without their values", function (done) { + const dom = createDOM({ + settings: { autoCollect: false }, + }); + + dom.window.sa_pageview("/manual?gclid=secret&foo=another&empty=&flag"); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fmanual/.test(r.url) + ); + expect(req, "pageview request").to.exist; + const url = new URL(req.url); + expect(url.searchParams.get("k")).to.equal("gclid,foo"); + expect(req.url).not.to.include("secret"); + expect(req.url).not.to.include("another"); + done(); + }, 10); + }); + + it("allows parameter name collection to be ignored", function (done) { + const dom = createDOM({ + settings: { autoCollect: false, ignoreMetrics: "querykeys" }, + }); + + dom.window.sa_pageview("/manual?gclid=secret"); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fmanual/.test(r.url) + ); + expect(req, "pageview request").to.exist; + const url = new URL(req.url); + expect(url.searchParams.has("k")).to.equal(false); + done(); + }, 10); + }); +}); diff --git a/test/unit/pageview.test.js b/test/unit/pageview.test.js new file mode 100644 index 0000000..19efe50 --- /dev/null +++ b/test/unit/pageview.test.js @@ -0,0 +1,179 @@ +const { expect } = require("chai"); +const { readFileSync } = require("fs"); +const { runInContext } = require("vm"); +const { createDOM, SCRIPT_PATH } = require("./helpers/dom"); + +describe("pageview", function () { + for (const [referrer, unique] of [ + ["https://external.example/?__cf_chl_tk=challenge", true], + ["https://external.example/?source=mail&__cf_chl_rt_tk=challenge", true], + ["https://example.com/?__cf_chl_tk=challenge", true], + ["https://example.com/?source=mail&__cf_chl_rt_tk=challenge", true], + ["https://example.com/previous", false], + ["https://example.com/docs/__cf_workers", false], + ["https://example.com/?next=?__cf_chl_tk=challenge", true], + ["https://example.com/#?__cf_chl_tk=challenge", true], + ]) { + it(`uses the simple Cloudflare marker for ${referrer}`, function () { + const dom = createDOM({ + beforeRun(context) { + Object.defineProperty(context.document, "referrer", { + value: referrer, + }); + }, + }); + const url = new URL(dom.sent[0].url); + expect(url.searchParams.get("unique")).to.equal(String(unique)); + expect(url.searchParams.get("referrer")).not.to.include("challenge"); + dom.window.close(); + }); + } + + it("recognizes challenge arrivals in an overwritten referrer without sending its query", function () { + const dom = createDOM({ + settings: { referrer: "https://example.com/?__cf_chl_tk=challenge" }, + }); + const url = new URL(dom.sent[0].url); + expect(url.searchParams.get("unique")).to.equal("true"); + expect(url.searchParams.get("referrer")).to.equal("example.com/"); + dom.window.close(); + }); + + for (const navigationType of ["reload", "back_forward"]) { + it(`keeps ${navigationType} non-unique with a challenge referrer`, function () { + const dom = createDOM({ + navigationType, + settings: { referrer: "https://example.com/?__cf_chl_tk=challenge" }, + }); + const url = new URL(dom.sent[0].url); + expect(url.searchParams.get("unique")).to.equal("false"); + dom.window.close(); + }); + } + + it("counts only the first pageview as unique after a challenge", function () { + const dom = createDOM({ + settings: { referrer: "https://example.com/?__cf_chl_tk=challenge" }, + }); + dom.window.sa_pageview("/manual"); + dom.window.history.pushState({}, "", "/spa"); + const pageviews = dom.sent.filter( + (request) => new URL(request.url).searchParams.get("type") === "pageview" + ); + expect( + pageviews.map((request) => + new URL(request.url).searchParams.get("unique") + ) + ).to.deep.equal(["true", "false", "false"]); + dom.window.close(); + }); + + it("exposes the pageview function under its configured namespace", function () { + const dom = createDOM({ + settings: { namespace: "ba", autoCollect: false }, + }); + expect(dom.window.ba_pageview).to.be.a("function"); + expect(dom.window.sa_pageview).to.equal(dom.window.ba_pageview); + dom.window.sa_pageview("/legacy"); + dom.window.ba_pageview("/namespaced"); + const paths = dom.sent.map((request) => + new URL(request.url).searchParams.get("path") + ); + expect(paths).to.deep.equal(["/legacy", "/namespaced"]); + dom.window.close(); + }); + + it("keeps a default manual tracker separate from an automatic namespaced tracker", function () { + const dom = createDOM({ + beforeRun(context) { + const script = context.document.createElement("script"); + script.setAttribute("data-auto-collect", "false"); + script.setAttribute("data-hostname", "primary.example.com"); + Object.defineProperty(context.document, "currentScript", { + value: script, + }); + }, + }); + const manualPageview = dom.window.sa_pageview; + const script = dom.window.document.currentScript; + script.setAttribute("data-auto-collect", "true"); + script.setAttribute("data-hostname", "secondary.example.com"); + script.setAttribute("data-namespace", "ba"); + runInContext(readFileSync(SCRIPT_PATH, "utf8"), dom.getInternalVMContext()); + expect(dom.window.sa_pageview).to.equal(manualPageview); + dom.window.sa_pageview("/manual"); + dom.window.ba_pageview("/other"); + const hostnames = dom.sent + .filter((request) => request.type === "image") + .map((request) => new URL(request.url).searchParams.get("hostname")); + expect(hostnames).to.deep.equal([ + "secondary.example.com", + "primary.example.com", + "secondary.example.com", + ]); + dom.window.close(); + }); + + it("sends pageview, event and beacon requests", function (done) { + const dom = createDOM({ navigationType: "reload" }); + + dom.window.sa_event("unit_test"); + + if (!("onpagehide" in dom.window)) { + dom.window.document.hidden = true; + dom.window.document.dispatchEvent( + new dom.window.Event("visibilitychange") + ); + } else { + dom.window.dispatchEvent(new dom.window.Event("pagehide")); + } + + setTimeout(() => { + const gif = dom.sent.find( + (r) => r.type === "image" && /simple\.gif/.test(r.url) + ); + const eventReq = dom.sent.find( + (r) => r.type === "image" && /event=unit_test/.test(r.url) + ); + const beacon = dom.sent.find((r) => r.type === "beacon"); + + expect(gif, "pageview gif request").to.exist; + expect(eventReq, "event gif request").to.exist; + expect(beacon, "append beacon request").to.exist; + expect(beacon.url).to.match(/\/append$/); + expect(beacon.data).to.include('"type":"append"'); + + done(); + }, 10); + }); + + it("falls back to pixel when sendBeacon fails", function (done) { + const dom = createDOM({ navigationType: "reload" }); + + dom.window.navigator.sendBeacon = function () { + throw new TypeError("Illegal invocation"); + }; + + dom.window.sa_event("unit_test"); + + if (!("onpagehide" in dom.window)) { + dom.window.document.hidden = true; + dom.window.document.dispatchEvent( + new dom.window.Event("visibilitychange") + ); + } else { + dom.window.dispatchEvent(new dom.window.Event("pagehide")); + } + + setTimeout(() => { + const beacon = dom.sent.find((r) => r.type === "beacon"); + const appendGif = dom.sent.find( + (r) => r.type === "image" && /type=append/.test(r.url) + ); + + expect(beacon, "append beacon request").to.not.exist; + expect(appendGif, "append gif request").to.exist; + done(); + }, 10); + }); +});