Segment’s documentation covers the API surface thoroughly. What it doesn’t cover is the set of decisions you have to make before you write a single line of code, the specific mistakes that will make your analytics data unreliable six months from now, and what to do when you inherited a tracking implementation that is already a mess.

This is that guide.

The Four Calls and When to Use Each

Segment’s SDK has four primary methods. Using the wrong one is the most common implementation error, and it compounds over time.

analytics.track(event, properties) records that a user performed an action. This is the workhorse. Use it for anything the user does: clicked a button, submitted a form, completed a checkout, viewed a product. The event name should be a past-tense action in object-verb format: Order Completed, Form Submitted, Plan Upgraded.

analytics.identify(userId, traits) associates the current anonymous session with a known user. Call this immediately after authentication — login, signup, or any moment you resolve who the user is. Traits are user-level attributes: name, email, plan type, company. Don’t put event context in identify; traits should describe the user’s current state, not what they just did.

analytics.page(name, properties) records a page view. In single-page applications, you need to call this manually on route changes — it doesn’t fire automatically. Pass the page name explicitly; relying on document.title produces inconsistent results as the page loads asynchronously.

analytics.group(groupId, traits) associates the current user with a group — a company, organization, or account. Use this in B2B products where a user belongs to an account. Group traits describe the account: company name, plan, employee count. If you’re not building a B2B product with organizational hierarchies, you probably don’t need group.

The mistake that kills analytics data: calling track where identify belongs, or calling identify with event-specific data. A trait like "lastPurchaseAmount": 99.00 doesn’t belong on the user — it belongs on a Purchase Completed track event. Traits should be durable attributes; events are ephemeral facts.

Design the Taxonomy Before Writing Code

This is the step that most implementations skip, and the reason most analytics data becomes unreliable within a year.

An event taxonomy is the agreed-upon naming system for your events and their properties. Without it, different engineers implement tracking independently and you end up with user_signed_up, UserSignedUp, User Signup, and signup_complete all coexisting in your data, all meaning slightly different things.

Event naming conventions: Pick one format and enforce it. Segment recommends Object Action in title case: Order Completed, User Registered, Plan Upgraded. The object-action format is searchable and groups related events naturally. Whatever you choose, document it and apply it consistently.

Property naming conventions: snake_case or camelCase — pick one. Define which properties are required on every track event: user_id, timestamp, session_id. Define which properties are contextual and optional. The key rule: the same concept should always use the same property name. If checkout events use order_id and refund events use orderId, you’ve created a join problem that doesn’t surface until someone runs an analysis.

Schema documentation: Maintain a living spec for every event: the event name, description, required properties, optional properties, and which destinations it should flow to. A spreadsheet works. A tool like Segment’s Protocols or Avo works better. What doesn’t work: undocumented tracking that accumulates over time.

The practical minimum before implementation: define your top 20 events, write out their required properties, agree on naming conventions, and get sign-off from whoever owns the data. It’s a one-day investment that prevents a year of data debt.

Common Implementation Mistakes

Tracking page views on every click

A common anti-pattern: calling analytics.page() inside click handlers or on component renders, rather than only on actual route changes. This inflates page view counts and makes navigation analysis meaningless. In a React app with React Router, fire analytics.page() once per route change, not once per render cycle.

Inconsistent user IDs

The userId passed to identify must be stable, unique, and consistent across all sessions and devices. The most common failure: using email as the userId. Users change email addresses. In B2B products, multiple users share email domains in ways that create collisions. Use your internal user ID from the database — a UUID or integer primary key that never changes.

Missing context properties

Segment automatically captures some context (user agent, IP, locale), but application context has to be explicit. If you want to know which product plan a user was on when they completed a checkout, that plan information needs to be on the Order Completed event. If you’re analyzing feature adoption by company size, company size needs to be a trait on the user’s identify call. Don’t assume you can join this data in later from another system — sometimes you can, but you’re betting on data availability you don’t control.

Sending events from the wrong environment

Development and staging events pollute production analytics. Configure separate Segment write keys per environment and make sure your build process uses the right one. In production, set integrations filtering to prevent test events from flowing to your ad platforms and CRM.

Testing with the Segment Debugger

Before any tracking code ships to production, verify it in Segment’s Source Debugger. Every event appears in real time with the full payload — event name, properties, context, timestamp.

The things to check for each event:

  • Is the event name correct and consistently cased?
  • Are all required properties present?
  • Is userId populated after identify has been called, and anonymousId before?
  • Are property values the expected type (string vs number vs boolean)?
  • Is the context.page object populated with the correct URL?

Don’t skip this step and assume the code is correct. The Debugger has caught naming typos, missing properties, and incorrect property types in every implementation I’ve worked on.

