Next.js integration (Pages Router)
The same server-side split-URL redirects, HTML experiments, and goal tracking as
the App Router integration — one middleware file and
one component in _app. You need your project ID from the dashboard (see
Get your script); replace
{YOUR_PROJECT_ID} below with it.
npm install @testa-soft/nextRequires v1.3.0 or later
The @testa-soft/next/pages entry point was added in v1.3.0. On the App Router,
use the App Router guide instead — a given app uses
one or the other, never both.
1. Create the middleware
middleware.ts at the project root (or under src/). It buckets each visitor
server-side, writes the sticky cookie, and issues split-URL redirects before any
HTML is sent — identical to the App Router; the proxy is router-agnostic.
// middleware.ts
import type { NextFetchEvent, NextRequest } from "next/server";
import { createTestaProxy } from "@testa-soft/next";
const testa = createTestaProxy({
projectId: "{YOUR_PROJECT_ID}",
secureCookies: process.env.NODE_ENV === "production",
// cache: "per-pageload", // config caching — see the table below
});
export function middleware(request: NextRequest, event: NextFetchEvent) {
return testa(request, event);
}
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
};Caching behavior determines how long it may take for Admin panel changes to
propagate to your site. It's controlled by the cache option of
createTestaProxy (shown commented out in the snippet above):
cache | Behavior |
|---|---|
true (default) | Cached 60s, then served stale while revalidating in the background — zero request latency, publishes live within ~1 min. |
'per-pageload' | Every hard page load fetches a fresh config (publishes live on the next pageview); soft navigations keep the config pinned for the session. |
2. Add the provider
Add <TestaProvider/> once in pages/_app.tsx. It applies HTML experiments,
arms goal tracking, manages the anti-flicker shield, and re-points next/link
navigations that the middleware cannot see.
// pages/_app.tsx
import type { AppProps } from "next/app";
import { TestaProvider } from "@testa-soft/next/pages";
export default function App({ Component, pageProps }: AppProps) {
return (
<TestaProvider projectId="{YOUR_PROJECT_ID}">
<Component {...pageProps} />
</TestaProvider>
);
}That is the whole integration. The config is fetched once per page load and shared by everything the provider wires up — soft navigations never refetch it.
3. Goals
Create goals in the dashboard (Goals tracking). Page-view and click goals need no code. Custom-event goals fire when your code sends a matching event:
import { pushEvent } from "@testa-soft/next";
pushEvent("signup_completed", { plan: "pro" });Also available as window.testa.pushEvent(...) and — legacy-compatible —
window.Analytica.pushEvent(...). Each goal counts once per visitor.