Tracking Product Events
Track the moments that tell you whether users are getting value from your product: signing up, creating a project, inviting a teammate, starting checkout, or completing a purchase.
Good event tracking is less about volume and more about signal. A small set of well-named events with useful properties is usually more valuable than capturing every click in your UI.
What to track
Start with events that answer product questions you already care about:
- Activation: Did a new user reach the first meaningful success moment?
- Conversion: What steps lead to purchase, upgrade, or account creation?
- Engagement: Which features do active users come back to?
- Retention: What behavior predicts long-term usage?
If an event would not change a decision, dashboard, or experiment, it probably does not need to be part of your initial instrumentation plan.
Recommended instrumentation pattern
Most teams get the best results with a simple pattern:
- Pick a small set of key business events first.
- Reuse the same event names across platforms so mobile, web, and backend data can be analyzed together.
- Add properties for the dimensions you expect to filter or group by, such as plan, currency, feature area, or experiment variant.
- Attach user context with
identify()as soon as the user is known. - Keep event names and properties stable over time so charts and SQL stay readable.
SDK examples
Use these examples as the starting point for your application code:
import { altertable } from '@altertable/altertable-js';// Initialize with your API keyaltertable.init('YOUR_API_KEY', {environment: 'production',});// Track a user eventaltertable.track('checkout_completed', {revenue: 49.99,plan: 'pro',currency: 'USD',});// Identify a useraltertable.identify('user_abc123', {plan: 'pro',});
Distinct ID
distinct_id is the field that ties each event to a person. It can be an anonymous visitor ID (before login) or a stable user ID (after login).
Client-side SDKs assign distinct_id automatically. Server-side SDKs have no shared browser state, so you pass it on every call. Use a session or temporary ID for anonymous activity, then switch to your internal user ID once the user authenticates.
For ID naming, traits, and the full identify payload, see Identifying users.
Event payload
All SDKs and API clients map to the same payload shape. You do not need every field on every call, but the model is shared across platforms so the resulting data stays consistent.
Field | Required | Description |
|---|---|---|
environment | Yes | Environment slug such as production or staging. |
event | Yes | Event name, for example Checkout Completed. |
properties | Yes | Event attributes used for filtering and analysis. Send {} when you have no custom properties. |
distinct_id | No | User or device identifier. Client-side SDKs set this automatically. |
anonymous_id | No | Anonymous identifier for pre-login activity. |
device_id | No | Device identifier to associate with the event. |
session_id | No | Session identifier to group related events. |
timestamp | No | Unix milliseconds or ISO 8601 timestamp. When omitted, the server uses the current time. |
event and properties are the core of every tracked event. The identity and session fields add context when you have it.
Anonymous and identified events
You can track events before a user logs in.
On client-side SDKs, the SDK automatically assigns an anonymous distinct_id. When the user logs in, call identify() to link that anonymous history to a stable user ID.
On server-side SDKs, pass distinct_id on every call yourself. Call identify() to store traits for the same user.
Auto-capture and page or screen tracking
Client-side SDKs automatically capture page views or screen views without extra code. The mechanism varies by platform:
// Disable auto-capture if you need manual controlaltertable.init('YOUR_API_KEY', { autoCapture: false });// Then track page views manuallyaltertable.page('https://example.com/products');
Server-side SDKs (Python, Ruby) do not auto-capture pages. Include page context in event properties when relevant.
When to send events from the backend
Send events from your backend when the source of truth lives on the server, such as billing changes, subscription renewals, entitlement updates, or job completion. This keeps critical business events aligned with the system that actually performed the action.
Direct API usage
Endpoint: POST https://api.altertable.ai/track
curl -X POST "https://api.altertable.ai/track?sync=true" \-H "X-API-Key: YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{"environment":"production","event":"Purchase Completed","properties":{"amount":99.99,"currency":"USD"},"distinct_id":"u_01jza857w4f23s1hf2s61befmw","session_id":"sess_01jza8h9v6s56pj9j3a4k1yqhz"}'
Set sync=true when you want the request to wait for processing instead of returning immediately after enqueueing.
Batch requests
The HTTP API accepts either a single event payload or an array of payloads. Batch requests are useful when you are forwarding events from a worker, importing historical data, or reducing request overhead from a backend service.
curl -X POST https://api.altertable.ai/track \-H "Authorization: Bearer YOUR_API_KEY" \-H "Content-Type: application/json" \-d '[{"environment":"production","event":"Checkout Started","properties":{"currency":"USD"},"distinct_id":"user_123"},{"environment":"production","event":"Checkout Completed","properties":{"currency":"USD","amount":99.99},"distinct_id":"user_123"}]'
Query tracked events
SELECTevent,properties->>'currency' AS currency,COUNT(*) AS totalFROM altertable.analytics.eventsGROUP BY ALLORDER BY total DESC;
Best practices
- Use clear event names and keep naming consistent across platforms.
- Track meaningful product actions, not every low-level UI interaction.
- Include only properties you plan to analyze, but always send the
propertiesfield even if it is an empty object. - Use environment-specific API keys and make sure the payload
environmentmatches where you want the event to land. - Add identity context with
identify()as soon as the user is known. - Avoid sensitive personal data in event properties.
- Version event schemas when making breaking changes so dashboards and downstream models remain interpretable.