Strona główna / Wiedza / Blog / Jak mierzyć scroll depth
Porady

Jak mierzyć scroll depth

Tomek BoguckiTomek BoguckiSEO APP Developer 19.02.2026 12 min czytania
dowiedz się

Pomiar faktycznego zaangażowania użytkownika nie kończy się na odsłonie strony. To, jak głęboko ktoś przewija treść, mówi wiele o jakości contentu, układzie strony i barierach w odbiorze. Dzięki metryce scroll depth możemy zbudować realne hipoteki optymalizacyjne: co skrócić, co przenieść wyżej, kiedy zaproponować CTA. Poniżej znajdziesz kompletną instrukcję, od wyboru narzędzi, przez konfigurację w GTM/GA4, po kod w JavaScript i dobre praktyki, które zapewnią rzetelne dane.

Co to jest scroll depth i po co to mierzyć

Definicje i podstawowe metryki

Scroll depth (głębokość przewijania) to odsetek wysokości dokumentu, który użytkownik obejrzał w pionie. W praktyce mierzymy najczęściej progi: 25%, 50%, 75%, 90% oraz 100%. Dla jasności: 100% nie oznacza, że ktoś „przeczytał” wszystko, tylko że dotarł do końca treści, a przynajmniej do dolnej granicy kontenera dokumentu.

Możliwe są też alternatywy:

  • piksele absolutne (np. 1500 px przewinięte),
  • sekcje/akapit (np. wejście w „Opinie” lub „FAQ”),
  • warunki złożone (np. osiągnięcie 50% + minimalnie 10 sekund na stronie).

Dlaczego to ma znaczenie

Głębokość przewijania to sygnał realnego zaangażowania i „konsumpcji” treści:

  • Ocena jakości contentu i układu: czy lead i nagłówki wystarczająco „niosą” dalej?
  • Optymalizacja rozmieszczenia CTA: czy przyciski nie są za nisko?
  • Wsparcie decyzji SEO: dopasowanie długości i struktury tekstów do intencji użytkownika.
  • Lejek konwersji: korelacja między głębokością a kliknięciami/konwersjami.

Standardy i konwencje raportowania

Najczęściej raportuje się ułamki procentowe (25/50/75/90/100). „90%” bywa praktycznym zamiennikiem „prawie koniec”, bo stopki, bannery lub dynamiczne komponenty potrafią przesuwać realny „koniec” strony. Pamiętaj, że GA4 domyślnie ma zdarzenie „scroll” w ramach Rozszerzonego Pomiaru, ale tylko dla 90%. Jeśli potrzebujesz innych progów, wdrożysz je niestandardowo.

Przygotowanie: narzędzia, zakres i architektura pomiaru

Wybór narzędzia i architektury

Najbardziej elastyczny zestaw to GTM + GA4. GTM udostępnia gotowy wyzwalacz przewijania i zmienne, a GA4: raportowanie i łączenie z innymi sygnałami. Alternatywy: Matomo, Plausible czy własna baza przez Measurement Protocol. Kluczowe, by zachować spójne nazwy zdarzeń i parametrów oraz kontrolę nad miejscem, w którym dane powstają (klient vs. serwer).

Plan progów i nazewnictwa

Zanim rozpoczniesz implementację, zdecyduj:

  • Progi: 25/50/75/90/100 (zalecane) czy inne?
  • Nazwa zdarzenia: np. scroll_depth (snake_case).
  • Parametry: percent_scrolled (liczba), direction (down/up), content_id (opcjonalnie).
  • Zakres stron: wszystkie, czy tylko blog/landing?

Zapisz te decyzje w krótkiej specyfikacji: ułatwi to utrzymanie i audyt.

Zgody i prywatność

Pamiętaj o RODO i zgodach. W GTM stosuj Consent Mode (analytics_storage). Zdarzenia zdarzenia przewijania to dane behawioralne, więc powinny respektować stan zgody. Jeżeli używasz CMP, skonfiguruj reguły „Fire only if consent = granted”.

Wydajność i jakość danych

Nie wywołuj zdarzeń przy każdym pikselu przewinięcia. Wysyłaj tylko przy osiąganiu progów i tylko raz na sesję strony (per próg). Zadbaj o wydajność: stosuj throttling/debouncing i lekką logikę warunkową. Ustal, jak obsłużysz dynamiczne wysokości (lazy-load, infinite scroll, akordeony).

Implementacja w Google Tag Manager + GA4 krok po kroku

Krok 1: Podstawy w GA4 i GTM

  • Zainstaluj GTM na stronie (kontener web). Zweryfikuj w Podglądzie (Preview).
  • W GTM dodaj tag „GA4 Configuration” z Measurement ID (G-XXXX). Włączodpowiednie ustawienia zgód.
  • W GA4 włącz Rozszerzony Pomiar (opcjonalnie). Pamiętaj: domyślne „scroll” to 90% i nie zastąpi własnych progów.

