Documentation
Documentation

Analytics Guide

Learn how to implement analytics in your Next.js application using Vercel Analytics and custom event tracking.

Setup

First, install the required dependencies and configure Vercel Analytics in your application:

terminalbash
1npm install @vercel/analytics
2# or
3yarn add @vercel/analytics
4# or
5pnpm add @vercel/analytics
app/layout.tsxtsx
1import { Analytics } from '@vercel/analytics/react'
2
3export default function RootLayout({
4 children,
5}: {
6 children: React.ReactNode
7}) {
8 return (
9 <html lang="en">
10 <body>
11 {children}
12 <Analytics />
13 </body>
14 </html>
15 )
16}

Page Views

Page views are automatically tracked when you add the Analytics component. For custom page view tracking:

components/analytics/page-view-tracker.tsxtsx
1'use client'
2
3import { usePathname, useSearchParams } from 'next/navigation'
4import { useEffect } from 'react'
5import { track } from '@vercel/analytics'
6
7export function PageViewTracker() {
8 const pathname = usePathname()
9 const searchParams = useSearchParams()
10
11 useEffect(() => {
12 const url = searchParams.toString()
13 ? `${pathname}?${searchParams}`
14 : pathname
15
16 track('page_view', {
17 page: url,
18 })
19 }, [pathname, searchParams])
20
21 return null
22}

Custom Events

Track custom events to measure user interactions and conversions:

components/signup-button.tsxtsx
1'use client'
2
3import { track } from '@vercel/analytics'
4
5export function SignupButton() {
6 const handleSignup = async () => {
7 try {
8 // Handle signup logic
9 await signup()
10
11 // Track successful signup
12 track('signup_complete', {
13 location: 'homepage',
14 plan: 'free',
15 })
16 } catch (error) {
17 // Track failed signup
18 track('signup_error', {
19 error: error.message,
20 })
21 }
22 }
23
24 return (
25 <button
26 onClick={handleSignup}
27 className="rounded-lg bg-gray-900 px-4 py-2 text-white hover:bg-gray-800"
28 >
29 Sign Up
30 </button>
31 )
32}

Create a custom hook for consistent event tracking:

hooks/use-analytics.tstsx
1'use client'
2
3import { track } from '@vercel/analytics'
4
5type EventName =
6 | 'signup_complete'
7 | 'signup_error'
8 | 'purchase_complete'
9 | 'feature_used'
10 | 'support_requested'
11
12type EventProperties = {
13 location?: string
14 plan?: string
15 amount?: number
16 feature?: string
17 error?: string
18}
19
20export function useAnalytics() {
21 const trackEvent = (name: EventName, properties?: EventProperties) => {
22 track(name, {
23 timestamp: new Date().toISOString(),
24 ...properties,
25 })
26 }
27
28 return {
29 trackEvent,
30 }
31}
32
33// Usage
34export function FeatureButton({ featureName }: { featureName: string }) {
35 const { trackEvent } = useAnalytics()
36
37 const handleClick = () => {
38 trackEvent('feature_used', {
39 feature: featureName,
40 })
41 }
42
43 return (
44 <button
45 onClick={handleClick}
46 className="rounded-lg bg-gray-900 px-4 py-2 text-white hover:bg-gray-800"
47 >
48 Use Feature
49 </button>
50 )
51}

Analytics Dashboard

View your analytics data in the Vercel Analytics dashboard or create a custom dashboard using the Analytics API:

components/analytics/dashboard.tsxtsx
1import { headers } from 'next/headers'
2import { getAnalytics } from '@vercel/analytics/server'
3
4export async function AnalyticsDashboard() {
5 const headersList = headers()
6 const domain = headersList.get('host')
7
8 const {
9 pageviews,
10 events,
11 } = await getAnalytics({
12 domain,
13 startTime: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
14 endTime: new Date(),
15 })
16
17 return (
18 <div className="grid gap-6">
19 <div className="rounded-lg border p-6">
20 <h3 className="text-lg font-semibold">Page Views</h3>
21 <p className="text-3xl font-bold">{pageviews.total}</p>
22 <div className="mt-4">
23 {pageviews.data.map((day) => (
24 <div key={day.date} className="flex justify-between py-2">
25 <span>{new Date(day.date).toLocaleDateString()}</span>
26 <span>{day.value}</span>
27 </div>
28 ))}
29 </div>
30 </div>
31
32 <div className="rounded-lg border p-6">
33 <h3 className="text-lg font-semibold">Events</h3>
34 <div className="mt-4">
35 {events.data.map((event) => (
36 <div key={event.name} className="flex justify-between py-2">
37 <span>{event.name}</span>
38 <span>{event.total}</span>
39 </div>
40 ))}
41 </div>
42 </div>
43 </div>
44 )
45}