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

# Tracking

> An account's tracked audience: everyone its pixel has seen, and every event they performed. Scope it to a company with `accountId`, then mount `people`, `events`, or both — they read the same window and the same credit rule, so two surfaces side by side can never disagree about what they are showing. `links` wires their person links to your own pages.

<Info>**Upcoming.** These docs cover unreleased development, ahead of any published release. Use the channel picker at the top of the sidebar for the docs of a published release.</Info>

*In development, not yet part of a stable release.*

## Playground

Assemble the elements with sample data. Drive the controls, add and arrange elements, and watch events fire live:

<div data-whop-demo-shell style={{ position: "relative", minHeight: "480px", transition: "min-height 200ms ease" }}>
  <div data-whop-demo-skeleton style={{ position: "absolute", inset: "0", borderRadius: "12px", background: "rgba(140, 140, 140, 0.12)", pointerEvents: "none", transition: "opacity 200ms ease" }} />

  <div data-whop-demo-native="playground:tracking" data-whop-elements-version="" style={{ position: "relative" }} />
</div>

## Usage

<div data-whop-usage="tracking/playground">
  <CodeGroup>
    ```tsx React theme={null}
    import { WhopElements, Tracking } from "@whop/elements-react";
    import { loadWhop } from "@whop/elements";

    function Example() {
      return (
        <WhopElements elements={loadWhop()}>
          <Tracking /* options */>
            {/* mount elements here */}
          </Tracking>
        </WhopElements>
      );
    }
    ```

    ```html Vanilla theme={null}
    <script src="https://js.whop.cloud/elements/amber/elements.js" data-whop-elements></script>
    <script type="module">
      const tracking = window.WhopElements().tracking.create({ /* options */ });
    </script>
    ```
  </CodeGroup>
</div>

## Options

Pass these to `whop.tracking.create({ … })`, or as props on `<Tracking>` in React.

<ResponseField name="accountId" type="string">
  The company (`biz_…`) whose people and events this reads. Required. Defaults to `""`.
</ResponseField>

<ResponseField name="accessToken" type="string">
  A scoped token both surfaces read with. Mint ONE token for the whole handle on your server with `POST /v1/access_tokens`, and set a fresh one with `update({ accessToken })` before it expires. Reading the lists needs `member:basic:read` or `company:basic:read`; the filter menus' option counts additionally use `stats:read`, and the People table's saved-audience filter uses `audience:basic:read` — without those the menus simply show fewer options. Omitted, the calls carry the viewer's own session, which only answers same-origin.
</ResponseField>

<ResponseField name="links" type="CrossLinksConfig">
  Where person links lead on YOUR site. `person` is an absolute-URL template with two placeholders, each replaced URL-encoded per row: `{personId}` is the stable `per_…` id, identical for the same person on every surface — key your page on it; `{identifier}` is the most human-meaningful identifier the surface has (a user id or email where known), so it can differ across surfaces. It must be absolute (`https://…`) — inside an element frame a relative URL would resolve against the frame, so one is treated as unset. Unset, a person click raises `personOpened` on its element instead. `people` and `events` base URLs are accepted for symmetry with the ads handle but nothing under this handle renders them. Defaults to `{}`.
</ResponseField>

<ResponseField name="period" type="&#x22;today&#x22; | &#x22;yesterday&#x22; | &#x22;last_7_days&#x22; | &#x22;last_14_days&#x22; | &#x22;last_30_days&#x22; | &#x22;last_90_days&#x22; | &#x22;all_time&#x22; | &#x22;custom&#x22;">
  The window both surfaces cover: `today`, `yesterday`, `last_7_days`, `last_14_days`, `last_30_days`, `last_90_days`, `all_time`, or `custom` (pair it with `customRange`). The elements carry the picker and move this; read it back off `periodChanged`. Defaults to `"last_14_days"`.
</ResponseField>

<ResponseField name="customRange" type="{ from: string; to: string; } | null">
  The explicit window, as ISO 8601 instants, used when `period` is `custom`. Ignored otherwise. Defaults to `null`.
</ResponseField>

