JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 44
  • Score
    100M100P100Q59735F
  • License MIT

Universal user activity tracking library

Package Exports

  • @vigneshwaranbs/activity-tracker
  • @vigneshwaranbs/activity-tracker/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@vigneshwaranbs/activity-tracker) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

๐ŸŽฏ Activity Tracker

Universal user activity tracking library for web applications

npm version npm downloads License: MIT

Track user activity across your web applications with automatic inactivity detection, cross-tab synchronization, and real-time heartbeat monitoring.


โœจ Features

Core Features

  • ๐Ÿ–ฑ๏ธ Activity Detection - Tracks mouse, keyboard, scroll, and touch events
  • โฑ๏ธ Inactivity Monitoring - Automatic detection after configurable timeout (default: 15 minutes)
  • ๐Ÿ’“ Heartbeat System - Regular server sync (default: 60 seconds)
  • ๐Ÿ”„ Cross-Tab Sync - Real-time activity sync across browser tabs via BroadcastChannel
  • ๐ŸŒ Cross-Domain Support - Server-based sync for different domains
  • ๐Ÿ“Š Page Visibility Tracking - Detects when users switch tabs (Page Visibility API)
  • ๐ŸŽฏ Window Focus Tracking - Monitors when users switch to other apps/windows
  • ๐Ÿ” JWT Token Support - Automatic JWT decoding to extract userId
  • ๐Ÿ” Retry Logic - Automatic retry for failed heartbeats with exponential backoff

Detailed Behavior Tracking

  • ๐Ÿ–ฑ๏ธ Click Tracking - Captures element ID, class, text, xpath, and coordinates
  • ๐Ÿ“œ Scroll Tracking - Records scroll depth %, position, and sections viewed
  • ๐Ÿ”— Navigation Tracking - Monitors page views, time on page, and navigation path
  • ๐Ÿ‘๏ธ Viewport Tracking - Tracks visible elements and time in view
  • ๐Ÿ“ฆ Event Batching - Automatically batches events (default: 30 seconds, max 100 events)
  • ๐Ÿ”’ Privacy-First - No PII, truncated text, respects data-no-track attribute

Developer Experience

  • ๐Ÿ”’ TypeScript Support - Full type definitions included
  • โšก Performance Optimized - Debounced events, passive listeners, minimal overhead
  • ๐Ÿ”ง Highly Configurable - 30+ configuration options
  • ๐Ÿ“ฑ Framework Agnostic - Works with React, Vue, Angular, Svelte, vanilla JS
  • ๐ŸŒ CDN Support - Drop-in script for no-build-tool projects
  • ๐Ÿ“ Comprehensive Callbacks - 7 lifecycle callbacks for custom logic
  • ๐ŸŽจ HTML Attributes - Mark elements with data-section, data-track-viewport, data-no-track

๐Ÿ“ฆ Installation

Option 1: NPM Package (For Build Tools)

npm install @vigneshwaranbs/activity-tracker
yarn add @vigneshwaranbs/activity-tracker
pnpm add @vigneshwaranbs/activity-tracker

Option 2: CDN (Drop-in Script - No Build Tools)

Basic Activity Tracking:

<!-- Latest version -->
<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@latest/dist/activity-tracker-universal.js"></script>

<!-- Access globally as window.activityTracker -->
<script>
  // Tracker auto-starts when page loads
  console.log('Tracker:', window.activityTracker);
</script>

Detailed Behavior Tracking (Single Collection):

<!-- Stores session + events in one collection (user_sessions) -->
<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@latest/dist/activity-tracker-universal-phase2.js"></script>

<!-- Access globally as window.activityTracker -->
<script>
  console.log('Detailed Tracker:', window.activityTracker);
</script>

Detailed Behavior Tracking (Separate Collections):

<!-- Stores sessions in user_sessions, events in user_activity_events -->
<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@latest/dist/activity-tracker-universal-userevent.js" 
        data-api-endpoint="https://your-api.com/api/user/activity">
</script>

<!-- Access globally as window.activityTracker -->
<script>
  console.log('Detailed Tracker:', window.activityTracker);
</script>

CDN Usage: Perfect for vanilla HTML, WordPress, legacy apps, or quick prototypes. No npm install needed!


๐Ÿš€ Quick Start

Three Tracking Options Available

This library offers three tracking options to suit different use cases:

  1. Basic Activity Tracking - Monitor user active/inactive status with heartbeat sync
  2. Detailed Behavior Tracking (Single Collection) - Track clicks, scrolls, navigation in same collection as sessions
  3. Detailed Behavior Tracking (Separate Collections) - Store events in separate collection for better data organization

Method 1: Basic Activity Tracking

Perfect for session management, timeout detection, and presence monitoring.

NPM Installation:

npm install @vigneshwaranbs/activity-tracker

Basic Usage:

import { ActivityTracker } from '@vigneshwaranbs/activity-tracker';

// Initialize tracker
const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || ''
});

// Start tracking
tracker.start();

// Stop tracking (cleanup)
tracker.stop();

React Example

import { useEffect } from 'react';
import { ActivityTracker } from '@vigneshwaranbs/activity-tracker';

function App() {
  useEffect(() => {
    const tracker = new ActivityTracker({
      appId: 'my-react-app',
      apiEndpoint: 'https://api.yourapp.com/api/user/activity',
      getAuthToken: () => localStorage.getItem('userId') || '',
      
      // Callbacks
      onActive: (data) => {
        console.log('โœ… User is active', data);
      },
      onInactive: (data) => {
        console.warn('โš ๏ธ User inactive for', data.inactivityDuration / 60000, 'minutes');
      }
    });

    tracker.start();

    return () => tracker.stop(); // Cleanup on unmount
  }, []);

  return <div>Your App</div>;
}

Vue Example

<script setup>
import { onMounted, onUnmounted } from 'vue';
import { ActivityTracker } from '@vigneshwaranbs/activity-tracker';

let tracker;

