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

@tech-culturex/core

v0.1.12

Published

Comprehensive engagement rate calculation library for social media posts, reels, and videos with TypeScript support

Readme

@tech-culturex/core

Comprehensive engagement rate calculation library for social media posts, reels, and videos with TypeScript support

Installation

npm install @tech-culturex/core

Usage

TypeScript

import {
  calculateProfileEngagementRate,
  calculatePostEngagementRate,
  calculatePostsArrayEngagementRate,
  type CalculatePostEngagementRate,
  type CalculatePostsArrayEngagementRate,
  type EngagementRateWithProfileResult,
  type PostsArrayEngagementRateResult,
  type Profile,
  type Post,
  EngagementRateValidationError,
  ErrorMessages,
} from "@tech-culturex/core";

// Calculate engagement for a single post with views
const postWithViews: CalculatePostEngagementRate = {
  likes: 100,
  comments: 50,
  views: 2000,
  followers: 1000,
};
const engagementRate1 = calculatePostEngagementRate(postWithViews);
console.log(`Post engagement: ${engagementRate1}%`); // 7.5% (uses views)

// Calculate engagement for a post without views (fallback to followers)
const postWithoutViews: CalculatePostEngagementRate = {
  likes: 100,
  comments: 50,
  followers: 1000,
};
const engagementRate2 = calculatePostEngagementRate(postWithoutViews);
console.log(`Post engagement: ${engagementRate2}%`); // 15% (uses followers)

// Returns null when neither views nor followers are available
const invalidPost: CalculatePostEngagementRate = {
  likes: 100,
  comments: 50,
};
const engagementRate3 = calculatePostEngagementRate(invalidPost);
console.log(`Post engagement: ${engagementRate3}`); // null

// Calculate engagement for array of posts
const postsData: CalculatePostsArrayEngagementRate = {
  posts: [
    {
      likes: 100,
      comments: 50,
      views: 0,
      media_type: "image",
      platform: "instagram",
      followers: 1000,
    },
    {
      likes: 200,
      comments: 30,
      views: 0,
      media_type: "carousel_album",
      platform: "instagram",
      followers: 1000,
    },
  ],
};
const arrayResult = calculatePostsArrayEngagementRate(postsData);
console.log(`Mean engagement: ${arrayResult.meanEngagementRate}%`); // 19.5%
console.log(`Median engagement: ${arrayResult.medianEngagementRate}%`); // 19.5%

// Calculate profile engagement for multiple posts
const profileData: Profile = {
  platform: "instagram",
  platform_id: "123456789",
  username: "testuser",
  profilePicture: "https://example.com/profile.jpg",
  follower: 1000,
  following: 500,
  totalContent: 10,
  totalLikes: 5000,
  totalComment: 500,
  verified: false,
};

const posts: Post[] = [
  {
    platform: "instagram",
    code: "ABC123",
    media_type: "image",
    permalink: "https://instagram.com/p/ABC123",
    published_at: new Date("2024-01-01"),
    stats: { likes: 100, comments: 20, views: 0, shares: 5, saves: 10 },
    hashtags: [],
    is_paid_partnership: false,
    system_is_paid_partnership: false,
    sponsored_users: [],
    tagged_users: [],
  },
];

const result = calculateProfileEngagementRate(profileData, posts);
const profileEngagementRate = result.staticPostsEngagementRate;
console.log(`Profile engagement: ${profileEngagementRate}%`); // 12%

// Access median engagement rate
const medianEngagementRate = result.staticPostsMedianEngagementRate;
console.log(`Median engagement: ${medianEngagementRate}%`); // 12%

JavaScript (with editor autocomplete)

// @ts-check
const {
  calculatePostEngagement,
  calculateStaticPostEngagement,
  calculateReelEngagement,
  EngagementRateValidationError,
} = require("@tech-culturex/core");

