Event Tracking
Learn how to track feature usage, exposure, and user identification
Event Tracking
Learn how to track user interactions and feature usage in your Next.js application using Adopture's React hooks.
Basic Event Tracking
The most common way to track events is using the useTrack hook:
'use client';
import { useTrack } from '@adopture/next';
export function FeatureButton() {
const { track } = useTrack();
const handleClick = () => {
// SDK automatically determines activation vs usage
track('feature-button-click', {
location: 'sidebar',
timestamp: new Date().toISOString(),
});
};
return (
<button onClick={handleClick}>
Use Feature
</button>
);
}Feature Exposure Tracking
Track when users see features using the useExpose hook:
'use client';
import { useExpose } from '@adopture/next';
import { useEffect } from 'react';
export function FeatureBanner() {
const { expose } = useExpose();
useEffect(() => {
// Track when the banner becomes visible
expose('new-feature-banner', 'homepage-banner', {
position: 'top',
campaign: 'feature-launch',
});
}, [expose]);
return (
<div className="banner">
Check out our new feature!
</div>
);
}Automatic Component Tracking
For simpler exposure tracking, use the useComponentTracking hook:
'use client';
import { useComponentTracking, useTrack } from '@adopture/next';
export function ProductCard({ productId }: { productId: string }) {
const { track } = useTrack();
// Automatically track when component is visible
useComponentTracking('product-card-view', {
exposureChannel: 'product-listing',
metadata: {
productId,
section: 'featured-products',
},
});
const handlePurchase = () => {
track('product-purchase-click', {
productId,
source: 'product-card',
});
};
return (
<div className="product-card">
<h3>Product {productId}</h3>
<button onClick={handlePurchase}>
Buy Now
</button>
</div>
);
}User Identification
Identify users to track their journey across sessions:
'use client';
import { useIdentify } from '@adopture/next';
import { useState } from 'react';
export function LoginForm() {
const { identify } = useIdentify();
const [email, setEmail] = useState('');
const handleLogin = async (userId: string) => {
// Identify the user with their properties
await identify(userId, {
email,
plan: 'pro',
signupDate: '2024-01-15',
company: 'Acme Corp',
});
// Now all future events will be associated with this user
};
return (
<form onSubmit={(e) => {
e.preventDefault();
handleLogin('user-123');
}}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<button type="submit">Login</button>
</form>
);
}Main Tracking Hook
For full control, use the useAdoptureTracking hook which combines all functionality:
'use client';
import { useAdoptureTracking } from '@adopture/next';
export function AdvancedComponent() {
const { track, expose, identify, isInitialized } = useAdoptureTracking();
const handleComplexAction = async () => {
if (!isInitialized) {
console.log('Adopture not ready yet');
return;
}
// Track feature usage
await track('complex-action', {
step: 'initiated',
timestamp: new Date().toISOString(),
});
// Expose a related feature
await expose('related-feature', 'action-flow', {
trigger: 'complex-action',
});
};
return (
<button onClick={handleComplexAction}>
Complex Action
</button>
);
}Metadata Best Practices
Include meaningful metadata with your events:
// ✅ Good metadata
track('button-click', {
buttonType: 'primary',
location: 'navbar',
section: 'user-menu',
variant: 'cta',
timestamp: new Date().toISOString(),
});
// ❌ Avoid metadata with sensitive information
track('user-action', {
email: 'user@example.com', // Don't include PII
password: '***', // Never include passwords
creditCard: '****', // No financial data
});Event Naming Conventions
Use consistent naming for your events:
// ✅ Good naming - descriptive and consistent
track('feature-dashboard-opened');
track('export-button-clicked');
track('settings-saved');
// ❌ Inconsistent naming
track('dash_open');
track('clickExport');
track('save-settings');Error Handling
Handle tracking errors gracefully:
'use client';
import { useTrack } from '@adopture/next';
export function RobustComponent() {
const { track, isReady } = useTrack();
const handleAction = async () => {
try {
if (!isReady) {
console.warn('Tracking not ready, action will be queued');
}
await track('important-action', {
timestamp: new Date().toISOString(),
});
} catch (error) {
console.error('Failed to track event:', error);
// Continue with the user action regardless
}
};
return (
<button onClick={handleAction}>
Important Action
</button>
);
}Conditional Tracking
Track events only when certain conditions are met:
'use client';
import { useTrack } from '@adopture/next';
export function ConditionalTracking({ userPlan }: { userPlan: string }) {
const { track } = useTrack();
const handlePremiumFeature = () => {
// Only track for premium users
if (userPlan === 'premium') {
track('premium-feature-used', {
feature: 'advanced-analytics',
plan: userPlan,
});
}
};
return (
<button onClick={handlePremiumFeature}>
Premium Feature
</button>
);
}Client-Side Only
Remember that all tracking hooks require the 'use client' directive:
'use client'; // Required for all components using Adopture hooks
import { useTrack } from '@adopture/next';
export function ClientComponent() {
const { track } = useTrack();
// Component logic...
}Next Steps
Common Patterns
Form Tracking
const handleSubmit = (formData) => {
track('form-submitted', {
formType: 'contact',
fields: Object.keys(formData),
timestamp: new Date().toISOString(),
});
};Page View Tracking
useEffect(() => {
expose('page-view', 'navigation', {
page: router.pathname,
referrer: document.referrer,
});
}, [router.pathname]);Feature Flag Integration
if (featureFlag.isEnabled('new-feature')) {
expose('new-feature', 'feature-flag');
}