onMounted(() => {
  tracker = new ActivityTracker({
    appId: 'my-vue-app',
    apiEndpoint: 'https://api.yourapp.com/api/user/activity',
    getAuthToken: () => localStorage.getItem('userId') || ''
  });
  
  tracker.start();
});

onUnmounted(() => {
  tracker?.stop();
});
</script>

CDN Usage (No Build Tools):

<!DOCTYPE html>
<html>
<head>
    <title>My App</title>
</head>
<body>
    <h1>My Application</h1>
    
    <!-- Step 1: Set JWT token in localStorage (your login code) -->
    <script>
        // After successful login, store JWT token
        localStorage.setItem('authToken', 'eyJhbGci...');
    </script>
    
    <!-- Step 2: Include universal script - appId auto-generated from domain -->
    <script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.3/dist/activity-tracker-universal.js" 
            data-api-endpoint="https://api.yourapp.com/api/user/activity">
    </script>
    
    <!-- That's it! Basic tracking starts automatically -->
    <!-- appId is automatically generated from domain (e.g., www.app.xxxx.com โ†’ app.xxxx) -->
</body>
</html>

Auto-Generated AppId:

The tracker automatically generates appId from your domain name:

Domain Auto-Generated AppId
www.app.xxxx.com app.xxxx
app.xxxx.com app.xxxx
xxxx.com xxxx
localhost localhost

Override AppId (Optional):

<!-- Manually specify appId if you want a custom name -->
<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.3/dist/activity-tracker-universal.js" 
        data-app-id="custom-app-name"
        data-api-endpoint="https://api.yourapp.com/api/user/activity">
</script>

Basic Tracking Configuration (CDN):

<!-- All configuration via data attributes -->
<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.0/dist/activity-tracker-universal.js" 
        data-app-id="my-app" 
        data-api-endpoint="https://api.yourapp.com/api/user/activity"
        data-auth-token-key="authToken"
        data-inactivity-timeout="900000"
        data-heartbeat-interval="60000"
        data-log-level="info">
</script>

Detailed Tracking Configuration (CDN):

<!-- Configuration for detailed tracking -->
<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.0/dist/activity-tracker-universal-phase2.js" 
        data-app-id="my-app" 
        data-api-endpoint="https://api.yourapp.com/api/user/activity"
        data-events-api-endpoint="https://api.yourapp.com/api/user/activity/events"
        data-auth-token-key="authToken"
        data-track-clicks="true"
        data-track-scrolls="true"
        data-track-navigation="true"
        data-track-viewport="true"
        data-event-batch-interval="30000"
        data-max-events-per-batch="100">
</script>

Or use global config object:

<script>
    window.ACTIVITY_TRACKER_CONFIG = {
        appId: 'my-app',
        apiEndpoint: 'https://api.yourapp.com/api/user/activity',
        authTokenKey: 'authToken',
        inactivityTimeout: 900000,
        heartbeatInterval: 60000,
        
        // For detailed tracking (phase2 script only)
        eventsApiEndpoint: 'https://api.yourapp.com/api/user/activity/events',
        trackClicks: true,
        trackScrolls: true,
        trackNavigation: true,
        trackViewport: true,
        
        // Callbacks
        onActive: function(data) {
            console.log('User is active!', data);
        },
        onInactive: function(data) {
            console.warn('User is inactive!', data);
        }
    };
</script>
<!-- Choose appropriate script -->
<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.3/dist/activity-tracker-universal-phase2.js"></script>

CDN is perfect for:

  • โœ… Vanilla HTML/CSS/JS projects
  • โœ… WordPress, Shopify, Wix sites
  • โœ… Legacy applications without build tools
  • โœ… Quick prototypes and demos
  • โœ… No npm install or build step needed
  • โœ… Auto-generated appId from domain (no manual configuration needed)


Method 2: Detailed Behavior Tracking

Perfect for analytics, UX optimization, heatmaps, and understanding user behavior.

Features:

  • ๐Ÿ–ฑ๏ธ Click Tracking - Captures element ID, class, text, xpath, and coordinates
  • ๐Ÿ“œ Scroll Tracking - Records scroll depth %, position, and sections viewed
  • ๐Ÿ”— Navigation Tracking - Monitors page views, time on page, and navigation path
  • ๐Ÿ‘๏ธ Viewport Tracking - Tracks visible elements and time in view
  • ๐Ÿ“ฆ Event Batching - Automatically batches events (sends every 30 seconds)
  • ๐Ÿ”’ Privacy-First - No PII, truncated text, respects data-no-track attribute
  • โšก Performance Optimized - Debounced events, passive listeners, minimal overhead

NPM Installation:

npm install @vigneshwaranbs/activity-tracker

Usage:

import { DetailedActivityTracker } from '@vigneshwaranbs/activity-tracker';

const tracker = new DetailedActivityTracker({
  // Phase 1 config (required)
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  authToken: localStorage.getItem('authToken'),
  
  // Phase 2 config (new)
  trackClicks: true,
  trackScrolls: true,
  trackNavigation: true,
  trackViewport: true,
  eventsApiEndpoint: 'https://api.yourapp.com/api/user/activity/events',
  eventBatchInterval: 30000,  // 30 seconds
  maxEventsPerBatch: 100,
  
  // Phase 2 callbacks
  onEventTracked: (event) => {
    console.log('Event tracked:', event);
  },
  onEventBatchSent: (response) => {
    console.log('Batch sent:', response.eventsReceived, 'events');
  }
});

tracker.start();

CDN Usage (No Build Tools):

<!DOCTYPE html>
<html>
<head>
    <title>My App</title>
</head>
<body>
    <h1>My Application</h1>
    
    <!-- Step 1: Set JWT token in localStorage -->
    <script>
        localStorage.setItem('authToken', 'eyJhbGci...');
    </script>
    
    <!-- Step 2: Include universal script - detailed tracking with auto-generated appId -->
    <script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.3/dist/activity-tracker-universal-phase2.js" 
            data-api-endpoint="https://api.yourapp.com/api/user/activity"
            data-events-api-endpoint="https://api.yourapp.com/api/user/activity/events"
            data-track-clicks="true"
            data-track-scrolls="true"
            data-track-navigation="true"
            data-track-viewport="true">
    </script>
    
    <!-- Detailed tracking starts automatically -->
    <!-- appId is auto-generated from domain (e.g., www.app.xxxx.com โ†’ app.xxxx) -->
    <!-- To override: add data-app-id="custom-name" -->
