Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Integracja z Web Analytics

W świecie aplikacji webowych, zrozumienie zachowań użytkowników i mierzenie efektywności jest kluczowe dla podejmowania trafnych decyzji biznesowych i technicznych. Integracja narzędzi analitycznych z aplikacją Next.js pozwala na śledzenie ruchu, zachowania użytkowników, konwersji i innych istotnych wskaźników wydajności.

Popularne narzędzia analityczne

Do najczęściej używanych narzędzi analitycznych w aplikacjach Next.js należą:

  1. Google Analytics - kompleksowe narzędzie z szerokim zakresem funkcji analitycznych
  2. Vercel Analytics - natywna analityka dla aplikacji hostowanych na Vercel
  3. Plausible - przyjazna dla prywatności alternatywa open-source
  4. Fathom - prosty i skoncentrowany na prywatności system analityczny
  5. PostHog - platforma all-in-one łącząca analitykę, sesje użytkowników i funkcje eksperymentalne
  6. Mixpanel - zaawansowana analityka z naciskiem na śledzenie zdarzeń i lejki konwersji
  7. Amplitude - skupiona na analizie zachowań użytkowników i analizie produktowej

Integracja Google Analytics 4 (GA4)

Google Analytics to najpopularniejsze narzędzie analityczne. Oto jak zintegrować GA4 z aplikacją Next.js:

1. Konfiguracja Google Analytics

Zacznij od utworzenia konta Google Analytics i konfiguracji strumienia danych:

  1. Przejdź do Google Analytics
  2. Utwórz nowe konto i ustaw wskaźnik witryny
  3. Skonfiguruj strumień danych internetowych i zanotuj ID pomiaru (G-XXXXXXXX)

2. Implementacja w Next.js za pomocą App Router

Utwórz komponent Google Analytics:

1// components/GoogleAnalytics.tsx
2'use client';
3
4import Script from 'next/script';
5
6export default function GoogleAnalytics({ GA_MEASUREMENT_ID }: { GA_MEASUREMENT_ID: string }) {
7  return (
8    <>
9      <Script
10        strategy="afterInteractive"
11        src={`https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`}
12      />
13      <Script
14        id="google-analytics"
15        strategy="afterInteractive"
16        dangerouslySetInnerHTML={{
17          __html: `
18            window.dataLayer = window.dataLayer || [];
19            function gtag(){dataLayer.push(arguments);}
20            gtag('js', new Date());
21            gtag('config', '${GA_MEASUREMENT_ID}', {
22              page_path: window.location.pathname,
23              cookie_flags: 'SameSite=None;Secure'
24            });
25          `,
26        }}
27      />
28    </>
29  );
30}

Następnie dodaj komponent do głównego layoutu aplikacji:

1// app/layout.tsx
2import GoogleAnalytics from '@/components/GoogleAnalytics';
3
4export default function RootLayout({
5  children,
6}: {
7  children: React.ReactNode;
8}) {
9  return (
10    <html lang="pl">
11      <body>
12        {process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID && (
13          <GoogleAnalytics GA_MEASUREMENT_ID={process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID} />
14        )}
15        {children}
16      </body>
17    </html>
18  );
19}

Upewnij się, że dodasz zmienną środowiskową do pliku

.env.local
:

1NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX

3. Śledzenie nawigacji między stronami

W App Router, powinieneś zaimplementować śledzenie zmian URL, ponieważ nawigacja klientska nie powoduje pełnego odświeżenia strony:

1// hooks/usePageTracking.ts
2'use client';
3
4import { usePathname, useSearchParams } from 'next/navigation';
5import { useEffect } from 'react';
6
7export function usePageTracking() {
8  const pathname = usePathname();
9  const searchParams = useSearchParams();
10
11  useEffect(() => {
12    if (pathname && window.gtag) {
13      let url = window.origin + pathname;
14      if (searchParams.toString()) {
15        url = url + '?' + searchParams.toString();
16      }
17      
18      window.gtag('config', process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID!, {
19        page_path: pathname,
20        page_location: url,
21      });
22    }
23  }, [pathname, searchParams]);
24}

