Mental Model

Understanding how to think about Appizer's event-driven architecture

Learn how to think about Appizer's event-driven architecture and data model.

Core Concepts

Events Are Everything

In Appizer, everything is an event. User actions, system events, and custom metrics are all tracked as events.

// User action
appizer.track({ event: 'button_clicked', userId: 'user_123' })

// System event
appizer.track({ event: 'payment_processed', userId: 'user_123' })

// Custom metric
appizer.track({ event: 'api_latency', properties: { ms: 145 } })

Users Are Identities

Users are identified by a unique ID and can have traits (properties) attached to them.

appizer.identify({
  userId: 'user_123',
  traits: {
    email: 'user@example.com',
    plan: 'pro',
    signupDate: '2024-01-15'
  }
})

Key Principle: One user can have multiple identities (anonymous → authenticated) that get merged.

Properties Add Context

Events and users can have properties that add context for segmentation and analysis.

appizer.track({
  event: 'purchase_completed',
  userId: 'user_123',
  properties: {
    amount: 99.99,
    currency: 'USD',
    product: 'Pro Plan',
    paymentMethod: 'credit_card'
  }
})

Data Flow Mental Model

Think of Appizer as a pipeline:

Capture

Events are captured from your application via SDK or API

Process

Events are validated, enriched, and stored in real-time

Analyze

Events become queryable data for analytics and segmentation

Act

Use analytics to trigger actions (notifications, campaigns)

Identity Resolution

Anonymous Users

Before a user signs up, track them with an anonymous ID:

const anonymousId = generateUUID()
appizer.track({
  event: 'page_view',
  anonymousId: anonymousId,
  properties: { page: '/pricing' }
})

Identified Users

When a user signs up, identify them:

appizer.identify({
  userId: 'user_123',
  traits: {
    email: 'user@example.com',
    name: 'John Doe'
  }
})

Aliasing

Link the anonymous ID to the user ID:

appizer.alias({
  userId: 'user_123',
  previousId: anonymousId
})

Result: All anonymous events are now attributed to user_123.

Event Properties vs User Traits

Event Properties

  • Temporary: Specific to that event occurrence
  • Variable: Can change with each event
  • Example: Purchase amount, page URL, button name
appizer.track({
  event: 'page_view',
  properties: {
    page: '/products',
    referrer: 'google.com',
    loadTime: 1.2
  }
})

User Traits

  • Persistent: Stored on the user profile
  • Stable: Represent user characteristics
  • Example: Email, plan, signup date
appizer.identify({
  userId: 'user_123',
  traits: {
    email: 'user@example.com',
    plan: 'enterprise',
    industry: 'technology'
  }
})

Segmentation Mental Model

Think of segments as dynamic groups based on conditions:

// Segment: High-value users
{
  filters: [
    { property: 'plan', operator: 'equals', value: 'enterprise' },
    { property: 'totalSpent', operator: 'greaterThan', value: 1000 }
  ]
}

Segments update in real-time as user traits and events change.

Time-Based Thinking

Event Timestamps

Every event has a timestamp (auto-generated or custom):

appizer.track({
  event: 'purchase',
  userId: 'user_123',
  timestamp: '2024-01-15T10:30:00Z' // Optional
})

Time Windows

Analytics queries use time windows:

appizer.analytics.query({
  startDate: '2024-01-01',
  endDate: '2024-01-31',
  event: 'purchase'
})

Best Practices

Think in Events, Not Pages

Instead of: "Track page views"
Think: "Track user journey events"

// Good: Specific events
appizer.track({ event: 'pricing_page_viewed' })
appizer.track({ event: 'demo_requested' })
appizer.track({ event: 'trial_started' })

// Less useful: Generic page views
appizer.track({ event: 'page_view', properties: { url: '/pricing' } })

Properties Should Be Queryable

Only include properties you'll use for segmentation or analysis:

// Good: Queryable properties
appizer.track({
  event: 'purchase',
  properties: {
    amount: 99.99,
    plan: 'pro',
    billingCycle: 'annual'
  }
})

// Avoid: Non-queryable data
appizer.track({
  event: 'purchase',
  properties: {
    fullTransactionLog: '...' // Too detailed
  }
})

User Traits Should Be Stable

Update traits when they change, not on every event:

// Good: Update when changed
appizer.identify({
  userId: 'user_123',
  traits: { plan: 'enterprise' } // User upgraded
})

// Avoid: Redundant updates
appizer.identify({
  userId: 'user_123',
  traits: { email: 'same@email.com' } // No change
})

Common Patterns

Funnel Tracking

Track each step of a conversion funnel:

appizer.track({ event: 'funnel_step_1_viewed' })
appizer.track({ event: 'funnel_step_2_started' })
appizer.track({ event: 'funnel_step_3_completed' })

Feature Usage

Track feature adoption and usage:

appizer.track({
  event: 'feature_used',
  properties: {
    feature: 'advanced_analytics',
    action: 'report_generated'
  }
})

Error Tracking

Track errors for monitoring:

appizer.track({
  event: 'error_occurred',
  properties: {
    errorType: 'ValidationError',
    errorMessage: 'Invalid email format',
    context: 'signup_form'
  }
})

Next Steps