React Router Integration
React Router is the most common SPA setup. Pulsora works out of the box—this guide stitches together the provider, pageview tracking, and event hooks.
Install Packages
npm install @pulsora/react @pulsora/core
Wrap Your App
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { PulsoraProvider } from '@pulsora/react';
import { App } from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<PulsoraProvider config={{ apiToken: import.meta.env.VITE_PULSORA_TOKEN }}>
<BrowserRouter>
<App />
</BrowserRouter>
</PulsoraProvider>
</React.StrictMode>,
);
Track Pageviews
Create a bridge component that listens to router changes and triggers usePageview():
// src/analytics/pageviews.tsx
import { useLocation } from 'react-router-dom';
import { usePageview } from '@pulsora/react';
export function PageviewTracker() {
const location = useLocation();
usePageview({ trigger: location.pathname + location.search });
return null;
}
Use Hooks in Routes
// src/App.tsx
import { Routes, Route } from 'react-router-dom';
import { PageviewTracker } from './analytics/pageviews';
import { useEvent } from '@pulsora/react';
function Home() {
const trackEvent = useEvent();
return (
<button
className="btn btn-primary"
onClick={() => trackEvent('cta_click', { plan: 'starter' })}
>
Start free trial
</button>
);
}
export function App() {
return (
<>
<PageviewTracker />
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</>
);
}
Capturing Checkout Metadata
import { usePulsora } from '@pulsora/react';
function CheckoutButton() {
const pulsora = usePulsora();
const handleClick = async () => {
const fingerprint = await pulsora?.getVisitorFingerprint();
const sessionId = pulsora?.getSessionId();
await fetch('/api/create-checkout', {
method: 'POST',
body: JSON.stringify({
priceId: 'price_123',
visitor_fingerprint: fingerprint,
session_id: sessionId,
}),
});
};
return <button onClick={handleClick}>Buy now</button>;
}
Revenue Webhook (Node.js)
import { Revenue } from '@pulsora/revenue';
const revenue = new Revenue({
apiToken: process.env.PULSORA_SECRET!,
});
app.post('/webhooks/stripe', async (req, res) => {
const session = req.body.data.object;
await revenue.track({
visitor_fingerprint: session.metadata.visitor_fingerprint,
session_id: session.metadata.session_id,
customer_id: session.customer,
amount: session.amount_total / 100,
currency: session.currency.toUpperCase(),
transaction_id: session.id,
payment_processor: 'stripe',
event_type: 'subscription',
customer_subscription_id: session.subscription,
is_recurring: true,
});
res.json({ received: true });
});
Troubleshooting
- Multiple pageviews per route — Ensure
PageviewTrackerrenders once at the top level. - Null pulsora instance — Guard
usePulsora()return values until initialization completes. - Revenue errors — Double-check that checkout metadata contains
visitor_fingerprintandsession_id.
Need Stripe-specific steps? Jump to the Stripe guide →