npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vimond-player-analytics-web

v1.1.11

Published

Vimond Analytics SDK for video player analytics

Readme

vimond-player-analytics-web

Vimond Analytics SDK for video player analytics. This package provides a wrapper around the Eyevinn Player Analytics Client SDK with Vimond-specific functionality and enhanced ad tracking capabilities.

Installation

pnpm install vimond-player-analytics-web

Features

  • 🎯 Automatic video event tracking via Eyevinn Player Analytics SDK
  • 📊 Enhanced ad analytics with IMA support
  • 🔄 Automatic metadata enrichment with URL parameters
  • 📱 Device detection and browser information
  • 🎬 Support for both live and VOD content
  • 🔐 DRM detection and reporting
  • 📈 Quality level and bitrate tracking
  • 👤 Persistent user ID generation for cross-session tracking

Usage

Basic Setup

import { vimondAnalytics } from 'vimond-player-analytics-web';

const analytics = vimondAnalytics({
  eventsinkUrl: 'https://your-eventsink-url.io',
  sessionId: 'unique-session-id',
  heartbeatInterval: 10000,
  debug: false,
  enableAdEvents: true,
  adProfileId: 'your-ad-profile-id',
  shardId: 'your-shard-id'
});

await analytics.init();
analytics.load(videoElement);

Video.js Integration

import { VimondAnalyticsIntegration } from 'vimond-player-analytics-web';

const integration = VimondAnalyticsIntegration({
  eventsinkUrl: 'https://your-eventsink-url.io',
  sessionId: crypto.randomUUID(),
  player: videoJsPlayer,
  playback: {
    assetId: 'content-id',
    assetTitle: 'Content Title',
    isLive: false,
    isDrmProtected: true,
    recommendedStream: {
      manifest: { uri: 'https://example.com/manifest.m3u8' },
      drmProxyType: 'widevine' // Optional
    },
    categoryId: 'category-id'
  },
  videoKey: 'unique-video-key', // Note: userId is automatically generated and persisted
  enableAdEvents: true,
  adProfileId: 'your-ad-profile-id',
  shardId: 'your-shard-id',
  additionalMetadata: {
    customField1: 'value1',
    customField2: 'value2'
  }
});

await integration.init();

Bitmovin React Native Integration

For React Native applications using Bitmovin Player:

import { BitmovinRNAnalyticsIntegration } from 'vimond-player-analytics-web';

const integration = BitmovinRNAnalyticsIntegration({
  eventsinkUrl: 'https://your-eventsink-url.io',
  sessionId: crypto.randomUUID(),
  playback: {
    assetId: 'content-id',
    assetTitle: 'Content Title',
    isLive: false,
    isDrmProtected: 'drm', // 'drm' or 'none'
    recommendedStream: {
      manifest: { uri: 'https://example.com/manifest.m3u8' }
    },
    categoryId: 'category-id'
  },
  videoKey: 'unique-video-key', // Note: userId is automatically generated and persisted
  duration: 120000, // Duration in milliseconds
  player: {
    getCurrentTime: async () => {
      // Return current playback time
      return await player.getCurrentTime();
    },
    isMuted: async () => {
      // Return muted state
      return await player.isMuted();
    },
    autoplay: () => {
      // Return autoplay state
      return player.autoplay();
    }
  },
  deviceInfo: {
    deviceName: 'Apple TV',
    model: 'Apple TV 4K'
  },
  domain: 'example.com',
  path: '/watch',
  playerProfileId: 'your-player-profile-id',
  adProfileId: 'your-ad-profile-id',
  shardId: 'your-shard-id',
  additionalMetadata: {
    customField1: 'value1'
  }
});

await integration.init();

// Handle player events
integration.handlePlayerEvent({
  name: 'onPlaying',
  // ... event data
});

integration.handlePlayerEvent({
  name: 'onAdStarted',
  ad: { id: 'ad-id' },
  adBreak: { id: 'break-id' },
  position: 'pre',
  duration: 30
});

Ad Event Tracking

// Report ad events with IMA integration
integration.reportAdEvent({
  data: imaAdEvent,
  adState: 'adStarted', // or 'adCompleted', 'adSkipped', 'adError', etc.
  adPosition: 'pre', // 'pre', 'mid', or 'post'
  metadata: {
    customAdField: 'value'
  }
});

// Track ad quartiles
const analytics = integration.getAnalyticsInstance();
analytics.setAdMidQuartile('1');
analytics.setAdThirdQuartile('1');
analytics.incrementCompletedAds();