Krok 2: Włącz zmienne przewijania

W GTM wejdź w Variables > Configure i zaznacz:

  • Scroll Depth Threshold,
  • Scroll Depth Units,
  • Scroll Direction.

Te zmienne udostępni wyzwalacz przewijania.

Krok 3: Utwórz wyzwalacz Scroll Depth

  • Trigger type: Scroll Depth.
  • Vertical Scroll Depths: 25, 50, 75, 90, 100 (wartości oddzielone przecinkami).
  • Enable this trigger on: All Pages (lub wg warunków, np. Page Path matches RegEx: ^/(blog|case-studies)/ ).
  • Throttling: GTM sam wywoła zdarzenie dopiero na progu: to bezpieczne.

Wyzwalacz emituje event gtm.scrollDepth z wartościami w zmiennych.

Krok 4: Tag zdarzenia GA4

Dodaj tag typu „GA4 Event”:

  • Event Name: scroll_depth.
  • Event Parameters:
    • percent_scrolled = {{Scroll Depth Threshold}}
    • scroll_units = {{Scroll Depth Units}}
    • direction = {{Scroll Direction}}
    • page_location = {{Page URL}} (opcjonalnie, GA4 i tak go doda)
  • Trigger: utworzony Scroll Depth.

Aby uniknąć duplikatów, nie dodawaj innych wyzwalaczy do tego taga. Jeśli wysyłasz do kilku strumieni, skonfiguruj „Send to server container” lub dodatkowe tagi GA4 z tą samą regułą.

Krok 5: Ograniczenie do jednorazowego wysłania progu

GTM z natury wywoła każdy próg tylko raz na „życie” strony, ale w SPA warto dodać filtr:

  • Utwórz 5 zmiennych typu 1st Party Cookie lub Session Storage (np. sd_25, sd_50…).
  • Dodaj warunek do taga: Fire gdy sd_{{threshold}} ≠ 1.
  • Ustaw tag Custom HTML (po odpaleniu eventu) do zapisania sd_{{threshold}} = 1 w sessionStorage.

To zabezpiecza przed ponownymi strzałami po zmianie routingu lub komponentów.

Krok 6: Definicje niestandardowe w GA4

Aby raportować procenty w Explorations:

  • GA4 > Admin > Custom definitions > Create custom dimension.
  • Event scope, Name: Percent Scrolled, Event parameter: percent_scrolled.
  • Analogicznie dla „direction”, jeśli potrzebujesz segmentacji po kierunku.

Po kilku godzinach parametry zaczną się pojawiać w raportach i w Eksploracjach.

Krok 7: Testy i weryfikacja

  • GTM Preview: przewijaj stronę i obserwuj gtm.scrollDepth. Sprawdzaj, czy wartości 25/50/75/90/100 są trafione.
  • GA4 DebugView: widoczne powinny być eventy scroll_depth z parametrami.
  • Realtime > Events: upewnij się, że multiple odsłony nie duplikują zdarzeń.

W razie problemów sprawdź, czy któraś warstwa CSS (np. overflow w kontenerze) nie przechwytuje scrolla: wyzwalacz bazuje na dokumencie, nie na wewnętrznym skrolowanym divie.

Implementacja bez GTM: czysty JavaScript

Algorytm procentu przewinięcia

Podstawowy wzór: percent = round( (scrollTop / (scrollHeight: clientHeight)) * 100 ). Należy używać document.documentElement dla nowoczesnych przeglądarek. Uważaj na „overscroll bounce” w iOS: wartości mogą wyjść poza [0,100]. Warto zatem clampować wynik do 0–100 i emitować zdarzenia dopiero, gdy przekroczymy próg i nie został on jeszcze wysłany.

Przykładowy kod z throttlingiem

// Pseudokod JavaScript (umieść w tagu w sekcji HEAD lub ładowany asynchronicznie)
const sent = new Set();
const thresholds = [25,50,75,90,100];
let ticking = false;
function getPercent(){
  const el = document.documentElement;
  const scrollTop = (window.pageYOffset || el.scrollTop || 0);
  const scrollHeight = el.scrollHeight;
  const clientHeight = el.clientHeight;
  const denom = Math.max(scrollHeight: clientHeight, 1);
  const raw = Math.round((scrollTop / denom) * 100);
  return Math.min(100, Math.max(0, raw));
}
function send(percent){
  if (sent.has(percent)) return;
  sent.add(percent);
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    event: 'scroll_depth',
    percent_scrolled: percent,
    direction: 'down'
  });
  if (window.gtag) {
    gtag('event','scroll_depth',{percent_scrolled: percent});
  }
}
function onScroll(){
  if (!ticking) {
    ticking = true;
    requestAnimationFrame(() => {
      const p = getPercent();
      thresholds.forEach(t => { if (p >= t) send(t); });
      ticking = false;
    });
  }
}
window.addEventListener('scroll', onScroll, {passive:true});
window.addEventListener('load', onScroll);

