Plugins

Scroll Tracking

Overview

This plugin tracks user scroll depth in a Nuxt 3 application and logs virtual scroll events at specific milestones (10%, 25%, 50%, 75%, 90%).

Useful for measuring engagement and visibility of content, especially in analytics platforms.


Plugin Source

export default defineNuxtPlugin((nuxtApp) => {
  let isTriggered = false;
  let triggeredPercentages = [false, false, false, false, false];

  function handleScrollLogEvent(percentage: number) {
    logEvent({
      options: {
        eventAction: "scroll",
        eventProperties: {
          scroll_depth: percentage,
        },
        eventInteraction: true,
        eventLabel: `scroll_depth:${percentage}%`,
        eventName: "virtual_scroll",
      },
    });
  }

  const handleScroll = () => {
    const scrollTop = window.scrollY || document.documentElement.scrollTop;
    const windowHeight = window.innerHeight;
    const documentHeight = document.documentElement.scrollHeight;
    const scrolledPercentage =
      (scrollTop / (documentHeight - windowHeight)) * 100;

    if (scrolledPercentage >= 10 && !triggeredPercentages[0]) {
      triggeredPercentages[0] = true;
      handleScrollLogEvent(10);
    }

    if (scrolledPercentage >= 25 && !triggeredPercentages[1]) {
      triggeredPercentages[1] = true;
      handleScrollLogEvent(25);
    }

    if (scrolledPercentage >= 50 && !triggeredPercentages[2]) {
      triggeredPercentages[2] = true;
      handleScrollLogEvent(50);
    }

    if (scrolledPercentage >= 75 && !triggeredPercentages[3]) {
      triggeredPercentages[3] = true;
      handleScrollLogEvent(75);
    }

    if (scrolledPercentage >= 90 && !triggeredPercentages[4]) {
      triggeredPercentages[4] = true;
      handleScrollLogEvent(90);
    }
  };

  // Attach scroll listener on app mount
  nuxtApp.hook("app:mounted", () => {
    window.addEventListener("scroll", handleScroll);
  });

  // Reset triggered flags on route change
  nuxtApp.hook("page:finish", () => {
    isTriggered = false;
    triggeredPercentages = [false, false, false, false, false];
  });
});

Scroll Depth Thresholds

The following scroll depths are tracked:

  • 10%
  • 25%
  • 50%
  • 75%
  • 90%

Each threshold is logged only once per page view.


Event Logging Schema

Each event uses this structure:

FieldValue
eventName"virtual_scroll"
eventAction"scroll"
eventLabel"scroll_depth:{percentage}%"
eventProperties.scroll_depthNumber (10, 25, 50, etc.)
eventInteractiontrue

Usage Notes

  • Works on client side only
  • Automatically resets scroll depth triggers after every route change
  • No native hook exists for app:unmounted or route:changed, so scroll listener persists between pages (should not be an issue unless component-scoped)

Copyright © 2026