Segment Event Tracking | OpsBlu Docs

Segment Event Tracking

How to implement custom event tracking in Segment. Covers event naming conventions, required and optional parameters, ecommerce events, debugging with.

Overview

Event tracking in Segment follows a unified, platform-agnostic model built around five core API methods: track, page, screen, identify, and group. This abstraction allows you to instrument once and send data to hundreds of destinations without rewriting tracking code for each platform.

Unlike traditional analytics platforms with rigid event structures, Segment provides flexibility while still offering standardized event specs (Ecommerce, B2B SaaS, Video, Mobile) that ensure destination compatibility and semantic consistency.

Segment's Event API Methods

Track

Records user actions and events with associated properties.

analytics.track('Event Name', {
  property1: 'value1',
  property2: 'value2'
});

Use for: Button clicks, form submissions, purchases, feature usage, content interactions

Page

Records page views in web applications.

analytics.page('Category', 'Name', {
  url: 'https://example.com/products',
  title: 'Products',
  referrer: 'https://google.com'
});

Use for: Single-page apps (SPA), traditional multi-page sites, virtual page views

Screen

Records screen views in mobile applications (iOS, Android).

analytics.screen('Category', 'Name', {
  screen_name: 'ProductDetail',
  product_id: 'SKU-12345'
});

Use for: Mobile app navigation, modal/dialog displays

Identify

Associates a user ID with traits and merges anonymous activity with known user profiles.

analytics.identify('user_12345', {
  email: 'user@example.com',
  name: 'Jane Doe',
  plan: 'premium'
});

Use for: Login, signup, profile updates

Group

Associates a user with a group/account and tracks group-level properties (B2B).

analytics.group('company_67890', {
  name: 'Acme Corporation',
  plan: 'enterprise',
  employees: 500
});

Use for: B2B SaaS multi-tenant apps, team-based products

Event Naming Standards

Use Object + Action naming:

Event Name Object Action Good/Bad
Product Viewed Product Viewed Good
Cart Item Added Cart Item Added Good
Email Sent Email Sent Good
Clicked Button N/A N/A Bad (action-first)
user_signup N/A N/A Bad (lowercase, verb-first)
productView N/A N/A Bad (camelCase, no space)

Event Name Best Practices

  1. Use Title Case: Product Viewed, not product viewed or PRODUCT VIEWED
  2. Use Past Tense: Clicked, Viewed, Completed, not Click, View, Complete
  3. Be specific but concise: Product Added to Cart vs Product Added to Shopping Cart from Product Detail Page After Clicking Add Button
  4. Avoid technical jargon: Subscription Started vs Stripe Checkout Session Completed
  5. Maximum length: Keep under 40 characters for destination compatibility

Reserved Event Names (Avoid Custom Use)

Segment reserves certain event names for automatic collection:

  • Application Installed
  • Application Opened
  • Application Updated
  • Application Backgrounded
  • Application Crashed
  • Push Notification Received
  • Push Notification Tapped

Segment Spec: Ecommerce Events

Segment provides a standardized Ecommerce Spec for consistent tracking across destinations.

Product Lifecycle Events

Products Searched

analytics.track('Products Searched', {
  query: 'wireless headphones',
  filters: {
    category: 'Electronics',
    price_min: 50,
    price_max: 150
  }
});

Product List Viewed

analytics.track('Product List Viewed', {
  list_id: 'category_electronics',
  category: 'Electronics',
  products: [
    {
      product_id: 'SKU-12345',
      name: 'Wireless Headphones',
      price: 79.99,
      position: 1
    },
    {
      product_id: 'SKU-67890',
      name: 'Bluetooth Speaker',
      price: 49.99,
      position: 2
    }
  ]
});

Product Viewed

analytics.track('Product Viewed', {
  product_id: 'SKU-12345',
  sku: 'WH-BLK-001',
  category: 'Electronics',
  name: 'Wireless Headphones',
  brand: 'AudioTech',
  variant: 'Black',
  price: 79.99,
  quantity: 1,
  currency: 'USD',
  position: 1,
  value: 79.99,
  url: 'https://example.com/products/wireless-headphones',
  image_url: 'https://cdn.example.com/images/wh-blk-001.jpg'
});