</body>
</html>

๐Ÿ“Š Event Types

1. Click Events

{
  eventId: "evt-1703456789-abc123",
  eventType: "click",
  timestamp: 1703456789000,
  url: "/products",
  element: "button",
  elementId: "buy-now-btn",
  elementClass: "btn btn-primary",
  text: "Buy Now",
  xpath: "/html/body/div[1]/button",
  x: 350,
  y: 250
}

2. Scroll Events

{
  eventId: "evt-1703456790-def456",
  eventType: "scroll",
  timestamp: 1703456790000,
  url: "/products",
  scrollDepth: 75,  // 75% down page
  scrollPosition: 1200,
  pageHeight: 1600,
  viewportHeight: 800,
  sectionsViewed: ["hero", "features", "pricing"]
}

3. Navigation Events

{
  eventId: "evt-1703456791-ghi789",
  eventType: "navigation",
  timestamp: 1703456791000,
  url: "/checkout",
  fromUrl: "/products",
  toUrl: "/checkout",
  timeOnPage: 45000  // 45 seconds on previous page
}

4. Viewport Events

{
  eventId: "evt-1703456792-jkl012",
  eventType: "viewport",
  timestamp: 1703456792000,
  url: "/products",
  elementsInView: [
    {
      id: "product-card-1",
      class: "product-card",
      tag: "div",
      text: "Premium Product",
      timeInView: 5000  // 5 seconds
    }
  ]
}

๐ŸŽจ HTML Attributes for Tracking

Track Scroll Sections

<div data-section="hero">
  <!-- Hero content -->
</div>

<div data-section="features">
  <!-- Features content -->
</div>

<div data-section="pricing">
  <!-- Pricing content -->
</div>

When users scroll through these sections, they'll be recorded in sectionsViewed array.

Track Viewport Elements

<div data-track-viewport id="important-content">
  <!-- This element's visibility will be tracked -->
</div>

<div data-track-viewport class="product-card">
  <!-- Track how long users view this product -->
</div>

Elements with data-track-viewport attribute are monitored for visibility and time in view.

Exclude Elements from Tracking

<button data-no-track="true">
  <!-- This button won't be tracked -->
</button>

<div data-no-track="true">
  <!-- Clicks inside this div won't be tracked -->
</div>

๐Ÿ”ง Detailed Tracking Configuration Options

{
  // Feature Flags
  trackClicks?: boolean;           // Enable click tracking (default: true)
  trackScrolls?: boolean;          // Enable scroll tracking (default: true)
  trackNavigation?: boolean;       // Enable navigation tracking (default: true)
  trackViewport?: boolean;         // Enable viewport tracking (default: true)
  
  // API Endpoints
  eventsApiEndpoint?: string;      // Separate endpoint for events
                                   // Default: apiEndpoint + '/events'
  
  // Batching Settings
  eventBatchInterval?: number;     // How often to send events (ms)
                                   // Default: 30000 (30 seconds)
  maxEventsPerBatch?: number;      // Max events per batch
                                   // Default: 100
  
  // Callbacks
  onEventTracked?: (event: ActivityEvent) => void;
  onEventBatchSent?: (response: EventBatchResponse) => void;
  onEventBatchError?: (error: Error) => void;
}

๐Ÿ“ฑ Framework Examples - Detailed Tracking

React with Detailed Tracking

import { useEffect } from 'react';
import { DetailedActivityTracker } from '@vigneshwaranbs/activity-tracker';

function App() {
  useEffect(() => {
    const tracker = new DetailedActivityTracker({
      appId: 'my-react-app',
      apiEndpoint: 'https://api.yourapp.com/api/user/activity',
      eventsApiEndpoint: 'https://api.yourapp.com/api/user/activity/events',
      authToken: localStorage.getItem('authToken'),
      
      // Enable all Phase 2 features
      trackClicks: true,
      trackScrolls: true,
      trackNavigation: true,
      trackViewport: true,
      
      // Callbacks
      onEventTracked: (event) => {
        // Send to analytics
        if (event.eventType === 'click') {
          analytics.track('Button Clicked', {
            elementId: event.elementId,
            text: event.text
          });
        }
      }
    });

    tracker.start();
    return () => tracker.stop();
  }, []);

  return (
    <div>
      <div data-section="hero">
        <h1>Welcome</h1>
        <button id="cta-button">Get Started</button>
      </div>
      
      <div data-section="features" data-track-viewport>
        <h2>Features</h2>
        {/* Feature cards */}
      </div>
    </div>
  );
}

Vue with Detailed Tracking

<template>
  <div>
    <div data-section="hero">
      <h1>Welcome</h1>
      <button id="cta-button">Get Started</button>
    </div>
    
    <div data-section="features" data-track-viewport>
      <h2>Features</h2>
    </div>
  </div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue';
import { DetailedActivityTracker } from '@vigneshwaranbs/activity-tracker';

let tracker;

onMounted(() => {
  tracker = new DetailedActivityTracker({
    appId: 'my-vue-app',
    apiEndpoint: 'https://api.yourapp.com/api/user/activity',
    eventsApiEndpoint: 'https://api.yourapp.com/api/user/activity/events',
    authToken: localStorage.getItem('authToken'),
    trackClicks: true,
    trackScrolls: true,
    trackNavigation: true,
    trackViewport: true
  });
  
  tracker.start();
});

onUnmounted(() => {
  tracker?.stop();
});
</script>

๐Ÿ” Use Cases - Detailed Tracking

1. E-commerce Analytics

Track which products users view, how long they spend on product pages, and which "Add to Cart" buttons they click:

const tracker = new DetailedActivityTracker({
  appId: 'ecommerce-store',
  trackClicks: true,      // Track "Add to Cart", "Buy Now" clicks
  trackScrolls: true,     // See how far users scroll on product pages
  trackViewport: true,    // Track which products are viewed
  
  onEventTracked: (event) => {
    if (event.eventType === 'click' && event.elementId?.includes('add-to-cart')) {
      // User clicked "Add to Cart"
      sendToAnalytics('add_to_cart', { productId: extractProductId(event.url) });
    }
    
    if (event.eventType === 'viewport' && event.elementsInView.length > 0) {
      // Track product impressions
      event.elementsInView.forEach(el => {
        if (el.class?.includes('product-card')) {
          sendToAnalytics('product_view', { productId: el.id });
        }
      });
    }
  }
});

2. Content Engagement

Measure how users engage with blog posts or documentation:

const tracker = new DetailedActivityTracker({
  appId: 'blog',
  trackScrolls: true,     // Measure read depth
  trackNavigation: true,  // Time spent on each article
  
  onEventTracked: (event) => {
    if (event.eventType === 'scroll') {
      // User scrolled to 75% - likely read the article
      if (event.scrollDepth >= 75) {
        sendToAnalytics('article_read', { 
          url: event.url,
          scrollDepth: event.scrollDepth
        });
      }
    }
    
    if (event.eventType === 'navigation') {
      // Track time spent on article
      if (event.timeOnPage > 60000) { // More than 1 minute
        sendToAnalytics('article_engagement', {
          url: event.fromUrl,
          timeSpent: event.timeOnPage
        });
      }
    }
  }
});

3. Form Optimization

Track which form fields users interact with:

<form>
  <input type="text" id="email" placeholder="Email">
  <input type="text" id="phone" placeholder="Phone">
  <button id="submit-form">Submit</button>
</form>

<script>
  const tracker = new DetailedActivityTracker({
    appId: 'signup-form',
    trackClicks: true,
    
    onEventTracked: (event) => {
      if (event.eventType === 'click') {
        if (event.elementId === 'submit-form') {
          // Track form submission
          sendToAnalytics('form_submit');
        }
      }
    }
  });
</script>

๐Ÿ”’ Privacy & Security

Detailed tracking respects user privacy:

  • โœ… No PII Captured - Never tracks password inputs, credit card fields
  • โœ… Text Truncation - Element text limited to 100 characters
  • โœ… Opt-out Support - data-no-track attribute excludes elements
  • โœ… No Form Values - Only tracks field interactions, not values
  • โœ… GDPR Compliant - Respects user consent and data retention policies

Excluded by Default:

  • <input type="password">
  • <input type="hidden">
  • Elements with data-no-track="true"

๐Ÿ“Š Backend Integration - Detailed Tracking

Detailed tracking uses two API endpoints:

Basic Tracking Endpoint (Heartbeat):

POST /api/user/activity

Detailed Tracking Endpoints (Events):

POST /api/user/activity/events    # Stores events in same collection (user_sessions)
POST /api/user/userevent           # Stores events in separate collection (user_activity_events)

Example Backend (Express + MongoDB):

Option 1: Events in Same Collection (/api/user/activity/events):

// Event batching endpoint - stores in user_sessions collection
app.post('/api/user/activity/events', async (req, res) => {
  const { userId, appId, events } = req.body;
  
  // Validate
  if (!userId || !appId || !events || events.length === 0) {
    return res.status(400).json({ success: false, message: 'Invalid request' });
  }
  
  if (events.length > 100) {
    return res.status(400).json({ success: false, message: 'Max 100 events per batch' });
  }
  
  // Append events to user document
  await db.collection('user_sessions').updateOne(
    { userId: new ObjectId(userId), appId },
    { 
      $push: { 
        events: {
          $each: events,
          $slice: -1000  // Keep only last 1000 events
        }
      },
      $set: { updatedAt: new Date() }
    },
    { upsert: true }
  );
  
  res.json({ 
    success: true, 
    eventsReceived: events.length 
  });
});

Option 2: Events in Separate Collection (/api/user/userevent):

// Event batching endpoint - stores in user_activity_events collection
app.post('/api/user/userevent', async (req, res) => {
  const { userId, appId, events, timestamp } = req.body;
  
  // Validate
  if (!userId || !appId || !events || events.length === 0) {
    return res.status(400).json({ success: false, message: 'Invalid request' });
  }
  
  if (events.length > 100) {
    return res.status(400).json({ success: false, message: 'Max 100 events per batch' });
  }
  
  const now = new Date();
  
  // Get last event timestamp
  const lastEventTimestamp = events.length > 0 
    ? new Date(Math.max(...events.map(e => e.timestamp)))
    : now;
  
  // Add receivedAt timestamp to each event
  const eventsWithTimestamps = events.map(event => ({
    ...event,
    timestamp: new Date(event.timestamp),
    receivedAt: now
  }));

  // Store in separate collection
  await db.collection('user_activity_events').updateOne(
    { userId: new ObjectId(userId), appId },
    { 
      $push: { 
        events: {
          $each: eventsWithTimestamps,
          $slice: -1000
        }
      },
      $set: { 
        lastEventActivityTime: lastEventTimestamp,
        updatedAt: now 
      },
      $setOnInsert: { createdAt: now }
    },
    { upsert: true }
  );
  
  res.json({ 
    success: true, 
    eventsReceived: events.length,
    message: 'User events tracked successfully'
  });
});

MongoDB Document Structures:

Collection: user_sessions (Basic tracking + optional events):

{
  _id: ObjectId("..."),
  userId: ObjectId("..."),
  appId: "my-app",
  
  // Basic tracking fields
  isActive: true,
  lastActivityTime: ISODate("2024-12-24T10:30:00Z"),
  lastHeartbeat: ISODate("2024-12-24T10:30:00Z"),
  tabVisible: true,
  windowFocused: true,
  
  // Events array (optional - only if using activity-tracker-universal-phase2.js)
  events: [
    { 
      eventType: "click", 
      element: "button", 
      timestamp: ISODate("2024-12-24T10:30:00Z"),
      receivedAt: ISODate("2024-12-24T10:30:30Z"),
      ... 
    },
    { 
      eventType: "scroll", 
      scrollDepth: 75, 
      timestamp: ISODate("2024-12-24T10:31:00Z"),
      receivedAt: ISODate("2024-12-24T10:31:30Z"),
      ... 
    }
  ],
  
  createdAt: ISODate("2024-12-24T09:00:00Z"),
  updatedAt: ISODate("2024-12-24T10:30:00Z")
}

