From 1631b4702e79c2eb4ba6ae10d7afbe86b8cc0397 Mon Sep 17 00:00:00 2001 From: Conductor Adriaan Date: Sun, 25 Oct 2026 19:40:05 +0000 Subject: [PATCH 1/8] Document script version 12 Update the SRI version and hashes, time on page, ignore metrics, unique visits and automated events for v12, rewrite the inline events page for the main script, and add a pings page. Fixes #61 Co-Authored-By: Claude Opus 5.5 (1M context) --- _docs/20_install-script/01_script.md | 6 +- _docs/20_install-script/19_sri.md | 6 +- _docs/20_script-settings/04_ignore-metrics.md | 33 ++++++----- _docs/20_script-settings/06_pings.md | 29 ++++++++++ _docs/33_explained/02_time-on-page.md | 4 +- _docs/33_explained/05_uniques.md | 6 +- _docs/55_events/00_inline-events.md | 56 ++++++++----------- _docs/55_events/05_automated-events.md | 12 ++-- 8 files changed, 92 insertions(+), 60 deletions(-) create mode 100644 _docs/20_script-settings/06_pings.md diff --git a/_docs/20_install-script/01_script.md b/_docs/20_install-script/01_script.md index fcdccd14..2c031fc4 100644 --- a/_docs/20_install-script/01_script.md +++ b/_docs/20_install-script/01_script.md @@ -2,7 +2,7 @@ title: How to add our script category: install-script permalink: /script -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-25 --- Include these two lines on every page at the end of your `` (or anywhere else): @@ -86,6 +86,8 @@ These settings are available: | `namespace` | [`data-namespace`][10] | `"ba"` | | `pathOverwriter` | [`data-path-overwriter`][11] | `"myPathOverwriter"` | | `metadataCollector` | [`data-metadata-collector`][12] | `"myAddMetadataFunction"` | +| `pings` | [`data-pings`][13] | `[5, 30, 60]` | +| `detect404` | [`data-detect-404`][14] | `true` | For `pathOverwriter` and `metadataCollector`, use the name of a function on `window`, not the function itself. The script logs the settings it received in the browser console. @@ -101,6 +103,8 @@ For `pathOverwriter` and `metadataCollector`, use the name of a function on `win [10]: /events#the-variable-sa_event-is-already-used [11]: /overwrite-path [12]: /metadata +[13]: /pings +[14]: /events/inline#404-pages ## Browser support diff --git a/_docs/20_install-script/19_sri.md b/_docs/20_install-script/19_sri.md index 82487620..8e278e3f 100644 --- a/_docs/20_install-script/19_sri.md +++ b/_docs/20_install-script/19_sri.md @@ -2,9 +2,9 @@ title: SRI version category: install-script permalink: /sri -sriVersion: 11 -sriHash: sha256-hkUzQr3zWmSDnmhw95ZmQSZ949upqD+ML9ejiN0UIIE= sha384-rfv15RJy1bBYZ1Mf4xizO26jorXb2myipCvHXy4rkG0SuEET96S+m0sTzu5vfbSI sha512-lQzjzTbOxHLwkZGDVMf4V0sm8v2Mrqm73IvKcXBftJ/MSZKQC4/jwKFToxT+3IVAVWQzLplSNHH8gM5d7b1BSg== -last_modified_at: 2023-05-03 +sriVersion: 12 +sriHash: sha256-iSFbgQEAJgoeLh+lTWPVLouX2RiBERlq4qAOgM8aK+g= sha384-VVOeJV8okLf6owAyITVK14p3AX78fPOStksa5tYEruAngS4yv5EYM26KP9bvcZ/L sha512-DrEJKCUTeTeOenmoMwQa6d3KSiKXCFdZjjbsJhzh4vYFXPxjoU8dfd8oISmIDqrkkRYeCriuEC5TEah3aONxsg== +last_modified_at: 2026-10-25 --- If you want to use SRI you can do this by using specific scripts. The default scripts are changing to reflect new features or code optimizations. You want to use SRI if you consider it a risk when our scripts change. You can also host our SRI script on your own server or CDN. diff --git a/_docs/20_script-settings/04_ignore-metrics.md b/_docs/20_script-settings/04_ignore-metrics.md index 1712dae5..d4fbcb68 100644 --- a/_docs/20_script-settings/04_ignore-metrics.md +++ b/_docs/20_script-settings/04_ignore-metrics.md @@ -3,23 +3,24 @@ title: Ignore metrics category: script-settings permalink: /ignore-metrics created_at: 2022-07-26 -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-25 --- Our script only collects non-personal data. Some customers might want to limit our metrics even more. That's why we created the ignore metrics feature. -| Metric | Slug | Inferrered metric | -| ------------------- | -------------- | ---------------------- | -| Referrer | `referrer` | UTM codes, `ref` param | -| UTM codes | `utm` | [`ref` param][0] | -| Country / time zone | `country` | | -| Page-load IDs | `session` | | -| Time on page | `timeonpage` | Data point ID, Page ID | -| Scrolled | `scrolled` | Data point ID, Page ID | -| User Agent | `useragent` | | -| Screen size | `screensize` | | -| Viewport size | `viewportsize` | | -| Language | `language` | | +| Metric | Slug | Inferrered metric | +| --------------------- | -------------- | ---------------------- | +| Referrer | `referrer` | UTM codes, `ref` param | +| UTM codes | `utm` | [`ref` param][0] | +| Country / time zone | `country` | | +| Page-load IDs | `session` | | +| Time on page | `timeonpage` | Data point ID, Page ID | +| Scrolled | `scrolled` | Data point ID, Page ID | +| User Agent | `useragent` | | +| Screen size | `screensize` | | +| Viewport size | `viewportsize` | | +| Language | `language` | | +| Query parameter names | `querykeys` | | [0]: /how-to-use-url-parameters#using-a-url-parameter @@ -40,7 +41,9 @@ Our script only collects non-personal data. Some customers might want to limit o [See page](/metrics) where we explain those metrics. -When you ignore `referrer`, we also drop UTM codes and the `ref` param from page views, because they describe where a visitor came from. Parameters from [allow params](/allow-params) are still collected. When a visitor navigates within your own website, we still send that internal referrer so we can tell [unique visits](/uniques) apart. +From script version 12, we collect the **names** of query parameters in the URL of the first page view of a visit, for example `gclid,ref` for `?gclid=123&ref=newsletter`. We never collect their values, and skip parameters without a value. Ignore `querykeys` to turn this off. + +When you ignore `referrer`, we also drop UTM codes, query parameter names and the `ref` param from page views, because they describe where a visitor came from. Parameters from [allow params](/allow-params) are still collected. When a visitor navigates within your own website, we still send that internal referrer so we can tell [unique visits](/uniques) apart. ## Script setting `data-ignore-metrics` @@ -72,7 +75,7 @@ To ignore all metrics that you can ignore, you can use this embed script: ```html ``` diff --git a/_docs/20_script-settings/06_pings.md b/_docs/20_script-settings/06_pings.md new file mode 100644 index 00000000..c45f2acc --- /dev/null +++ b/_docs/20_script-settings/06_pings.md @@ -0,0 +1,29 @@ +--- +title: Pings +category: script-settings +permalink: /pings +created_at: 2026-10-25 +last_modified_at: 2026-10-25 +--- + +We send the [time on page](/explained/time-on-page) when a page gets hidden. If a browser discards a page before that, for example on mobile, we don't get any time for that page view. + +With pings, the script also sends the time on page when the visible time passes the thresholds you set, in seconds. Each ping replaces the time sent earlier for that page view, so seconds are never counted twice. Pings require script version 12. + +```html + +``` + +Or with the [settings object](/script#settings-via-javascript): + +```html + +``` + +There are no pings by default. Every threshold adds a request per page view, so only add the ones you need. Pings don't send anything when you ignore `timeonpage` with [ignore metrics](/ignore-metrics). diff --git a/_docs/33_explained/02_time-on-page.md b/_docs/33_explained/02_time-on-page.md index 6e98c67b..b6ac8bab 100644 --- a/_docs/33_explained/02_time-on-page.md +++ b/_docs/33_explained/02_time-on-page.md @@ -3,7 +3,7 @@ title: Time on page explained menu: Time on page category: explained permalink: /explained/time-on-page -last_modified_at: 2022-04-14 +last_modified_at: 2026-10-25 --- _Time on page_ is an important metric to measure how engaged your visitors are with your content. But in most analytics tools, there is something very wrong with that metric. You might think when using Simple Analytics: "These numbers are lower than I'm used to", well, that's probably right. @@ -36,6 +36,8 @@ Simple Analytics detects when a user navigates to a different website (in a new In the above example, we get the expected result: a visitor was 15 seconds on `page1` and 5 seconds on `page2`. Nothing more, nothing less. That's what you can expect from Simple Analytics. We make sure your data is as close to real-world scenarios as possible. +From script version 12, only the time a page is visible counts. The timer pauses when a visitor switches to another tab or app, and continues when they come back. We send the time every time the page gets hidden, so we also keep it when a mobile browser closes the page in the background. Times are rounded down to whole seconds. To also send the time while the page is still open, use [pings](/pings). + {% include video.html slug="time-on-page" diff --git a/_docs/33_explained/05_uniques.md b/_docs/33_explained/05_uniques.md index ec6c9376..e89b0051 100644 --- a/_docs/33_explained/05_uniques.md +++ b/_docs/33_explained/05_uniques.md @@ -5,7 +5,7 @@ category: explained permalink: /explained/unique-visits redirect_from: - /uniques -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-25 --- At Simple Analytics, we approach things differently. Our priority is protecting your visitors' privacy while staying compliant with strict privacy laws. This means some of our statistics work differently than traditional analytics tools. @@ -33,7 +33,7 @@ We use the [referrer](https://en.wikipedia.org/wiki/HTTP_referer) to determine w **A pageview is NOT counted as unique when:** -- The referrer's hostname matches your website's hostname (internal navigation) +- The referrer's hostname matches your website's hostname (internal navigation), except right after a Cloudflare challenge (see below) - The user navigates using browser history (back/forward buttons) - The user reloads the page - The referrer's hostname is in your [non-unique hostnames](/non-unique-hostnames) list, for example a payment provider @@ -50,6 +50,8 @@ If they then navigate to `yourwebsite.com/page`, the referrer is now `yourwebsit ![](/images/direct-visit.jpg) +If your website uses a Cloudflare challenge (such as "I'm Under Attack" mode), visitors arrive from the challenge page on your own domain. From script version 12, we count that first pageview as unique and send it without a referrer, because the challenge replaced the original one. + ## Why some pages have pageviews but (almost) no visitors This happens naturally with internal navigation. Once someone enters your site (counted as a visitor on their entry page), any subsequent pages they visit during that session only add to pageviews, not visitors. Only pages that users land on directly (with no referrer or a referrer from an external site) can be counted as visitors. diff --git a/_docs/55_events/00_inline-events.md b/_docs/55_events/00_inline-events.md index e09b4233..29c0f39a 100644 --- a/_docs/55_events/00_inline-events.md +++ b/_docs/55_events/00_inline-events.md @@ -1,69 +1,57 @@ --- -title: Inline events helper +title: Inline events category: events permalink: /events/inline -hidden: true -last_modified_at: 2025-04-22 +last_modified_at: 2026-10-25 --- -This small script watches your page for any element with a `data-simple-event`-attribute and automatically sends events to Simple Analytics when the user interacts. You don’t need to write any extra JavaScript calls—just add the right attributes to your HTML. - -
-