try {
  // Use the flexible calculatePostEngagementRate function
  const postData = { likes: 100, comments: 25, followers: 1000 };
  const engagementRate1 = calculatePostEngagementRate(postData);
  console.log(`Engagement rate: ${engagementRate1}%`); // 12.5%

  // Or use array calculation for multiple posts
  const postsArrayData = {
    posts: [
      {
        likes: 100,
        comments: 25,
        views: 0,
        media_type: "image",
        platform: "instagram",
        followers: 1000,
      },
    ],
  };
  const arrayResult = calculatePostsArrayEngagementRate(postsArrayData);
  console.log(`Mean engagement rate: ${arrayResult.meanEngagementRate}%`); // 12.5%
} catch (error) {
  if (error instanceof EngagementRateValidationError) {
    console.error("Validation error:", error.message);
  }
}

CDN Usage (Browser)

<script src="https://unpkg.com/@tech-culturex/core/dist/index.global.js"></script>
<script>
  const {
    calculatePostEngagementRate,
    calculatePostsArrayEngagementRate,
    calculateProfileEngagementRate,
  } = window.EngagementRate;

  // Use the flexible function
  const postData = { likes: 50, comments: 10, followers: 500 };
  const engagementRate1 = calculatePostEngagementRate(postData);
  console.log(`Post engagement: ${engagementRate1}%`); // 12%

  // Or use array calculation
  const postsData = {
    posts: [
      {
        likes: 50,
        comments: 10,
        views: 0,
        media_type: "image",
        platform: "instagram",
        followers: 500,
      },
    ],
  };
  const arrayResult = calculatePostsArrayEngagementRate(postsData);
  console.log(`Array engagement: ${arrayResult.meanEngagementRate}%`); // 12%
</script>

API Reference

Single Post/Content Calculations

calculatePostEngagementRate(postData)

Calculate engagement rate for a single post with flexible input options.

Parameters:

  • postData: CalculatePostEngagementRate - Object containing:
    • likes: number - Number of likes (required)
    • comments: number - Number of comments (required)
    • shares?: number - Number of shares || 0 (optional)
    • views?: number - Number of views (optional)
    • followers?: number - Number of followers (optional)

Returns: Number | null - Engagement rate as a percentage, or null if neither views nor followers are available

Formula:

  • If views available and > 0: ((likes + comments + shares) / views) * 100
  • Else if followers available and > 0: ((likes + comments + shares) / followers) * 100
  • Else: returns null

Enhanced Features:

  • Flexible input validation with Zod schema
  • Graceful null handling when insufficient data is provided
  • Prioritizes views over followers for more accurate video engagement calculation

calculatePostsArrayEngagementRate(data)

Calculate engagement rate for an array of posts.

Parameters:

  • data: CalculatePostsArrayEngagementRate - Object containing:
    • posts: OldPost[] - Array of post objects with likes, comments, views (optional), media_type, platform, and followers

Returns: PostsArrayEngagementRateResult - Object containing:

  • meanEngagementRate: number | null - Mean engagement rate as a percentage (null if insufficient data)
  • medianEngagementRate: number | null - Median engagement rate as a percentage (null if insufficient data)
  • platform: Platform - Platform of the posts
  • totalPosts: number - Number of posts processed

Formula:

  • For static posts: ((Σ(likes + comments) for M posts) / Σ(followers for M posts)) × 100
  • For video posts: ((Σ(likes + comments) for M posts) / Σ(views for M posts)) × 100

Validation Features:

  • Platform consistency validation - All posts must be from the same platform
  • Media type consistency validation - All posts must have the same media_type
  • Automatic categorization of posts into static (image, carousel_album) vs video-based content

Profile-Level Calculations

calculateProfileEngagementRate(profileData, postsData)

Calculate engagement rate with profile data and posts. Supports both static posts (uses follower count) and video posts (uses view count).

Parameters:

  • profileData: Profile - Profile object with platform, follower count, and other profile information
  • postsData: Post[] - Array of post objects with complete post data

Returns: EngagementRateWithProfileResult - Object containing:

  • staticPostsEngagementRate?: number - Engagement rate for static posts
  • staticPostsMedianEngagementRate?: number - Median engagement rate for static posts
  • videoPostsEngagementRate?: number - Engagement rate for video posts
  • videoPostsMedianEngagementRate?: number - Median engagement rate for video posts

Formula:

  • Static posts: ((Σ(likes + comments + shares) for M posts) / (M × followers)) × 100
  • Video posts: ((Σ(likes + comments + shares) for M posts) / Σ(views for M posts)) × 100