Configuration

VimondAnalyticsConfig

type VimondAnalyticsConfig = {
  eventsinkUrl: string;           // Required: Analytics endpoint URL
  sessionId?: string;              // Optional: Unique session identifier
  heartbeatInterval?: number;      // Optional: Heartbeat interval in ms (default: 10000)
  debug?: boolean;                 // Optional: Enable debug logging
  enableAdEvents?: boolean;        // Optional: Enable ad event tracking
  adProfileId?: string;           // Optional: Ad profile identifier
  shardId?: string;               // Optional: Shard identifier for data partitioning
  player?: {                       // Optional: Player state callbacks
    muted?: () => boolean;         // Optional: Function to get muted state
    autoplay?: () => boolean;      // Optional: Function to get autoplay state
  };
}

VideoJsAnalyticsConfig

type VideoJsAnalyticsConfig = {
  player: Player;                  // Required: Video.js player instance
  playback: {
    assetId: string;
    assetTitle: string;
    isLive: boolean;
    isDrmProtected: boolean;
    recommendedStream?: {
      manifest?: { uri: string };
      drmProxyType?: string;       // Optional: DRM proxy type
    };
    categoryId?: string;
  };
  videoKey: string;                // Required: Unique video identifier
  eventsinkUrl: string;
  sessionId?: string;
  heartbeatInterval?: number;
  debug?: boolean;
  enableAdEvents?: boolean;
  adProfileId?: string;
  shardId?: string;
  additionalMetadata?: Record<string, unknown>;  // Custom metadata fields
}

BitmovinRNAnalyticsConfig

type BitmovinRNAnalyticsConfig = {
  playback: {
    assetId: string;
    assetTitle: string;
    isLive: boolean;
    isDrmProtected: string;        // 'drm' or 'none'
    recommendedStream?: {
      manifest?: { uri: string };
    };
    categoryId?: string;
  };
  videoKey: string;                // Required: Unique video identifier
  eventsinkUrl: string;
  sessionId?: string;
  heartbeatInterval?: number;
  debug?: boolean;
  adProfileId?: string;
  shardId?: string;
  domain?: string;                 // Optional: Domain for analytics
  path?: string;                   // Optional: Path for analytics
  playerProfileId?: string;        // Optional: Player profile identifier
  deviceInfo?: {
    deviceName?: string;           // Optional: Device name
    model?: string;                // Optional: Device model
  };
  duration: number;                // Required: Content duration in milliseconds
  player?: {
    getCurrentTime?: () => Promise<number>;  // Optional: Get current playback time
    isMuted?: () => Promise<boolean>;       // Optional: Get muted state
    autoplay?: () => boolean;               // Optional: Get autoplay state
  };
  additionalMetadata?: Record<string, string>;  // Custom metadata fields
}

API Reference

vimondAnalytics()

Factory function that creates an analytics instance.

Methods

  • init(): Promise<void> - Initialize the analytics connector
  • load(videoElement: HTMLVideoElement): void - Attach to video element for automatic event tracking
  • reportMetadata(metadata: Record<string, unknown>): void - Report custom metadata (automatically enriched with playerProfileId from URL)
  • reportAdEvent(payload: VimondAdEventPayload): void - Report ad events with automatic IMA data extraction
  • reportBitrateChange(bitrate: number): void - Report quality/bitrate changes
  • setAdMidQuartile(value: string): void - Set ad mid-quartile tracking
  • setAdThirdQuartile(value: string): void - Set ad third-quartile tracking
  • incrementCompletedAds(): void - Increment completed ads counter
  • resetCompletedAds(): void - Reset completed ads counter
  • getCompletedAdsCount(): number - Get current completed ads count
  • deinit(): void - Clean up resources and disconnect

VimondAnalyticsIntegration()

Factory function for Video.js integration.

Features:

  • Automatically monitors quality level changes and reports bitrate changes
  • Sets up player state callbacks (muted, autoplay) for metadata enrichment

Methods

  • init(): Promise<void> - Initialize integration and report initial metadata
  • reportAdEvent(payload): void - Report ad events
  • reportMetadata(metadata): void - Report custom metadata
  • getAnalyticsInstance() - Get the underlying analytics instance
  • deinit(): void - Clean up resources and remove event listeners

BitmovinRNAnalyticsIntegration()

Factory function for Bitmovin React Native integration.

