Skip to main content

Custom Events

Custom events let you track business-specific actions that automatic tracking doesn't capture: sign-ups, purchases, feature usage, onboarding steps, and anything else meaningful to your product.

Basic Usage

import { tracelog } from '@tracelog/lib';

// Simple event (no metadata)
tracelog.event('onboarding_completed');

// Event with metadata
tracelog.event('purchase_completed', {
orderId: 'ORD-789',
total: 149.99,
currency: 'USD'
});

tracelog.event() must be called after tracelog.init().

Signature

tracelog.event(
name: string,
metadata?: Record<string, MetadataType> | Record<string, MetadataType>[],
options?: { critical?: boolean }
): void
ParameterTypeRequiredDescription
namestringYesEvent name identifier
metadataobject or object[]NoAdditional data attached to the event
options{ critical?: boolean }NoPass { critical: true } to flush via sendBeacon so the event survives an imminent navigation. See Critical Events.

Metadata Types

Values in the metadata object can be:

  • Primitives: string, number, boolean
  • Arrays of strings
  • Nested objects (1 level deep)

Not allowed: functions, symbols, undefined, deeply nested objects.

Limits: 100 keys max, 48KB total, 500 items per array, 1000 characters per string (500 for strings inside arrays).

Naming Conventions

Use snake_case for event names. Descriptive verb-noun pairs work best:

// Good
tracelog.event('trial_started');
tracelog.event('feature_used', { featureId: 'dark-mode' });
tracelog.event('purchase_completed', { total: 99 });
tracelog.event('plan_upgraded', { from: 'starter', to: 'pro' });

// Avoid
tracelog.event('click'); // Too generic — automatic tracking already captures clicks
tracelog.event('Event1'); // Not descriptive
tracelog.event('userDidSomething'); // camelCase, hard to read in dashboard
tip

Once you set an event name, it shows up in your Event Catalog. Consistent naming keeps your catalog readable as the product grows.

Examples by Vertical

SaaS

// Onboarding
tracelog.event('account_created');
tracelog.event('onboarding_step_completed', { step: 'connect_integration', stepNumber: 2 });
tracelog.event('onboarding_completed');

// Feature usage
tracelog.event('feature_used', { featureId: 'export-csv', plan: 'pro' });
tracelog.event('report_generated', { reportType: 'weekly', recipients: 3 });

// Billing
tracelog.event('trial_started', { planId: 'pro', trialDays: 14 });
tracelog.event('plan_upgraded', { from: 'starter', to: 'pro', mrr: 49 });
tracelog.event('plan_downgraded', { from: 'pro', to: 'starter', reason: 'too_expensive' });
tracelog.event('subscription_cancelled', { reason: 'no_longer_needed', tenure: 6 });

E-commerce

// Product discovery
tracelog.event('product_viewed', { productId: 'SKU-123', category: 'electronics', price: 299 });
tracelog.event('search_performed', { query: 'wireless headphones', resultsCount: 42 });

// Cart
tracelog.event('cart_item_added', { productId: 'SKU-123', quantity: 1, price: 299 });
tracelog.event('cart_abandoned', { itemCount: 3, cartValue: 149.97 });

// Checkout
tracelog.event('checkout_started', { cartValue: 149.97, itemCount: 3 });
tracelog.event('purchase_completed', {
orderId: 'ORD-789',
total: 149.97,
currency: 'EUR',
itemCount: 3
});

Marketing / Lead Gen

// Lead capture
tracelog.event('newsletter_subscribed', { source: 'footer-form' });
tracelog.event('demo_requested', { company: 'Acme Inc', plan: 'enterprise' });
tracelog.event('contact_form_submitted', { subject: 'pricing' });

// Content engagement
tracelog.event('video_played', { videoId: 'demo-tour', durationSeconds: 120 });
tracelog.event('webinar_registered', { webinarId: 'q1-launch' });

Array Metadata

Pass an array when the event represents multiple items:

tracelog.event('cart_updated', [
{ productId: 'SKU-123', quantity: 2, price: 299 },
{ productId: 'SKU-456', quantity: 1, price: 49 }
]);

Privacy

You are responsible for sanitizing metadata before passing it to tracelog.event(). Do not include PII.

// Do NOT send PII
tracelog.event('user_registered', {
email: user.email, // PII — do not send
phone: user.phone, // PII — do not send
});

// Send safe identifiers instead
tracelog.event('user_registered', {
userId: user.id, // Internal ID, not personal data
plan: 'starter'
});

TraceLog auto-sanitizes text fields (error messages, click text) but does not sanitize values you pass explicitly via tracelog.event().

Critical Events

When you track an event right before a navigation — a purchase that immediately redirects to a thank-you page, a signup that hands off to onboarding — pass { critical: true }. The library flushes the queue via navigator.sendBeacon(), which the browser guarantees to deliver even if the page is closing.

tracelog.event(
'purchase_completed',
{ orderId: 'ord-789', total: 599.98 },
{ critical: true }
);
window.location.href = '/thanks'; // sendBeacon survives this navigation

Without critical: true, an async fetch flush would be cancelled by the navigation and the event would be lost.

Caveats (inherited from the sendBeacon API):

  • 64 KB payload cap. If the combined queue + critical event exceeds it, the batch is persisted to localStorage and recovered on the next init().
  • No retry on failure (fire-and-forget).
  • Custom headers are not applied (browser API limitation).

For non-unload scenarios, the library already auto-flushes on SPA navigation (pushState, replaceState, popstate, hashchange) and when the document becomes hidden. Both behaviors are opt-out via the flushOnSpaNavigation and flushOnPageHidden config flags.

Rate Limiting

TraceLog enforces multiple rate limits to prevent accidental event floods:

  • 60 per minute per event name
  • 50 per second across all custom events
  • 500 custom events per session

If you hit these limits in development, it usually indicates an event being fired inside a render loop.

Connecting Events to Product Features

After sending custom events, configure them in the TraceLog dashboard:

  1. Event Catalog (Events page) — Assign a semantic type (Conversion, Goal, Feature Usage) to each event. This powers the Goals, Funnels, and Reports features.
  2. Revenue Tracking — If an event has a value field (e.g., total), configure it in Revenue Tracking to aggregate revenue metrics.
  3. Funnels — Chain multiple events into a funnel to see where users drop off in a multi-step flow.

See Goals & Conversions for the full walkthrough.