[invisit](https://invisit.dev) · [Docs](https://invisit.dev/docs) · [llms.txt](https://invisit.dev/llms.txt) · [llms-full.txt](https://invisit.dev/llms-full.txt)

# Privacy and exclusions

> How invisit counts visitors without cookies, how to gate tracking behind consent, and how to keep your own visits and internal pages out.

Source: https://invisit.dev/docs/guides/privacy

invisit measures without cookies or device identifiers. Visitors are told apart with a hash that mixes in a fresh random salt for each UTC day, so a visitor cannot be followed from one day to the next by anything stored on their device. Each day's salt is deleted automatically about 25 hours after the day ends, once its late events can no longer arrive, and from then on nobody, invisit included, can recompute that day's hashes. Only two choices are ever kept on the device: a consent answer you set, and a site owner's own opt-out. `storage: 'none'` keeps even those off.

## What is kept out

- Sensitive query parameters (`token`, `code`, `email`, `password`, `state` and similar, plus any you add under **Settings → Collection**) are stripped from recorded URLs, along with the fragment and any credentials.
- Property keys that look sensitive are dropped, and email addresses and long digit runs in values become `[redacted]`.
- Optionally, browsers that send [Global Privacy Control](https://globalprivacycontrol.org) or Do Not Track can be left out: turn on `respectGpc` or `respectDnt` (`data-respect-gpc` or `data-respect-dnt` on the script tag). Both are off unless you set them, so those browsers are measured like any other. For server events, pass `respectGpc: true` to `createInvisit` in the [server SDK](https://invisit.dev/docs/server/sdk.md).

Analytics data is kept forever on every plan, except that a free site with no events for about six months is [cleaned up](https://invisit.dev/docs/guides/billing.md#inactive-free-sites). Deleting a site deletes its analytics; see [Workspaces](https://invisit.dev/docs/guides/workspaces.md#deleting).

## Requiring consent

Where your policy needs consent first, start the tracker with `requireConsent` and answer from your banner:

```ts title="src/consent.ts"
import { consent, init } from '@invisitdev/web'

init({ site: '<site id>', requireConsent: true })

// from your consent banner
consent('granted')
```

Nothing is sent until `'granted'`. `consent('denied')` stops all collection, and `'unknown'` forgets the answer. The answer is remembered on the device unless `storage: 'none'`. With the script tag, set `data-require-consent="true"`.

To keep nothing on the device at all, start with `storage: 'none'`. The consent answer and the owner opt-out are then not remembered between page loads.

## Excluding traffic

### Your own visits

Open any page of your site with `#invisit-ignore` at the end of the address. That browser stops being counted, on every page, until you open a page with `#invisit-unignore`. The choice is kept on the device, unless the tracker runs with `storage: 'none'`. Do it once in each browser you use, including on your phone.

### Paths

All paths are tracked by default. List the ones that never should be:

```ts title="src/main.ts"
init({ site: '<site id>', excludePaths: ['/admin/*', '/health'] })
```

With the script tag, the same list goes in `data-exclude-paths="/admin/*,/health"`.

- An exact path matches only itself: `/health` excludes `/health`, not `/health/db`.
- One trailing `*` matches any suffix: `/admin/*` excludes everything under `/admin/`.
- Matching is case-sensitive and uses the pathname only, without query or fragment.

An excluded path sends no events or heartbeats and loads no optional tracker modules. Tracking resumes as soon as client-side navigation reaches an allowed path, and the setting applies before the first page view, even when the tracker configuration was cached.

### Bots

Visits from bots are never counted as visitors. The script sends nothing from a browser driven by automation, such as Playwright, Puppeteer, Selenium or Lighthouse, where `navigator.webdriver` is true; the `debug` option lifts that for your own tests. Crawler reads, such as search engines and AI crawlers fetching your pages, are their own report, recorded on your server with [`@invisitdev/server`](https://invisit.dev/docs/server/sdk.md#crawler-reads).