Methods

  • init(): Promise<void> - Initialize integration and report initial metadata
  • handlePlayerEvent(event: PlayerEventData): void - Handle player events from Bitmovin player
  • reportAdEvent(payload: AdEventPayload): void - Report ad events manually
  • reportMetadata(metadata): void - Report custom metadata
  • getAnalyticsInstance() - Get the underlying analytics instance
  • deinit(): void - Clean up resources

Supported Player Events

The Bitmovin integration handles the following player events automatically:

  • onPlaying - Playback started
  • onPaused - Playback paused
  • onSeek - Seeking started
  • onSeeked - Seeking completed
  • onPlaybackFinished - Playback ended
  • onPlayerError / SourceError - Player errors
  • onStallStarted - Buffering started
  • onStallEnded - Buffering ended
  • onVideoPlaybackQualityChanged - Quality/bitrate changed
  • onAdStarted - Ad playback started
  • onAdFinished - Ad playback completed
  • onAdSkipped - Ad was skipped
  • onAdBreakFinished - Ad break completed
  • onAdError - Ad error occurred
  • onAdQuartile - Ad quartile reached (mid_point, third)

Automatic Metadata Enrichment

The SDK automatically enriches metadata with:

From URL Parameters (Web only)

  • playerProfileId - Extracted from playerId URL parameter
  • adProfileId - Extracted from profileId URL parameter (for embedded players)

Player Source Detection (Web)

  • playerSource - Automatically set to 'inline' for embedded players (path includes /embedded/) or 'appbuilder' for app players
  • For Bitmovin RN: playerSource is set to 'TvOS'

Device & Browser Information (Web)

  • deviceId - Browser name (from user agent)
  • deviceModel - OS name (from user agent)
  • deviceType - 'Desktop', 'Mobile', or 'Tablet' (detected from user agent)

Device Information (Bitmovin RN)

  • deviceId - Device name (from config)
  • deviceModel - Device model (from config)
  • deviceType - Always 'TvOS'

Player State

  • muted - Player muted state ('0' or '1')
  • autoplay - Player autoplay state ('0' or '1')

Content Information

  • contentId - Asset ID
  • contentTitle - Asset title
  • contentUrl - Manifest URL
  • drmType - 'drm' or 'none'
  • live - Boolean for live/VOD
  • categoryId - Content category
  • userId - Persistent UUID automatically generated and stored for cross-session user tracking (see User ID Persistence below)

User ID Persistence

The SDK automatically generates and persists a unique user ID (UUID) for tracking customer journeys across sessions. This enables analytics at a unique user level.

How It Works

  • Automatic Generation: A UUID v4 is generated on first use and stored persistently
  • Cross-Session Tracking: The same UUID is reused across sessions until the user clears their data
  • Platform Support:
    • Web: Stored in localStorage (persists until browser data is cleared)
    • React Native/tvOS/webOS: Stored using React Native's Settings API (persists across app restarts)
  • Privacy: The UUID is stored locally and only sent in analytics events. Users can clear it by clearing browser/app data

Storage Details

  • Storage Key: vimond_analytics_user_id
  • Web: Uses browser localStorage API
  • React Native/tvOS/webOS: Uses React Native Settings API (compatible with tvOS storage limitations)
  • Fallback: If storage is unavailable, a UUID is still generated but won't persist (new UUID on each session)

Benefits

  • ✅ Track user behavior across multiple video sessions
  • ✅ Analyze customer journey at individual user level
  • ✅ No manual user ID management required
  • ✅ Works seamlessly across web and native platforms

Note: The videoKey parameter in configuration is still accepted for backward compatibility but is no longer used as the userId in analytics events. The persistent UUID takes precedence.

Ad Events

Supported Ad States

  • adStarted - Ad playback started
  • adCompleted - Ad playback completed
  • adSkipped - Ad was skipped
  • adError - Ad error occurred
  • adAllCompleted - All ads in break completed (Bitmovin RN)
  • adClicked - Ad was clicked (Bitmovin RN)
  • adRequested - Ad was scheduled/requested (Bitmovin RN)
  • adBlocked - Ad blocker detected
  • Custom states as needed

IMA Ad Data Extraction

The SDK automatically extracts from IMA ad objects:

  • Ad ID (adImpressionId)
  • Ad title
  • Ad duration
  • Ad tag URL
  • Ad pod position
  • Total ads in pod
  • Skippable status
  • VAST/VMAP detection

Environment Variables

When used in a web application, the following environment variables can be configured:

