Analytics Hooks
useAnalytics hook: access the analytics tracker to send custom events and track tour interactions in React components
Overview
User Tour Kit provides two hooks for accessing the analytics tracker in your components:
useAnalytics()- Throws error if not in provider (strict)useAnalyticsOptional()- Returnsnullif not in provider (lenient)
useAnalytics
Access the analytics tracker with strict provider enforcement.
Usage
import { useAnalytics } from '@tour-kit/analytics'
function MyComponent() {
const analytics = useAnalytics()
const handleClick = () => {
analytics.track('feature_used', {
tourId: 'feature-demo',
metadata: { feature: 'export-data' }
})
}
return <button onClick={handleClick}>Export</button>
}Error Handling
This hook throws an error if used outside an AnalyticsProvider:
// This will throw an error
function BadComponent() {
const analytics = useAnalytics() // Error: useAnalytics must be used within AnalyticsProvider
return <div>...</div>
}Always ensure components using useAnalytics are rendered within an AnalyticsProvider.
When to Use
Use useAnalytics() when:
- Analytics are required for the component to function
- You want to catch configuration errors early
- The component is always rendered within a provider
useAnalyticsOptional
Access the analytics tracker with optional provider support.
Usage
import { useAnalyticsOptional } from '@tour-kit/analytics'
function OptionalTrackingComponent() {
const analytics = useAnalyticsOptional()
const handleClick = () => {
// Only track if analytics is available
analytics?.track('button_clicked', {
tourId: 'optional-feature',
metadata: { source: 'sidebar' }
})
}
return <button onClick={handleClick}>Click Me</button>
}Null Safety
This hook returns null when not in a provider:
function SafeComponent() {
const analytics = useAnalyticsOptional()
if (!analytics) {
// Analytics not configured - component still works
return <div>No tracking</div>
}
return <div>Tracking enabled</div>
}When to Use
Use useAnalyticsOptional() when:
- Analytics are nice-to-have but not required
- The component should work without a provider
- You're building reusable components for multiple apps
Tracking Custom Events
Feature Usage
Track when users interact with specific features:
import { useAnalytics } from '@tour-kit/analytics'
function AdvancedSearch() {
const analytics = useAnalytics()
const handleSearch = (query: string, filters: string[]) => {
analytics.track('feature_used', {
tourId: 'advanced-search',
metadata: {
query_length: query.length,
filter_count: filters.length,
filters: filters.join(',')
}
})
}
return <SearchForm onSubmit={handleSearch} />
}Step Interactions
Track user interactions within tour steps:
import { useAnalytics } from '@tour-kit/analytics'
import { useTour } from '@tour-kit/core'
function InteractiveTourStep() {
const analytics = useAnalytics()
const { tourId, currentStep } = useTour()
const handleVideoPlay = () => {
analytics.stepInteraction(
tourId,
currentStep.id,
'video_played',
{ video_duration: 120 }
)
}
return (
<div>
<video onPlay={handleVideoPlay}>...</video>
</div>
)
}User Identification
Identify users after authentication:
'use client'
import { useAnalytics } from '@tour-kit/analytics'
import { useEffect } from 'react'
function UserIdentifier({ user }) {
const analytics = useAnalytics()
useEffect(() => {
if (user) {
analytics.identify(user.id, {
email: user.email,
plan: user.plan,
signup_date: user.createdAt
})
}
}, [user, analytics])
return null
}TourAnalytics Methods
The analytics object returned by both hooks provides these methods:
Identification
// Identify a user
analytics.identify(userId: string, properties?: Record<string, unknown>)Raw Event Tracking
// Track any event type
analytics.track(
eventName: TourEventName,
data: TourEventData
)Tour Lifecycle
// Track tour start
analytics.tourStarted(tourId: string, totalSteps: number, metadata?: Record<string, unknown>)
// Track tour completion
analytics.tourCompleted(tourId: string, metadata?: Record<string, unknown>)
// Track tour skip
analytics.tourSkipped(
tourId: string,
stepIndex: number,
stepId?: string,
metadata?: Record<string, unknown>
)
// Track tour abandonment
analytics.tourAbandoned(
tourId: string,
stepIndex: number,
stepId?: string,
metadata?: Record<string, unknown>
)Step Lifecycle
// Track step view
analytics.stepViewed(
tourId: string,
stepId: string,
stepIndex: number,
totalSteps: number,
metadata?: Record<string, unknown>
)
// Track step completion
analytics.stepCompleted(
tourId: string,
stepId: string,
stepIndex: number,
metadata?: Record<string, unknown>
)
// Track step skip
analytics.stepSkipped(
tourId: string,
stepId: string,
stepIndex: number,
metadata?: Record<string, unknown>
)
// Track step interaction
analytics.stepInteraction(
tourId: string,
stepId: string,
interactionType: string,
metadata?: Record<string, unknown>
)Hint Tracking
// Track hint shown
analytics.hintShown(hintId: string, metadata?: Record<string, unknown>)
// Track hint dismissed
analytics.hintDismissed(hintId: string, metadata?: Record<string, unknown>)
// Track hint clicked
analytics.hintClicked(hintId: string, metadata?: Record<string, unknown>)Utility Methods
// Flush queued events immediately
await analytics.flush()
// Clean up and destroy tracker
analytics.destroy()Type Safety
Both hooks return a fully typed TourAnalytics instance:
import { useAnalytics } from '@tour-kit/analytics'
import type { TourAnalytics } from '@tour-kit/analytics'
function TypedComponent() {
const analytics: TourAnalytics = useAnalytics()
// Full TypeScript autocomplete and type checking
analytics.track('tour_started', {
tourId: 'onboarding',
totalSteps: 5
})
return <div>...</div>
}Combining with Tour Hooks
Use analytics hooks alongside tour hooks for rich tracking:
import { useAnalytics } from '@tour-kit/analytics'
import { useTour } from '@tour-kit/core'
function TourWithAnalytics() {
const analytics = useAnalytics()
const { tourId, currentStep, next, skip } = useTour()
const handleNext = () => {
analytics.stepCompleted(tourId, currentStep.id, currentStep.index)
next()
}
const handleSkip = () => {
analytics.tourSkipped(tourId, currentStep.index, currentStep.id)
skip()
}
return (
<div>
<button onClick={handleNext}>Next</button>
<button onClick={handleSkip}>Skip Tour</button>
</div>
)
}Related
- AnalyticsProvider - Configure analytics
- Types - Event types and interfaces
- Plugins - Available analytics plugins