Integrating CounterAPI with Next.js in 2025
Learn how to implement efficient analytics in your Next.js applications using CounterAPI's lightweight tracking solution.
Tutorial Expert
• 4 min read
Enhancing Next.js Applications with CounterAPI
Next.js has remained the leading React framework for building modern web applications in 2025. When it comes to tracking user interactions and page views, CounterAPI offers an elegant solution that works seamlessly with Next.js's server components, client components, and app router.
In this quick guide, I'll show you how to integrate CounterAPI with your Next.js application to track analytics without compromising performance.
Setting Up CounterAPI in Next.js
First, install the CounterAPI package:
npm install counterapi@latest
Creating a CounterAPI Service
Let's create a simple service for managing our CounterAPI instance:
// lib/counterapi.js
import { Counter } from 'counterapi';
// For client components
export const createCounter = () => {
return new Counter({
workspace: process.env.NEXT_PUBLIC_COUNTER_WORKSPACE,
accessToken: process.env.NEXT_PUBLIC_COUNTER_TOKEN,
});
};
// For server components
let serverCounter;
export const getServerCounter = () => {
if (!serverCounter && typeof process !== 'undefined') {
serverCounter = new Counter({
workspace: process.env.COUNTER_WORKSPACE,
accessToken: process.env.COUNTER_TOKEN,
});
}
return serverCounter;
};
Add your environment variables in .env.local
:
NEXT_PUBLIC_COUNTER_WORKSPACE=your-workspace
NEXT_PUBLIC_COUNTER_TOKEN=public-token
COUNTER_WORKSPACE=your-workspace
COUNTER_TOKEN=private-token
Client-Side Page View Tracking
For client components, create a hook to track page views:
// hooks/usePageViews.js
'use client';
import { useEffect } from 'react';
import { usePathname } from 'next/navigation';
import { createCounter } from '@/lib/counterapi';
export function usePageViews() {
const pathname = usePathname();
useEffect(() => {
const counter = createCounter();
const trackPage = async () => {
try {
await counter.up(`page-${pathname}`);
} catch (error) {
console.error('Analytics error:', error);
}
};
trackPage();
}, [pathname]);
}
Use the hook in your layout:
// app/layout.js
'use client';
import { usePageViews } from '@/hooks/usePageViews';
export default function Layout({ children }) {
usePageViews(); // Track page views
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Server Component Analytics
With Next.js server components, you can track server-side metrics:
// app/posts/[slug]/page.js
import { getServerCounter } from '@/lib/counterapi';
export default async function PostPage({ params }) {
const counter = getServerCounter();
// Track this post being served
try {
await counter.up(`post-${params.slug}`);
} catch (error) {
// Log but don't fail rendering
console.error('Failed to track post view:', error);
}
// Rest of your component
return (
<article>
<h1>Post: {params.slug}</h1>
{/* Post content */}
</article>
);
}
API Routes Integration
Create an API route for client-side-only tracking needs:
// app/api/track/route.js
import { getServerCounter } from '@/lib/counterapi';
import { NextResponse } from 'next/server';
export async function POST(request) {
try {
const { event } = await request.json();
const counter = getServerCounter();
const result = await counter.up(event);
return NextResponse.json({
success: true,
count: result.value
});
} catch (error) {
return NextResponse.json(
{ success: false, message: error.message },
{ status: 500 }
);
}
}
Then use it from client components:
// components/LikeButton.js
'use client';
import { useState } from 'react';
export default function LikeButton({ postId }) {
const [likes, setLikes] = useState(0);
const handleLike = async () => {
try {
const response = await fetch('/api/track', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ event: `post-${postId}-like` }),
});
const data = await response.json();
if (data.success) {
setLikes(data.count);
}
} catch (error) {
console.error('Failed to track like:', error);
}
};
return (
<button onClick={handleLike}>
Like ({likes})
</button>
);
}
Custom Analytics Dashboard Component
Create a simple dashboard to view your analytics:
// components/AnalyticsDashboard.js
'use client';
import { useState, useEffect } from 'react';
import { createCounter } from '@/lib/counterapi';
export default function AnalyticsDashboard({ counterNames }) {
const [stats, setStats] = useState({});
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchStats = async () => {
try {
const counter = createCounter();
const results = await Promise.all(
counterNames.map(async (name) => {
const result = await counter.get(name);
return { name, value: result.value };
})
);
const statsObj = results.reduce((acc, { name, value }) => {
acc[name] = value;
return acc;
}, {});
setStats(statsObj);
} catch (error) {
console.error('Failed to fetch stats:', error);
} finally {
setLoading(false);
}
};
fetchStats();
}, [counterNames]);
if (loading) return <div>Loading analytics data...</div>;
return (
<div className="analytics-dashboard">
<h2>Analytics Dashboard</h2>
<div className="stats-grid">
{Object.entries(stats).map(([name, value]) => (
<div key={name} className="stat-card">
<h3>{name}</h3>
<p className="stat-value">{value}</p>
</div>
))}
</div>
</div>
);
}
Conclusion
With these simple integrations, you can add powerful analytics to your Next.js application using CounterAPI. The solution works well with both client and server components, and can be extended to track any user interactions or events you need.
Remember to handle errors gracefully and avoid blocking rendering or interaction when analytics calls fail. This way, your analytics enhance your application without compromising user experience.
For more information about CounterAPI and its features, visit the official documentation.