Product Clicked

analytics.track('Product Clicked', {
  product_id: 'SKU-12345',
  name: 'Wireless Headphones',
  price: 79.99,
  position: 3,
  url: 'https://example.com/products/wireless-headphones'
});

Shopping Cart Events

Product Added

analytics.track('Product Added', {
  cart_id: 'cart_abc123',
  product_id: 'SKU-12345',
  sku: 'WH-BLK-001',
  category: 'Electronics',
  name: 'Wireless Headphones',
  brand: 'AudioTech',
  variant: 'Black',
  price: 79.99,
  quantity: 1,
  coupon: 'SUMMER10',
  position: 1,
  url: 'https://example.com/products/wireless-headphones',
  image_url: 'https://cdn.example.com/images/wh-blk-001.jpg'
});

Product Removed

analytics.track('Product Removed', {
  cart_id: 'cart_abc123',
  product_id: 'SKU-12345',
  name: 'Wireless Headphones',
  price: 79.99,
  quantity: 1
});

Cart Viewed

analytics.track('Cart Viewed', {
  cart_id: 'cart_abc123',
  products: [
    {
      product_id: 'SKU-12345',
      name: 'Wireless Headphones',
      price: 79.99,
      quantity: 1
    }
  ],
  value: 79.99,
  currency: 'USD'
});

Checkout Events

Checkout Started

analytics.track('Checkout Started', {
  order_id: 'order_temp_xyz',  // Temporary ID, may not be final
  value: 156.96,
  revenue: 142.97,
  shipping: 5.99,
  tax: 8.00,
  discount: 10.00,
  coupon: 'SUMMER10',
  currency: 'USD',
  products: [
    {
      product_id: 'SKU-12345',
      sku: 'WH-BLK-001',
      name: 'Wireless Headphones',
      price: 79.99,
      quantity: 1,
      category: 'Electronics',
      brand: 'AudioTech'
    },
    {
      product_id: 'SKU-67890',
      sku: 'BT-SPK-002',
      name: 'Bluetooth Speaker',
      price: 62.98,
      quantity: 2,
      category: 'Electronics',
      brand: 'SoundWave'
    }
  ]
});

Checkout Step Viewed

analytics.track('Checkout Step Viewed', {
  checkout_id: 'checkout_abc123',
  step: 2,
  step_name: 'shipping_info',
  payment_method: null,
  shipping_method: null
});

Checkout Step Completed

analytics.track('Checkout Step Completed', {
  checkout_id: 'checkout_abc123',
  step: 2,
  step_name: 'shipping_info',
  shipping_method: 'ground',
  shipping_cost: 5.99
});

Payment Info Entered

analytics.track('Payment Info Entered', {
  checkout_id: 'checkout_abc123',
  order_id: 'order_xyz789',
  payment_method: 'credit_card',
  // Don't include sensitive payment details
  card_type: 'visa',  // OK to include
  card_last_four: '4242'  // OK to include
  // card_number: 'xxxx'  // NEVER include full card numbers
});

Order Events

Order Completed

The most critical ecommerce event:

analytics.track('Order Completed', {
  checkout_id: 'checkout_abc123',
  order_id: 'ORD-20240315-001',
  affiliation: 'Online Store',
  total: 156.96,
  revenue: 142.97,  // Subtotal after discounts, before shipping/tax
  shipping: 5.99,
  tax: 8.00,
  discount: 10.00,
  coupon: 'SUMMER10',
  currency: 'USD',

  products: [
    {
      product_id: 'SKU-12345',
      sku: 'WH-BLK-001',
      name: 'Wireless Headphones',
      price: 79.99,
      quantity: 1,
      category: 'Electronics',
      brand: 'AudioTech',
      variant: 'Black',
      coupon: 'SUMMER10'
    }
  ],

  // Payment details
  payment_method: 'credit_card',
  payment_processor: 'stripe',

  // Shipping details
  shipping_method: 'ground',
  shipping_carrier: 'UPS',
  shipping_address: {
    city: 'San Francisco',
    state: 'CA',
    country: 'US',
    postal_code: '94102'
  },

  // Customer classification
  customer_type: 'returning',
  is_first_purchase: false,

  // Timestamps
  created_at: '2024-03-15T14:30:00Z',
  completed_at: '2024-03-15T14:35:22Z'
});