Następnie wykorzystaj ten hook w komponencie klienckim:

1// components/PageTracker.tsx
2'use client';
3
4import { usePageTracking } from '@/hooks/usePageTracking';
5
6export default function PageTracker() {
7  usePageTracking();
8  return null;
9}
10
11// app/layout.tsx
12import PageTracker from '@/components/PageTracker';
13
14export default function RootLayout({ children }: { children: React.ReactNode }) {
15  return (
16    <html lang="pl">
17      <body>
18        {process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID && (
19          <>
20            <GoogleAnalytics GA_MEASUREMENT_ID={process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID} />
21            <PageTracker />
22          </>
23        )}
24        {children}
25      </body>
26    </html>
27  );
28}

4. Śledzenie niestandardowych zdarzeń

Utwórz narzędzie do śledzenia niestandardowych zdarzeń:

1// lib/analytics.ts
2'use client';
3
4export type EventOptions = {
5  category: string;
6  label?: string;
7  value?: number;
8  nonInteraction?: boolean;
9  [key: string]: any;
10};
11
12export const trackEvent = (action: string, options: EventOptions) => {
13  const { category, label, value, nonInteraction = false, ...restOptions } = options;
14  
15  if (typeof window !== 'undefined' && window.gtag) {
16    window.gtag('event', action, {
17      event_category: category,
18      event_label: label,
19      value: value,
20      non_interaction: nonInteraction,
21      ...restOptions,
22    });
23  }
24};

Użycie w komponencie:

1// components/SubscribeButton.tsx
2'use client';
3
4import { trackEvent } from '@/lib/analytics';
5
6export default function SubscribeButton() {
7  const handleSubscribe = () => {
8    // Logika subskrypcji...
9    
10    // Śledzenie zdarzenia
11    trackEvent('subscribe', {
12      category: 'Engagement',
13      label: 'Newsletter',
14      value: 1,
15    });
16  };
17  
18  return (
19    <button
20      onClick={handleSubscribe}
21      className="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded"
22    >
23      Zapisz się do newslettera
24    </button>
25  );
26}

Integracja z Vercel Analytics

Jeśli hostujesz swoją aplikację Next.js na Vercel, możesz skorzystać z wbudowanej analityki Vercel, która oferuje proste wdrożenie i solidne metryki wydajności.

1. Instalacja pakietu @vercel/analytics

1npm install @vercel/analytics
2# lub
3yarn add @vercel/analytics
4# lub
5pnpm add @vercel/analytics

2. Dodanie providera analityki

1// app/layout.tsx
2import { Analytics } from '@vercel/analytics/react';
3
4export default function RootLayout({
5  children,
6}: {
7  children: React.ReactNode;
8}) {
9  return (
10    <html lang="pl">
11      <body>
12        {children}
13        <Analytics />
14      </body>
15    </html>
16  );
17}

To wszystko! Vercel automatycznie zbiera dane dotyczące odwiedzin stron i kluczowych metryk Web Vitals.

3. Śledzenie niestandardowych zdarzeń w Vercel Analytics

1// components/ContactForm.tsx
2'use client';
3
4import { track } from '@vercel/analytics';
5import { useState } from 'react';
6
7export default function ContactForm() {
8  const [email, setEmail] = useState('');
9  
10  const handleSubmit = (e: React.FormEvent) => {
11    e.preventDefault();
12    // Logika formularza kontaktowego...
13    
14    // Śledzenie zdarzenia
15    track('contact_form_submitted', { email_domain: email.split('@')[1] });
16  };
17  
18  return (
19    <form onSubmit={handleSubmit} className="space-y-4">
20      <div>
21        <label htmlFor="email" className="block mb-1">Email</label>
22        <input
23          id="email"
24          type="email"
25          value={email}
26          onChange={(e) => setEmail(e.target.value)}
27          required
28          className="w-full px-3 py-2 border rounded"
29        />
30      </div>
31      <button
32        type="submit"
33        className="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded"
34      >
35        Wyślij
36      </button>
37    </form>
38  );
39}