Warning, this script is in beta and can change any time.

-
- -### Installation - -Include the tracker snippet somewhere on your page, just before the closing `` tag. +From script version 12, our main script sends an event when a visitor interacts with an element that has a `data-simple-event` attribute. You don't need to write JavaScript or load an extra script. ```html - ``` -### Tracking button clicks +If you added the beta `inline-events.js` script, remove it. Otherwise every event is sent twice. + +### Clicks -To track a click, add `data-simple-event="event_name"` to any clickable element. The script prevents the default action, sends your event, then continues with the click (including opening links). +Add `data-simple-event="event_name"` to any clickable element: ```html See pricing ``` -Tracking form submissions +The script never delays or cancels the click, so links, downloads and new tabs work as before. -Simply put `data-simple-event="form_name"` on your form tag. When the user submits, the script sends an event with the name of the form and the text of the submit button, then submits the form. +### Form submissions + +Put `data-simple-event="form_name"` on your `form` tag. The event is sent when the form is submitted and includes the text of the submit button as `button_text`. We never collect what visitors type into your form. ```html
-
``` -### Adding custom metadata +### Metadata -Any attribute starting with `data-simple-event-` will be included as event metadata. Dashes convert to underscores. +Every inline event includes the element's tag name as `tag`. Attributes starting with `data-simple-event-` are added as [metadata](/metadata), with dashes converted to underscores: ```html - ``` -### Manual event tracking +### 404 pages -You can also fire events from code using `sa_event("event_name", { key: value })`. This works before or after the auto‑binding. For this you don't need this extra script. +Add `data-detect-404="true"` to the script to send a `page_404` event when a page contains "404" and a request to the same URL confirms the 404 status. -```js -// custom event on newsletter popup -sa_event("newsletter_signup", { source: "modal" }) +```html + ``` - -### 404 detection - -On DOMContentLoaded the script checks for "404" in your page HTML. If it finds it and the server HEAD request confirms status 404, it will send a page_404 event with the URL and status code. diff --git a/_docs/55_events/05_automated-events.md b/_docs/55_events/05_automated-events.md index 148e14f7..5f5e96b9 100644 --- a/_docs/55_events/05_automated-events.md +++ b/_docs/55_events/05_automated-events.md @@ -4,10 +4,10 @@ category: events permalink: /automated-events redirect_from: - /capture-outbound-links -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-25 --- -[Normal events](/events) need to be added into your code. To make it easier we created a separate automated events script. This script has to be installed once, and it will track outbound links, email addresses clicks, and amount of downloads for common files (pdf, csv, docx, xlsx). Events will appear on [your events page](https://simpleanalytics.com/select-website/events). +[Normal events](/events) need to be added into your code. To make it easier we created a separate automated events script. This script has to be installed once, and it will track outbound links, email addresses clicks, phone number clicks, and amount of downloads for common files (pdf, csv, docx, xlsx). Events will appear on [your events page](https://simpleanalytics.com/select-website/events). We created a simple video showing how to collect automated events in Simple Analytics. [Here you go](https://www.youtube.com/watch?v=CCvdgTReqms) @@ -19,6 +19,10 @@ Outbound links are basically just links that go to a different website. For exam Do you have links to email addresses on your website? Then it could make sense to see how many clicks you get on your `mailto` links. +## Phone numbers + +From script version 12, we also collect clicks on `tel:` links. The event is named after the number (for example `phone_31612345678`) and includes the number as `phone` metadata. To keep the old behavior, leave `phones` out of `data-collect`. + ## Downloads Do you have links to pdf's or other files? Collect the amount of downloads. You can specify the extensions of the files your want to collect downloads for. @@ -42,14 +46,14 @@ Or if you want to change some settings (these are the defaults): ``` -It takes care of sending it as an event to Simple Analytics. Events can only be letters, numbers, and underscores. We convert the event names directly in this script. +It takes care of sending it as an event to Simple Analytics. Events can only be letters, numbers, and underscores. We convert the event names directly in this script. From script version 12, the script never delays or cancels a click. Links with a [`data-simple-event`](/events/inline) attribute are tracked as inline events instead. If you changed the event function with [`data-namespace`](/events#the-variable-sa_event-is-already-used), add `data-sa-global` with the name of that function to the automated events script. For example, with `data-namespace="ba"`: From 855a6765cbdc9f258b14730a7a9b3798f66a4fd6 Mon Sep 17 00:00:00 2001 From: Conductor Adriaan Date: Sun, 25 Oct 2026 19:45:58 +0000 Subject: [PATCH 2/8] Correct query names, pings and phone events; cache proxy scripts 1h Query parameter names are sent on every full page load, pings still send the scroll depth when time on page is ignored, and phone links with a title use the title as event name. The nginx proxy example now caches scripts for one hour, like custom domains. Co-Authored-By: Claude Opus 5.5 (1M context) --- _docs/20_install-script/25_proxy.md | 6 +++--- _docs/20_script-settings/04_ignore-metrics.md | 2 +- _docs/20_script-settings/06_pings.md | 2 +- _docs/55_events/05_automated-events.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_docs/20_install-script/25_proxy.md b/_docs/20_install-script/25_proxy.md index 1189614c..0d3e40b2 100644 --- a/_docs/20_install-script/25_proxy.md +++ b/_docs/20_install-script/25_proxy.md @@ -2,7 +2,7 @@ title: Proxy category: install-script permalink: /proxy -last_modified_at: 2025-06-18 +last_modified_at: 2026-10-25 --- Concerned about your website visitors’ privacy when using Simple Analytics? We understand. Let’s be clear: we never collect your visitors’ IP addresses. And with our proxy setup option using Caddy, NGINX, Netlify, or Vercel, you have the power to ensure those IP addresses never reach us. This setup acts as a privacy shield, keeping your visitors' IP addresses from reaching external services. @@ -30,13 +30,13 @@ location ^~ /simple/ { } location = /proxy.js { - expires 7d; + expires 1h; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; proxy_pass https://simpleanalyticsexternal.com/proxy.js?hostname=example.com&path=/simple; } location = /auto-events.js { - expires 7d; + expires 1h; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; proxy_pass https://scripts.simpleanalyticscdn.com/auto-events.js; } diff --git a/_docs/20_script-settings/04_ignore-metrics.md b/_docs/20_script-settings/04_ignore-metrics.md index d4fbcb68..19722364 100644 --- a/_docs/20_script-settings/04_ignore-metrics.md +++ b/_docs/20_script-settings/04_ignore-metrics.md @@ -41,7 +41,7 @@ Our script only collects non-personal data. Some customers might want to limit o [See page](/metrics) where we explain those metrics. -From script version 12, we collect the **names** of query parameters in the URL of the first page view of a visit, for example `gclid,ref` for `?gclid=123&ref=newsletter`. We never collect their values, and skip parameters without a value. Ignore `querykeys` to turn this off. +From script version 12, we collect the **names** of query parameters in the page URL, for example `gclid,ref` for `?gclid=123&ref=newsletter`. We skip them for single-page app navigations, reloads and back/forward navigation. This only adds names: values are still only collected for UTM codes, `ref` and [allowed parameters](/allow-params). Ignore `querykeys` to turn this off. When you ignore `referrer`, we also drop UTM codes, query parameter names and the `ref` param from page views, because they describe where a visitor came from. Parameters from [allow params](/allow-params) are still collected. When a visitor navigates within your own website, we still send that internal referrer so we can tell [unique visits](/uniques) apart. diff --git a/_docs/20_script-settings/06_pings.md b/_docs/20_script-settings/06_pings.md index c45f2acc..1606f03d 100644 --- a/_docs/20_script-settings/06_pings.md +++ b/_docs/20_script-settings/06_pings.md @@ -26,4 +26,4 @@ Or with the [settings object](/script#settings-via-javascript): ``` -There are no pings by default. Every threshold adds a request per page view, so only add the ones you need. Pings don't send anything when you ignore `timeonpage` with [ignore metrics](/ignore-metrics). +There are no pings by default. Every threshold adds a request per page view, so only add the ones you need. When you ignore `timeonpage` with [ignore metrics](/ignore-metrics), pings only send how far visitors scrolled. diff --git a/_docs/55_events/05_automated-events.md b/_docs/55_events/05_automated-events.md index 5f5e96b9..540ae0c5 100644 --- a/_docs/55_events/05_automated-events.md +++ b/_docs/55_events/05_automated-events.md @@ -21,7 +21,7 @@ Do you have links to email addresses on your website? Then it could make sense t ## Phone numbers -From script version 12, we also collect clicks on `tel:` links. The event is named after the number (for example `phone_31612345678`) and includes the number as `phone` metadata. To keep the old behavior, leave `phones` out of `data-collect`. +From script version 12, we also collect clicks on `tel:` links. The event is named after the number (for example `phone_31612345678`), or after the link's title if it has one, and includes the number as `phone` metadata. To keep the old behavior, leave `phones` out of `data-collect`. ## Downloads From f0996d167dbb6db09f313a20af0c569fe2ed7dd0 Mon Sep 17 00:00:00 2001 From: Conductor Adriaan Date: Thu, 29 Oct 2026 18:46:48 +0000 Subject: [PATCH 3/8] Document the remaining script version 12 changes Add the referrer setting, the new sa_pageview options, a v12 changelog page, and update metadata, allow params, CSP, and collected data docs. Co-Authored-By: Claude Opus 5.5 (1M context) --- _docs/10_general/03_how-to-use-url-params.md | 4 +-- _docs/10_general/10_what_we_collect.md | 6 ++-- _docs/10_general/15_metrics.md | 6 ++-- _docs/20_install-script/00_v12.md | 35 +++++++++++++++++++ _docs/20_install-script/01_script.md | 4 ++- _docs/20_install-script/02_custom.md | 18 ++++++++-- _docs/20_install-script/20_csp.md | 6 ++-- .../03_overwrite-referrer.md | 23 ++++++++++++ .../05_allow-url-parameters.md | 4 +-- _docs/55_events/01_introduction.md | 8 ++--- _docs/55_events/15_metadata.md | 6 ++-- _docs/55_events/20-sa-link-event.md | 4 +-- 12 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 _docs/20_install-script/00_v12.md create mode 100644 _docs/20_script-settings/03_overwrite-referrer.md diff --git a/_docs/10_general/03_how-to-use-url-params.md b/_docs/10_general/03_how-to-use-url-params.md index baa5b9cf..e01b89db 100644 --- a/_docs/10_general/03_how-to-use-url-params.md +++ b/_docs/10_general/03_how-to-use-url-params.md @@ -4,7 +4,7 @@ menu: How to use URL params category: general permalink: /how-to-use-url-parameters excerpt: "You can add URL parameters to see where your customers are coming from." -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-29 --- There are a few ways we determine where a visitor comes from. We automatically detect the previous page (referrer) from the visitor's browser, but you can also add a URL parameter to override this and set a custom referrer. @@ -43,7 +43,7 @@ The UTM codes will show up on the dashboard in the "Referrals" dropdown menu: [Read the UTM guide](https://buffer.com/library/utm-guide/) at Buffer to learn more about UTM codes. -We drop non-UTM parameters from the URLs. If you want to allow more URL parameters, for example, `project-id`, use our [allow params](/allow-params)-feature. +We drop non-UTM parameters from the URLs. From script version 12, we do collect their names, like `gclid`, but never their values, so you can tell paid from organic traffic. You can turn this off with [ignore metrics](/ignore-metrics). If you want to allow more URL parameters, for example, `project-id`, use our [allow params](/allow-params)-feature. ### Forbidden characters diff --git a/_docs/10_general/10_what_we_collect.md b/_docs/10_general/10_what_we_collect.md index 26e7256f..2d7fa127 100644 --- a/_docs/10_general/10_what_we_collect.md +++ b/_docs/10_general/10_what_we_collect.md @@ -4,7 +4,7 @@ category: general permalink: /what-we-collect hidden: true excerpt: "Simple Analytics only collects privacy-insensitive data. Here is a list of what we do and don’t collect from your visitors." -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-29 --- Not collecting any information would be silly and unrealistic for an analytics tool. We do collect information that is necessary to show you _simple_ analytics, but unlike other analytics tools, we don't collect more than absolutely necessary. Here is a list of what we **do and don't** collect from your visitors. @@ -131,7 +131,7 @@ None of these IDs are linked to a person or personal data, and none are stored o > We **partially collect** and **partially store** URLs -Too much information in the URL can be confusing and can make your stats messy. We only collect and store the first part of the URL. If an URL looks like this `https://example.com/index.html?search=keyword#top` we will only store `https://example.com/index.html`, also known as the protocol (`https`), hostname (`example.com`), and pathname (`/index.html`). +Too much information in the URL can be confusing and can make your stats messy. We only collect and store the first part of the URL. If an URL looks like this `https://example.com/index.html?search=keyword#top` we will only store `https://example.com/index.html`, also known as the protocol (`https`), hostname (`example.com`), and pathname (`/index.html`). From script version 12, we also collect the names of the URL parameters, like `search`, but never their values. Read more on [using URL parameters](/how-to-use-url-parameters). ### Referrers @@ -195,7 +195,7 @@ When a visitor scrolls on a page we record how far they scrolled. We do store th ### Script settings -We send some script settings along with the page view. To identify the embed script and check if the page view comes from a robot. The script settings include things like `version: script_version_2`, `robot: true`. +We send some script settings along with the page view. To identify the embed script and check if the page view comes from a robot. The script settings include things like `version: script_version_2`, `robot: true`. From script version 12, we also send the URL of the embed script without its query string. ### Do Not Track diff --git a/_docs/10_general/15_metrics.md b/_docs/10_general/15_metrics.md index 36b41af7..fa66df21 100644 --- a/_docs/10_general/15_metrics.md +++ b/_docs/10_general/15_metrics.md @@ -3,7 +3,7 @@ title: Metrics category: general permalink: /metrics excerpt: "We never track visitors so the data below is never linked to one specific visitor. Here is a list of metrics we collect." -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-29 hidden: true redirect_from: - /data-points @@ -39,7 +39,7 @@ To know where customers come from, we store the page's referrer. This means that For example `https://simpleanalytics.com/?utm_source=newsletter` -The part after the `?` is called [URL parameters](/how-to-use-url-parameters). We only keep the UTM codes (`utm_source`/`ref`, `utm_medium`, `utm_content`, `utm_campaign`, `utm_term`) and drop all other URL parameters, unless you [allow them](/allow-params). The UTM codes are something that the customer adds to the URLs. They are usually generic terms like "newsletter_may" or "twitter_campaign_2". Don't put personal data in UTM codes. [See below][5]. +The part after the `?` is called [URL parameters](/how-to-use-url-parameters). We only keep the UTM codes (`utm_source`/`ref`, `utm_medium`, `utm_content`, `utm_campaign`, `utm_term`) and drop all other URL parameters, unless you [allow them](/allow-params). From script version 12, we also collect the names of the other parameters, never their values, unless you [ignore `querykeys`](/ignore-metrics). The UTM codes are something that the customer adds to the URLs. They are usually generic terms like "newsletter_may" or "twitter_campaign_2". Don't put personal data in UTM codes. [See below][5]. ### Unique @@ -89,7 +89,7 @@ To know which type of device the visitor used, we store the user agent. This is

