> ## Documentation Index
> Fetch the complete documentation index at: https://highseat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Track events

> Send custom events such as signups and purchases with track() from the highseat package, type their names and properties, or tag elements in HTML.

Page views, outbound links, file downloads and a 404 on a full page load are tracked with no code. Anything else your site cares about, such as a signup, is a custom event you send.

## With the package

```ts theme={null}
import { identify, track } from "highseat"

track("signup")
track("purchase", { revenue: { amount: 4999, currency: "USD" }, order_id: order.id })
identify(user.id)
```

`revenue.amount` is an integer in the currency's smallest unit: 4999 is \$49.99. Event names are stored exactly as written, so `Purchase` and `purchase` are two events. A call made before the tracker has loaded waits for it, and no call ever throws.

## Typed events

A few names are built in, with typed properties: `signup`, `login`, `purchase`, `subscription_started`, `trial_started`, `file_download`, `outbound_link_click` and `404`. Declare your own in any file your compiler sees. With `strict: true`, a misspelt name is a type error.

```ts src/analytics.d.ts theme={null}
declare module "highseat" {
  interface Register {
    events: {
      signup: { plan: "free" | "pro" }
      invite_sent: { role: "admin" | "member" }
      [name: `view_${string}`]: { variant: string }
    }
    strict: true
  }
}
```

A key written as a template literal, such as `` `view_${string}` ``, covers every name it matches, so a name built at run time still compiles under `strict: true`. A call such as ``track(`view_${slug}`, { variant: "b" })`` checks its properties against the declaration. The declarations are types only and add nothing to your bundle.

## Typed tracked links

A link component that tracks a click can keep each event name paired with its properties. `EventName` lists every name `track()` knows, and `TrackArgs` gives the properties a name takes:

```tsx components/tracked-link.tsx theme={null}
import { type EventName, track, type TrackArgs } from "highseat"
import type { ComponentProps } from "react"

interface TrackedLinkProps<Name extends EventName> extends ComponentProps<"a"> {
  event: [name: Name, ...args: TrackArgs<Name>]
}

export function TrackedLink<Name extends EventName>({
  event,
  href,
  onClick,
  ...props
}: TrackedLinkProps<Name>) {
  const [name, ...args] = event

  return (
    <a
      href={href}
      {...props}
      onClick={clickEvent => {
        track(name, ...args)
        onClick?.(clickEvent)
      }}
    />
  )
}
```

```tsx theme={null}
<TrackedLink href="/pricing" event={["signup", { plan: "pro" }]}>
  Start free
</TrackedLink>
```

A link with the wrong properties for its event, or none where they are required, fails the type check.

## Without the package

On a site with the plain script tag, tag the element in HTML. A click on a link or a button sends the event, and a form sends it on submit. Each `data-highseat-prop-*` attribute becomes a property.

```html theme={null}
<button data-highseat-event="signup" data-highseat-prop-plan="pro">Start free</button>
```

From a script, call `window.highseat.track("signup", { plan: "pro" })` once the tracker has loaded.

## Check your calls

In development, the package logs every `track()` and `identify()` call to the browser console, with its properties. It also warns once per page when nothing can reach Highseat: the page has no tracker script, or the script failed to load, as one an ad blocker stopped does. Logging is on when `process.env.NODE_ENV` is `development`. Pass `debug` to `<Highseat />` to turn it on in a production build, or `debug={false}` to turn it off.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.