Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions _docs/10_general/03_how-to-use-url-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 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

Expand Down
6 changes: 3 additions & 3 deletions _docs/10_general/10_what_we_collect.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 URL parameters that have a value, like `search`. We don't collect their values, except for [UTM codes](#utm-parameters) and [allowed parameters](/allow-params). Read more on [using URL parameters](/how-to-use-url-parameters).

### Referrers

Expand Down Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions _docs/10_general/15_metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 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

Expand Down Expand Up @@ -89,7 +89,7 @@ To know which type of device the visitor used, we store the user agent. This is

<p class="rating"><svg xmlns="http://www.w3.org/2000/svg" width="16px" viewBox="0 0 24 24"><circle cx="12" cy="12" r="12" fill="#65aed7"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16px" viewBox="0 0 24 24"><circle cx="12" cy="12" r="12" fill="#65aed7"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16px" viewBox="0 0 24 24"><path fill="#65aed7" fill-rule="evenodd" d="M12 24a12 12 0 1 0 0-24 12 12 0 0 0 0 24Zm0-5a7 7 0 1 0 0-14 7 7 0 0 0 0 14Z" /></svg> Somewhat important</p>

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

Expand Down
34 changes: 34 additions & 0 deletions _docs/20_install-script/00_v12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
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.
- 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`.
- Optional [time on page pings](/pings): `data-pings="5,60"` sends the visible time at those seconds.
- [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.

## 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.
8 changes: 7 additions & 1 deletion _docs/20_install-script/01_script.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-29
---

Include these two lines on every page at the end of your `<body>` (or anywhere else):
Expand Down Expand Up @@ -86,6 +86,9 @@ 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` |
| `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.

Expand All @@ -101,6 +104,9 @@ 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
[15]: /overwrite-referrer

## Browser support

Expand Down
18 changes: 16 additions & 2 deletions _docs/20_install-script/02_custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 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
<script>
Expand Down Expand Up @@ -82,4 +82,18 @@ window.sa_pageview("/pricing", { plan: "pro" });

If you call `sa_pageview` with the same path as the previous page view, we don't send it again.

From script version 12:

- `sa_pageview` is also available when we collect page views automatically.
- You can pass a callback as the last argument. It runs after the page view is sent, and also when we skip it (for example, for the same path or an [ignored page](/ignore-pages)):

```js
window.sa_pageview("/pricing", { plan: "pro" }, function () {
window.location.href = "/checkout";
});
```

- You can add a query string to the path, for example `/pricing?utm_source=newsletter`. We treat it like the query string of a normal page view. The same path with a different query string counts as a new page view.
- With a [custom namespace](/events#the-variable-sa_event-is-already-used), the function uses that namespace, for example `ba_pageview`. `sa_pageview` stays available unless your website already uses that name.

If you encounter issues, don't hesitate to contact us via [our support channels](https://simpleanalytics.com/contact).
6 changes: 3 additions & 3 deletions _docs/20_install-script/19_sri.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions _docs/20_install-script/20_csp.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Content Security Policy
category: install-script
permalink: /csp
last_modified_at: 2022-07-14
last_modified_at: 2026-10-29
---

Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement to distribution of malware. [Read more on CSP at MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
Expand All @@ -24,10 +24,10 @@ Alternatively, a `<meta>` element can be used to configure a policy, for example
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' https://scripts.simpleanalyticscdn.com; connect-src 'self' https://queue.simpleanalyticscdn.com; img-src 'self' https://queue.simpleanalyticscdn.com https://simpleanalyticsbadges.com;">
```

Basically we use `https://scripts.simpleanalyticscdn.com` for our public script, `https://queue.simpleanalyticscdn.com` to send Beacon API data and error requests, and we use `https://queue.simpleanalyticscdn.com` also for sending data through our "pixel". If you show our badge, you need to have `https://simpleanalyticsbadges.com`.
Basically we use `https://scripts.simpleanalyticscdn.com` for our public script, `https://queue.simpleanalyticscdn.com` to send Beacon API data, events sent with `fetch`, and error requests, and we use `https://queue.simpleanalyticscdn.com` also for sending data through our "pixel". If you show our badge, you need to have `https://simpleanalyticsbadges.com`.

## Why `script-src 'unsafe-inline'`?

If you use the automated events, make sure to have `'unsafe-inline'` in your `script-src`, otherwise you can remove that from the examples above. We use `'unsafe-inline'` to add [`onClick`](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) event listeners to your download buttons, email links, and outbound links.
The examples include `'unsafe-inline'` for inline scripts on your page, like the [event placeholder function](/events#placeholder-event-function) or [`sa_settings`](/script#settings-via-javascript). Since script version 12, our scripts don't need it: the [automated events script](/automated-events) used to add [`onclick`](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) attributes to your download buttons, email links, and outbound links, but now it adds event listeners. If you don't use inline scripts, you can remove `'unsafe-inline'` from the examples above.

Don't forget to add your own assets to the above Content Security Policy.
6 changes: 3 additions & 3 deletions _docs/20_install-script/25_proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down
23 changes: 23 additions & 0 deletions _docs/20_script-settings/03_overwrite-referrer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: Overwrite referrer
category: script-settings
permalink: /overwrite-referrer
last_modified_at: 2026-10-29
created_at: 2026-10-29
---

From script version 12, you can overwrite the referrer of the first page view. This helps when the browser doesn't pass the original referrer but you know where the visitor came from, for example after a redirect through your own server.

Add the referrer URL to `data-referrer`:

```html
<script
async
data-referrer="https://example.com/newsletter"
src="https://scripts.simpleanalyticscdn.com/latest.js"
></script>
```

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).
Loading