[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)

# Events and users

> Record signups, purchases and anything worth counting with track(), conversions or HTML attributes, and link visits to your own users.

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

Page views, outbound links and file downloads are recorded on their own. Everything specific to your product, such as a signup, a checkout or a plan change, is a **custom event** you name.

## Custom events

```ts title="src/checkout.ts"
import { track } from '@invisitdev/web'

track('checkout_completed', { plan: 'pro', seats: 5, annual: true })
```

Events appear under **Events** in the dashboard with their properties, and can be steps in a [funnel](#funnels).

> [!TIP]
> Name events as `object_action` in the past tense (`signup_completed`, `invoice_paid`). The list stays sorted by object, and the name says what happened rather than what was clicked.

## Conversions

A conversion is an event that marks a goal reached, reported apart from ordinary events. Record one on the tracker `init()` returns:

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

const tracker = init({ site: '<site id>' })
tracker?.conversion('trial_started', { plan: 'growth' })
```

## Without JavaScript

Any element records an event when clicked, and any `<form>` when submitted, with data attributes. This works with the script tag as well as the package.

```html title="pricing.html"
<button data-invisit-event="pricing_cta" data-invisit-prop-plan="pro">Upgrade</button>

<form data-invisit-event="newsletter_signup">…</form>
```

Each `data-invisit-prop-<key>` attribute becomes a string property.

An event can also be defined as a rule instead of code: a click on an element matching a CSS selector, a form submit, or a visit to a URL pattern. Rules are managed through the [REST API](https://invisit.dev/docs/api/rest.md) (event definitions) or by an assistant over [MCP](https://invisit.dev/docs/api/mcp.md). The tracker fetches them when it starts, so a new rule needs no deploy.

## Names and properties

The tracker validates and cleans everything before it leaves the browser. Invalid input is dropped quietly, never thrown.

| Rule           | Limit                                                                                                               |
| -------------- | ------------------------------------------------------------------------------------------------------------------- |
| Event name     | 1 to 64 characters, `A-Z a-z 0-9 _ . : -`, starting with a letter or digit. An invalid name drops the event.        |
| Property key   | 1 to 40 characters, `A-Z a-z 0-9 _ . -`, starting with a letter or `_`. Keys starting with `invisit_` are reserved. |
| Property value | `string`, finite `number`, `boolean` or `null`. Strings are cut at 256 characters; other types are dropped.         |
| Properties     | At most 32 per event.                                                                                               |

To keep personal data out of your analytics, property keys that look sensitive (`password`, `token`, `email`, `phone` and similar) are dropped, and email addresses and long digit runs in string values are replaced with `[redacted]`.

## Identify signed-in users

Visits are anonymous by default. When someone signs in, link the visit to your own id for them:

```ts title="src/auth/session.ts"
import { identify } from '@invisitdev/web'

identify(user.id)
```

The id, up to 128 characters, is **hashed** on arrival and only the hash is kept, attached to the visit. Reports and raw exports carry that hash, never the id you sent, and the same id always gives the same hash on a site, so one signed-in person's visits line up across devices and days. Calls made before `init()` are queued, so it is safe to call from your auth code whenever the session is known.

> [!CAUTION]
> Pass an opaque id from your database. Never an email address, a name or any other personal data.

## Funnels

A funnel is a sequence of pages or custom events. The dashboard shows how many visits reached each step and where they dropped off, split by source, country or device if you like. Save the funnels you look at often; assistants can run them too through [MCP](https://invisit.dev/docs/api/mcp.md).

## From your server

When the thing worth counting happens on your server, such as a payment confirmed in a route handler, send the event from there with [`@invisitdev/server`](https://invisit.dev/docs/server/sdk.md#server-side-events). It joins the visit the visitor's browser started, and takes the same user id as `userId`.