Collection: user_activity_events (Separate events collection - only if using activity-tracker-universal-userevent.js):

{
  _id: ObjectId("..."),
  userId: ObjectId("..."),
  appId: "my-app",
  
  // Events array
  events: [
    { 
      eventId: "evt-1234567890-abc",
      eventType: "click", 
      element: "button",
      elementId: "submit-btn",
      timestamp: ISODate("2024-12-24T10:30:00Z"),
      receivedAt: ISODate("2024-12-24T10:30:30Z"),
      x: 100,
      y: 200
    },
    { 
      eventId: "evt-1234567891-def",
      eventType: "scroll", 
      scrollDepth: 75,
      scrollY: 500,
      timestamp: ISODate("2024-12-24T10:31:00Z"),
      receivedAt: ISODate("2024-12-24T10:31:30Z")
    },
    { 
      eventId: "evt-1234567892-ghi",
      eventType: "navigation", 
      fromUrl: "/home", 
      toUrl: "/about",
      timeOnPage: 45000,
      timestamp: ISODate("2024-12-24T10:32:00Z"),
      receivedAt: ISODate("2024-12-24T10:32:30Z")
    }
  ],
  
  lastEventActivityTime: ISODate("2024-12-24T10:32:00Z"),
  createdAt: ISODate("2024-12-24T09:00:00Z"),
  updatedAt: ISODate("2024-12-24T10:32:30Z")
}

๐ŸŽ›๏ธ Advanced Usage - Detailed Tracking

Selective Feature Enabling

// Only track clicks and scrolls
const tracker = new DetailedActivityTracker({
  appId: 'my-app',
  trackClicks: true,
  trackScrolls: true,
  trackNavigation: false,  // Disabled
  trackViewport: false     // Disabled
});

Custom Event Handling

const tracker = new DetailedActivityTracker({
  appId: 'my-app',
  trackClicks: true,
  
  onEventTracked: (event) => {
    // Send to multiple analytics platforms
    if (event.eventType === 'click') {
      googleAnalytics.event('click', { elementId: event.elementId });
      mixpanel.track('Button Click', { button: event.text });
      amplitude.logEvent('click', { element: event.element });
    }
  },
  
  onEventBatchSent: (response) => {
    console.log(`โœ… Sent ${response.eventsReceived} events to backend`);
  },
  
  onEventBatchError: (error) => {
    console.error('โŒ Failed to send events:', error);
    // Retry logic or alert user
  }
});

Force Send Batch

// Manually trigger batch send (useful before page unload)
tracker.forceSendBatch();

// Example: Send batch before user leaves
window.addEventListener('beforeunload', () => {
  tracker.forceSendBatch();
});

Get Current Batch Size

const batchSize = tracker.getBatchSize();
console.log(`Current batch has ${batchSize} events`);

๐Ÿ“ˆ Performance Considerations

Detailed tracking is optimized for production:

  • โœ… Debounced Events - Scroll events debounced by 1 second
  • โœ… Passive Listeners - Non-blocking event listeners
  • โœ… Event Batching - Reduces API calls by 50%
  • โœ… Smart Filtering - Only tracks significant scroll changes (5%+)
  • โœ… Memory Management - Automatic queue cleanup
  • โœ… Minimal Overhead - <1% CPU usage, <50MB memory

Data Volume Estimate (1000 users):

  • Events per user per day: ~5,000
  • Storage per user per day: ~25 MB
  • With 1000-event limit: ~5 MB per user
  • Total: ~5 GB per day (1000 users)

Optimization Tips:

  • Use 90-day data retention (auto-delete old events)
  • Enable only needed features (disable viewport if not needed)
  • Increase eventBatchInterval to reduce API calls
  • Use sampling (track 10% of users for detailed analytics)

๐Ÿ†š Comparison: Basic vs Detailed Tracking

Feature Basic Tracking Detailed Tracking
Active/Inactive Detection โœ… โœ…
Heartbeat to Backend โœ… โœ…
Tab Visibility โœ… โœ…
Window Focus โœ… โœ…
Click Tracking โŒ โœ…
Scroll Tracking โŒ โœ…
Navigation Tracking โŒ โœ…
Viewport Tracking โŒ โœ…
Event Batching โŒ โœ…
Class ActivityTracker DetailedActivityTracker
CDN Script activity-tracker-universal.js activity-tracker-universal-phase2.js
API Endpoints 1 endpoint 2 endpoints
Use Case Session management, timeouts Analytics, UX optimization

Choose Basic Tracking for:

  • โœ… Session timeout management
  • โœ… User presence monitoring
  • โœ… Active/inactive status
  • โœ… Lightweight tracking
  • โœ… Simple analytics

Choose Detailed Tracking for:

  • โœ… E-commerce analytics
  • โœ… Content engagement metrics
  • โœ… UX optimization
  • โœ… A/B testing insights
  • โœ… Heatmap data collection
  • โœ… User behavior analysis

โš™๏ธ Configuration Reference

Basic Tracking Configuration

Required Options

Option Type Description
appId string Unique identifier for your application
apiEndpoint string API endpoint URL for heartbeat requests
userId or authToken or getAuthToken string | function User identification

Optional Options

Option Type Default Description
inactivityTimeout number 900000 (15 min) Time before marking user inactive (ms)
heartbeatInterval number 60000 (1 min) Interval between heartbeat requests (ms)
checkInterval number 10000 (10 sec) Interval for checking inactivity (ms)
crossTabSync boolean true Enable cross-tab activity sync via BroadcastChannel
serverSync boolean true Enable server heartbeat sync
trackPageVisibility boolean true Track tab visibility changes (Page Visibility API)
trackWindowFocus boolean true Track window focus/blur events
debounceDelay number 1000 (1 sec) Debounce delay for activity events (ms)
retryAttempts number 3 Number of retry attempts for failed heartbeats
logLevel string 'warn' Log level: 'debug', 'info', 'warn', 'error', 'none'
customHeaders object {} Custom HTTP headers for API requests
metadata object {} Custom metadata to include in heartbeat