Integracja przyjaznych dla prywatności narzędzi analitycznych

Z rosnącą świadomością prywatności i regulacjami jak RODO/GDPR, wiele firm wybiera narzędzia analityczne, które są przyjazne dla prywatności. Poniżej znajdziesz przykład integracji z Plausible Analytics.

Integracja z Plausible Analytics

1// components/PlausibleAnalytics.tsx
2'use client';
3
4import Script from 'next/script';
5
6export default function PlausibleAnalytics({ domain }: { domain: string }) {
7  return (
8    <Script
9      strategy="afterInteractive"
10      data-domain={domain}
11      src="https://plausible.io/js/script.js"
12    />
13  );
14}
15
16// app/layout.tsx
17import PlausibleAnalytics from '@/components/PlausibleAnalytics';
18
19export default function RootLayout({
20  children,
21}: {
22  children: React.ReactNode;
23}) {
24  return (
25    <html lang="pl">
26      <body>
27        {process.env.NEXT_PUBLIC_ANALYTICS_DOMAIN && (
28          <PlausibleAnalytics domain={process.env.NEXT_PUBLIC_ANALYTICS_DOMAIN} />
29        )}
30        {children}
31      </body>
32    </html>
33  );
34}

Integracja z PostHog

PostHog to kompleksowa platforma analityczna open-source, która łączy w sobie analitykę, nagrywanie sesji, funkcje AB testów i inne.

1// app/providers.tsx
2'use client';
3
4import posthog from 'posthog-js';
5import { PostHogProvider } from 'posthog-js/react';
6import { usePathname, useSearchParams } from 'next/navigation';
7import { useEffect } from 'react';
8
9if (typeof window !== 'undefined' && process.env.NEXT_PUBLIC_POSTHOG_KEY) {
10  posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
11    api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://app.posthog.com',
12    // Inne opcje...
13    capture_pageview: false // Wyłącz automatyczne śledzenie widoku strony
14  });
15}
16
17export function PostHogPageview(): JSX.Element {
18  const pathname = usePathname();
19  const searchParams = useSearchParams();
20
21  useEffect(() => {
22    if (pathname) {
23      let url = window.origin + pathname;
24      if (searchParams && searchParams.toString()) {
25        url = url + `?${searchParams.toString()}`;
26      }
27      posthog.capture('$pageview', {
28        $current_url: url,
29      });
30    }
31  }, [pathname, searchParams]);
32
33  return <></>;
34}
35
36export function PHProvider({ children }: { children: React.ReactNode }) {
37  return (
38    <PostHogProvider client={posthog}>
39      <PostHogPageview />
40      {children}
41    </PostHogProvider>
42  );
43}
44
45// app/layout.tsx
46import { PHProvider } from './providers';
47
48export default function RootLayout({
49  children,
50}: {
51  children: React.ReactNode;
52}) {
53  return (
54    <html lang="pl">
55      <body>
56        <PHProvider>{children}</PHProvider>
57      </body>
58    </html>
59  );
60}

Obsługa RODO/GDPR i zgody użytkownika

Zgodnie z przepisami o ochronie danych osobowych, należy uzyskać zgodę użytkownika przed rozpoczęciem śledzenia. Implementacja prostego banner z informacją o cookies:

