Tracking

Events vs Properties

When to track a new event versus add a property, plus naming conventions that keep your analytics clean and queryable.

The single most common tracking mistake is creating too many events. This page covers the one rule that prevents it — and the naming conventions that keep your data queryable.

The Rule: Add a Property, Don't Create a New Event

An event is something a user did. A property is a detail about what they did.

Track the action once, and describe its variations with properties (passed as metadata). Don't encode the variation into the event name.

Don't create an event per variant:

Logspot.track({ event: 'SubscribedToProPlan' });
Logspot.track({ event: 'SubscribedToTeamPlan' });
Logspot.track({ event: 'SubscribedToEnterprisePlan' });

Do track one event and put the variant in metadata:

Logspot.track({
  event: 'Subscribed',
  metadata: { plan: 'pro', interval: 'monthly', amount: 20 },
});

Why It Matters

  • One event, many questions. With a plan property you can break "Subscribed" down by plan, filter to just Enterprise, or compare monthly vs annual — all from one event. With three separate events you can't compare them in a single view.
  • No event-name explosion. A dozen Subscribed* events become noise in your event list. One Subscribed event with rich properties stays legible.
  • Stable funnels. Funnels and retention reports reference event names. If you add a new plan tomorrow, a property-based model needs zero changes; a name-based model needs a new event wired into every report.

A good gut check: if you'd want to compare two things side by side, they should be the same event with different property values.

Naming Conventions

Events: a Noun + Past-Tense Verb, in PascalCase

Name events after the action that completed: SignedUp, ProjectCreated, Subscribed, InviteSent. Past tense reads naturally in reports ("show me users who Subscribed"). Keep them consistent — pick Object Action (ProjectCreated) or Verb Object and stick to it across the whole plan.

Properties: snake_case

Property keys go in snake_case:

Logspot.track({
  event: 'OrderCompleted',
  metadata: {
    order_id: 'ord_8842',
    total_amount: 149.0,
    item_count: 3,
    coupon_code: 'LAUNCH20',
    is_first_order: true,
  },
});

Why snake_case for properties:

  • One casing, everywhere. Mixing orderId, OrderID, and order_id creates three "different" properties that are really one. A single convention keeps them merged.
  • Readable in queries and exports. total_amount is unambiguous in SQL-style filters and CSV exports.
  • Matches the wire format. The SDK already sends top-level fields in snake_case (user_id, anonymous_id) — your custom properties fit right in.

Keep values descriptive too: prefer plan: 'pro' over plan: 'p'. Use booleans for yes/no facts (is_trial: true), numbers for amounts (amount: 20, not '$20'), and lowercase string enums for categories (source: 'pricing_page').

Quick Reference

Use a...WhenExample
New eventA genuinely different action happenedSignedUp, Subscribed, OrderCompleted
PropertyThe same action varies in detailplan, amount, source, item_count

Reserved and Automatic Fields

A few names are handled for you — don't redefine them as custom properties:

  • Pageview is the reserved event name the SDK sends for page views.
  • Payment is the default reserved event name for revenue (Logspot.revenue(...)); value and currency are first-class fields, not metadata.
  • privacy_categories, privacy_signals, consent_source are stamped automatically — see How Tracking & Identity Works.

Next Steps