CDN Data Attributes (Basic Tracking)

Attribute Type Default Description
data-app-id string required Application identifier
data-api-endpoint string required Heartbeat API endpoint
data-auth-token-key string 'authToken' localStorage key for auth token
data-user-id-key string 'userId' localStorage key for user ID
data-inactivity-timeout number 900000 Inactivity timeout in milliseconds
data-heartbeat-interval number 60000 Heartbeat interval in milliseconds
data-check-interval number 10000 Activity check interval in milliseconds
data-cross-tab-sync boolean true Enable cross-tab sync
data-server-sync boolean true Enable server sync
data-track-page-visibility boolean true Track page visibility
data-track-window-focus boolean true Track window focus
data-debounce-delay number 1000 Debounce delay in milliseconds
data-retry-attempts number 3 Retry attempts for failed requests
data-log-level string 'warn' Log level

Callbacks

Callback Parameters Description
onActive (data: ActivityData) => void Called when user becomes active
onInactive (data: InactivityData) => void Called when user becomes inactive
onHeartbeatSuccess (response: HeartbeatResponse) => void Called on successful heartbeat
onHeartbeatError (error: Error) => void Called on heartbeat failure

Detailed Tracking Configuration

Additional Options (extends Basic Tracking)

Option Type Default Description
eventsApiEndpoint string apiEndpoint + '/events' Separate endpoint for event batching
trackClicks boolean true Enable click event tracking
trackScrolls boolean true Enable scroll event tracking
trackNavigation boolean true Enable navigation event tracking
trackViewport boolean true Enable viewport element tracking
eventBatchInterval number 30000 (30 sec) How often to send event batches (ms)
maxEventsPerBatch number 100 Maximum events per batch

CDN Data Attributes (Detailed Tracking)

Attribute Type Default Description
data-events-api-endpoint string apiEndpoint + '/events' Events API endpoint
data-track-clicks boolean true Enable click tracking
data-track-scrolls boolean true Enable scroll tracking
data-track-navigation boolean true Enable navigation tracking
data-track-viewport boolean true Enable viewport tracking
data-event-batch-interval number 30000 Event batch interval in milliseconds
data-max-events-per-batch number 100 Max events per batch

Additional Callbacks

Callback Parameters Description
onEventTracked (event: ActivityEvent) => void Called when an event is tracked
onEventBatchSent (response: EventBatchResponse) => void Called when batch is sent successfully
onEventBatchError (error: Error) => void Called when batch send fails

Configuration Examples

Minimal Configuration (NPM)

const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  userId: 'user-123'
});
tracker.start();

Minimal Configuration (CDN)

<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.0/dist/activity-tracker-universal.js" 
        data-app-id="my-app" 
        data-api-endpoint="https://api.yourapp.com/api/user/activity">
</script>

Full Configuration (NPM)

const tracker = new DetailedActivityTracker({
  // Basic tracking
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('authToken') || '',
  inactivityTimeout: 600000,      // 10 minutes
  heartbeatInterval: 30000,       // 30 seconds
  checkInterval: 5000,            // 5 seconds
  crossTabSync: true,
  serverSync: true,
  trackPageVisibility: true,
  trackWindowFocused: true,
  debounceDelay: 2000,           // 2 seconds
  retryAttempts: 5,
  logLevel: 'info',
  
  // Detailed tracking
  eventsApiEndpoint: 'https://api.yourapp.com/api/user/activity/events',
  trackClicks: true,
  trackScrolls: true,
  trackNavigation: true,
  trackViewport: true,
  eventBatchInterval: 20000,     // 20 seconds
  maxEventsPerBatch: 50,
  
  // Callbacks
  onActive: (data) => console.log('Active:', data),
  onInactive: (data) => console.warn('Inactive:', data),
  onHeartbeatSuccess: (res) => console.log('Heartbeat:', res),
  onHeartbeatError: (err) => console.error('Error:', err),
  onEventTracked: (event) => console.log('Event:', event),
  onEventBatchSent: (res) => console.log('Batch sent:', res),
  onEventBatchError: (err) => console.error('Batch error:', err)
});
tracker.start();

Full Configuration (CDN)

<script src="https://unpkg.com/@vigneshwaranbs/activity-tracker@2.0.0/dist/activity-tracker-universal-phase2.js" 
        data-app-id="my-app" 
        data-api-endpoint="https://api.yourapp.com/api/user/activity"
        data-events-api-endpoint="https://api.yourapp.com/api/user/activity/events"
        data-auth-token-key="authToken"
        data-inactivity-timeout="600000"
        data-heartbeat-interval="30000"
        data-check-interval="5000"
        data-cross-tab-sync="true"
        data-server-sync="true"
        data-track-page-visibility="true"
        data-track-window-focus="true"
        data-debounce-delay="2000"
        data-retry-attempts="5"
        data-log-level="info"
        data-track-clicks="true"
        data-track-scrolls="true"
        data-track-navigation="true"
        data-track-viewport="true"
        data-event-batch-interval="20000"
        data-max-events-per-batch="50">
</script>

๐Ÿ“– Advanced Examples

With Custom Metadata

const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  
  // Custom metadata
  metadata: {
    userAgent: navigator.userAgent,
    screenResolution: `${window.screen.width}x${window.screen.height}`,
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    language: navigator.language,
    referrer: document.referrer
  }
});

tracker.start();

With Custom Headers (Authentication)

const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  userId: 'user-123',
  
  // Custom headers for API authentication
  customHeaders: {
    'Authorization': `Bearer ${localStorage.getItem('authToken')}`,
    'X-API-Key': 'your-api-key',
    'X-App-Version': '1.0.0'
  }
});

