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',
});