Ten przykład wysyła zdarzenia do dataLayer i (jeśli dostępny) bezpośrednio do GA4 przez gtag(). Zadbaj, by nazwy eventów/parametrów pokrywały się z definicjami w raportach. W SPA opróżniaj Set() po zmianie trasy, jeśli traktujesz każdą trasę jak „nową stronę”.

Metoda IntersectionObserver i znaczniki progów

W złożonych layoutach (parallax, wewnętrzne skrolowane kontenery) rozważ IntersectionObserver. Tworzysz markery w dokumencie na wysokości progów i nasłuchujesz ich przecięcia z viewportem.

// Pseudokod tworzenia markerów i obserwacji
const el = document.documentElement;
const thresholds = [25,50,75,90,100];
const markers = [];
function placeMarkers(){
  const h = el.scrollHeight: el.clientHeight;
  markers.forEach(m => m.remove());
  markers.length = 0;
  thresholds.forEach(t => {
    const m = document.createElement('div');
    m.style.position='absolute';
    m.style.top = Math.round(h * (t/100)) + 'px';
    m.style.width='1px'; m.style.height='1px'; m.style.pointerEvents='none';
    m.dataset.threshold = t;
    document.body.appendChild(m);
    markers.push(m);
  });
}
const sent = new Set();
const io = new IntersectionObserver(entries => {
  entries.forEach(e => {
    if (e.isIntersecting) {
      const t = Number(e.target.dataset.threshold);
      if (!sent.has(t)) { sent.add(t); gtag('event','scroll_depth',{percent_scrolled:t}); }
    }
  });
},{root:null, threshold:0});
placeMarkers(); markers.forEach(m => io.observe(m));
window.addEventListener('resize', debounce(placeMarkers, 300));

Ta metoda minimalizuje przeliczenia i dobrze radzi sobie z dynamicznym DOM (po dopracowaniu logiki aktualizacji). Pamiętaj, że absolutnie pozycjonowane markery powinny być potomkami dokumentu, który faktycznie się przewija.

Wysyłka do GA4 bez gtag: Measurement Protocol

Jeśli nie możesz użyć gtag() (np. środowisko niestandardowe), wyślij zdarzenie do GA4 Measurement Protocol (wymaga api_secret):

  • Endpoint: https://www.google-analytics.com/mp/collect?measurement_id=G-XXXX&api_secret=YYYY
  • Body JSON zawiera client_id i events[].

Pamiętaj o zgodach i o tym, że MP nie zasila raportu Realtime, jeśli nie dostarczysz poprawnego client_id i session_id.

Jakość danych, analiza i rozwiązywanie problemów

Typowe pułapki techniczne

  • Różne wysokości dokumentu: lazy-load obrazów/komponentów zmienia scrollHeight; rozważ ponowną kalkulację progów po „content loaded”/„resize”.
  • Kontenery z overflow: auto: w takim układzie zdarzenia dokumentu nie odzwierciedlają przewijania kontenera. Mierz przewinięcie konkretnego elementu (target = kontener) i wysyłaj osobne zdarzenia.
  • Sticky header/footer: zawyżają lub zaniżają osiągalność 100%; praktycznie lepszy próg 90%.
  • iOS overscroll/bounce: clampuj wynik do 0–100, stosuj requestAnimationFrame zamiast intensywnych handlerów.
  • SPA: po zmianie trasy resetuj zestaw wysłanych progów i ponownie inicjalizuj obserwacje; w GTM użyj History Change Trigger.

Projektowanie progów: 25/50/75/90/100 czy inne?

Domyślne progi są dobre na start. Z czasem dopasuj je do długości treści: dla krótkich stron (do 2–3 ekranów) wystarczy 50/90/100; dla bardzo długich: dodaj 10/30/60/80. Ważniejsza niż liczba progów jest ich stabilność w czasie, aby móc porównywać serie.

Łączenie z konwersjami i segmentacją

W GA4 zbuduj Eksplorację typu Funnel lub Free Form:

  • Segment użytkowników z percent_scrolled >= 75 i porównaj współczynnik konwersji z segmentem < 25.
  • Oceń wpływ głębokości na kliknięcia w CTA umieszczone niżej.
  • Wyznacz „sweet spot” długości, gdzie krzywa spadku zaangażowania jest najbardziej stroma.

Aby parametry były dostępne, pamiętaj o definicjach niestandardowych. Dla bardziej zaawansowanej analizy wyeksportuj zdarzenia do BigQuery.