tracker.start();

With All Callbacks

const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  
  // Activity callbacks
  onActive: (data) => {
    console.log('โœ… User is active');
    console.log('Last activity:', new Date(data.lastActivityTime));
    // Send to analytics
    analytics.track('user_active', data);
  },
  
  onInactive: (data) => {
    console.warn('โš ๏ธ User inactive');
    console.warn('Duration:', data.inactivityDuration / 60000, 'minutes');
    // Show warning modal
    showInactivityWarning();
  },
  
  onHeartbeatSuccess: (response) => {
    console.log('๐Ÿ’“ Heartbeat sent successfully');
    // Handle server response
    if (response.action === 'logout') {
      logout();
    }
  },
  
  onHeartbeatError: (error) => {
    console.error('โŒ Heartbeat failed:', error.message);
    // Send to error tracking (e.g., Sentry)
    Sentry.captureException(error);
  }
});

tracker.start();

Development vs Production Config

const isDevelopment = process.env.NODE_ENV === 'development';

const tracker = new ActivityTracker({
  appId: isDevelopment ? 'my-app-dev' : 'my-app',
  apiEndpoint: isDevelopment 
    ? 'http://localhost:4000/api/user/activity'
    : 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  
  // Development: shorter intervals for testing
  inactivityTimeout: isDevelopment ? 2 * 60 * 1000 : 15 * 60 * 1000,
  heartbeatInterval: isDevelopment ? 10 * 1000 : 60 * 1000,
  
  // Development: verbose logging
  logLevel: isDevelopment ? 'debug' : 'warn'
});

tracker.start();

React Custom Hook

// hooks/useActivityTracker.ts
import { useEffect, useState } from 'react';
import { ActivityTracker } from '@vigneshwaranbs/activity-tracker';

export function useActivityTracker(appId: string) {
  const [isActive, setIsActive] = useState(true);
  const [tracker, setTracker] = useState<ActivityTracker | null>(null);

  useEffect(() => {
    const activityTracker = new ActivityTracker({
      appId,
      apiEndpoint: 'https://api.yourapp.com/api/user/activity',
      getAuthToken: () => localStorage.getItem('userId') || '',
      
      onActive: () => setIsActive(true),
      onInactive: () => setIsActive(false)
    });

    activityTracker.start();
    setTracker(activityTracker);

    return () => activityTracker.stop();
  }, [appId]);

  return { isActive, tracker };
}

// Usage
function MyComponent() {
  const { isActive } = useActivityTracker('my-app');
  
  return (
    <div>
      <StatusBadge active={isActive} />
      {!isActive && <InactivityWarning />}
    </div>
  );
}

๐Ÿ”Œ Backend API Integration

Expected API Endpoint

Your backend should handle POST requests to the configured apiEndpoint:

Request:

POST /api/user/activity
Content-Type: application/json

{
  "userId": "676966c6c0b4b40f8cc2db9a",
  "appId": "my-app",
  "isActive": true,
  "lastActivityTime": 1703456789000,
  "tabVisible": true,
  "windowFocused": true,
  "metadata": {
    "userAgent": "Mozilla/5.0...",
    "platform": "MacIntel",
    "language": "en-US",
    "screenResolution": "1920x1080",
    "viewport": "1440x900",
    "timezone": "America/New_York",
    "url": "https://app.example.com/dashboard"
  }
}

Response:

{
  "success": true,
  "message": "Activity tracked successfully",
  "activeInOtherApp": false,
  "lastActivityTime": 1703456789000,
  "action": "continue" // or "logout", "warn"
}

Express.js Backend Example

// server.js
import express from 'express';
import { MongoClient, ObjectId } from 'mongodb';

const app = express();
app.use(express.json());

const MONGODB_URI = process.env.MONGODB_URI;
const client = await MongoClient.connect(MONGODB_URI);
const db = client.db('your-database');

app.post('/api/user/activity', async (req, res) => {
  try {
    const { userId, appId, isActive, lastActivityTime, tabVisible, windowFocused, metadata } = req.body;
    
    const now = new Date();
    const sessionData = {
      userId: new ObjectId(userId),
      appId,
      isActive,
      lastActivityTime: new Date(lastActivityTime),
      lastHeartbeat: now,
      tabVisible,
      windowFocused,
      metadata,
      updatedAt: now
    };
    
    // Upsert: one document per userId + appId
    await db.collection('user_sessions').updateOne(
      { userId: new ObjectId(userId), appId },
      { $set: sessionData, $setOnInsert: { createdAt: now } },
      { upsert: true }
    );
    
    res.json({ success: true, message: 'Activity tracked successfully' });
  } catch (error) {
    console.error('Activity tracking error:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

app.listen(4000, () => console.log('Server running on port 4000'));

MongoDB Schema

// Collection: user_sessions
{
  "_id": ObjectId("..."),
  "userId": ObjectId("676966c6c0b4b40f8cc2db9a"),
  "appId": "my-app",
  "isActive": true,
  "lastActivityTime": ISODate("2024-12-24T10:30:00.000Z"),
  "lastHeartbeat": ISODate("2024-12-24T10:30:00.000Z"),
  "tabVisible": true,
  "windowFocused": true,
  "metadata": {
    "userAgent": "Mozilla/5.0...",
    "platform": "MacIntel",
    "language": "en-US",
    "screenResolution": "1920x1080",
    "viewport": "1440x900",
    "timezone": "America/New_York",
    "url": "https://app.example.com/dashboard"
  },
  "createdAt": ISODate("2024-12-24T09:00:00.000Z"),
  "updatedAt": ISODate("2024-12-24T10:30:00.000Z")
}

// Recommended indexes
db.user_sessions.createIndex({ userId: 1, appId: 1 }, { unique: true });
db.user_sessions.createIndex({ lastActivityTime: -1 });
db.user_sessions.createIndex({ isActive: 1 });
db.user_sessions.createIndex({ updatedAt: -1 });

๐ŸŽฏ Use Cases

1. Session Timeout Management

const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  inactivityTimeout: 15 * 60 * 1000, // 15 minutes
  
  onInactive: (data) => {
    // Show warning modal
    showModal({
      title: 'Session Timeout Warning',
      message: `You've been inactive for ${data.inactivityDuration / 60000} minutes. Your session will expire soon.`,
      actions: ['Stay Logged In', 'Logout']
    });
  }
});

2. Multi-Tab Activity Sync

const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  crossTabSync: true, // Enable cross-tab sync
  
  onActive: () => {
    // Activity detected in any tab syncs to all tabs
    console.log('User active in this or another tab');
  }
});