Order Updated

analytics.track('Order Updated', {
  order_id: 'ORD-20240315-001',
  update_type: 'item_added',
  total: 180.95,
  products: [/* updated products array */]
});

Order Refunded

analytics.track('Order Refunded', {
  order_id: 'ORD-20240315-001',
  total: 156.96,
  refund_amount: 79.99,
  refund_type: 'partial',  // or 'full'
  refund_reason: 'customer_request',
  products: [
    {
      product_id: 'SKU-12345',
      name: 'Wireless Headphones',
      quantity: 1,
      price: 79.99
    }
  ]
});

Order Cancelled

analytics.track('Order Cancelled', {
  order_id: 'ORD-20240315-001',
  total: 156.96,
  cancellation_reason: 'customer_request',
  products: [/* products array */]
});

Promotion Events

Promotion Viewed

analytics.track('Promotion Viewed', {
  promotion_id: 'promo_summer2024',
  creative: 'summer_sale_banner',
  name: 'Summer Sale 2024',
  position: 'homepage_hero'
});

Promotion Clicked

analytics.track('Promotion Clicked', {
  promotion_id: 'promo_summer2024',
  creative: 'summer_sale_banner',
  name: 'Summer Sale 2024',
  position: 'homepage_hero'
});

Coupon Events

Coupon Entered

analytics.track('Coupon Entered', {
  order_id: 'order_xyz789',
  cart_id: 'cart_abc123',
  coupon_id: 'SUMMER10',
  coupon_name: 'Summer 10% Off',
  discount: 10.00
});

Coupon Applied

analytics.track('Coupon Applied', {
  order_id: 'order_xyz789',
  cart_id: 'cart_abc123',
  coupon_id: 'SUMMER10',
  coupon_name: 'Summer 10% Off',
  discount: 10.00
});

Coupon Denied

analytics.track('Coupon Denied', {
  order_id: 'order_xyz789',
  cart_id: 'cart_abc123',
  coupon_id: 'EXPIRED10',
  reason: 'expired'
});

Wishlist Events

Product Added to Wishlist

analytics.track('Product Added to Wishlist', {
  wishlist_id: 'wishlist_user123',
  wishlist_name: 'Holiday Gift Ideas',
  product_id: 'SKU-12345',
  name: 'Wireless Headphones',
  price: 79.99,
  currency: 'USD'
});

Product Removed from Wishlist

analytics.track('Product Removed from Wishlist', {
  wishlist_id: 'wishlist_user123',
  product_id: 'SKU-12345'
});

Segment Spec: B2B SaaS Events

For software-as-a-service and B2B products.

Account Lifecycle

Account Created

analytics.track('Account Created', {
  account_id: 'acct_12345',
  account_name: 'Acme Corporation',
  plan_id: 'plan_trial',
  plan_name: 'Trial',
  trial_start_date: '2024-03-15',
  trial_end_date: '2024-03-29',
  source: 'website_signup'
});

Trial Started

analytics.track('Trial Started', {
  trial_id: 'trial_abc123',
  trial_plan: 'professional',
  trial_duration_days: 14,
  trial_end_date: '2024-03-29',
  source: 'homepage_cta',
  payment_method_added: false
});

Trial Ended

analytics.track('Trial Ended', {
  trial_id: 'trial_abc123',
  trial_plan: 'professional',
  trial_outcome: 'converted',  // or 'expired', 'cancelled'
  days_active: 14,
  features_used: ['dashboards', 'alerts', 'integrations']
});

Subscription Events

Subscription Started

