Skip to main content

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

  1. Create a tracking hook - Reusable across components
  2. Use context for global access - Avoid prop drilling
  3. Type your events - Use TypeScript for safety
  4. Test your tracking - Mock window.ovyxa in tests
  5. Only track in production - Use environment variables

Example App

Complete example: github.com/ovyxa/examples/react

Next Steps

Questions? Email support@ovyxa.com