Skip to content

Best Practices

Guidelines for effective event tracking and getting the most from LoopKit's AI insights.

Event Design Principles

1. Use Clear, Consistent Naming

Good Examples:

javascript
LoopKit.track('user_signup', { method: 'email' });
LoopKit.track('level_completed', { level: 3 });
LoopKit.track('item_purchased', { item_id: 'sword_001' });

Avoid:

javascript
LoopKit.track('userSignUp', { method: 'email' }); // inconsistent casing
LoopKit.track('clicked', { button: 'signup' }); // too generic
LoopKit.track('user does signup with email', {}); // too verbose

Convention:

  • Use snake_case for event names
  • Use verbs for actions (user_signup, level_completed)
  • Use nouns for states (page_view, session_start)

2. Include Relevant Context

Always include properties that help understand the who, what, when, and where:

javascript
LoopKit.track('feature_used', {
  feature: 'export_data', // what
  user_id: 'user123', // who
  user_plan: 'pro', // user context
  source: 'main_menu', // where
  session_id: 'session456', // when/context
  platform: 'web', // environment
});

3. Use Consistent Data Types

Keep property types consistent across events:

javascript
// Good - consistent types
LoopKit.track('purchase', {
  price: 29.99, // number
  currency: 'USD', // string
  item_count: 3, // number
  user_id: 'user123', // string
});

// Avoid - inconsistent types
LoopKit.track('purchase', {
  price: '29.99', // string instead of number
  item_count: '3', // string instead of number
});

Essential Events to Track

User Lifecycle

javascript
// Registration/Authentication
LoopKit.track('user_signup', {
  method: 'email|google|facebook',
  source: 'homepage|feature_page|referral',
  user_id: newUser.id,
});

LoopKit.track('user_login', {
  method: 'email|google|facebook',
  user_id: user.id,
  session_id: session.id,
});

// Onboarding
LoopKit.track('onboarding_step_completed', {
  step: 1,
  step_name: 'profile_setup',
  user_id: user.id,
});

LoopKit.track('onboarding_completed', {
  total_steps: 5,
  time_to_complete: 180, // seconds
  user_id: user.id,
});

Feature Usage

javascript
// Core feature interactions
LoopKit.track('feature_used', {
  feature: 'data_export',
  user_id: user.id,
  context: 'dashboard|settings|main_menu',
  is_first_use: true,
});

// Feature discovery
LoopKit.track('feature_discovered', {
  feature: 'advanced_filters',
  discovery_method: 'tooltip|exploration|tutorial',
  user_id: user.id,
});

Business Events

javascript
// Purchases/Upgrades
LoopKit.track('subscription_started', {
  plan: 'pro|enterprise',
  billing_cycle: 'monthly|annual',
  price: 29.99,
  currency: 'USD',
  user_id: user.id,
});

LoopKit.track('trial_started', {
  plan: 'pro',
  trial_length_days: 14,
  user_id: user.id,
});

User Engagement

javascript
// Session tracking
LoopKit.track('session_started', {
  platform: 'web|unity',
  device_type: 'mobile|desktop|tablet',
  user_id: user.id,
});

// Content interaction
LoopKit.track('content_viewed', {
  content_type: 'tutorial|documentation|blog_post',
  content_id: 'getting-started-guide',
  time_spent: 120, // seconds
  user_id: user.id,
});

Game-Specific Best Practices

Player Progression

csharp
// Level progression
LoopKit.Track("level_started", new {
    level = 3,
    difficulty = "normal",
    player_level = 15,
    player_id = playerId
});

LoopKit.Track("level_completed", new {
    level = 3,
    completion_time = 240, // seconds
    score = 8500,
    deaths = 2,
    player_id = playerId
});

// Player advancement
LoopKit.Track("player_level_up", new {
    old_level = 14,
    new_level = 15,
    experience_gained = 1500,
    total_experience = 45000,
    player_id = playerId
});

Game Economy

csharp
// In-game purchases
LoopKit.Track("item_purchased", new {
    item_id = "health_potion",
    item_category = "consumable",
    cost = 50,
    currency_type = "gold",
    player_level = 15,
    player_id = playerId
});