1// components/CookieConsent.tsx
2'use client';
3
4import { useState, useEffect } from 'react';
5
6export default function CookieConsent() {
7  const [consent, setConsent] = useState<boolean | null>(null);
8  
9  useEffect(() => {
10    // Sprawdzenie, czy użytkownik już wyraził zgodę
11    const storedConsent = localStorage.getItem('cookieConsent');
12    if (storedConsent !== null) {
13      setConsent(storedConsent === 'true');
14    } else {
15      setConsent(false); // Domyślnie brak zgody
16    }
17  }, []);
18  
19  const handleAccept = () => {
20    localStorage.setItem('cookieConsent', 'true');
21    setConsent(true);
22    
23    // Włącz analitykę
24    if (window.gtag) {
25      window.gtag('consent', 'update', {
26        'analytics_storage': 'granted'
27      });
28    }
29  };
30  
31  const handleReject = () => {
32    localStorage.setItem('cookieConsent', 'false');
33    setConsent(false);
34    
35    // Wyłącz analitykę
36    if (window.gtag) {
37      window.gtag('consent', 'update', {
38        'analytics_storage': 'denied'
39      });
40    }
41  };
42  
43  if (consent === null || consent === true) {
44    return null; // Nie pokazuj bannera, jeśli zgoda została wyrażona lub jeszcze nie załadowano
45  }
46  
47  return (
48    <div className="fixed bottom-0 left-0 right-0 bg-gray-100 p-4 shadow-md z-50">
49      <div className="max-w-6xl mx-auto flex flex-col md:flex-row items-center justify-between">
50        <div className="mb-4 md:mb-0">
51          <p className="text-sm">
52            Ta strona używa plików cookie do analizy ruchu. Możesz zdecydować, czy chcesz zaakceptować pliki cookie.
53          </p>
54        </div>
55        <div className="flex space-x-4">
56          <button
57            onClick={handleReject}
58            className="px-4 py-2 text-sm border border-gray-300 rounded hover:bg-gray-200"
59          >
60            Odrzuć
61          </button>
62          <button
63            onClick={handleAccept}
64            className="px-4 py-2 text-sm bg-blue-500 text-white rounded hover:bg-blue-600"
65          >
66            Akceptuj
67          </button>
68        </div>
69      </div>
70    </div>
71  );
72}
73
74// app/layout.tsx
75import CookieConsent from '@/components/CookieConsent';
76
77export default function RootLayout({
78  children,
79}: {
80  children: React.ReactNode;
81}) {
82  return (
83    <html lang="pl">
84      <body>
85        {children}
86        <CookieConsent />
87      </body>
88    </html>
89  );
90}

Dostosowanie Google Analytics do wymogów RODO

Zmodyfikuj inicjalizację Google Analytics, aby uwzględnić zgodę użytkownika:

1// components/GoogleAnalytics.tsx
2'use client';
3
4import Script from 'next/script';
5import { useEffect } from 'react';
6
7export default function GoogleAnalytics({ GA_MEASUREMENT_ID }: { GA_MEASUREMENT_ID: string }) {
8  useEffect(() => {
9    // Sprawdzenie zgody użytkownika
10    const consent = localStorage.getItem('cookieConsent') === 'true';
11    
12    // Aktualizacja stanu zgody w Google Analytics
13    if (window.gtag) {
14      window.gtag('consent', 'update', {
15        'analytics_storage': consent ? 'granted' : 'denied'
16      });
17    }
18  }, []);
19  
20  return (
21    <>
22      <Script
23        strategy="afterInteractive"
24        src={`https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`}
25      />
26      <Script
27        id="google-analytics"
28        strategy="afterInteractive"
29        dangerouslySetInnerHTML={{
30          __html: `
31            window.dataLayer = window.dataLayer || [];
32            function gtag(){dataLayer.push(arguments);}
33            gtag('js', new Date());
34            
35            // Ustaw domyślną zgodę jako 'denied'
36            gtag('consent', 'default', {
37              'analytics_storage': 'denied'
38            });
39            
40            // Skonfiguruj Google Analytics
41            gtag('config', '${GA_MEASUREMENT_ID}', {
42              page_path: window.location.pathname,
43            });
44          `,
45        }}
46      />
47    </>
48  );
49}

Integracja kros-platform: Web, iOS, Android

Dla aplikacji, które działają na wielu platformach, warto zaimplementować spójne śledzenie analityczne. Możesz skorzystać z bibliotek takich jak Segment, Amplitude lub Firebase Analytics, które oferują SDK dla różnych platform.

Przykład z Firebase Analytics

