Next.js Integration
Track your Next.js application with Ovyxa for both App Router and Pages Router.
Installation
Install the Ovyxa package:
npm install @ovyxa/next
# or
yarn add @ovyxa/next
# or
pnpm add @ovyxa/next
App Router (Next.js 13+)
For Next.js 13+ using the App Router:
Root Layout Setup
Add the tracking script to your root layout (app/layout.tsx or app/layout.jsx):
// app/layout.tsx
import { OvyxaScript } from '@ovyxa/next'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{children}
<OvyxaScript siteId="YOUR_DOMAIN" />
</body>
</html>
)
}
Configuration Options
<OvyxaScript
siteId="YOUR_DOMAIN"
domain="analytics.yourdomain.com" // Optional: custom domain
trackOutboundLinks={true} // Optional: track external links
trackFileDownloads={true} // Optional: track downloads
/>
Tracking Custom Events
'use client'
import { trackEvent } from '@ovyxa/next'
export function SignupButton() {
const handleSignup = async () => {
// Your signup logic
await signup()
// Track the event
trackEvent('signup', {
plan: 'pro',
source: 'landing-page'
})
}
return <button onClick={handleSignup}>Sign Up</button>
}
Pages Router (Next.js 12 and below)
For traditional Pages Router setup:
_app.tsx Setup
// pages/_app.tsx
import type { AppProps } from 'next/app'
import { OvyxaScript } from '@ovyxa/next'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
<OvyxaScript siteId="YOUR_DOMAIN" />
</>
)
}
Tracking Page Views
Page views are tracked automatically on route changes. No additional configuration needed.
Custom Events
import { trackEvent } from '@ovyxa/next'
function MyComponent() {
const handleAction = () => {
trackEvent('ButtonClick', {
button: 'subscribe',
location: 'header'
})
}
return <button onClick={handleAction}>Subscribe</button>
}
Server-Side Tracking
Track events from your API routes or server components:
API Route Example
// app/api/purchase/route.ts (App Router)
import { trackServerEvent } from '@ovyxa/next'
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
const { amount, product } = await request.json()
// Process purchase...
// Track server-side
await trackServerEvent('purchase', {
revenue: amount,
product: product,
currency: 'USD'
}, {
siteId: process.env.OVYXA_SITE_ID!,
apiKey: process.env.OVYXA_API_KEY!
})
return NextResponse.json({ success: true })
}
Pages API Route
// pages/api/signup.ts (Pages Router)
import type { NextApiRequest, NextApiResponse } from 'next'
import { trackServerEvent } from '@ovyxa/next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
// Process signup...
// Track event
await trackServerEvent('signup', {
plan: req.body.plan
}, {
siteId: process.env.OVYXA_SITE_ID!,
apiKey: process.env.OVYXA_API_KEY!
})
res.status(200).json({ success: true })
}
Environment Variables
Store your credentials securely:
# .env.local
NEXT_PUBLIC_OVYXA_SITE_ID=your_site_id
OVYXA_API_KEY=your_api_key # For server-side tracking
Usage:
<OvyxaScript siteId={process.env.NEXT_PUBLIC_OVYXA_SITE_ID!} />
Important: Only prefix with NEXT_PUBLIC_ for client-side variables. Keep API keys private without the prefix.
Advanced Features
Conditional Tracking
Only track in production:
<OvyxaScript
siteId="YOUR_DOMAIN"
enabled={process.env.NODE_ENV === 'production'}
/>
Multiple Sites
Track different environments separately:
const siteId = process.env.NODE_ENV === 'production'
? 'prod_site_id'
: 'dev_site_id'
<OvyxaScript siteId={siteId} />
Custom Hooks
Create a custom tracking hook:
// hooks/useTracking.ts
import { trackEvent } from '@ovyxa/next'
import { useCallback } from 'react'
export function useTracking() {
const track = useCallback((event: string, properties?: object) => {
if (process.env.NODE_ENV === 'production') {
trackEvent(event, properties)
}
}, [])
return { track }
}
// Usage
function MyComponent() {
const { track } = useTracking()
return (
<button onClick={() => track('click', { button: 'cta' })}>
Click Me
</button>
)
}
TypeScript Support
Full TypeScript types included:
import type { EventProperties } from '@ovyxa/next'
const properties: EventProperties = {
revenue: 99.99,
plan: 'pro',
currency: 'USD'
}
trackEvent('purchase', properties)
Middleware Tracking
Track requests in middleware:
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { trackPageView } from '@ovyxa/next/middleware'
export function middleware(request: NextRequest) {
const response = NextResponse.next()
// Track page view
trackPageView(request, {
siteId: process.env.OVYXA_SITE_ID!
})
return response
}
export const config = {
matcher: '/:path*',
}
Vercel Deployment
Ovyxa works seamlessly on Vercel:
- Add environment variables in Vercel dashboard
- Deploy your app
- Tracking works automatically
Vercel Analytics Comparison
Ovyxa vs Vercel Analytics:
- More privacy-focused (cookieless mode available)
- More generous free tier
- Self-hosting option available
- Can run alongside Vercel Analytics
Troubleshooting
Events Not Tracking
Check script loaded:
# Open browser console
window.ovyxa
# Should show function
Common issues:
- Site ID not set
- Script blocked by ad blocker
- Environment variable not prefixed with NEXT_PUBLIC_
TypeScript Errors
# Ensure types are installed
npm install @types/node --save-dev
Server-Side Events Failing
- Verify API key is set (without NEXT_PUBLIC_ prefix)
- Check API key permissions
- Ensure siteId matches your dashboard
Best Practices
- Use environment variables - Never hardcode credentials
- Track server-side for sensitive events - Purchases, signups
- Disable in development - Only track production traffic
- Use TypeScript - Catch errors early
- Test locally - Verify tracking before deploying
Example Implementation
Complete example:
// app/layout.tsx
import { OvyxaScript } from '@ovyxa/next'
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<OvyxaScript
siteId={process.env.NEXT_PUBLIC_OVYXA_SITE_ID!}
enabled={process.env.NODE_ENV === 'production'}
/>
</body>
</html>
)
}
// app/signup/page.tsx
'use client'
import { trackEvent } from '@ovyxa/next'
import { useState } from 'react'
export default function SignupPage() {
const [email, setEmail] = useState('')
const handleSubmit = async (e) => {
e.preventDefault()
const response = await fetch('/api/signup', {
method: 'POST',
body: JSON.stringify({ email })
})
if (response.ok) {
trackEvent('signup', {
source: 'organic',
page: 'signup'
})
}
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit">Sign Up</button>
</form>
)
}
// app/api/signup/route.ts
import { trackServerEvent } from '@ovyxa/next'
export async function POST(request: Request) {
const { email } = await request.json()
// Create user...
// Track server-side
await trackServerEvent('signup_completed', {
method: 'email'
}, {
siteId: process.env.OVYXA_SITE_ID!,
apiKey: process.env.OVYXA_API_KEY!
})
return Response.json({ success: true })
}
Next Steps
Questions? Email support@ovyxa.com