# Analytics Configuration
NEXT_PUBLIC_EYEVINN_ANALYTICS_URL=https://your-eventsink-url.io
NEXT_PUBLIC_ENABLE_EYEVINN_AD_EVENTS=true
NEXT_PUBLIC_HEARTBEAT_INTERVAL=10000

# Ad Configuration
NEXT_PUBLIC_DEFAULT_AD_PROFILE_ID=your-ad-profile-id

# Shard Configuration
NEXT_PUBLIC_SHARD_ID=your-shard-id

# Optional: Custom metadata fields (comma-separated)
NEXT_PUBLIC_EYEVINN_METADATA_FIELDS=keywords,tags,genre

Real-World Example

Here's how the SDK is used in a React/Next.js application:

import { useEffect, useMemo, useRef } from 'react';
import { VimondAnalyticsIntegration } from 'vimond-player-analytics-web';
import type Player from 'video.js/dist/types/player';

export const useVideoAnalytics = (args: {
  playback: {
    assetId: string;
    assetTitle: string;
    isLive: boolean;
    isDrmProtected: boolean;
    recommendedStream?: {
      manifest?: { uri: string };
      drmProxyType?: string;
    };
    categoryId?: string;
  };
  playerInstanceRef: React.MutableRefObject<Player | null>;
  videoKey?: string;
  asset?: {
    keywords?: string;
    tags?: string;
  };
}) => {
  const analyticsIntegrationRef = useRef(null);
  const analyticsSessionId = useMemo(() => crypto.randomUUID(), []);

  useEffect(() => {
    if (!playerInstanceRef.current) return;

    const integration = VimondAnalyticsIntegration({
      eventsinkUrl: process.env.NEXT_PUBLIC_EYEVINN_ANALYTICS_URL,
      sessionId: analyticsSessionId,
      heartbeatInterval: 10000,
      debug: false,
      enableAdEvents: true,
      adProfileId: process.env.NEXT_PUBLIC_DEFAULT_AD_PROFILE_ID,
      shardId: process.env.NEXT_PUBLIC_SHARD_ID,
      player: playerInstanceRef.current,
      playback: args.playback,
      videoKey: args.videoKey ?? args.playback.assetId,
      additionalMetadata: {
        keywords: args.asset?.keywords,
        tags: args.asset?.tags,
      }
    });

    analyticsIntegrationRef.current = integration;

    integration.init().catch(console.error);

    return () => {
      integration.deinit();
    };
  }, [args.playback.assetId]);

  return {
    reportAdEvent: (data, adState, adPosition = 'pre') => {
      analyticsIntegrationRef.current?.reportAdEvent({
        data,
        adState,
        adPosition,
      });
    },
    getAnalyticsInstance: () => {
      return analyticsIntegrationRef.current?.getAnalyticsInstance();
    }
  };
};

Types

VimondAdEventPayload

Used for web integrations (Video.js and basic HTML video element).

type VimondAdEventPayload = {
  data: unknown;                    // IMA ad event data
  adState: string;                  // Ad state (e.g., 'adStarted', 'adCompleted')
  adPosition?: 'pre' | 'mid' | 'post';  // Ad position in content
  adMidQuartile?: string;          // Mid-quartile reached ('0' or '1')
  adThirdQuartile?: string;        // Third-quartile reached ('0' or '1')
  completedAdsCount?: string;      // Number of completed ads
  metadata?: Record<string, unknown>;  // Additional metadata
}

AdEventPayload

Used for Bitmovin React Native integration.

type AdEventPayload = {
  data: unknown;                    // Ad event data
  adState: string;                  // Ad state (e.g., 'adStarted', 'adCompleted')
  event?: Record<string, unknown>;  // Optional: Additional event data (ad, adBreak, position, duration, etc.)
}

PlayerEventData

Event data structure for Bitmovin React Native player events.

type PlayerEventData = Record<string, unknown> & {
  name: string;                    // Event name (e.g., 'onPlaying', 'onAdStarted')
  // Additional properties vary by event type
}

Development

Scripts

  • pnpm run build - Build the package
  • pnpm run dev - Watch mode for development
  • pnpm run lint - Run ESLint
  • pnpm run lint:fix - Fix ESLint issues
  • pnpm run format - Format code with Prettier
  • pnpm run format:check - Check code formatting

Code Quality

This package uses ESLint and Prettier for code quality and formatting:

  • ESLint: TypeScript linting with strict rules
  • Prettier: Code formatting with consistent style
  • TypeScript: Strict type checking

Dependencies

Peer Dependencies

  • video.js - Video.js player (for VimondAnalyticsIntegration)

License

MIT