Visitant w Next.js
Jeden <Script> w głównym layoucie liczy odwiedzających razem ze zmianami tras po stronie klienta. Jedno małe middleware liczy boty AI, które nigdy nie uruchamiają JavaScriptu. Oba to kopiuj-wklej; bez SDK, bez paczki npm.
Czego potrzebujesz
- Projekt Next.js (App Router albo Pages Router), który możesz wdrożyć. Przykłady są w TypeScripcie; wersja JavaScript jest taka sama bez typów.
- Darmowe konto Visitant z dodaną domeną, np.
twojastrona.pl. - Do części o botach AI: Klucz serwera strony z zakładki Ustawienia strony - Śledzenie botów AI (serwer) w panelu oraz hosting, który uruchamia middleware (serwer Node.js, Docker, Vercel albo inny adapter - nie statyczny build
output: 'export').
Instalacja w 5 krokach
-
01 Dodaj Script do głównego layoutu
Otwórz
app/layout.tsx, zaimportujScriptznext/scripti wyrenderuj go w<body>głównego layoutu, żeby był na każdej podstronie. Zamieńtwojastrona.plna swoją domenę.strategy="afterInteractive"to wartość domyślna: skrypt ładuje się wcześnie, po starcie hydratacji - dokładnie to dokumentacja Next.js zaleca dla analityki.// app/layout.tsx import Script from 'next/script' export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="pl"> <body> {children} <Script src="https://annuora.com/v.js" data-domain="twojastrona.pl" strategy="afterInteractive" /> </body> </html> ) }Pages Router? Wstaw ten sam
<Script>wpages/_app.tsxobok<Component {...pageProps} />. Next.js ładuje go raz dla każdej trasy. Dodatkowe atrybuty, takie jakdata-domain, trafiają do końcowego elementu<script>. -
02 Zmiany tras liczą się same
Tu nic nie dodajesz, ale warto wiedzieć, co się dzieje. Next.js nawiguje przez
history.pushState. Tracker Visitant przy załadowaniu raz opakowujepushStatei nasłuchujepopstate(Wstecz i Dalej). Po każdej nawigacji porównuje nowy adres z ostatnim wysłanym i jeśli się różni, zapisuje odsłonę, a poprzednią zamyka z czasem aktywności i głębokością przewinięcia. Liczą się więcrouter.push,<Link>i przycisk Wstecz, a ponowne renderowanie z tym samym adresem nie liczy się podwójnie.Zmiany samego hasha (
#sekcja) są pomijane, chyba że dodasz do Scriptudata-hash. Nie wywołuj samvisitant("pageview")wuseEffect- to podwoiłoby liczby. -
03 Wdróż i otwórz stronę
Wdróż aplikację, otwórz produkcyjną domenę i przejdź przez kilka podstron. Tracker celowo ignoruje
localhost, więcnpm run devnic nie pokaże w panelu; jeśli chcesz testować lokalnie, dodaj do Scriptudata-local. -
04 Policz boty AI przez middleware
Boty takie jak GPTBot czy ClaudeBot nigdy nie wykonują Scriptu, więc strona klienta ich nie widzi. Utwórz
middleware.tsw katalogu głównym projektu (obokappalbo wsrc) z poniższym kodem i zamieńTWÓJ-KLUCZna swój Klucz serwera. Kod sprawdza user agent z listą botów i tylko przy trafieniu wysyła jedno małe żądanie przezevent.waitUntil, więc żądania ludzi nic nie kosztują. To ten sam fragment, który panel pokazuje z wpisanym Twoim kluczem.import { NextResponse } from 'next/server'; const AI_UA = /bot|crawl|spider|GPTBot|ChatGPT-User|OAI-SearchBot|Claude|anthropic|Perplexity|Google-|GoogleOther|Applebot|meta-external|Meta-WebIndexer|Amazonbot|Amzn-|Bytespider|CCBot|MistralAI|DuckAssist|YouBot|xAI|Grok|cohere|Diffbot|Kimi|Qwen|Manus|Firecrawl/i; export function middleware(req, ev) { const ua = req.headers.get('user-agent') || ''; if (AI_UA.test(ua)) ev.waitUntil(fetch('https://annuora.com/api/bot', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Visitant-Key': 'TWÓJ-KLUCZ' }, body: JSON.stringify({ ua, path: req.nextUrl.pathname, ip: req.headers.get('x-forwarded-for') || '' }) }).catch(() => {})); return NextResponse.next(); }Next.js 16 lub nowszy: konwencja pliku zmieniła nazwę - nazwij plik
proxy.ts, a eksportowaną funkcjęproxy(ta sama treść, to samoevent.waitUntil).middleware.tsnadal działa, ale jest oznaczony jako przestarzały;npx @next/codemod@canary middleware-to-proxy .zmieni nazwę za Ciebie. Jeśli wolisz, żeby middleware nie dotykało żądań o zasoby, dodajmatcherwykluczający_next/statici_next/image. -
05 Potwierdź kanał botów
Wdróż ponownie. W panelu otwórz Ustawienia strony - Śledzenie botów AI (serwer): ramka mówi Czekamy na pierwsze wejście bota, dopóki żaden nie zajrzy, a potem Działa: N wizyt botów zapisanych. Żeby sprawdzić od razu, poproś o dowolną stronę z user agentem bota:
curl -A "GPTBot/1.4" https://twojastrona.pl/. Wejścia botów nigdy nie wliczają się do limitu zdarzeń w planie.Statyczny eksport (
output: 'export') nie ma middleware, więc ten krok jest tam niemożliwy. Na Vercelu lub Netlify bez middleware albo za CDN-em, który serwuje strony z cache, użyj zamiast tego fragmentu dla Cloudflare Workers z panelu - on widzi każde żądanie, z cache czy bez.
Czy działa? Sprawdź w 60 sekund
Zrób to na wdrożonej stronie, z panelem Visitant otwartym w drugiej karcie.
- Licznik osób teraz na górze panelu pokazuje 1, gdy Twoja produkcyjna strona jest otwarta.
- Kliknij dwa wewnętrzne
<Link>bez przeładowania: obie ścieżki pojawiają się w tabeli Strony, po jednej odsłonie. Naciśnij Wstecz: pierwsza ścieżka dostaje drugą odsłonę. - W narzędziach deweloperskich, zakładka Sieć, filtr
api/e: jedno żądanie ze statusem 202 na każdą nawigację, żadnego przy ponownym renderowaniu z tym samym adresem. - Wykonaj
curl -A "GPTBot/1.4" https://twojastrona.pl/; w ciągu minuty sekcja Boty AI czytające Twoją stronę w panelu pokaże GPTBot z 1 wejściem. - Wejdź na stronę z linku w odpowiedzi ChatGPT (albo dodaj
?utm_source=chatgpt.comdo adresu): tabela Źródła pokaże ChatGPT w kanale AI.
Częste problemy
| Lokalnie nic się nie pojawia | Tak ma być: tracker nie działa na localhost, 127.0.0.1 ani na stronach file:. Dodaj do Scriptu data-local, żeby testować w trakcie pracy, i usuń go przed wdrożeniem, jeśli nie chcesz liczyć wizyt deweloperskich. |
| Każda zmiana trasy liczy się podwójnie | Coś jeszcze zgłasza odsłony - ręczne visitant("pageview") w useEffect albo Script wyrenderowany dwa razy (główny i zagnieżdżony layout, albo _app i _document naraz). Zostaw dokładnie jeden. |
| Script działa, ale wejścia botów stoją na zerze | Sprawdź Klucz serwera w middleware, upewnij się, że plik middleware leży w katalogu głównym projektu (albo w src) na tym samym poziomie co app, i sprawdź, czy build nie jest statycznym eksportem. Sprawdź też, czy matcher nie wyklucza Twoich stron. |
| TypeScript narzeka na sygnaturę middleware | Zaimportuj typy: import type { NextRequest, NextFetchEvent } from 'next/server' i opisz parametry (req: NextRequest, ev: NextFetchEvent). Fragment to zwykły JavaScript, więc działa zarówno w plikach .js, jak i .ts. |
Pytania
Czy nie lepiej użyć beforeInteractive?
Nie. beforeInteractive jest dla skryptów, bez których strona nie działa, i musi siedzieć w głównym layoucie. Analityka to dokładnie to, co dokumentacja Next.js wymienia przy afterInteractive; tracker i tak wysyła odsłonę, gdy tylko się uruchomi.
Czy Visitant działa z React Server Components i streamingiem?
Tak. Script renderuje główny layout, który jest komponentem serwerowym, a next/script zajmuje się stroną klienta. 'use client' nie jest potrzebne, bo nie używamy handlera onLoad.
Czy potrzebuję banera cookies?
Nie z powodu Visitant. Bez cookies, bez identyfikatorów w local storage, bez zapisywania adresów IP, hosting w UE. Jeśli masz już baner dla innych narzędzi, nie uzależniaj od niego Scriptu.
Jakie są limity planu Free?
5000 zdarzeń miesięcznie i 2 strony. Liczą się odsłony i własne zdarzenia; wejścia botów AI z middleware nigdy się nie liczą. 14-dniowy okres próbny planu Business nie wymaga karty.
Załóż darmowe konto - instrukcje w panelu pokażą się już z Twoją domeną i kluczem.
Zacznij za darmo →