Skip to content

Track Custom Events

Kitbase lets you track custom events with rich metadata to understand what your users are doing, monitor business metrics, and trigger real-time notifications. Events are sent asynchronously to the Kitbase API and processed in the background.

All events are sent via POST /sdk/v1/logs with API key authentication (X-API-Key header) and return 202 Accepted for async processing.

Basic Usage

typescript
import { init } from '@kitbase/analytics';

const kitbase = init({ sdkKey: 'YOUR_SDK_KEY' });

await kitbase.track({
  channel: 'payments',
  event: 'Purchase Completed',
  tags: {
    amount: 99.99,
    currency: 'USD',
    plan: 'premium'
  }
});

Track Options

The track method accepts a TrackOptions object with the following fields:

typescript
interface TrackOptions {
  channel: string;              // Required: event category (e.g., 'payments', 'users', 'errors')
  event: string;                // Required: event name (e.g., 'Purchase Completed')
  user_id?: string;             // Optional: explicit user identifier
  icon?: string;                // Optional: emoji icon for dashboard
  notify?: boolean;             // Optional: trigger real-time notification
  description?: string;         // Optional: human-readable event description
  tags?: Record<string, unknown>; // Optional: metadata (string, number, boolean values)
}
ParameterTypeRequiredDescription
channelstringYesCategory for the event (e.g., "payments", "users")
eventstringYesName of the event (e.g., "Purchase Completed")
user_idstringNoExplicit user identifier
iconstringNoEmoji icon displayed in the dashboard
notifybooleanNoTrigger a real-time notification
descriptionstringNoHuman-readable event description
tagsobjectNoKey-value metadata (string, number, boolean)

Response

A successful call returns a TrackResponse with the event's unique identifier and timestamp:

typescript
interface TrackResponse {
  id: string;        // Unique event ID (UUID)
  event: string;     // Event name
  timestamp: string; // ISO 8601 timestamp
}

Channels

Channels organize your events into logical categories. Use consistent channel names across your application to keep your dashboard clean and filterable.

ChannelUse Case
paymentsPurchases, refunds, subscription changes
usersSignups, logins, profile updates
errorsApplication errors, failed requests
notificationsAlerts, messages, delivery status
apiAPI calls, webhooks, integrations
systemInfrastructure events, deployments

You are not limited to these defaults. Custom channels are fully supported -- use whatever names make sense for your domain.

Channel Naming

Use lowercase, plural nouns for channel names (e.g., payments, errors, users). This keeps your events organized and easy to filter in the dashboard.

Tags

Tags are key-value metadata attached to events. They allow you to store additional context that you can filter and analyze later.

Supported Types

TypeExample
string"premium"
number99.99
booleantrue

Example

typescript
tags: {
  plan_name: 'premium',      // string
  amount: 99.99,             // number
  is_upgrade: true,          // boolean
}

Tag Naming

Use snake_case for tag names:

  • plan_name, user_type, error_code
  • Not: PlanName, planName, ERROR-CODE

Server-Side Tag Enrichment

The Kitbase backend automatically enriches every event with additional context derived from the request. These enriched fields are prefixed with __ and stored as dedicated columns, available as first-class filter dimensions in the dashboard.

Browser and Device

TagDescription
__browserBrowser name (Chrome, Firefox, Safari)
__browser_versionBrowser version
__osOperating system (Windows, macOS, iOS)
__os_versionOS version
__deviceDevice type (desktop, mobile, tablet)
__brandDevice brand (Apple, Samsung, Google)
__modelDevice model (iPhone 15, Pixel 8)

Geolocation

TagDescription
__countryCountry (derived from IP)
__regionRegion or state
__cityCity

Page and Attribution

TagDescription
__pathPage path
__referrerReferrer URL
__utm_sourceUTM source parameter
__utm_mediumUTM medium parameter
__utm_campaignUTM campaign parameter
__utm_termUTM term parameter
__utm_contentUTM content parameter

Query Filters

These enriched fields are available as filter dimensions in the dashboard. Filter events by browser, country, device, UTM parameters, and more directly from the events list.

Notifications

When notify: true is set, the event triggers a real-time notification in the Kitbase dashboard. Combine with icon and description to make notifications informative at a glance.

typescript
await kitbase.track({
  channel: 'payments',
  event: 'Large Purchase',
  icon: '💰',
  notify: true,
  description: 'A customer just made a $500+ purchase',
  tags: { amount: 549.99 }
});

Good candidates for notifications:

  • New signups and subscriptions
  • Failed payments and billing issues
  • Critical application errors
  • Security events (login from new device)
  • Large or unusual transactions

Revenue Tracking

Track revenue with the dedicated trackRevenue method. Revenue events are automatically sent to the __analytics channel.

typescript
await kitbase.trackRevenue({
  amount: 99.99,
  currency: 'USD',
  orderId: 'order_123',
  productId: 'prod_premium',
  tags: { plan: 'premium' }
});