1// lib/analytics.ts
2import { initializeApp } from 'firebase/app';
3import { getAnalytics, logEvent, isSupported } from 'firebase/analytics';
4
5const firebaseConfig = {
6  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
7  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
8  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
9  // Inne konfiguracje...
10};
11
12let analytics: any = null;
13
14export async function initAnalytics() {
15  if (typeof window !== 'undefined' && await isSupported()) {
16    const app = initializeApp(firebaseConfig);
17    analytics = getAnalytics(app);
18    return true;
19  }
20  return false;
21}
22
23export function trackEvent(eventName: string, eventParams?: any) {
24  if (analytics) {
25    logEvent(analytics, eventName, eventParams);
26  }
27}
28
29// components/AnalyticsProvider.tsx
30'use client';
31
32import { useEffect } from 'react';
33import { usePathname, useSearchParams } from 'next/navigation';
34import { initAnalytics, trackEvent } from '@/lib/analytics';
35
36export default function AnalyticsProvider({ children }: { children: React.ReactNode }) {
37  const pathname = usePathname();
38  const searchParams = useSearchParams();
39  
40  useEffect(() => {
41    initAnalytics();
42  }, []);
43  
44  useEffect(() => {
45    if (pathname) {
46      trackEvent('page_view', {
47        page_path: pathname,
48        page_search: searchParams?.toString(),
49      });
50    }
51  }, [pathname, searchParams]);
52  
53  return <>{children}</>;
54}

Pomiar Web Vitals

Metryki Web Vitals są kluczowe dla zrozumienia wydajności twojej aplikacji. Next.js oferuje wbudowane narzędzie do raportowania Web Vitals do systemów analitycznych:

1// app/layout.tsx
2import { useReportWebVitals } from 'next/web-vitals';
3
4export function WebVitals() {
5  useReportWebVitals((metric) => {
6    const { id, name, label, value } = metric;
7    
8    // Raportowanie do Google Analytics
9    if (window.gtag) {
10      window.gtag('event', name, {
11        event_category: 'Web Vitals',
12        event_label: label,
13        value: Math.round(name === 'CLS' ? value * 1000 : value),
14        non_interaction: true,
15        metric_id: id,
16      });
17    }
18    
19    // Raportowanie do konsoli w środowisku deweloperskim
20    if (process.env.NODE_ENV === 'development') {
21      console.log(`Web Vital: ${name}`, metric);
22    }
23  });
24  
25  return null;
26}
27
28export default function RootLayout({ children }: { children: React.ReactNode }) {
29  return (
30    <html lang="pl">
31      <body>
32        <WebVitals />
33        {children}
34      </body>
35    </html>
36  );
37}

Własne panele analityczne

Czasami potrzebujesz wizualizować dane analityczne bezpośrednio w swojej aplikacji. Możesz zaimplementować własny dashboard analityczny, pobierając dane z API Google Analytics lub innego narzędzia:

1// app/admin/analytics/page.tsx
2import { google } from 'googleapis';
3import { BarChart, LineChart } from '@/components/Charts';
4
5async function getAnalyticsData() {
6  try {
7    // Inicjalizacja klienta Google Analytics
8    const auth = new google.auth.GoogleAuth({
9      keyFile: process.env.GOOGLE_APPLICATION_CREDENTIALS,
10      scopes: ['https://www.googleapis.com/auth/analytics.readonly'],
11    });
12    
13    const analyticsreporting = google.analyticsreporting({
14      version: 'v4',
15      auth,
16    });
17    
18    // Pobranie danych analitycznych
19    const response = await analyticsreporting.reports.batchGet({
20      requestBody: {
21        reportRequests: [
22          {
23            viewId: process.env.GA_VIEW_ID,
24            dateRanges: [{ startDate: '30daysAgo', endDate: 'today' }],
25            metrics: [{ expression: 'ga:sessions' }, { expression: 'ga:pageviews' }],
26            dimensions: [{ name: 'ga:date' }],
27          },
28        ],
29      },
30    });
31    
32    // Przetworzenie danych
33    const report = response.data.reports[0];
34    const rows = report.data.rows;
35    
36    return rows.map((row) => ({
37      date: row.dimensions[0],
38      sessions: parseInt(row.metrics[0].values[0], 10),
39      pageviews: parseInt(row.metrics[0].values[1], 10),
40    }));
41  } catch (error) {
42    console.error('Błąd podczas pobierania danych analitycznych:', error);
43    return [];
44  }
45}
46
47export default async function AnalyticsDashboard() {
48  const analyticsData = await getAnalyticsData();
49  
50  return (
51    <div className="p-6">
52      <h1 className="text-2xl font-bold mb-6">Panel analityczny</h1>
53      
54      <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
55        <div className="bg-white p-4 rounded shadow">
56          <h2 className="text-lg font-semibold mb-4">Sesje vs. odsłony strony</h2>
57          <LineChart 
58            data={analyticsData} 
59            categories={['sessions', 'pageviews']} 
60            xKey="date" 
61          />
62        </div>
63        
64        <div className="bg-white p-4 rounded shadow">
65          <h2 className="text-lg font-semibold mb-4">Odsłony według dnia</h2>
66          <BarChart 
67            data={analyticsData} 
68            category="pageviews" 
69            xKey="date" 
70          />
71        </div>
72      </div>
73    </div>
74  );
75}

