Skip to content

Repository files navigation

PDF Viewer Analytics

CI License: MIT Zero Dependencies

A lightweight, zero-dependency client-side document viewer analytics engine that tracks per-page dwell time, tab visibility state changes, scroll depth, and reader drop-off points.


Overview

Traditional web analytics tools (like Google Analytics or Mixpanel) are built for web page navigations, not intra-document interactions. When a prospect or investor opens a 20-slide pitch deck or a 50-page legal contract, standard analytics only record a single pageview.

PDF Viewer Analytics provides fine-grained, slide-by-slide and page-by-page telemetry:

  • Active Dwell Time: Accurately measures how many seconds a reader actively spends on each individual page.
  • Tab Visibility Awareness: Automatically pauses timers when the viewer switches browser tabs or minimizes the window via the HTML5 visibilitychange API.
  • Drop-Off Tracking: Identifies the exact slide where readers lose interest or stop reading.
  • Privacy-First: Operates entirely client-side without third-party cookies or intrusive tracking pixels.

Relationship to SendNow

This project is created and maintained by the engineering team at SendNow.

  • Use this library if: You are building your own in-house PDF viewer (using PDF.js, Canvas, or HTML slides) and need embeddable client-side engagement telemetry.
  • Use SendNow document tracking analytics if: You need an end-to-end hosted document distribution platform with real-time viewer notifications, slide dwell heatmaps, domain gating, and screenshot deterrence.
  • Explore our detailed feature breakdown on presentation dwell time analytics.

Quick Start

Installation

npm install pdf-viewer-analytics

Basic Usage

import { DocumentEngagementTracker } from 'pdf-viewer-analytics';

// 1. Initialize tracker
const tracker = new DocumentEngagementTracker({
  onEvent: (event) => console.log('Analytics Event:', event)
});

// 2. Start session for a 10-page document
tracker.startSession('pitch-deck-2026', 10, { viewerEmail: 'lead-investor@fund.vc' });

// 3. Record page transitions as viewer scrolls or clicks next
tracker.recordPageView(1);

// When user navigates to slide 2:
tracker.recordPageView(2);

// 4. Handle visibility state changes (tab switching)
document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    tracker.pauseSession();
  } else {
    tracker.resumeSession();
  }
});

// 5. Retrieve metrics on document close or periodic heartbeat
const metrics = tracker.getMetrics();
console.log('Engagement Metrics:', metrics);

Sample Metrics Payload

{
  "sessionId": "ses_9a7x12z8917",
  "documentId": "pitch-deck-2026",
  "totalPages": 5,
  "viewedPagesCount": 3,
  "completionRatePercent": 60,
  "dropOffPage": 3,
  "totalDwellSeconds": 84,
  "pages": [
    { "page": 1, "dwellSeconds": 32, "visits": 2 },
    { "page": 2, "dwellSeconds": 45, "visits": 1 },
    { "page": 3, "dwellSeconds": 7, "visits": 1 },
    { "page": 4, "dwellSeconds": 0, "visits": 0 },
    { "page": 5, "dwellSeconds": 0, "visits": 0 }
  ]
}

Live Interactive Demo

Run the local demo server:

npm start

Then open http://localhost:8080 in your browser. Click through the presentation slides, switch tabs to verify pause behavior, and observe the live dwell-time heatmaps update in real time.


License

MIT License. See LICENSE for details.

Releases

Packages

Contributors

Languages