analytics.track('Subscription Started', {
  subscription_id: 'sub_xyz789',
  plan_id: 'plan_professional_monthly',
  plan_name: 'Professional',
  billing_cycle: 'monthly',
  price: 99.00,
  currency: 'USD',
  trial_converted: true,
  source: 'trial_conversion'
});

Subscription Changed

analytics.track('Subscription Changed', {
  subscription_id: 'sub_xyz789',
  previous_plan_id: 'plan_professional_monthly',
  previous_plan_name: 'Professional',
  new_plan_id: 'plan_enterprise_monthly',
  new_plan_name: 'Enterprise',
  previous_price: 99.00,
  new_price: 299.00,
  change_type: 'upgrade',  // or 'downgrade'
  effective_date: '2024-04-01'
});

Subscription Cancelled

analytics.track('Subscription Cancelled', {
  subscription_id: 'sub_xyz789',
  plan_id: 'plan_professional_monthly',
  plan_name: 'Professional',
  cancellation_reason: 'too_expensive',
  feedback: 'Switching to competitor with better pricing',
  scheduled_end_date: '2024-04-30',  // End of billing period
  immediate: false
});

Subscription Paused

analytics.track('Subscription Paused', {
  subscription_id: 'sub_xyz789',
  plan_id: 'plan_professional_monthly',
  pause_reason: 'seasonal_business',
  pause_duration_days: 90,
  resume_date: '2024-06-15'
});

Subscription Resumed

analytics.track('Subscription Resumed', {
  subscription_id: 'sub_xyz789',
  plan_id: 'plan_professional_monthly',
  pause_duration_days: 45,
  resume_date: '2024-05-01'
});

Feature Engagement

Feature Used

analytics.track('Feature Used', {
  feature_name: 'Advanced Filters',
  feature_category: 'Analytics',
  feature_id: 'feature_advanced_filters',
  usage_count: 1,  // Lifetime count
  session_usage_count: 1,  // This session
  user_tier: 'enterprise',
  feature_tier: 'enterprise'  // Minimum tier required
});

Feature Enabled

analytics.track('Feature Enabled', {
  feature_name: 'Single Sign-On',
  feature_id: 'feature_sso',
  enabled_by: 'admin_user_456',
  account_id: 'acct_12345'
});

Feature Disabled

analytics.track('Feature Disabled', {
  feature_name: 'Email Notifications',
  feature_id: 'feature_email_notif',
  disabled_by: 'user_789',
  reason: 'user_preference'
});

Invite and Collaboration

Invite Sent

analytics.track('Invite Sent', {
  invite_id: 'invite_abc123',
  invitee_email: 'colleague@acme.com',
  inviter_id: 'user_12345',
  role: 'member',
  account_id: 'acct_12345',
  invite_method: 'email'
});

Invite Accepted

analytics.track('Invite Accepted', {
  invite_id: 'invite_abc123',
  invitee_id: 'user_98765',
  inviter_id: 'user_12345',
  role: 'member',
  account_id: 'acct_12345',
  time_to_accept_hours: 2.5
});

Custom Event Examples

Content Engagement

Article Read

analytics.track('Article Read', {
  article_id: 'article_123',
  article_title: 'How to Set Up Analytics',
  article_category: 'Guides',
  author: 'Jane Doe',
  word_count: 1500,
  read_percentage: 85,
  time_spent_seconds: 245
});

Video Played

analytics.track('Video Played', {
  video_id: 'video_456',
  video_title: 'Product Demo',
  video_duration_seconds: 180,
  video_provider: 'youtube',
  autoplay: false,
  sound: true,
  quality: '1080p'
});

Video Progress

analytics.track('Video Progress', {
  video_id: 'video_456',
  video_title: 'Product Demo',
  position_seconds: 90,
  duration_seconds: 180,
  percent_complete: 50,
  milestone: '50_percent'  // or '25_percent', '75_percent', '100_percent'
});

Lead Generation

Form Started