Testowanie i debugowanie analityki

Przed wdrożeniem na produkcję, warto przetestować integrację analityczną w środowisku deweloperskim:

1// lib/analytics.ts
2export function trackEvent(eventName: string, eventParams: any = {}) {
3  // W środowisku deweloperskim wypisuj zdarzenia do konsoli
4  if (process.env.NODE_ENV === 'development') {
5    console.log(`Analytics Event: ${eventName}`, eventParams);
6    return;
7  }
8  
9  // W środowisku produkcyjnym wysyłaj do serwisu analitycznego
10  if (window.gtag) {
11    window.gtag('event', eventName, eventParams);
12  }
13}

Do testowania możesz także użyć dodatków przeglądarkowych, takich jak Google Analytics Debugger, Tag Assistant lub Facebook Pixel Helper.

Najlepsze praktyki

  1. Szanuj prywatność użytkowników - zawsze informuj o użyciu narzędzi analitycznych i zbieraj zgodę
  2. Minimalizuj wpływ na wydajność - używaj strategii
    afterInteractive
    lub
    lazyOnload
    dla skryptów analitycznych
  3. Segmentuj dane - kategoryzuj zdarzenia, aby łatwiej analizować dane
  4. Korzystaj z wielu źródeł danych - łącz dane z różnych narzędzi dla pełniejszego obrazu
  5. Regularnie weryfikuj dane - sprawdzaj poprawność danych analitycznych
  6. Analizuj trendy - szukaj wzorców i anomalii w danych
  7. Anonimizuj dane - zbieraj dane w sposób zgodny z RODO

Frameworki analityczne dla Next.js

Dla bardziej zaawansowanych potrzeb, warto rozważyć użycie specjalizowanych frameworków analitycznych dla Next.js:

  1. Next-GA - uproszczona integracja z Google Analytics
  2. Use-Analytics - uniwersalny hook do integracji z różnymi dostawcami analitycznymi
  3. React-GA - popularna biblioteka do integracji React z Google Analytics
  4. Next-Plausible - integracja z przyjaznym dla prywatności narzędziem Plausible

Podsumowanie

Analityka webowa jest kluczowym narzędziem do zrozumienia użytkowników i optymalizacji aplikacji. Next.js oferuje wiele sposobów integracji z różnymi narzędziami analitycznymi, od Google Analytics przez Vercel Analytics po alternatywy bardziej przyjazne dla prywatności, takie jak Plausible czy Fathom.

Pamiętaj, że najważniejsze jest, aby zbierać tylko te dane, które są naprawdę potrzebne i robić to z poszanowaniem prywatności użytkowników. Dobre praktyki obejmują uzyskiwanie zgody, anonimizację danych i informowanie użytkowników o tym, jakie dane są zbierane i w jakim celu.

Vai a CodeWorlds