React Integration
Track your React single-page application with Ovyxa, including React Router integration and custom event tracking.
Installation
Add the Tracking Script
Add Ovyxa to your public/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My React App</title>
<!-- Ovyxa Analytics -->
<script async src="https://ingest.ovyxa.com/js/script.js" data-domain="YOUR_DOMAIN"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
That's it! Ovyxa will automatically track pageviews and route changes.
React Router Integration
For React Router v6, track route changes automatically.
Create Analytics Component
// src/components/Analytics.jsx
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
function Analytics() {
const location = useLocation()
useEffect(() => {
// Track pageview on route change
if (window.ovyxa) {
window.ovyxa('pageview', {
url: location.pathname + location.search
})
}
}, [location])
return null
}
export default Analytics
Add to Your App
// src/App.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Analytics from './components/Analytics'
import Home from './pages/Home'
import About from './pages/About'
function App() {
return (
<BrowserRouter>
<Analytics />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
)
}
export default App
Custom Events
Track user interactions with custom events.
Button Clicks
function SignupButton() {
const handleClick = () => {
// Track the event
window.ovyxa('event', 'SignupClick', {
location: 'homepage',
plan: 'free'
})
}
return (
<button onClick={handleClick}>
Sign Up
</button>
)
}
Form Submissions
function ContactForm() {
const handleSubmit = (e) => {
e.preventDefault()
// Track form submission
window.ovyxa('event', 'ContactForm', {
source: 'contact-page'
})
// Submit form...
}
return (
<form onSubmit={handleSubmit}>
<input type="email" name="email" />
<button type="submit">Submit</button>
</form>
)
}
Video Plays
function VideoPlayer({ videoId }) {
const handlePlay = () => {
window.ovyxa('event', 'VideoPlay', {
videoId: videoId,
page: window.location.pathname
})
}
return (
<video onPlay={handlePlay}>
<source src={`/videos/${videoId}.mp4`} />
</video>
)
}
Custom Hook
Create a reusable tracking hook:
// src/hooks/useTracking.js
import { useCallback } from 'react'
export function useTracking() {
const trackEvent = useCallback((eventName, properties = {}) => {
if (window.ovyxa) {
window.ovyxa('event', eventName, properties)
}
}, [])
const trackPageView = useCallback((url) => {
if (window.ovyxa) {
window.ovyxa('pageview', { url })
}
}, [])
return { trackEvent, trackPageView }
}
// Usage
import { useTracking } from './hooks/useTracking'
function MyComponent() {
const { trackEvent } = useTracking()
return (
<button onClick={() => trackEvent('Click', { button: 'cta' })}>
Click Me
</button>
)
}
TypeScript Support
Type-safe tracking with TypeScript:
// src/types/analytics.ts
declare global {
interface Window {
ovyxa: (
action: 'event' | 'pageview',
name: string,
properties?: Record<string, any>
) => void
}
}
export {}
// src/hooks/useTracking.ts
import { useCallback } from 'react'
interface EventProperties {
[key: string]: string | number | boolean
}
export function useTracking() {
const trackEvent = useCallback((
eventName: string,
properties?: EventProperties
) => {
window.ovyxa?.('event', eventName, properties)
}, [])
return { trackEvent }
}
Environment-Based Tracking
Only track in production:
// src/config/analytics.js
export const ANALYTICS_ENABLED = process.env.NODE_ENV === 'production'
export const SITE_ID = process.env.REACT_APP_OVYXA_SITE_ID
// src/hooks/useTracking.js
import { ANALYTICS_ENABLED } from '../config/analytics'
export function useTracking() {
const trackEvent = useCallback((eventName, properties) => {
if (ANALYTICS_ENABLED && window.ovyxa) {
window.ovyxa('event', eventName, properties)
}
}, [])
return { trackEvent }
}
Environment Variables
Create .env file:
# .env.production
REACT_APP_OVYXA_SITE_ID=your_site_id
# .env.development
REACT_APP_OVYXA_SITE_ID=dev_site_id
Tracking User Actions
E-commerce Tracking
function ProductCard({ product }) {
const { trackEvent } = useTracking()
const handleAddToCart = () => {
// Add to cart logic...
trackEvent('AddToCart', {
productId: product.id,
productName: product.name,
price: product.price,
category: product.category
})
}
return (
<div>
<h3>{product.name}</h3>
<p>${product.price}</p>
<button onClick={handleAddToCart}>Add to Cart</button>
</div>
)
}
function Checkout({ total }) {
const { trackEvent } = useTracking()
const handlePurchase = async () => {
// Process payment...
trackEvent('Purchase', {
revenue: total,
currency: 'USD',
items: cartItems.length
})
}
return (
<button onClick={handlePurchase}>
Complete Purchase
</button>
)
}
Feature Usage
function FeatureToggle() {
const { trackEvent } = useTracking()
const [enabled, setEnabled] = useState(false)
const handleToggle = () => {
setEnabled(!enabled)
trackEvent('FeatureToggle', {
feature: 'dark-mode',
enabled: !enabled
})
}
return (
<button onClick={handleToggle}>
{enabled ? 'Disable' : 'Enable'} Dark Mode
</button>
)
}
Context Provider
Create a global analytics context:
// src/contexts/AnalyticsContext.jsx
import React, { createContext, useContext, useCallback } from 'react'
const AnalyticsContext = createContext(null)
export function AnalyticsProvider({ children }) {
const trackEvent = useCallback((eventName, properties) => {
if (window.ovyxa) {
window.ovyxa('event', eventName, properties)
}
}, [])
const trackPageView = useCallback((url) => {
if (window.ovyxa) {
window.ovyxa('pageview', { url })
}
}, [])
return (
<AnalyticsContext.Provider value={{ trackEvent, trackPageView }}>
{children}
</AnalyticsContext.Provider>
)
}
export function useAnalytics() {
const context = useContext(AnalyticsContext)
if (!context) {
throw new Error('useAnalytics must be used within AnalyticsProvider')
}
return context
}
// Usage in App.jsx
import { AnalyticsProvider } from './contexts/AnalyticsContext'
function App() {
return (
<AnalyticsProvider>
<BrowserRouter>
<Routes>
{/* routes */}
</Routes>
</BrowserRouter>
</AnalyticsProvider>
)
}
// Usage in components
import { useAnalytics } from './contexts/AnalyticsContext'
function MyComponent() {
const { trackEvent } = useAnalytics()
return (
<button onClick={() => trackEvent('Click')}>
Track Me
</button>
)
}
Create React App
Works out of the box with Create React App. Just add the script to public/index.html.
Vite
For Vite projects:
// vite.config.js
export default {
// ... other config
define: {
'process.env.REACT_APP_OVYXA_SITE_ID': JSON.stringify(
process.env.VITE_OVYXA_SITE_ID
)
}
}
Testing
Mock analytics in tests:
// src/setupTests.js
beforeEach(() => {
window.ovyxa = jest.fn()
})
// src/MyComponent.test.jsx
import { render, fireEvent } from '@testing-library/react'
import MyComponent from './MyComponent'
test('tracks event on click', () => {
const { getByText } = render(<MyComponent />)
fireEvent.click(getByText('Sign Up'))
expect(window.ovyxa).toHaveBeenCalledWith('event', 'SignupClick', {
location: 'homepage'
})
})
Troubleshooting
Events Not Tracking
Check if script loaded:
console.log(typeof window.ovyxa) // Should be 'function'
Route Changes Not Tracked
Ensure Analytics component is rendered inside BrowserRouter.
TypeScript Errors
Add global type declaration (see TypeScript Support section above).
Best Practices
- Create a tracking hook - Reusable across components
- Use context for global access - Avoid prop drilling
- Type your events - Use TypeScript for safety
- Test your tracking - Mock window.ovyxa in tests
- Only track in production - Use environment variables
Example App
Complete example: github.com/ovyxa/examples/react
Next Steps
Questions? Email support@ovyxa.com