analytics.track('Form Started', {
  form_id: 'contact-sales-form',
  form_name: 'Contact Sales',
  form_type: 'lead',
  form_location: 'pricing_page'
});

Form Submitted

analytics.track('Form Submitted', {
  form_id: 'contact-sales-form',
  form_name: 'Contact Sales',
  form_type: 'lead',
  form_location: 'pricing_page',

  // Lead qualification fields (avoid PII)
  company_size: '50-100',
  industry: 'Technology',
  use_case: 'Marketing Analytics',
  budget_range: '$10k-$50k',

  // Form metadata
  time_to_submit_seconds: 120,
  fields_completed: 8,
  fields_total: 10
});

Lead Created

analytics.track('Lead Created', {
  lead_id: 'lead_abc123',
  lead_score: 75,
  lead_source: 'inbound',
  lead_status: 'new',
  campaign_id: 'campaign_spring2024',
  expected_value: 5000.00,
  assigned_to: 'sales_rep_456'
});

User Authentication

Signed Up

analytics.track('Signed Up', {
  user_id: 'user_12345',
  signup_method: 'email',  // or 'google', 'github', 'saml'
  source: 'homepage_cta',
  referrer: 'https://google.com/search',
  plan: 'trial',
  invite_code: null
});

Signed In

analytics.track('Signed In', {
  user_id: 'user_12345',
  login_method: 'email',  // or 'google', 'sso'
  device_type: 'desktop',
  location: 'San Francisco, CA',
  ip_address: '192.0.2.1',  // Only if necessary, respect privacy
  failed_attempts: 0
});

Signed Out

analytics.track('Signed Out', {
  user_id: 'user_12345',
  session_duration_seconds: 3600,
  events_in_session: 25,
  logout_method: 'manual'  // or 'timeout', 'forced'
});

Error Tracking

Error Occurred

analytics.track('Error Occurred', {
  error_type: 'API Error',
  error_code: 'ERR_500',
  error_message: 'Internal Server Error',
  error_source: 'checkout_api',
  user_id: 'user_12345',
  page_url: 'https://example.com/checkout',
  severity: 'high',  // low, medium, high, critical
  recoverable: false
});

Event Properties Best Practices

Property Data Types

Type Example Use Case
String "Wireless Headphones" Names, IDs, categories
Number 79.99 Prices, quantities, scores
Boolean true Flags, states
ISO 8601 Date "2024-03-15T14:30:00Z" Timestamps
Array ["feature1", "feature2"] Lists, tags
Object {city: "SF", state: "CA"} Nested data (use sparingly)

Common Property Mistakes

Mistake Example Fix
Price as string "$79.99" 79.99 (number)
Currency as number 840 (ISO code) "USD" (string)
Boolean as string "true" true (boolean)
Date as timestamp 1710511800000 "2024-03-15T14:30:00Z"
Inconsistent casing productId and product_name Pick one: snake_case

Event Validation and QA

Pre-Production Checklist

Check Validation Method
Event name follows conventions Title Case, Object-Action format
All required properties present Match tracking plan schema
Property data types correct Number for prices, string for IDs
Currency always included with monetary values currency: "USD"
Consistent property naming All snake_case or all camelCase
No PII in properties Hash email/phone if needed
Product IDs match product catalog Cross-reference with database
Order IDs are unique No collisions across orders

Segment Debugger Validation

  1. Open Live Debugger

    • Navigate to app.segment.com/[workspace]/sources/[source]/debugger
  2. Trigger Test Event

    • Perform action on your site/app
    • Event should appear within 10 seconds
  3. Inspect Event Payload

    {
      "anonymousId": "abc-123-def-456",
      "event": "Product Viewed",
      "properties": {
        "product_id": "SKU-12345",
        "name": "Wireless Headphones",
        "price": 79.99,
        "currency": "USD"
      },
      "context": {
        "page": { "url": "https://example.com/products/headphones" }
      },
      "timestamp": "2024-03-15T14:30:00.000Z"
    }
    
  4. Verify Destinations

    • Check which destinations received the event
    • Confirm destination-specific transformations applied correctly