Somewhat important

-We send some script settings along with the page view. To identify the embed script and check if the page view comes from a robot. The script settings include things like `version: script_version_2`, `robot: true`. +We send some script settings along with the page view. To identify the embed script and check if the page view comes from a robot. The script settings include things like `version: script_version_2`, `robot: true`. From script version 12, we also send the URL of the embed script without its query string. ### Dimensions diff --git a/_docs/20_install-script/00_v12.md b/_docs/20_install-script/00_v12.md new file mode 100644 index 00000000..c354e904 --- /dev/null +++ b/_docs/20_install-script/00_v12.md @@ -0,0 +1,35 @@ +--- +title: Embed script v12 +category: install-script +hidden: true +permalink: /script/v12 +last_modified_at: 2026-10-29 +created_at: 2026-10-29 +--- + +Our public script is now at v12. You get it automatically with `latest.js`. If you use [SRI](/sri), update to the v12 script and hash. + +## New features + +- [Inline events](/events/inline) are part of the main script: add `data-simple-event` to clicks and form submits, with `data-simple-event-*` attributes as metadata. Remove the separate `inline-events.js` script, otherwise events are counted twice. +- Optional [404 detection](/events/inline#404-pages): `data-detect-404="true"` sends a `page_404` event. +- We collect the names of query parameters, never their values. For example, `gclid` tells paid from organic traffic. Opt out with [`data-ignore-metrics="querykeys"`](/ignore-metrics). +- [Overwrite the referrer](/overwrite-referrer) with `data-referrer` or `sa_settings.referrer`. +- Optional [time on page pings](/pings): `data-pings="5,60"` sends the visible time at those seconds. +- [`sa_pageview(path, metadata, callback)`](/trigger-custom-page-views#use-custom-collection-anyway) has a callback that always runs, accepts a query string in the path, and follows a custom namespace (for example `ba_pageview`). +- [Automated events](/automated-events) collect clicks on phone (`tel:`) links. +- Inline and automated events are sent with `fetch` and `keepalive`, so they are not lost when the visitor navigates away. + +## Improvements and fixes + +- [Time on page](/explained/time-on-page) is reliable on mobile and only counts visible time. +- Automated events no longer block or delay links: Cmd, Ctrl, and middle clicks work, and there's no 5 second delay. +- Automated events work with a [custom namespace](/events#the-variable-sa_event-is-already-used) and skip links with `data-simple-event`. +- Visitors arriving through a Cloudflare challenge are counted as [unique](/uniques). +- Ignoring `scrolled` no longer drops the screen size. +- Manual page views with a different query string are no longer merged. +- [`data-allow-params`](/allow-params) is case-insensitive. +- Fixed false bot detection with the Phantom wallet extension. +- Removed the retired Cloudflare app build. + +If you are a developer you might want to see [what changed](https://github.com/simpleanalytics/scripts/compare/v11...v12) in our open-source repository. diff --git a/_docs/20_install-script/01_script.md b/_docs/20_install-script/01_script.md index 2c031fc4..c6e7b7a5 100644 --- a/_docs/20_install-script/01_script.md +++ b/_docs/20_install-script/01_script.md @@ -2,7 +2,7 @@ title: How to add our script category: install-script permalink: /script -last_modified_at: 2026-10-25 +last_modified_at: 2026-10-29 --- Include these two lines on every page at the end of your `` (or anywhere else): @@ -88,6 +88,7 @@ These settings are available: | `metadataCollector` | [`data-metadata-collector`][12] | `"myAddMetadataFunction"` | | `pings` | [`data-pings`][13] | `[5, 30, 60]` | | `detect404` | [`data-detect-404`][14] | `true` | +| `referrer` | [`data-referrer`][15] | `"https://example.com/"` | For `pathOverwriter` and `metadataCollector`, use the name of a function on `window`, not the function itself. The script logs the settings it received in the browser console. @@ -105,6 +106,7 @@ For `pathOverwriter` and `metadataCollector`, use the name of a function on `win [12]: /metadata [13]: /pings [14]: /events/inline#404-pages +[15]: /overwrite-referrer ## Browser support diff --git a/_docs/20_install-script/02_custom.md b/_docs/20_install-script/02_custom.md index a32881f2..61ebc18e 100644 --- a/_docs/20_install-script/02_custom.md +++ b/_docs/20_install-script/02_custom.md @@ -2,7 +2,7 @@ title: Trigger custom page views category: install-script permalink: /trigger-custom-page-views -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-29 --- Normally you want to trigger a custom page view for _Single Page Apps_ (SPAs) like React, Vue, and Angular. Because pages are not completely reloaded on navigation we need a way to track those navigations as page views. @@ -49,7 +49,7 @@ You can read our source code [on GitHub](https://github.com/simpleanalytics/scri ## Use custom collection anyway -There might be situation where you don't want to auto collect page views. When you add the `data-auto-collect="false"` attribute you can expose a function called `sa_pageview`. When you call this function, the script will send a page view with the path you give as a parameter. If you don't give a path it will use `window.location.pathname` as a default. This only works with `latest.js`, not with our [light script](/light). +There might be situation where you don't want to auto collect page views. When you add the `data-auto-collect="false"` attribute, the script doesn't send page views by itself and you send them with the `sa_pageview` function. When you call this function, the script will send a page view with the path you give as a parameter. If you don't give a path it will use `window.location.pathname` as a default. This only works with `latest.js`, not with our [light script](/light). ```html +``` + +We clean this referrer the same way as [the referrer from the browser](/how-to-use-url-parameters#using-the-referrer-url). Later page views in a single page app still use the previous page as their referrer. If you [ignore the `referrer` metric](/ignore-metrics), we don't send it. + +You can also set it with `referrer` in [`sa_settings`](/script#settings-via-javascript). diff --git a/_docs/20_script-settings/05_allow-url-parameters.md b/_docs/20_script-settings/05_allow-url-parameters.md index a40248d6..c5885770 100644 --- a/_docs/20_script-settings/05_allow-url-parameters.md +++ b/_docs/20_script-settings/05_allow-url-parameters.md @@ -3,7 +3,7 @@ title: Allow URL parameters category: script-settings permalink: /allow-params created_at: 2022-07-26 -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-29 --- By default, we collect all UTM parameters (with and without the `utm_` prefix) and the `ref` (which is short for `utm_source`) parameter: @@ -27,6 +27,6 @@ If you want to capture `product-id` and `article-slug` from your website's URLs, > ``` -> **Warning:** Defined parameters in `data-allow-params` are case-sensitive. +From script version 12, parameter names in `data-allow-params` are case-insensitive, so `product-id` also allows `Product-ID`. In older versions they are case-sensitive. Read more on [how to use URL parameters](/how-to-use-url-parameters) on your website. diff --git a/_docs/55_events/01_introduction.md b/_docs/55_events/01_introduction.md index a2b817be..6570d7ae 100644 --- a/_docs/55_events/01_introduction.md +++ b/_docs/55_events/01_introduction.md @@ -3,10 +3,10 @@ title: Introduction to events menu: Introduction category: events permalink: /events -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-29 --- -With events in Simple Analytics you can collect counts of certain events. Let's say, you want to record a button click, you can fire an event for that. To make it easier for non-developers, we created [an automated events script](/automated-events). This script collects events for downloads, outbound links, and clicks on email links. You will need to install our separate script for it, but after that you don't need to modify any code. +With events in Simple Analytics you can collect counts of certain events. Let's say, you want to record a button click, you can fire an event for that. To make it easier for non-developers, we created [an automated events script](/automated-events). This script collects events for downloads, outbound links, and clicks on email and phone links. You will need to install our separate script for it, but after that you don't need to modify any code. If you want to get your hands dirty, you can collect events for all kinds of custom events. Like form submits, button clicks, and many more. We created a simple video showing how to collect events in Simple Analytics. [Here you go](https://www.youtube.com/watch?v=CCvdgTReqms) @@ -64,7 +64,7 @@ To send metadata with your event, [check our metadata page](/metadata). ## Inline events helper -We created a simple helper script that allows you to use data attributes for events: +From script version 12, our main script supports data attributes for events: ```html See pricing @@ -143,4 +143,4 @@ If the `sa_event` variable is already in use you can change it with the `data-na ``` -The namespace also changes other variables. For example, `sa_metadata` becomes `ba_metadata` and `sa_loaded` becomes `ba_loaded`. The [`sa_pageview`](/trigger-custom-page-views#use-custom-collection-anyway) function keeps its name. If you use [automated events](/automated-events), add `data-sa-global="ba_event"` to the automated events script. +The namespace also changes other variables. For example, `sa_metadata` becomes `ba_metadata` and `sa_loaded` becomes `ba_loaded`. From script version 12, the [`sa_pageview`](/trigger-custom-page-views#use-custom-collection-anyway) function becomes `ba_pageview` too. Older versions keep `sa_pageview`. If you use [automated events](/automated-events), add `data-sa-global="ba_event"` to the automated events script. diff --git a/_docs/55_events/15_metadata.md b/_docs/55_events/15_metadata.md index d5034e05..2d709fde 100644 --- a/_docs/55_events/15_metadata.md +++ b/_docs/55_events/15_metadata.md @@ -3,7 +3,7 @@ title: Collect metadata category: events permalink: /metadata created_at: 2022-07-26 -last_modified_at: 2026-10-17 +last_modified_at: 2026-10-29 --- To collect additional data on top of [our collected metrics](/metrics), you can append metadata. With this feature you can specify specific parameters and it will be included in our database with your datapoints (events or page views). @@ -81,7 +81,9 @@ An example on how to to set metadata on the `window` object: ``` -Our script reads the `sa_metadata` object once, when it loads, and appends this metadata to every event and page view. Make sure to define it before the script loads. To change the metadata later, for example after a route change in a single page app, update the properties of the same object instead of assigning a new object: +Our script appends this metadata to every event and page view. From script version 12, it reads `sa_metadata` every time it sends data, so you can also assign a new object later, for example after a route change in a single page app. + +Older versions read the object once, when the script loads. With those, define it before the script loads and update the properties of the same object instead of assigning a new object: ```js sa_metadata.theme_color = "blue"; diff --git a/_docs/55_events/20-sa-link-event.md b/_docs/55_events/20-sa-link-event.md index cfd7cfe5..263e49d0 100644 --- a/_docs/55_events/20-sa-link-event.md +++ b/_docs/55_events/20-sa-link-event.md @@ -3,10 +3,10 @@ title: Collect events for link clicks category: events permalink: /events/custom-link-clicks menu: Custom link clicks -last_modified_at: 2022-07-18 +last_modified_at: 2026-10-29 --- -The [automated events script](/automated-events) does collect events for outbound links. It does not require any coding, just adding a script. You probably want to use [that script](/automated-events). +The [automated events script](/automated-events) does collect events for outbound links. It does not require any coding, just adding a script. You probably want to use [that script](/automated-events). From script version 12, you can also add a [`data-simple-event`](/events/inline) attribute to any link without extra code. If you want to collect events for other links or control a bit more on how it works, you can use the code below. Let's say you have a HTML page with this content: From 1a08fd8023b3258baab23525dfd317b6f7e06756 Mon Sep 17 00:00:00 2001 From: Conductor Adriaan Date: Thu, 29 Oct 2026 18:54:01 +0000 Subject: [PATCH 4/8] Qualify query names and keepalive, fix an article Co-Authored-By: Claude Opus 5.5 (1M context) --- _docs/10_general/03_how-to-use-url-params.md | 2 +- _docs/10_general/10_what_we_collect.md | 2 +- _docs/10_general/15_metrics.md | 2 +- _docs/20_install-script/00_v12.md | 4 ++-- _docs/20_install-script/02_custom.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_docs/10_general/03_how-to-use-url-params.md b/_docs/10_general/03_how-to-use-url-params.md index e01b89db..ddbc1dc4 100644 --- a/_docs/10_general/03_how-to-use-url-params.md +++ b/_docs/10_general/03_how-to-use-url-params.md @@ -43,7 +43,7 @@ The UTM codes will show up on the dashboard in the "Referrals" dropdown menu: [Read the UTM guide](https://buffer.com/library/utm-guide/) at Buffer to learn more about UTM codes. -We drop non-UTM parameters from the URLs. From script version 12, we do collect their names, like `gclid`, but never their values, so you can tell paid from organic traffic. You can turn this off with [ignore metrics](/ignore-metrics). If you want to allow more URL parameters, for example, `project-id`, use our [allow params](/allow-params)-feature. +We drop non-UTM parameters from the URLs. From script version 12, we do collect the names of parameters that have a value, like `gclid`, but not their values, so you can tell paid from organic traffic. You can turn this off with [ignore metrics](/ignore-metrics). If you want to allow more URL parameters, for example, `project-id`, use our [allow params](/allow-params)-feature. ### Forbidden characters diff --git a/_docs/10_general/10_what_we_collect.md b/_docs/10_general/10_what_we_collect.md index 2d7fa127..bd44d46e 100644 --- a/_docs/10_general/10_what_we_collect.md +++ b/_docs/10_general/10_what_we_collect.md @@ -131,7 +131,7 @@ None of these IDs are linked to a person or personal data, and none are stored o > We **partially collect** and **partially store** URLs -Too much information in the URL can be confusing and can make your stats messy. We only collect and store the first part of the URL. If an URL looks like this `https://example.com/index.html?search=keyword#top` we will only store `https://example.com/index.html`, also known as the protocol (`https`), hostname (`example.com`), and pathname (`/index.html`). From script version 12, we also collect the names of the URL parameters, like `search`, but never their values. Read more on [using URL parameters](/how-to-use-url-parameters). +Too much information in the URL can be confusing and can make your stats messy. We only collect and store the first part of the URL. If an URL looks like this `https://example.com/index.html?search=keyword#top` we will only store `https://example.com/index.html`, also known as the protocol (`https`), hostname (`example.com`), and pathname (`/index.html`). From script version 12, we also collect the names of URL parameters that have a value, like `search`, but not their values. Read more on [using URL parameters](/how-to-use-url-parameters). ### Referrers diff --git a/_docs/10_general/15_metrics.md b/_docs/10_general/15_metrics.md index fa66df21..4d2a0bad 100644 --- a/_docs/10_general/15_metrics.md +++ b/_docs/10_general/15_metrics.md @@ -39,7 +39,7 @@ To know where customers come from, we store the page's referrer. This means that For example `https://simpleanalytics.com/?utm_source=newsletter` -The part after the `?` is called [URL parameters](/how-to-use-url-parameters). We only keep the UTM codes (`utm_source`/`ref`, `utm_medium`, `utm_content`, `utm_campaign`, `utm_term`) and drop all other URL parameters, unless you [allow them](/allow-params). From script version 12, we also collect the names of the other parameters, never their values, unless you [ignore `querykeys`](/ignore-metrics). The UTM codes are something that the customer adds to the URLs. They are usually generic terms like "newsletter_may" or "twitter_campaign_2". Don't put personal data in UTM codes. [See below][5]. +The part after the `?` is called [URL parameters](/how-to-use-url-parameters). We only keep the UTM codes (`utm_source`/`ref`, `utm_medium`, `utm_content`, `utm_campaign`, `utm_term`) and drop all other URL parameters, unless you [allow them](/allow-params). From script version 12, we also collect the names of the other parameters that have a value, but not their values, unless you [ignore `querykeys`](/ignore-metrics). The UTM codes are something that the customer adds to the URLs. They are usually generic terms like "newsletter_may" or "twitter_campaign_2". Don't put personal data in UTM codes. [See below][5]. ### Unique diff --git a/_docs/20_install-script/00_v12.md b/_docs/20_install-script/00_v12.md index c354e904..2787b9cc 100644 --- a/_docs/20_install-script/00_v12.md +++ b/_docs/20_install-script/00_v12.md @@ -13,12 +13,12 @@ Our public script is now at v12. You get it automatically with `latest.js`. If y - [Inline events](/events/inline) are part of the main script: add `data-simple-event` to clicks and form submits, with `data-simple-event-*` attributes as metadata. Remove the separate `inline-events.js` script, otherwise events are counted twice. - Optional [404 detection](/events/inline#404-pages): `data-detect-404="true"` sends a `page_404` event. -- We collect the names of query parameters, never their values. For example, `gclid` tells paid from organic traffic. Opt out with [`data-ignore-metrics="querykeys"`](/ignore-metrics). +- We collect the names of query parameters that have a value. For example, `gclid` tells paid from organic traffic. We still only collect values of UTM codes, `ref`, and [allowed parameters](/allow-params). Opt out with [`data-ignore-metrics="querykeys"`](/ignore-metrics). - [Overwrite the referrer](/overwrite-referrer) with `data-referrer` or `sa_settings.referrer`. - Optional [time on page pings](/pings): `data-pings="5,60"` sends the visible time at those seconds. - [`sa_pageview(path, metadata, callback)`](/trigger-custom-page-views#use-custom-collection-anyway) has a callback that always runs, accepts a query string in the path, and follows a custom namespace (for example `ba_pageview`). - [Automated events](/automated-events) collect clicks on phone (`tel:`) links. -- Inline and automated events are sent with `fetch` and `keepalive`, so they are not lost when the visitor navigates away. +- Inline and automated events are sent with `fetch` and `keepalive`, so they are more likely to arrive when the visitor navigates away. ## Improvements and fixes diff --git a/_docs/20_install-script/02_custom.md b/_docs/20_install-script/02_custom.md index 61ebc18e..7d9cb942 100644 --- a/_docs/20_install-script/02_custom.md +++ b/_docs/20_install-script/02_custom.md @@ -49,7 +49,7 @@ You can read our source code [on GitHub](https://github.com/simpleanalytics/scri ## Use custom collection anyway -There might be situation where you don't want to auto collect page views. When you add the `data-auto-collect="false"` attribute, the script doesn't send page views by itself and you send them with the `sa_pageview` function. When you call this function, the script will send a page view with the path you give as a parameter. If you don't give a path it will use `window.location.pathname` as a default. This only works with `latest.js`, not with our [light script](/light). +There might be a situation where you don't want to auto collect page views. When you add the `data-auto-collect="false"` attribute, the script doesn't send page views by itself and you send them with the `sa_pageview` function. When you call this function, the script will send a page view with the path you give as a parameter. If you don't give a path it will use `window.location.pathname` as a default. This only works with `latest.js`, not with our [light script](/light). ```html ``` -If you added the beta `inline-events.js` script, remove it. Otherwise every event is sent twice. +The beta `inline-events.js` script no longer does anything, besides logging a warning in the browser console, so you can remove it. The beta also sent `page_404` events by default. To keep those, turn on [404 detection](#404-pages). ### Clicks From bd38a69becb46d9b19783719edbb471100b932a2 Mon Sep 17 00:00:00 2001 From: Conductor Adriaan Date: Thu, 29 Oct 2026 19:15:40 +0000 Subject: [PATCH 7/8] Remove the mentions of the beta inline events script Co-Authored-By: Claude Opus 5.5 (1M context) --- _docs/20_install-script/00_v12.md | 2 +- _docs/55_events/00_inline-events.md | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/_docs/20_install-script/00_v12.md b/_docs/20_install-script/00_v12.md index 82119114..843e510f 100644 --- a/_docs/20_install-script/00_v12.md +++ b/_docs/20_install-script/00_v12.md @@ -11,7 +11,7 @@ Our public script is now at v12. You get it automatically with `latest.js`. If y ## New features -- [Inline events](/events/inline) are part of the main script: add `data-simple-event` to clicks and form submits, with `data-simple-event-*` attributes as metadata. The beta `inline-events.js` script no longer does anything, so you can remove it. To keep its `page_404` events, add `data-detect-404="true"`. +- [Inline events](/events/inline) are part of the main script: add `data-simple-event` to clicks and form submits, with `data-simple-event-*` attributes as metadata. - Optional [404 detection](/events/inline#404-pages): `data-detect-404="true"` sends a `page_404` event. - We collect the names of query parameters that have a value. For example, `gclid` tells paid from organic traffic. We still only collect values of UTM codes, `ref`, and [allowed parameters](/allow-params). Opt out with [`data-ignore-metrics="querykeys"`](/ignore-metrics). - [Overwrite the referrer](/overwrite-referrer) with `data-referrer` or `sa_settings.referrer`. diff --git a/_docs/55_events/00_inline-events.md b/_docs/55_events/00_inline-events.md index b5b4a916..a7c34730 100644 --- a/_docs/55_events/00_inline-events.md +++ b/_docs/55_events/00_inline-events.md @@ -11,8 +11,6 @@ From script version 12, our main script sends an event when a visitor interacts ``` -The beta `inline-events.js` script no longer does anything, besides logging a warning in the browser console, so you can remove it. The beta also sent `page_404` events by default. To keep those, turn on [404 detection](#404-pages). - ### Clicks Add `data-simple-event="event_name"` to any clickable element: From 11b4dc4d9cf14548d107761b5d0edfc0bfbf6549 Mon Sep 17 00:00:00 2001 From: Conductor Adriaan Date: Thu, 29 Oct 2026 19:18:35 +0000 Subject: [PATCH 8/8] Remove the sa_pageview line from the v12 changelog Co-Authored-By: Claude Opus 5.5 (1M context) --- _docs/20_install-script/00_v12.md | 1 - 1 file changed, 1 deletion(-) diff --git a/_docs/20_install-script/00_v12.md b/_docs/20_install-script/00_v12.md index 843e510f..e2ba5ec7 100644 --- a/_docs/20_install-script/00_v12.md +++ b/_docs/20_install-script/00_v12.md @@ -16,7 +16,6 @@ Our public script is now at v12. You get it automatically with `latest.js`. If y - We collect the names of query parameters that have a value. For example, `gclid` tells paid from organic traffic. We still only collect values of UTM codes, `ref`, and [allowed parameters](/allow-params). Opt out with [`data-ignore-metrics="querykeys"`](/ignore-metrics). - [Overwrite the referrer](/overwrite-referrer) with `data-referrer` or `sa_settings.referrer`. - Optional [time on page pings](/pings): `data-pings="5,60"` sends the visible time at those seconds. -- [`sa_pageview(path, metadata, callback)`](/trigger-custom-page-views#use-custom-collection-anyway) has a callback that always runs, accepts a query string in the path, and follows a custom namespace (for example `ba_pageview`). - [Automated events](/automated-events) collect clicks on phone (`tel:`) links. - Inline and automated events use `fetch` with `keepalive` when the browser supports it, with an image request as fallback, so they are more likely to arrive when the visitor navigates away.