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

# JavaScript API

> Once the script is on the page it exposes a global window.clickbase you can call from your own code — to send custom events, report revenue, identify visitors,

Once the [script](/install/script) is on the page it exposes a global `window.clickbase` you can call from your own code — to send custom events, report revenue, identify visitors, drive pageviews manually, report errors, and control session replay.

## The queue: safe to call before load

The snippet installs a tiny **stub** synchronously, then loads the real widget asynchronously. The stub queues any call you make and the widget drains the queue once it finishes loading, so **you never have to wait** — call `clickbase.*` as soon as the snippet tag is in the page.

Two methods are synchronous **getters** that must return a value immediately, so before the widget has loaded they return a safe default:

* `getVisitorId()` returns `null` until loaded.
* `getSessionId()` returns `null` until loaded.
* `isSessionReplayActive()` returns `false` until loaded.

Every other method is queued and runs in order once the widget is ready.

## Methods

### `event(name, options?)`

Record a custom event.

```js theme={null}
clickbase.event('signup', { props: { plan: 'pro' } });
```

| Argument  | Type                            | Description                                  |
| --------- | ------------------------------- | -------------------------------------------- |
| `name`    | `string`                        | The event name.                              |
| `options` | [`EventOptions`](#eventoptions) | Optional properties, callback, url, revenue. |

Reserved names are refused (see [Reserved names](#reserved-names)).

### `sale(name, revenue, options?)`

Report a one-off, **client-reported** sale. Revenue is a **required** positional argument.

```js theme={null}
clickbase.sale('purchase', { amount: 4990, currency: 'USD' });
```

| Argument  | Type                                          | Description                                            |
| --------- | --------------------------------------------- | ------------------------------------------------------ |
| `name`    | `string`                                      | The goal name to attribute to.                         |
| `revenue` | [`RevenuePayload`](#revenuepayload)           | **Required.** Integer minor units + ISO 4217 currency. |
| `options` | [`RevenueEventOptions`](#revenueeventoptions) | Optional `props` / `callback`.                         |

### `subscription(name, revenue, options?)`

Report a recurring-flavored **client-reported** revenue event. Same mechanics as `sale()`; the name is for readability — it cannot represent a real subscription lifecycle (only Stripe can). Revenue is **required**.

```js theme={null}
clickbase.subscription('pro-plan', { amount: 2900, currency: 'USD' });
```

Reported revenue from `sale()` / `subscription()` / `event({ revenue })` attaches to **goals** for attribution — it is never treated as verified money and never reaches the Revenue page or MRR. See [Track revenue](/track-revenue) and [Revenue](/api/revenue).

### `identify(payload, callback?)`

Associate the current visitor with a known identity (a "site user"). See [People](/api/people).

```js theme={null}
clickbase.identify({
  identifier: 'user_123',
  name: 'Ada Lovelace',
  avatar: 'https://example.com/ada.png',
  custom: { plan: 'pro' },
});
```

| Argument   | Type                                    | Description                        |
| ---------- | --------------------------------------- | ---------------------------------- |
| `payload`  | [`IdentifyPayload`](#identifypayload)   | The visitor's identity.            |
| `callback` | [`DeliveryCallback`](#deliverycallback) | Optional delivery-result callback. |

### `pageview(options?)`

Record a pageview manually. Useful with `data-manual="true"`, which turns off all automatic pageviews (see [Pageviews & SPAs](/widget/pageviews)).

```js theme={null}
clickbase.pageview();
clickbase.pageview({ url: '/virtual/checkout-step-2' });
```

`options` is an [`EventOptions`](#eventoptions); the `url` field overrides the recorded path.

### `error(error, context?)`

Report an error manually. No-op unless error tracking is enabled for the site (`track_errors`).

```js theme={null}
try {
  doRisky();
} catch (e) {
  clickbase.error(e, { where: 'checkout' });
}
```

| Argument  | Type                          | Description                                |
| --------- | ----------------------------- | ------------------------------------------ |
| `error`   | `unknown`                     | An `Error` instance, string, or any value. |
| `context` | [`PropertyMap`](#propertymap) | Optional extra properties.                 |

Unhandled errors and promise rejections are captured automatically when `track_errors` is on — see [Error tracking](/api/errors).

### `startSessionReplay()` / `stopSessionReplay()`

Manually start or stop recording the current session for replay.

```js theme={null}
clickbase.startSessionReplay();
clickbase.stopSessionReplay();
```

`startSessionReplay()` is a no-op unless session replay is enabled for the site (`track_session_replay`) **and** the current session is within the configured sample rate.

### `isSessionReplayActive()`

Returns `boolean` — whether replay is currently recording. Synchronous; returns `false` before the widget has loaded.

```js theme={null}
if (clickbase.isSessionReplayActive()) { /* ... */ }
```

### `getVisitorId()`

Returns `string | null` — the current visitor id, or `null` before the widget has loaded and in cookieless mode where no id is stored. Synchronous.

```js theme={null}
const visitorId = window.clickbase.getVisitorId();
```

The main use is bridging a server-side Stripe checkout back to the visit that earned it — see [Track revenue → Attribute a Stripe checkout](/track-revenue).

### `getSessionId()`

Returns `string | null` — the current analytics session id (`_cb_sid`), or `null` before the widget has loaded and in cookieless mode. Synchronous. Sliding inactivity window matches the product-wide session duration (`config('clickbase.session_duration_minutes')`, default 30 minutes).

```js theme={null}
const sessionId = window.clickbase.getSessionId();
```

Optional companion to `getVisitorId()` on Stripe Checkout / PaymentIntent metadata as `clickbase_session_id`. Visitor remains the primary attribution join key.

## Types

### `PropertyMap`

```ts theme={null}
type PropertyMap = Record<string, string | number | boolean>;
```

### `RevenuePayload`

Integer **minor units** (cents), not dollars — `$49.90` is `4990`.

```ts theme={null}
interface RevenuePayload {
  amount: number;   // integer minor units
  currency: string; // ISO 4217, e.g. "USD"
}
```

### `EventOptions`

```ts theme={null}
interface EventOptions {
  props?: PropertyMap;        // custom properties
  callback?: DeliveryCallback; // delivery result
  url?: string;               // override the recorded path (pageview)
  revenue?: RevenuePayload;   // attach reported revenue to a goal
}
```

### `RevenueEventOptions`

Options for `sale()` / `subscription()` — revenue is a required positional argument on those methods, so it is not part of these options.

```ts theme={null}
interface RevenueEventOptions {
  props?: PropertyMap;
  callback?: DeliveryCallback;
}
```

### `IdentifyPayload`

```ts theme={null}
interface IdentifyPayload {
  identifier: string;   // your stable id for the visitor
  name?: string;
  avatar?: string;
  custom?: PropertyMap;
}
```

### `DeliveryCallback`

Called with the outcome of the network delivery.

```ts theme={null}
type DeliveryCallback = (result: DeliveryResult) => void;

interface DeliveryResult {
  status?: number | 'ignored'; // HTTP status, or 'ignored' when the hit was filtered
  error?: unknown;
}
```

## Reserved names

`event()`, `sale()`, and `subscription()` all **refuse** the event names Clickbase writes only from trusted server sources, so a browser can never forge verified revenue. A refused call sends no beacon, logs a `console.warn`, and fires the delivery callback with `status: 'ignored'`. The reserved names (case-insensitive) are:

`payment`, `free_trial`, `trial_started`, `trial_converted`, `subscription_started`, `subscription_renewed`, `subscription_upgraded`, `subscription_downgraded`, `subscription_cancel_scheduled`, `subscription_reactivated`, `subscription_ended`.

See [Track revenue](/track-revenue) for why these are locked, and [Goals](/api/goals) for the matching server-side rule.
