Client-side Tracking
Track events in web browsers using the core Better Analytics client SDK. This guide covers vanilla JavaScript, React, and other web frameworks.
Installation
pnpm add better-analyticsBasic Usage
Manual Initialization
import { init, trackPageview, track } from 'better-analytics'
// Initialize once
init({
site: 'your-site-id',
endpoint: 'https://your-endpoint.com/api/collect', // Optional
debug: false // Enable console logging
})
// Track page views
trackPageview()
// Track custom events
track('button_click', {
button: 'hero-cta',
location: 'homepage'
})Quick Start with Pageview
import { initWithPageview } from 'better-analytics'
// Initialize and track pageview in one call
initWithPageview({
site: 'your-site-id'
})Configuration
import { init } from 'better-analytics'
init({
site: 'your-site-id', // Required
endpoint: '/api/collect', // Optional, defaults to SaaS
mode: 'auto', // auto | development | production
debug: false, // Enable console logging
beforeSend: (event) => event // Transform events before sending
})Core Functions
track(event, props?)
Track custom events with optional properties:
import { track } from 'better-analytics'
// Simple event
track('button_click')
// Event with properties
track('purchase', {
value: 99.99,
currency: 'USD',
items: ['product-1', 'product-2']
})
// User interaction
track('video_play', {
video_id: 'intro-video',
duration: 120,
position: 'hero'
})trackPageview(path?)
Track page views:
import { trackPageview } from 'better-analytics'
// Track current page
trackPageview()
// Track specific path
trackPageview('/custom-path')identify(userId, traits?)
Identify users for session continuity:
import { identify } from 'better-analytics'
// Basic identification
identify('user-123')
// With user traits
identify('user-123', {
email: 'user@example.com',
plan: 'premium',
signup_date: '2024-01-15'
})Framework Examples
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<button id="cta-button">Sign Up</button>
<script type="module">
import { init, trackPageview, track } from 'https://esm.sh/better-analytics'
// Initialize
init({ site: 'your-site-id' })
trackPageview()
// Track interactions
document.getElementById('cta-button').addEventListener('click', () => {
track('cta_click', { location: 'hero' })
})
</script>
</body>
</html>Automatic Data Collection
Client events automatically include:
{
// Session tracking
sessionId: "1704067200000_abc123",
deviceId: "persistent-device-id",
// Page context
url: "https://example.com/page",
referrer: "https://google.com",
// Device information
device: {
userAgent: "Mozilla/5.0...",
screenWidth: 1920,
screenHeight: 1080,
viewportWidth: 1200,
viewportHeight: 800,
language: "en-US",
timezone: "America/New_York",
connectionType: "4g"
},
// Page information
page: {
title: "Page Title",
pathname: "/page",
hostname: "example.com",
loadTime: 1250
},
// UTM parameters (if present)
utm: {
source: "google",
medium: "cpc",
campaign: "summer-sale"
}
}Single Page Applications
Route Changes
For SPAs, track route changes manually:
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import { trackPageview } from 'better-analytics'
function App() {
const location = useLocation()
useEffect(() => {
trackPageview(location.pathname)
}, [location.pathname])
return <Router />
}Route Computation
Automatically compute route patterns for dynamic routes:
import { computeRoute } from 'better-analytics'
// Convert dynamic paths to patterns
const route = computeRoute('/user/123/settings', { id: '123' })
// Returns: '/user/[id]/settings'
// Track with computed route
track('page_view', { route })Event Queueing
Events are automatically queued before SDK initialization:
<script>
// Events are queued automatically
window.ba = window.ba || function() { (window.ba.q = window.ba.q || []).push(arguments) }
// These events are queued until SDK loads
ba('track', 'early_event', { timestamp: Date.now() })
</script>
<script type="module">
import { init } from 'better-analytics'
// SDK processes queued events on init
init({ site: 'your-site-id' })
</script>Offline Support
Events are automatically stored when offline and sent when connectivity is restored:
// Events are queued automatically when offline
track('offline_event', { data: 'important' })
// Check queue status
import { getQueueSize } from 'better-analytics/queue'
console.log('Queued events:', getQueueSize())Privacy & Data Control
BeforeSend Middleware
Transform or filter events before sending:
init({
site: 'your-site-id',
beforeSend: (event) => {
// Filter sensitive data
if (event.data?.props?.email) {
delete event.data.props.email
}
// Add custom data
event.data.environment = 'production'
// Cancel event by returning null
if (event.name === 'internal_event') {
return null
}
return event
}
})Session Management
Sessions are automatically managed with 30-minute timeout:
- Session ID: Refreshed on activity, expires after 30 minutes
- Device ID: Persistent identifier stored in localStorage
- User ID: Set via
identify()and persists across sessions
Development vs Production
// Development behavior - events logged to console
init({ site: 'your-site-id', debug: true })
track('test_event') // Logs to console, doesn't send to server
// Enable debug mode explicitly
init({
site: 'your-site-id',
mode: 'development',
debug: true
})Error Handling
The SDK fails silently by default to avoid breaking your application:
// Enable debug mode to see errors
init({
site: 'your-site-id',
debug: true
})
// Errors are logged to console in debug mode
track('event_with_error', { invalid: undefined })TypeScript Support
Full TypeScript support with type definitions:
import type { AnalyticsConfig, EventData, BeforeSend } from 'better-analytics'
const config: AnalyticsConfig = {
site: 'your-site-id',
debug: true,
beforeSend: (event) => {
// Type-safe event transformation
return event
}
}
// Type-safe event tracking
interface CustomEventProps {
category: string
value: number
}
track('custom_event', {
category: 'user_action',
value: 100
} as CustomEventProps)Best Practices
- Initialize early - Call
init()as soon as possible in your app - Use environment detection - Let the SDK detect development vs production
- Track meaningful events - Focus on user actions that matter to your business
- Use beforeSend for privacy - Filter sensitive data before sending
- Enable debug in development - Monitor events during development
- Handle SPAs properly - Track route changes in single-page applications
Common Patterns
// Product view
track('product_viewed', {
product_id: 'item-123',
category: 'electronics',
price: 299.99,
currency: 'USD'
})
// Add to cart
track('add_to_cart', {
product_id: 'item-123',
quantity: 1,
value: 299.99
})
// Purchase
track('purchase', {
transaction_id: 'txn-456',
value: 299.99,
currency: 'USD',
items: ['item-123']
})Troubleshooting
Events not appearing
- Check that site ID is set correctly
- Verify initialization is called before tracking
- Enable debug mode to see console logs
- Check network tab for outgoing requests
Development vs Production
- Development: Events are logged to console by default
- Production: Events are sent to the configured endpoint
- Use
debug: trueto see events in production console
Session Issues
- Check localStorage availability
- Verify session timeout (30 minutes)
- Use browser dev tools to inspect stored data
- Test across different browsers and devices
How is this guide?