For more structured validation, Segment’s Protocols lets you define a schema and flags events that violate it. This is worth setting up for production environments — it catches regressions when engineers add new tracking without consulting the taxonomy.

Handling Anonymous-to-Identified Transitions

This is the piece most implementations get wrong, and it silently breaks funnel analysis.

When a user first arrives at your site, Segment assigns them an anonymousId — a UUID stored in localStorage. All events before authentication carry this ID. When the user logs in, you call identify with their userId. At this point, Segment needs to link the pre-authentication events to the now-identified user.

// On login success:
analytics.identify(user.id, {
  email: user.email,
  name: user.name,
  plan: user.plan,
  createdAt: user.createdAt
});

What most implementations miss: Segment’s client-side SDK handles this automatically on the web — once you call identify, subsequent events carry both userId and the original anonymousId. The problem is with server-side events. If you’re sending server-side track events before the user authenticates (common for checkout events in e-commerce), those events have no anonymousId to link back to the browser session.

The fix is explicit aliasing when a user transitions from anonymous to identified for the first time. The analytics.alias() call creates a permanent link between the anonymous ID and the user ID in Segment’s identity graph. This only needs to happen once per user — typically at the moment of account creation:

// At signup — before identify:
analytics.alias(user.id);

// Then immediately after:
analytics.identify(user.id, {
  email: user.email,
  name: user.name,
  createdAt: new Date().toISOString()
});

Note that alias behavior differs by Segment destination — some destinations handle this natively, others require the explicit call. Check Segment’s destination-specific documentation for the tools you’re sending data to.

What to Do When Your Events Are Already a Mess

You inherited a Segment implementation with five naming conventions, missing properties on half the events, and an identify call that runs on every page load instead of only on authentication. Now what?

Don’t delete events. Existing events are referenced in dashboards, funnels, and automation tools. Deleting them breaks analysis history and may trigger alerts you don’t know exist.

Extend, don’t replace. Add correct events alongside the broken ones. Order Completed can coexist with order_complete while you migrate downstream tools off the old event. Once nothing references the old event for 30+ days, you can suppress it.

Add a schema validation tool. Segment’s Protocols or a custom middleware in your Segment source lets you flag schema violations without blocking events. Start logging violations to understand the scope of the problem before you start fixing it.

Fix identify first. If identify is being called incorrectly — on every page load, with the wrong userId format, with event-level data stuffed into traits — fix it. Incorrect identity calls corrupt your user profiles in every downstream destination and the damage is hard to undo.

Prioritize by business impact. Fix the events used in conversion funnels, revenue attribution, and sales automation first. Fix aesthetic issues (naming conventions, extra properties) in a second pass once the critical events are solid.


FAQ

Should we use Segment’s server-side source or client-side SDK?

Use both. The client-side SDK captures browser context (session data, UTM parameters, referrer, device type) that isn’t available server-side. The server-side source is authoritative for transactional events — purchases, subscription changes, account actions — where you need guaranteed delivery and don’t want the browser to be the source of truth for revenue data. A common architecture: client-side for behavioral and engagement events, server-side for transactional events, with explicit userId passing to link them together.

How do we handle Segment in a single-page application with route-based page views?

In React with React Router, add a listener to the history object and call analytics.page() on every location change. In Next.js, use the routeChangeComplete event from next/router. The key detail: call analytics.page() after the route change completes and the new page title is available, not before. Calling it during the transition captures the previous page’s title and URL, which makes navigation analysis meaningless.

Segment supports consent management through two mechanisms: conditional loading (don’t load the SDK until consent is given) and destination filtering (load the SDK, but only forward events to consented destinations). For strict GDPR compliance, conditional loading is safer — no events are captured until consent is recorded. For user experience, destination filtering is less disruptive. Either way, store consent status in your own database, not just in a cookie — you need to be able to demonstrate consent history on request. Map your Segment destinations to consent categories and configure the integrations object on your events accordingly.

How many events is too many?

The practical limit isn’t a number — it’s governance capacity. If your team can maintain a schema doc for 200 events and enforce naming conventions across 15 engineers, 200 events is fine. If you have 50 events with no documentation and inconsistent naming, you already have too many. The failure mode isn’t volume — it’s events that mean ambiguous things. A Button Clicked event with no properties that distinguishes which button is useless. An Add to Cart Clicked event with product_id, product_name, and price is valuable. Specificity matters more than count.

Can we use Segment to replace our internal analytics database?

No. Segment is a routing and ingestion layer, not a data store. Events you send to Segment flow to destinations; Segment itself doesn’t give you queryable access to historical events at scale (Segment’s Data Lakes or Storage destinations send data to your own warehouse, which is the right pattern). If you want SQL access to your event history, set up a Segment warehouse destination (Snowflake, BigQuery, Redshift) from day one. Trying to reconstruct historical event data from individual destination exports is painful and usually incomplete.