kromemo
Version:
Browser event capture SDK for Kromemo: batching, retries, dedupe, TypeScript-first.
238 lines (174 loc) • 5.6 kB
Markdown
# Kromemo Browser SDK
A lightweight, high-performance browser SDK for sending events to your Kromemo ingest endpoint. Built for reliability (batching + retries), graceful shutdown, and TypeScript-first DX.
[](https://www.npmjs.com/package/kromemo)
[](https://www.npmjs.com/package/kromemo)
[](https://bundlephobia.com/package/kromemo)
[](#)
## Features
- **Zero Dependencies**: Small footprint for minimal impact on bundle size.
- **Smart Batching**: Configurable byte-size limits and periodic flushing.
- **Reliable Delivery**: Automatic retries with exponential backoff for transient failures.
- **Graceful Shutdown**: Ensures pending events are sent when the user leaves the page using `sendBeacon` or `fetch` with `keepalive`.
- **Type Safety**: First-class TypeScript support for a robust development experience.
- **Data Sanitization**: Automatically handles circular references and truncates long strings.
### Why Kromemo?
- ~4.4 kB min+gzip, zero dependencies (bundlephobia).
- Tree-shakeable (`sideEffects: false`) with ESM/CJS/UMD builds.
- Built for modern SPAs: dedupe window for React Strict Mode, byte/queue limits to protect the main thread, beacon fallback on unload.
- Clean ingest contract: `POST /{projectId}/events` with `x-api-ingest-key` header.
## Installation
```bash
npm install kromemo
# or
pnpm add kromemo
# or
yarn add kromemo
```
### CDN (UMD)
```html
<script src="https://unpkg.com/kromemo/dist/index.umd.js"></script>
<script>
window.kromemo.init({ projectId: 'pub_xxx', apiKey: 'kro_abcdef' });
</script>
```
## Quick Start
```ts
import kromemo from 'kromemo';
// Initialize the SDK
kromemo.init({
projectId: 'pub_xxx',
apiKey: 'kro_abcdef...',
endpointBase: 'https://metrics.your-domain.com', // Optional
});
// Track a page view
kromemo.trackView({ name: 'Home', url: '/home' });
// Track a custom event
kromemo.trackEvent({
name: 'clicked_buy',
payload: { plan: 'pro', value: 99 },
});
// Track an error
try {
throw new Error('Something went wrong');
} catch (err) {
kromemo.trackError({ error: err, payload: { context: 'checkout' } });
}
```
### React / Next.js
```tsx
import { useEffect } from 'react';
import kromemo from 'kromemo';
export default function AppLayout({ children }) {
useEffect(() => {
const { deviceId } = kromemo.init({
projectId: process.env.NEXT_PUBLIC_KROMEMO_PROJECT_ID!,
apiKey: process.env.NEXT_PUBLIC_KROMEMO_API_KEY!,
endpointBase: process.env.NEXT_PUBLIC_KROMEMO_ENDPOINT, // optional
dedupeWindowMs: 1000,
});
console.info('kromemo device', deviceId);
kromemo.trackView();
}, []);
return children;
}
```
## API Reference
### `init(options)`
Initializes the SDK. Must be called before tracking any events.
```ts
init(options: KromemoInitOptions): { deviceId: string }
```
#### Options
| Option | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `projectId` | `string` | **Required** | Your project's public identifier. |
| `apiKey` | `string` | **Required** | Public API key sent via `x-api-ingest-key`. |
| `endpointBase` | `string` | — | Base URL for the ingest endpoint. |
| `maxBatchSize` | `number` | `100` | Maximum number of events per batch. |
| `maxQueueBytes` | `number` | `500,000` | Maximum size of the memory queue in bytes. |
| `flushIntervalMs` | `number` | `5000` | Interval in milliseconds to flush the queue. |
| `retryMaxAttempts` | `number` | `3` | Maximum retry attempts for transient errors. |
| `dedupeWindowMs` | `number` | `0` | Time window (ms) to drop duplicate events (same type/name/url). |
### `trackEvent(input)`
Tracks a custom event.
```ts
trackEvent(input: {
name: string;
payload?: Record<string, any>;
ts?: number | string;
}): void
```
### `trackView(input)`
Tracks a page view.
```ts
trackView(input?: {
name?: string;
url?: string;
payload?: Record<string, any>;
}): void
```
### `trackError(input)`
Tracks an error.
```ts
trackError(input: {
error: Error | string;
payload?: Record<string, any>;
}): void
```
### `flush()`
Forces the queue to send all pending events immediately.
```ts
flush(): Promise<void>
```
### `shutdown()`
Stops the queue and cleans up resources.
```ts
shutdown(): void
```
## Advanced Usage
### Deduplication
To prevent duplicate events (e.g., from React Strict Mode double-invocations), you can enable client-side deduplication.
```ts
kromemo.init({
projectId: '...',
apiKey: '...',
dedupeWindowMs: 1000, // Drop duplicates within 1 second
});
```
### HTTP Contract
Events are sent via `POST` to `{endpointBase}/{projectId}/events`.
**Headers:**
- `Content-Type: application/json`
- `x-api-ingest-key: <your-public-api-key>`
**Body:**
```json
{
"events": [
{
"name": "event_name",
"type": "event",
"ts": 1730394050000,
"device_id": "generated_uuid",
"url": "https://...",
"os": "macOS",
"country": "US",
"payload": { ... }
}
]
}
```
## Projects Admin UI
This repository includes a lightweight admin UI for managing projects.
1. Open `examples/projects/index.html` in your browser.
2. Configure your API endpoint and credentials.
3. Manage your projects directly.
## License
MIT