Protocols Schema Validation

Enable Protocols to enforce tracking plan compliance:

// Events that violate schema are blocked or flagged
analytics.track('Product Viewed', {
  product_id: 'SKU-12345',  // Required: ✓
  name: 'Wireless Headphones',  // Required: ✓
  price: 79.99,  // Required: ✓
  currency: 'USD',  // Required: ✓
  invalid_field: 'xyz'  // Not in schema: Violation!
});

Protocols Actions:

  • Block: Reject the entire event (strict, recommended for production)
  • Allow: Send event but log violation (permissive, good for development)
  • Omit Properties: Remove violating properties, send the rest

Automated Testing

// Jest test example
describe('Order Completed Event', () => {
  it('fires with correct properties on checkout success', async () => {
    const analyticsSpy = jest.spyOn(analytics, 'track');

    await completeCheckout({
      orderId: 'ORD-TEST-001',
      total: 99.99,
      products: [{ product_id: 'SKU-123', price: 99.99, quantity: 1 }]
    });

    expect(analyticsSpy).toHaveBeenCalledWith('Order Completed', {
      order_id: 'ORD-TEST-001',
      total: 99.99,
      currency: 'USD',
      products: expect.arrayContaining([
        expect.objectContaining({
          product_id: 'SKU-123',
          price: 99.99,
          quantity: 1
        })
      ])
    });
  });
});

Troubleshooting

Symptom Likely Cause Solution
Event not appearing in debugger Analytics.js not loaded Check network tab for script errors
Event appearing but no properties Properties object not passed Verify analytics.track('Event', {props}) syntax
Properties missing in destination Destination mapping incorrect Review destination field mappings
Duplicate events firing Multiple triggers Check for event listeners firing multiple times
Event timestamp incorrect Client clock skew Use server-side tracking for critical events
Currency not appearing in destination Sent as number instead of string Change currency: 840 to currency: "USD"
Ecommerce events not in GA4 Missing GA4 property mapping Use item_id, item_name, etc. for GA4 compatibility
Protocols blocking events Schema violation Update event properties to match tracking plan
Events delayed or missing Ad blocker Implement server-side fallback
anonymousId different after login Identify called incorrectly Call identify() with same anonymousId to merge

Performance Considerations

Event Batching

Segment automatically batches events for performance:

// These fire rapidly but are batched into a single HTTP request
for (let i = 0; i < 10; i++) {
  analytics.track('Item Clicked', { item_id: i });
}

Async Tracking

Events are sent asynchronously and don't block the UI:

// Non-blocking - returns immediately
analytics.track('Button Clicked', { button_id: 'cta' });

// Continue with user experience
redirectToNextPage();

Critical Event Guarantee

For critical events (purchases, signups), ensure delivery:

// Wait for event to send before redirect
analytics.track('Order Completed', orderData, (err, data) => {
  // Callback fires after event sent
  window.location.href = '/confirmation';
});

// Or use navigator.sendBeacon for page unload
window.addEventListener('beforeunload', () => {
  const data = JSON.stringify({
    event: 'Page Exited',
    properties: { time_on_page: getTimeOnPage() }
  });

  navigator.sendBeacon('https://api.segment.io/v1/track', data);
});

Best Practices Summary

  1. Use Segment Specs: Adopt Ecommerce, B2B, Video specs for standard events
  2. Consistent Naming: Title Case, Object-Action format, past tense
  3. snake_case Properties: Universal compatibility across destinations
  4. Required Properties: Always include currency with monetary values
  5. Flat Structure: Avoid deep nesting; flatten for destination compatibility
  6. Protocols Enforcement: Enable schema validation in production
  7. Test in Debugger: Validate every event before deploying
  8. Document Everything: Maintain tracking plan with business context
  9. Version Events: Include schema_version for breaking changes
  10. Monitor Delivery: Set up alerts for failed events or violations
  11. Privacy First: Hash PII, respect consent, minimize data collection
  12. Server-Side Critical Events: Use server-side tracking for purchases, conversions