Type Definitions

CalculatePostEngagementRate

interface CalculatePostEngagementRate {
  likes: number;
  comments: number;
  views?: number;
  followers?: number;
}

CalculatePostsArrayEngagementRate

interface CalculatePostsArrayEngagementRate {
  posts: OldPost[];
}

EngagementRateWithProfileResult

interface EngagementRateWithProfileResult {
  staticPostsEngagementRate?: number;
  staticPostsMedianEngagementRate?: number;
  videoPostsEngagementRate?: number;
  videoPostsMedianEngagementRate?: number;
}

PostsArrayEngagementRateResult

interface PostsArrayEngagementRateResult {
  meanEngagementRate: number | null;
  medianEngagementRate: number | null;
  platform: Platform;
  totalPosts: number;
}

Validation & Error Handling

The library includes comprehensive validation with custom error types:

EngagementRateValidationError

Custom error class for validation failures.

ErrorMessages

Available error messages:

  • PLATFORM_MISMATCH: "All posts must be from the same platform"
  • PROFILE_POST_MISMATCH: "Profile and posts must be from the same platform"
  • MIN_FOLLOWERS: "Profile must have at least 1 follower"
  • MIN_VIEWS: "Post must have at least 1 view for engagementRate calculation"
  • MIN_POSTS: "At least one post is required"
  • STATIC_POST_SINGLE: "Static posts require follower count for engagementRate calculation. Use calculateEngagementRateWithProfile instead."
  • UNSUPPORTED_MEDIA: "Unsupported media type for single post engagementRate calculation"
  • NO_VIDEO_POSTS: "No video-based posts found for engagementRate calculation"
  • ZERO_TOTAL_VIEWS: "Total views must be greater than 0"
  • MEDIA_TYPE_MISMATCH: "All posts must have the same media_type"

Validation Features

  • Platform Consistency: Validates that all posts and profile data come from the same platform
  • Media Type Consistency: Ensures all posts in an array have the same media_type
  • Post Categorization: Automatically categorizes posts as static (image, carousel_album) or video-based (video, reel, shorts, story, igtv)
  • Schema Validation: Uses Zod schemas for robust input validation
  • Null Handling: Gracefully handles missing or insufficient data by returning null instead of throwing errors

Examples

Error Handling

try {
  // Invalid data will throw validation errors
  const postData = { likes: -10, comments: 5, followers: 1000 };
  const engagementRate = calculatePostEngagementRate(postData);
} catch (error) {
  if (error instanceof EngagementRateValidationError) {
    console.error(error.message); // Validation error message
  }
}

// Insufficient data returns null instead of throwing
const postData = { likes: 100, comments: 50 };
const engagementRate = calculatePostEngagement(postData);
console.log(engagementRate); // null

Batch Processing

const posts: StaticPost[] = [
  { likes: 120, comments: 25, followers: 1000 },
  { likes: 95, comments: 18, followers: 1000 },
  { likes: 200, comments: 40, followers: 1000 },
];

// Calculate various metrics
const avgEngagement = calculateProfileEngagementForStaticPosts(posts, 1000);
const medianEngagement = calculateMedianEngagementForStaticPosts(posts);
const combinedEngagement = calculateCombinedStaticPostMeanEngagement(posts);

console.log(`Average: ${avgEngagement}%`);
console.log(`Median: ${medianEngagement}%`);
console.log(`Combined: ${combinedEngagement}%`);

Features

  • 🎯 Type-safe: Full TypeScript support with exact types
  • 🌐 Universal: Works in browser and Node.js environments
  • 📦 Tree-shakeable: Import only what you need
  • 🛡️ Defensive: Comprehensive input validation and error handling
  • 📊 Flexible: Support for posts, reels, videos, and profile-level calculations
  • 🚀 Zero dependencies: Lightweight and fast
  • 📈 Multiple metrics: Average, median, and combined engagement calculations

Development

# Install dependencies
npm install

# Build the package
npm run build

# Run tests
npm test

# Lint code
npm run lint

# Clean build artifacts
npm run clean

License

MIT