A lightweight, TypeScript-ready Matomo analytics integration for Next.js applications with support for both Pages Router and App Router.
- ✅ Pages Router & App Router Support - Works with both Next.js routing systems
- ✅ Automatic Page Tracking - Tracks route changes and page views automatically
- ✅ Search Tracking - Built-in search query tracking
- ✅ GDPR Compliant - Cookie-less tracking option
- ✅ Custom Events - Type-safe event tracking API
- ✅ Heatmap & Session Recording - Optional user behavior visualization
- ✅ TypeScript Support - Full type safety and auto-completion
npm install @socialgouv/matomo-nextAdd the trackPagesRouter() call in your _app.js:
import { useEffect } from "react";
import { trackPagesRouter } from "@socialgouv/matomo-next";
const MATOMO_URL = process.env.NEXT_PUBLIC_MATOMO_URL;
const MATOMO_SITE_ID = process.env.NEXT_PUBLIC_MATOMO_SITE_ID;
function MyApp({ Component, pageProps }) {
useEffect(() => {
trackPagesRouter({ url: MATOMO_URL, siteId: MATOMO_SITE_ID });
}, []);
return <Component {...pageProps} />;
}
export default MyApp;Create a client component for tracking with trackAppRouter():
"use client";
import { trackAppRouter } from "@socialgouv/matomo-next";
import { usePathname, useSearchParams } from "next/navigation";
import { useEffect } from "react";
const MATOMO_URL = process.env.NEXT_PUBLIC_MATOMO_URL;
const MATOMO_SITE_ID = process.env.NEXT_PUBLIC_MATOMO_SITE_ID;
export function MatomoAnalytics() {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
trackAppRouter({
url: MATOMO_URL,
siteId: MATOMO_SITE_ID,
pathname,
searchParams,
});
}, [pathname, searchParams]);
return null;
}Add it to your root layout wrapped in a Suspense boundary:
import { Suspense } from "react";
import { MatomoAnalytics } from "./matomo";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
<Suspense fallback={null}>
<MatomoAnalytics />
</Suspense>
</body>
</html>
);
}- Advanced Configuration - All configuration options, HeartBeat timer, callbacks, and extensibility
- Event Tracking - Track custom user interactions
- Heatmap & Session Recording - User behavior tracking and visualization
- Security & Privacy - CSP configuration and GDPR compliance
Use the sendEvent() helper for type-safe event tracking:
import { sendEvent } from "@socialgouv/matomo-next";
// Track a button click
sendEvent({ category: "contact", action: "click phone" });
// Track with additional context
sendEvent({
category: "video",
action: "play",
name: "intro-video",
value: "120",
});| Option | Type | Description | Default | Docs |
|---|---|---|---|---|
url |
string |
Matomo instance URL | - | Required |
siteId |
string |
Matomo site ID | - | Required |
pathname |
string |
Current pathname (App Router only) | - | Required for App Router |
searchParams |
URLSearchParams |
URL search params (App Router only) | - | Required for App Router |
jsTrackerFile |
string |
Custom JS tracker filename | "matomo.js" |
Advanced |
phpTrackerFile |
string |
Custom PHP tracker filename | "matomo.php" |
Advanced |
excludeUrlsPatterns |
RegExp[] |
URLs to exclude from tracking | [] |
Advanced |
disableCookies |
boolean |
Cookie-less tracking | false |
Advanced |
cleanUrl |
boolean |
Remove query params from URLs | false |
Advanced |
searchKeyword |
string |
Search query parameter name | "q" |
Advanced |
searchRoutes |
string[] |
Custom search route paths | ["/recherche", "/search"] |
Advanced |
enableHeartBeatTimer |
boolean |
Track time on page | false |
Advanced |
heartBeatTimerInterval |
number |
HeartBeat timer interval (seconds) | 15 (Matomo default) |
Advanced |
enableHeatmapSessionRecording |
boolean |
Enable session recording | false |
Heatmap |
heatmapConfig |
HeatmapConfig |
Heatmap configuration object | {} |
Heatmap |
debug |
boolean |
Enable debug logs | false |
Advanced |
nonce |
string |
CSP nonce value | - | Security |
trustedPolicyName |
string |
Trusted Types policy name | "matomo-next" |
Security |
onInitialization |
() => void |
Callback on init | - | Advanced |
onRouteChangeStart |
(path) => void |
Callback on route change start | - | Advanced |
onRouteChangeComplete |
(path) => void |
Callback on route change complete | - | Advanced |
onScriptLoadingError |
() => void |
Callback on script loading error | - | Advanced |
See complete configuration options for full details.
Contributions are welcome! Please feel free to submit a Pull Request.