// Currency tracking
LoopKit.Track("currency_earned", new {
    amount = 100,
    currency_type = "gold",
    source = "quest_completion",
    player_level = 15,
    player_id = playerId
});

Performance Optimization

Batch Events for High Volume

javascript
// For high-frequency events, consider batching
const eventQueue = [];

function trackEvent(event, properties) {
  eventQueue.push({ event, properties });

  // Send in batches of 50 or every 30 seconds
  if (eventQueue.length >= 50) {
    flushEvents();
  }
}

function flushEvents() {
  if (eventQueue.length > 0) {
    LoopKit.trackBatch(eventQueue);
    eventQueue.length = 0;
  }
}

// Flush remaining events periodically
setInterval(flushEvents, 30000);

Avoid Over-Tracking

Don't track everything:

  • Mouse movements
  • Scroll events (unless specifically needed)
  • Rapid repeated actions
  • Debug/development events in production

Do track meaningful interactions:

  • User decisions
  • Goal completions
  • Error states
  • Key user journeys

Privacy Considerations

Anonymous Tracking

javascript
// Use anonymous IDs when possible
const anonymousId = localStorage.getItem('anonymous_id') || generateUUID();

LoopKit.track('page_view', {
  page: '/pricing',
  anonymous_id: anonymousId,
  // no email, name, or PII
});

Opt-Out Support

javascript
// Respect user privacy preferences
const analyticsEnabled = getUserPrivacyPreference('analytics');

if (analyticsEnabled) {
  LoopKit.track('feature_used', {
    feature: 'export',
    user_id: user.id,
  });
}

Error Handling

Graceful Degradation

javascript
function trackEvent(event, properties) {
  try {
    LoopKit.track(event, properties);
  } catch (error) {
    // Log error but don't break user experience
    console.warn('Analytics tracking failed:', error);

    // Optionally queue for retry
    queueForRetry(event, properties);
  }
}

Development vs Production

javascript
// Different tracking for different environments
const isDev = process.env.NODE_ENV === 'development';

if (!isDev) {
  LoopKit.track('user_signup', {
    method: 'email',
    source: 'homepage',
    user_id: user.id,
  });
}

Testing Your Events

Validate Event Structure

javascript
function validateEvent(event, properties) {
  // Check required fields
  if (!event || typeof event !== 'string') {
    throw new Error('Event name is required and must be string');
  }

  // Check for common mistakes
  if (event.includes(' ')) {
    console.warn('Event name contains spaces, consider snake_case');
  }

  // Validate properties
  if (properties) {
    Object.keys(properties).forEach((key) => {
      if (key.includes(' ')) {
        console.warn(`Property "${key}" contains spaces`);
      }
    });
  }
}

Debug Mode

javascript
// Enable detailed logging in development
if (isDevelopment) {
  LoopKit.enableDebugMode(true);
}

Common Mistakes to Avoid

❌ Don't Do This

javascript
// Too generic
LoopKit.track('click');

// Inconsistent naming
LoopKit.track('userSignUp');
LoopKit.track('user_login');

// Missing context
LoopKit.track('error');

// PII in events
LoopKit.track('user_signup', {
  email: 'user@example.com', // Don't include email
  name: 'John Doe', // Don't include real name
});

✅ Do This Instead

javascript
// Specific and descriptive
LoopKit.track('signup_button_clicked');

// Consistent naming
LoopKit.track('user_signup');
LoopKit.track('user_login');

// Rich context
LoopKit.track('api_error', {
  endpoint: '/api/users',
  status_code: 500,
  error_type: 'timeout',
});

// Privacy-safe
LoopKit.track('user_signup', {
  method: 'email',
  source: 'homepage',
  user_id: 'anonymous_123', // Use anonymous/hashed IDs
});

Next Steps


Need help implementing these practices? Join our Discord for community support.

Context Enrichment

System Information

Include relevant system context:

javascript
track('app_opened', {
  // App context
  app_version: '2.1.0',
  platform: 'web', // or 'unity'

  // Device context (for games)
  screen_resolution: '1920x1080',
  graphics_quality: 'high',

  // User context
  user_level: 15,
  subscription_status: 'premium',
});