Skip to content

Next.js

Use Next.js’s own <Script> component so the pixel loads once and survives client-side navigation.

Add it to your root layout, app/layout.tsx:

import Script from 'next/script'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Script
src="https://10.vidstats.top/js/p.js?s=YOUR_TAG_KEY"
strategy="afterInteractive"
/>
</body>
</html>
)
}

strategy="afterInteractive" is the equivalent of defer: the script runs after hydration and never blocks your render.

Add it to pages/_app.tsx:

import Script from 'next/script'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
<Script
src="https://10.vidstats.top/js/p.js?s=YOUR_TAG_KEY"
strategy="afterInteractive"
/>
</>
)
}

Both routers navigate through history.pushState, which the pixel watches, so route changes are recorded as pageviews with no extra code.

Add the fallback below only if navigations are missing from your reports.

app/_components/PageviewTracker.tsx
'use client'
import { usePathname, useSearchParams } from 'next/navigation'
import { useEffect } from 'react'
export function PageviewTracker() {
const pathname = usePathname()
const searchParams = useSearchParams()
useEffect(() => {
window.webstats && webstats('pageview')
}, [pathname, searchParams])
return null
}

Mount it inside a <Suspense> boundary. useSearchParams opts the component into client-side rendering, and Next.js will fail the build without one:

import { Suspense } from 'react'
import { PageviewTracker } from './_components/PageviewTracker'
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
<Suspense>
<PageviewTracker />
</Suspense>
<Script
src="https://10.vidstats.top/js/p.js?s=YOUR_TAG_KEY"
strategy="afterInteractive"
/>
</body>
</html>
)
}

afterInteractive can load the pixel after your components first render, so a content call on mount could miss. If you call webstats() from components, load the pixel with strategy="beforeInteractive" so window.webstats exists before they render:

<Script
src="https://10.vidstats.top/js/p.js?s=YOUR_TAG_KEY"
strategy="beforeInteractive"
/>

Then call it from any client component, no queue stub needed:

'use client'
import { useEffect } from 'react'
export function VideoPlayer({ movie }) {
useEffect(() => {
webstats('content', {
type: 'movie',
ids: { tmdb: String(movie.tmdbId) },
title: movie.title,
})
webstats('video', '#player', { id: `tmdb-${movie.tmdbId}`, title: movie.title })
}, [movie.tmdbId])
return <video id="player" src={movie.streamUrl} />
}

Run your app, load a page, then navigate to a second route without reloading. Both should appear in your dashboard within a few seconds. If only the first one does, add the PageviewTracker fallback above.