Skip to main content

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:

  1. Add environment variables in Vercel dashboard
  2. Deploy your app
  3. 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

  1. Use environment variables - Never hardcode credentials
  2. Track server-side for sensitive events - Purchases, signups
  3. Disable in development - Only track production traffic
  4. Use TypeScript - Catch errors early
  5. 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