This provides structured revenue data in the dashboard, separate from general custom events, so you can track MRR, ARPU, and other financial metrics out of the box.

Timed Events

Measure how long user flows take by starting a timer and letting the SDK automatically attach the duration when the event is tracked.

typescript
// Start timing
kitbase.timeEvent('Checkout Flow');

// ... user completes checkout ...

// Track with automatic $duration tag (in milliseconds)
await kitbase.track({
  channel: 'conversions',
  event: 'Checkout Flow',
  tags: { items: 3 }
});
// The $duration tag is automatically added to the event

Methods

MethodDescription
timeEvent(eventName)Start timing an event
cancelTimeEvent(eventName)Cancel a timed event without tracking
getTimedEvents()Get list of event names currently being timed
getEventDuration(eventName)Get current elapsed duration in milliseconds

Example

typescript
// Check active timers
const activeTimers = kitbase.getTimedEvents();
// => ['Checkout Flow', 'Video Watched']

// Get duration without tracking
const duration = kitbase.getEventDuration('Checkout Flow');
// => 45000 (ms)

// Cancel a timer
kitbase.cancelTimeEvent('Video Watched');

Super Properties

Super properties are automatically included with every event you track. They are useful for attaching persistent context like app version, environment, or user segment.

typescript
// Register properties (overwrites existing)
kitbase.register({ app_version: '2.1.0', environment: 'production' });

// Register only if not already set
kitbase.registerOnce({ first_visit_source: 'google' });

// Remove a specific super property
kitbase.unregister('first_visit_source');

// Get all registered super properties
kitbase.getSuperProperties();

// Clear all super properties
kitbase.clearSuperProperties();

Methods

MethodDescription
register(properties)Set properties (overwrites existing)
registerOnce(properties)Set properties only if not already set
unregister(key)Remove a specific property
getSuperProperties()Get all registered properties
clearSuperProperties()Remove all super properties

In-Memory Storage

Super properties are stored in memory and reset on page reload. For persistent properties, store them externally (e.g., localStorage) and call register() on initialization.

Data Attribute Events

Track events declaratively from HTML without writing JavaScript. The SDK automatically binds event listeners based on data-kb-* attributes.

Click Tracking

html
<button
  data-kb-track-click="Add to Cart"
  data-kb-click-channel="ecommerce"
>
  Add to Cart
</button>

When the button is clicked, an event named "Add to Cart" is tracked on the "ecommerce" channel.

Visibility Tracking

html
<section
  data-kb-track-visibility="Pricing Section Viewed"
  data-kb-visibility-channel="marketing"
  data-kb-visibility-threshold="0.75"
>
  <!-- content -->
</section>

When 75% of the section becomes visible in the viewport, an event named "Pricing Section Viewed" is tracked on the "marketing" channel.

Error Handling

The SDK provides typed error classes so you can handle specific failure modes precisely.

typescript
import {
  AuthenticationError,
  ValidationError,
  TimeoutError,
  ApiError,
  KitbaseError
} from '@kitbase/analytics';

try {
  await kitbase.track({ channel: 'payments', event: 'Purchase' });
} catch (error) {
  if (error instanceof AuthenticationError) {
    // 401: Invalid or missing API key
  } else if (error instanceof ValidationError) {
    // 400/422: Missing or invalid fields - check error.field
  } else if (error instanceof TimeoutError) {
    // Request timed out (default: 30s)
  } else if (error instanceof ApiError) {
    // Other API error - check error.statusCode and error.response
  } else if (error instanceof KitbaseError) {
    // Generic SDK error
  }
}
ErrorHTTP StatusDescription
AuthenticationError401Invalid or missing API key
ValidationError400/422Missing or invalid required fields
TimeoutError--Request exceeded 30s timeout
ApiError4xx/5xxAPI returned an error response

For detailed error handling patterns including retry logic and best practices, see Error Handling.

REST API

You can send events directly to the Kitbase REST API without the SDK. This is useful for server-side integrations or languages without an official SDK.

Single Event

bash
curl -X POST https://api.kitbase.dev/sdk/v1/logs \
  -H "X-API-Key: YOUR_SDK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "Purchase Completed",
    "properties": {
      "channel": "payments",
      "tags": { "amount": 99.99 }
    }
  }'

Response (202 Accepted):

json
{
  "id": "evt_abc123",
  "event": "Purchase Completed",
  "timestamp": "2026-02-13T12:00:00.000Z"
}

Batch Events

Send multiple events in a single request for better performance:

POST /sdk/v1/logs/batch

Request body:

json
{
  "events": [
    {
      "event": "Page Viewed",
      "properties": { "channel": "analytics", "tags": { "path": "/pricing" } }
    },
    {
      "event": "CTA Clicked",
      "properties": { "channel": "conversions", "tags": { "button": "signup" } }
    }
  ]
}

Response (202 Accepted):

json
{
  "accepted": 2,
  "total": 2
}

The batch endpoint accepts an array of events and returns the count of accepted events vs. total submitted.

Released under the MIT License.