3. Analytics Integration

const tracker = new ActivityTracker({
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  
  onActive: (data) => {
    // Track active sessions in analytics
    analytics.track('session_active', {
      userId: data.userId,
      appId: data.appId,
      timestamp: data.lastActivityTime
    });
  },
  
  onInactive: (data) => {
    // Track session end in analytics
    analytics.track('session_inactive', {
      userId: data.userId,
      duration: data.inactivityDuration
    });
  }
});

4. Real-Time User Presence

const tracker = new ActivityTracker({
  appId: 'collaboration-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  heartbeatInterval: 30 * 1000, // 30 seconds for real-time presence
  
  onHeartbeatSuccess: (response) => {
    // Update UI with active users from server response
    updateActiveUsersList(response.activeUsers);
  }
});

๐Ÿ” What Gets Tracked?

Activity Events

  • Mouse: mousedown, mousemove, click
  • Keyboard: keypress, keydown
  • Touch: touchstart (mobile devices)
  • Scroll: scroll (page scrolling)

Browser State

  • Page Visibility: Tab active/hidden (Visibility API)
  • Window Focus: Window focused/blurred
  • Tab Visibility: User switched tabs

Metadata (Optional)

  • User agent
  • Platform (OS)
  • Language
  • Screen resolution
  • Viewport size
  • Timezone
  • Current URL
  • Referrer
  • Custom metadata

๐Ÿ—๏ธ Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   Browser Tab 1                         โ”‚
โ”‚  ActivityTracker Instance                               โ”‚
โ”‚    โ”œโ”€ DOM Event Listeners (mouse, keyboard, scroll)     โ”‚
โ”‚    โ”œโ”€ BroadcastChannel (cross-tab sync)                 โ”‚
โ”‚    โ””โ”€ Heartbeat Timer (60s)                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ”‚ POST /api/user/activity
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   Backend API                           โ”‚
โ”‚  Express / Next.js / Fastify                            โ”‚
โ”‚    โ””โ”€ POST /api/user/activity                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ”‚ Upsert (one doc per user)
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   MongoDB Database                      โ”‚
โ”‚  Collection: user_sessions                              โ”‚
โ”‚    โ””โ”€ { userId, appId, isActive, lastActivityTime }     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โšก Performance

Optimizations

  • Debouncing: Activity events debounced by 1 second (configurable)
  • Passive Listeners: Non-blocking event listeners for scroll/touch
  • Efficient Intervals: Minimal timer overhead
  • Retry Queue: Failed heartbeats queued and retried
  • Cross-Tab Sync: BroadcastChannel for instant sync (no polling)

Benchmarks

  • Memory: ~50KB (minified + gzipped)
  • CPU: < 0.1% average
  • Network: 1 request per 60 seconds (configurable)
  • Event Overhead: < 1ms per debounced event

๐Ÿ› ๏ธ TypeScript Support

Full TypeScript definitions included:

import { 
  ActivityTracker, 
  ActivityTrackerConfig,
  ActivityData,
  InactivityData,
  HeartbeatPayload,
  HeartbeatResponse 
} from '@vigneshwaranbs/activity-tracker';

const config: ActivityTrackerConfig = {
  appId: 'my-app',
  apiEndpoint: 'https://api.yourapp.com/api/user/activity',
  getAuthToken: () => localStorage.getItem('userId') || '',
  inactivityTimeout: 15 * 60 * 1000,
  onActive: (data: ActivityData) => console.log(data),
  onInactive: (data: InactivityData) => console.warn(data)
};

const tracker = new ActivityTracker(config);
tracker.start();

๐Ÿงช Testing

Manual Testing

// Create tracker with short timeouts for testing
const tracker = new ActivityTracker({
  appId: 'test-app',
  apiEndpoint: 'http://localhost:4000/api/user/activity',
  userId: 'test-user',
  
  // Short intervals for testing
  inactivityTimeout: 30 * 1000,  // 30 seconds
  heartbeatInterval: 10 * 1000,  // 10 seconds
  checkInterval: 5 * 1000,       // 5 seconds
  
  // Verbose logging
  logLevel: 'debug',
  
  // Test callbacks
  onActive: () => console.log('โœ… ACTIVE'),
  onInactive: () => console.log('โš ๏ธ INACTIVE'),
  onHeartbeatSuccess: (res) => console.log('๐Ÿ’“ HEARTBEAT', res),
  onHeartbeatError: (err) => console.error('โŒ ERROR', err)
});

tracker.start();

// Test inactivity: Stop moving mouse for 30 seconds
// Test heartbeat: Check network tab for POST requests every 10 seconds
// Test cross-tab: Open multiple tabs and check sync

๐Ÿ“š API Reference

Constructor

new ActivityTracker(config: ActivityTrackerConfig)

Methods

Method Description
start() Start tracking user activity
stop() Stop tracking and cleanup
isUserActive() Check if user is currently active
getLastActivityTime() Get timestamp of last activity
forceHeartbeat() Manually trigger a heartbeat

Example

const tracker = new ActivityTracker({ /* config */ });

tracker.start();                        // Start tracking
const active = tracker.isUserActive();  // Check status
const lastTime = tracker.getLastActivityTime(); // Get timestamp
tracker.forceHeartbeat();              // Force sync
tracker.stop();                        // Stop and cleanup

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


๐Ÿ“„ License

MIT ยฉ Vigneshwaran BS



๐Ÿ’ก Support

For questions, issues, or feature requests:


Made with โค๏ธ by Vigneshwaran BS