Hooks Reference
Complete documentation for all hooks provided by @pulsora/react.
Available Hooks
usePulsora- Access the Pulsora instanceusePageview- Track pageviews automaticallyuseEvent- Track custom events
usePulsora
Access the underlying Pulsora instance for advanced use cases.
Syntax
usePulsora(): PulsoraCore
Returns
The initialized Pulsora instance from @pulsora/core.
Example
import { usePulsora } from '@pulsora/react';
function AdvancedTracking() {
const pulsora = usePulsora();
const handleCheckout = async () => {
// Get attribution data for payment
const fingerprint = await pulsora.getVisitorFingerprint();
const sessionId = pulsora.getSessionId();
// Send to payment processor
await createCheckout({
visitor_fingerprint: fingerprint,
session_id: sessionId,
});
};
return <button onClick={handleCheckout}>Checkout</button>;
}
Use Cases
- Access visitor fingerprint for attribution
- Get session ID for server correlation
- Check initialization status
- Access advanced Pulsora methods
TypeScript
import { usePulsora } from '@pulsora/react';
import type { PulsoraCore } from '@pulsora/core';
function Component() {
const pulsora: PulsoraCore = usePulsora();
// Full type safety
}
usePageview
Automatically track pageviews with optional triggers.
Syntax
usePageview(options?: UsePageviewOptions): void
interface UsePageviewOptions {
trigger?: any; // Value that triggers pageview when changed
disabled?: boolean; // Disable tracking
}
Parameters
options(optional) - Configuration objecttrigger- Any value that triggers a pageview when it changesdisabled- Set totrueto disable tracking
Examples
Basic Usage
import { usePageview } from '@pulsora/react';
function Page() {
usePageview(); // Tracks once on mount
return <div>Page Content</div>;
}
With React Router
import { useLocation } from 'react-router-dom';
import { usePageview } from '@pulsora/react';
function App() {
const location = useLocation();
// Track pageview on route change
usePageview({ trigger: location.pathname });
return <Routes>...</Routes>;
}
With Next.js App Router
'use client';
import { usePathname } from 'next/navigation';
import { usePageview } from '@pulsora/react';
export function PageviewTracker() {
const pathname = usePathname();
usePageview({ trigger: pathname });
return null;
}
Conditional Tracking
function ConditionalPage({ shouldTrack }) {
usePageview({
disabled: !shouldTrack,
});
return <div>...</div>;
}
Custom Pageview Data
import { usePulsora, usePageview } from '@pulsora/react';
function CustomPageview() {
const pulsora = usePulsora();
const [category, setCategory] = useState('all');
// Track category changes as pageviews
usePageview({ trigger: category });
// Or manually with custom data
const trackCustomPageview = () => {
pulsora.pageview({
url: `/products?category=${category}`,
title: `Products - ${category}`,
});
};
return (
<select onChange={(e) => setCategory(e.target.value)}>
<option value="all">All Products</option>
<option value="electronics">Electronics</option>
</select>
);
}
Best Practices
- Route-Level Tracking: Place
usePageviewat the router level for SPAs - Avoid Duplicates: Don't use in every component if using route-level tracking
- Meaningful Triggers: Use values that represent actual navigation
useEvent
Track custom events with a simple function interface.
Syntax
useEvent(): TrackEventFunction
type TrackEventFunction = (
eventName: string,
eventData?: Record<string, any>
) => Promise<void>
Returns
A function to track events.
Examples
Basic Event Tracking
import { useEvent } from '@pulsora/react';
function Button() {
const trackEvent = useEvent();
return <button onClick={() => trackEvent('button_click')}>Click Me</button>;
}
Event with Properties
function ProductCard({ product }) {
const trackEvent = useEvent();
const handleAddToCart = () => {
trackEvent('add_to_cart', {
product_id: product.id,
product_name: product.name,
price: product.price,
currency: 'USD',
category: product.category,
});
// Add to cart logic...
};
return (
<div>
<h3>{product.name}</h3>
<button onClick={handleAddToCart}>Add to Cart</button>
</div>
);
}
Form Tracking
function ContactForm() {
const trackEvent = useEvent();
const [formStarted, setFormStarted] = useState(false);
const handleFocus = () => {
if (!formStarted) {
trackEvent('form_start', { form_id: 'contact' });
setFormStarted(true);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
trackEvent('form_submit', {
form_id: 'contact',
fields_filled: ['name', 'email', 'message'],
});
// Submit form...
};
return (
<form onSubmit={handleSubmit}>
<input name="email" onFocus={handleFocus} />
<button type="submit">Submit</button>
</form>
);
}
Video Tracking
function VideoPlayer({ video }) {
const trackEvent = useEvent();
const [progress, setProgress] = useState(0);
const handlePlay = () => {
trackEvent('video_play', {
video_id: video.id,
video_title: video.title,
duration: video.duration,
});
};
const handleProgress = (currentTime) => {
const percentage = (currentTime / video.duration) * 100;
// Track quartiles
if (percentage >= 25 && progress < 25) {
trackEvent('video_progress', {
video_id: video.id,
milestone: '25%',
});
setProgress(25);
}
// ... track 50%, 75%, 100%
};
return (
<video
onPlay={handlePlay}
onTimeUpdate={(e) => handleProgress(e.target.currentTime)}
>
<source src={video.url} />
</video>
);
}
Error Tracking
function ErrorBoundary({ children }) {
const trackEvent = useEvent();
const logError = (error, errorInfo) => {
trackEvent('javascript_error', {
message: error.toString(),
stack: error.stack?.substring(0, 500),
component_stack: errorInfo.componentStack?.substring(0, 500),
});
};
return <ReactErrorBoundary onError={logError}>{children}</ReactErrorBoundary>;
}
TypeScript
import { useEvent } from '@pulsora/react';
interface CartEvent {
product_id: string;
price: number;
quantity: number;
}
function Cart() {
const trackEvent = useEvent();
const addToCart = (product: Product) => {
const eventData: CartEvent = {
product_id: product.id,
price: product.price,
quantity: 1,
};
trackEvent('add_to_cart', eventData);
};
}
Hook Composition
Custom Analytics Hook
function useAnalytics() {
const pulsora = usePulsora();
const trackEvent = useEvent();
const trackPurchase = async (orderData) => {
const fingerprint = await pulsora.getVisitorFingerprint();
const sessionId = pulsora.getSessionId();
await trackEvent('purchase', {
order_id: orderData.id,
total: orderData.total,
items: orderData.items.length,
});
// Send attribution data to backend
return { fingerprint, sessionId };
};
return {
trackEvent,
trackPurchase,
};
}
Page Analytics Hook
function usePageAnalytics(pageName: string) {
const trackEvent = useEvent();
const startTime = useRef(Date.now());
usePageview();
useEffect(() => {
// Track page view duration on unmount
return () => {
const duration = Date.now() - startTime.current;
trackEvent('page_view_duration', {
page: pageName,
duration_ms: duration,
duration_seconds: Math.round(duration / 1000),
});
};
}, [pageName, trackEvent]);
const trackInteraction = (action: string, data?: any) => {
trackEvent(`${pageName}_${action}`, {
page: pageName,
...data,
});
};
return { trackInteraction };
}
// Usage
function ProductPage({ product }) {
const { trackInteraction } = usePageAnalytics('product_detail');
return (
<div>
<button
onClick={() =>
trackInteraction('add_to_wishlist', {
product_id: product.id,
})
}
>
Add to Wishlist
</button>
</div>
);
}
Error Handling
Safe Event Tracking
function useSafeEvent() {
const trackEvent = useEvent();
return useCallback(
async (name: string, data?: any) => {
try {
await trackEvent(name, data);
} catch (error) {
console.error('Analytics error:', error);
// Don't let analytics errors break the app
}
},
[trackEvent],
);
}
Provider Error Boundary
function AnalyticsProvider({ children, config }) {
return (
<ErrorBoundary fallback={<>{children}</>}>
<PulsoraProvider config={config}>{children}</PulsoraProvider>
</ErrorBoundary>
);
}
Testing
Mock Hooks
// __mocks__/@pulsora/react.ts
export const usePageview = jest.fn();
export const useEvent = jest.fn(() => jest.fn());
export const usePulsora = jest.fn(() => ({
getVisitorFingerprint: jest.fn(() => 'test_fp'),
getSessionId: jest.fn(() => 'test_session'),
}));
Component Tests
import { render, fireEvent } from '@testing-library/react';
import { useEvent } from '@pulsora/react';
jest.mock('@pulsora/react');
test('tracks button click', () => {
const mockTrackEvent = jest.fn();
(useEvent as jest.Mock).mockReturnValue(mockTrackEvent);
const { getByText } = render(<Button />);
fireEvent.click(getByText('Click Me'));
expect(mockTrackEvent).toHaveBeenCalledWith('button_click');
});
Performance
Memoization
function OptimizedTracking() {
const trackEvent = useEvent();
// Memoize event handler
const handleClick = useCallback(() => {
trackEvent('expensive_calculation', {
timestamp: Date.now(),
});
}, [trackEvent]);
return <ExpensiveComponent onClick={handleClick} />;
}
Debounced Tracking
function SearchBox() {
const trackEvent = useEvent();
const trackSearch = useMemo(
() =>
debounce((query: string) => {
trackEvent('search', { query });
}, 1000),
[trackEvent],
);
return (
<input
onChange={(e) => trackSearch(e.target.value)}
placeholder="Search..."
/>
);
}
Next Steps
- Provider Setup - Configure PulsoraProvider
- Examples - Real-world implementations
- SSR Support - Server-side rendering guide
- API Reference - Core package methods