<ResponseField name="timezone" type="&#x22;account&#x22; | &#x22;local&#x22;">
  Which of two zones the window resolves in: `account`, the account's own scheduling zone, or `local`, whichever zone the viewer's browser is in. `account` falls back to the viewer's own when the account has set none. Defaults to `"account"`.
</ResponseField>

<ResponseField name="attributionModel" type="&#x22;last_touch&#x22; | &#x22;first_touch&#x22;">
  Which touch in a person’s journey gets the credit when filtering by source: `last_touch`, the default, or `first_touch`. The elements carry the picker and move this, so a host can drive it and read it back off `attributionModelChanged`. Defaults to `"last_touch"`.
</ResponseField>

<ResponseField name="appearance" type="Appearance">
  Visual customization for this group's elements. Overrides the global `WhopElements({ appearance })`; change it live with `update({ appearance })`.
</ResponseField>

<ResponseField name="locale" type="WhopElementsLocale">
  Locale for this group's element UI text. One of the app's built locales, overriding the global config; any other value falls back to the default locale.
</ResponseField>

## Events

Pass a callback in the create options / React props.

### `onLoadingChange`

Fired when the grouped loading state changes. `true` while any mounted element is still loading.

**Signature:** `((loading: boolean) => void)`

## Methods

Call these on the Tracking handle, which is the return of `whop.tracking.create({ … })` (vanilla) or `useTracking()` (React).

### `update`

Update the handle live: any of its options (`appearance` and `locale` included), propagated to every mounted element. React consumers never call it; updating the namespace component's props does the same.

**Signature:** `(options: Partial<TrackingOptions>) => void`

## Returned objects

Live objects returned by the methods above. Hold the reference and call it on your page; these are capabilities, not serializable data.

## `CrossLinksConfig`

The consumer-facing shape of an element's `links` prop. `people`/`events` are base URLs the canonical query params are appended to; `person` is a template whose `{personId}` and `{identifier}` placeholders are replaced with the row's URL-encoded values.

### `people`

**Signature:** `string | undefined`

### `events`

**Signature:** `string | undefined`

### `person`

**Signature:** `string | undefined`

## `PeopleFilterBag`

The element's consumer filter vocabulary — camelCase twins of the flat `/v1/people` params.

### `source`

**Signature:** `string`

### `eventName`

**Signature:** `string`

### `customEvent`

**Signature:** `string`

### `utmSource`

**Signature:** `string`

### `country`

**Signature:** `string`

### `device`

**Signature:** `string`

### `browser`

**Signature:** `string`

### `os`

**Signature:** `string`

### `hasPurchased`

**Signature:** `string`

### `query`

**Signature:** `string`

### `audienceId`

**Signature:** `string`

### `eventFrom`

**Signature:** `string`

### `eventTo`

**Signature:** `string`

## `EventsFilterBag`

The element's consumer filter vocabulary — camelCase twins of the flat `/v1/events` params.

### `identifier`

**Signature:** `string`

### `event`

**Signature:** `string`

### `source`

**Signature:** `string`

### `country`

**Signature:** `string`

### `utmSource`

**Signature:** `string`

### `device`

**Signature:** `string`

### `browser`

**Signature:** `string`

### `os`

**Signature:** `string`

### `from`

**Signature:** `string`

### `to`

**Signature:** `string`

## Elements

The elements this group mounts. Each has its own page:

<CardGroup cols={2}>
  <Card title="PeopleElement" href="/elements/upcoming/tracking/people">
    Everyone the account has seen — visitors and customers resolved from pixel activity, with their source, spend and activity counters. Search, filter by source, event, geography or device, sort any column, and page through. A row click follows `links.person` when the handle configures it, and otherwise comes back to you as `personOpened`.
  </Card>

  <Card title="EventsElement" href="/elements/upcoming/tracking/events">
    Every event the account measured — page views, leads, purchases and custom pixel events — as a raw, filterable stream. The rows behind any metric: filter by event, source, geography or device over the handle’s window, or search one person’s identifier to read their whole journey. A person cell follows `links.person` when the handle configures it, and otherwise comes back to you as `personOpened`.
  </Card>
</CardGroup>
