npm package: @self-vectra/sdk
Description: Vectra analytics browser SDK
Latest version: 0.2.10

# @self-vectra/sdk

Browser analytics SDK for [Vectra](https://github.com/yourorg/self-vectra) — self-hosted product analytics. Autocapture (pageview, clicks, forms), behavioral events (rage click, dead click, scroll depth), and metadata enrichment. Batches events and sends to your server.

## Install

```bash
npm install @self-vectra/sdk
```

Or load via script tag (global `Vectra`):

```html
<script src="https://unpkg.com/@self-vectra/sdk/dist/vectra.min.js"></script>
```

## Usage

### Vanilla / any framework

```js
import vectra from '@self-vectra/sdk';

vectra.init({
  apiKey: 'pk_test_xxxxxxxx',
  apiHost: 'https://vectra.yourdomain.com',
});

// Autocapture is on by default: pageview, click, form submit, history changes.
// Behavioral: rage click, dead click, scroll depth (25/50/75/100%).
// Optional: custom events and identify
vectra.track('signup', { plan: 'pro' });
vectra.identify('user_123');
vectra.page(); // manual page view if needed
vectra.flush(); // flush queue now
await vectra.shutdown(); // flush and stop (e.g. on app unload)
```

### Next.js (React)

Wrap your app with `VectraProvider` so the SDK initializes once on the client:

```js
// app/layout.tsx
import { VectraProvider } from '@self-vectra/sdk';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <VectraProvider
          apiKey="pk_test_xxx"
          apiHost="https://vectra.yourdomain.com"
        >
          {children}
        </VectraProvider>
      </body>
    </html>
  );
}
```

Then use `vectra` anywhere (e.g. in components or server components don’t run in browser, so use in client components):

```js
'use client';
import vectra from '@self-vectra/sdk';

vectra.track('button_clicked', { name: 'pricing_cta' });
```

## Configuration

| Option          | Type    | Default | Description |
|-----------------|---------|---------|-------------|
| `apiKey`        | string  | —       | **Required.** Project API key (ingest scope). |
| `apiHost`       | string  | —       | **Required.** Vectra server base URL (no trailing slash). |
| `flushInterval` | number  | 5000    | Ms between batch flushes. |
| `batchSize`     | number  | 20      | Max events per batch. |
| `maxRetries`    | number  | 3       | Retries with exponential backoff on send failure. |
| `debug`         | boolean | false   | Log send attempts and results to the console (for debugging). |
| `maskText`      | boolean | true    | Strip element text longer than 200 chars. |
| `maskInputs`    | boolean | true    | Never capture password, email, textarea. |
| `enableHeartbeat` | boolean | true  | Emit `$heartbeat` events while tab is visible (online detection). |
| `heartbeatIntervalMs` | number | 20000 | Heartbeat interval in milliseconds while visible. |

## Event types (autocapture + behavioral)

- **`$pageview`** — On load, `pushState`, `replaceState`, `popstate`. Properties: `page_url`, `pathname`, `referrer`, `title`.
- **`$click`** — Every click. Properties: `element_tag`, `element_text`, `element_id`, `element_class`, `element_href`, `css_selector`, `click_x`, `click_y`.
- **`$form_submit`** — Form submit. Properties: `form_id`, `form_action`, `form_method`, `input_count` (no input values).
- **`$rage_click`** — 3+ clicks within 1.5s and 30px. Properties: `click_count`, `element_selector`, `page_url`.
- **`$dead_click`** — Click with no navigation and no DOM change within 2s. Properties: `element_selector`, `page_url`.
- **`$scroll_depth`** — When user reaches 25%, 50%, 75%, 100%. Properties: `depth_percent`, `page_url`.
- **`$heartbeat`** — Emitted periodically while tab is visible. Properties: `reason`, `page_url`, `pathname`, `visibility_state`.

All events include **context**: `page_url`, `referrer`, `browser`, `os`, `device`, `screen_resolution`, `timezone`, `language`. Session ID (30min inactivity) and distinct ID are sent on every event. Geo is **not** captured in the browser; the server can enrich from IP (GeoIP).

## API

- **`init(config)`** — Initialize the SDK (call once). Enables autocapture and behavioral listeners.
- **`track(eventName, properties?)`** — Send a custom event.
- **`page(properties?)`** — Send a page view (also sent automatically on navigation).
- **`identify(distinctId)`** — Set user ID for subsequent events (stored in `localStorage`).
- **`flush()`** — Flush the queue immediately (returns a Promise).
- **`shutdown()`** — Flush remaining events and stop the timer (returns a Promise).
- **`getDistinctId()`** / **`getSessionId()`** — Read current IDs.

Events are sent as `POST /api/v1/event/batch` with header `X-API-Key`. Batches run every 5s or when the queue reaches 20 events, with up to 3 retries and exponential backoff.

## Debugging

- **Browser:** Set `debug: true` in `init()` to see `[Vectra]` logs in the console: when a batch is sent, success (status + `accepted` count), or failure (status/error and retries). Use this to confirm the SDK is sending and whether the server responds.
- **Server (Docker):** To see if requests reach the API, run `docker compose -f docker/docker-compose.yml logs api -f`. Each batch is logged as `event/batch received` with `project_id`, `accepted`, `requested`, and `origin`. If you see no such lines when the SDK sends, the request is not reaching the API (e.g. CORS, network, or wrong URL).

## License

MIT