Walidacja i sanity-check

  • Rozkład: 25% powinno mieć więcej trafień niż 50%, a 50% więcej niż 75% itd. Jeśli jest odwrotnie: błąd implementacji.
  • Różnice urządzeń: mobile zwykle osiąga niższe progi; jeśli jest identycznie jak desktop, sprawdź czy viewport jest mierzony poprawnie.
  • Sesje 100% bez czasu: mogą wskazywać na auto-scrolling lub anchor link po wejściu: rozważ rozdzielenie zdarzenia „anchor_jump”.

Wielokrotne przewinięcia i kierunek

Dodanie parametru direction (down/up) pozwala odróżnić „pierwszy zjazd” od „przeglądania w górę”. Często interesuje nas tylko „down”: jeśli tak, filtruj zdarzenia w tagu lub w raporcie. Dla jakości danych nie wysyłaj up, jeśli próg down już został osiągnięty.

Makiety raportów i nazewnictwo

Spójne nazewnictwo przyspiesza pracę analityków:

  • Nazwa eventu: scroll_depth (nie używaj spacji).
  • Parametry: percent_scrolled (liczba), direction (string), content_group.
  • Wymiary niestandardowe: jasne, opisowe nazwy (np. Depth Percent).

Dzięki temu Twoja analityka będzie jednolita w wielu projektach i narzędziach.

WordPress i gotowe wtyczki

W WordPress najprościej użyć GTM (wtyczki: GTM4WP) i skonfigurować wyzwalacz przewijania. Jeśli korzystasz z wtyczek „scroll depth”, sprawdź:

  • czy wysyłają progi tylko raz,
  • jakie nazwy eventów/parametrów stosują,
  • czy działają poprawnie w lazy-load (np. Jetpack, optymalizatory obrazów).

Konsekwencja w nazewnictwie ułatwia łączenie danych między stronami.

Fallback i odporność

Warto przewidzieć scenariusze ograniczeń:

  • Brak JS lub zablokowane skrypty: brak zdarzeń, zaplanuj minimalne KPI niezależne od JS.
  • Adblock: korzystaj z własnego hostingu plików i serwera Tagowania (Server-Side), jeśli to kluczowe dane.
  • Degradacja: jeśli nie zainicjuje się GTM/gtag, buforuj zdarzenia i wyślij po inicjalizacji (kolejka w local/sessionStorage).

Utrzymanie i wersjonowanie

Zmiany w konfiguracji trzymaj w changelogu kontenera GTM i w repozytorium (eksport JSON). Twórz środowiska (Dev/QA/Prod) i testuj na realnych długich stronach. Audytuj raz na kwartał, czy progi i nazewnictwo nie rozjechały się z praktyką zespołu contentowego.

Alternatywy i rozszerzenia

Poza procentami, możesz mierzyć wejścia sekcji:

  • Dodaj data-attributes do nagłówków (data-section="faq") i wyślij event przy ich wejściu w viewport.
  • Mierz widoczność kluczowych modułów (np. rekomendacje, formularz) przez IntersectionObserver.
  • Połącz głębokość przewijania z odtwarzaniem wideo (czas vs. procent) dla pełniejszego obrazu atencji.

Takie podejście daje precyzyjniejszy kontekst niż same progi.

Uwagi końcowe o dokładności

Pamiętaj, że „głębokość przewijania” nie równa się „przeczytano”. Aby zbliżyć się do realnej atencji, połącz progi z minimalnym czasem spędzonym na stronie (np. engaged_time_msec) albo z aktywnością myszki/klawiatury. W GA4 możesz użyć metryki engaged sessions, ale najlepiej dodać własną logikę „aktywnych 10 s” przed uznaniem progu za „wartościowy”.

Podsumowując operacyjnie: wybierz stabilne progi, zaplanuj nazwy zdarzeń i parametrów, wdroż w GTM i GA4 lub przez JS, dopilnuj zgodności z RODO, a następnie regularnie weryfikuj rozkład i wpływ na konwersje. Konsekwentne mierzenie i iteracyjne poprawki szybko przełożą się na lepsze decyzje produktowe i biznesowe, bez zgadywania.

Masz podobny problem na swojej stronie?

Podaj adres strony i e-mail. Sprawdzimy ją bezpłatnie i odpiszemy z konkretnymi wnioskami.

Administratorem danych jest icomSEO Sp. z o.o. z siedzibą w Lublinie. Dane przetwarzamy, aby odpowiedzieć na zgłoszenie. Więcej w Polityce prywatności.

Tomek Bogucki
O autorze

Tomek Bogucki

SEO APP Developer · 964 artykuły

Tomek Bogucki tworzy treści dla bloga icomSEO: praktyczne poradniki o SEO, reklamie i marketingu internetowym.

Podobne artykuły

Partnerzy i organizacje

Zadzwoń