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 🙏

© 2025 – Pkg Stats / Ryan Hefner

bekender-analytics

v0.0.11

Published

Official JavaScript/TypeScript SDK for Bekender Analytics - a powerful analytics and telemetry service similar to Amplitude.

Readme

Bekender Analytics from BEKENDER.RU 📊

Official JavaScript/TypeScript SDK for Bekender Analytics - a powerful analytics and telemetry service similar to Amplitude.

Track events, identify users, and analyze behavior in your web applications with ease. Bekender Analytics provides a simple, reliable, and cost-effective alternative to services like Amplitude, Mixpanel, and Google Analytics.

Detail Documentation

DOC.BEKENDER.RU 📊

Analytics Dashboard

Why Bekender Analytics?

  • 🚀 Fast & Lightweight - Minimal bundle size, maximum performance
  • 💰 Cost-Effective - Affordable pricing compared to alternatives
  • 🔒 Privacy-Focused - Your data stays on your infrastructure
  • 📊 Powerful Insights - Real-time analytics and user behavior tracking
  • 🛠 Easy Integration - Simple API, works with any JavaScript framework
  • 🌍 Self-Hosted Option - Full control over your analytics data
  • 🔧 Cross-Platform - Works on Web, React Native, Node.js, Electron, and more

Supported Platforms

| Platform | Support | Storage | Notes | |----------|---------|---------|-------| | 🌐 Web (Browser) | ✅ Full | localStorage | Works out of the box | | ⚛️ React Native | ✅ Full | AsyncStorage | Requires AsyncStorage adapter | | 🖥 Electron | ✅ Full | localStorage | Auto-detected | | 🟢 Node.js | ✅ Full | Memory only | Server-side tracking | | ⚡️ Next.js | ✅ Full | localStorage | SSR compatible | | 📱 Expo | ✅ Full | AsyncStorage | Same as React Native | | 🎯 Vue.js | ✅ Full | localStorage | Works as standard web | | ⚙️ Angular | ✅ Full | localStorage | Works as standard web | | 🔷 TypeScript | ✅ Full | - | Full type definitions included |

Features

  • 📊 Event Tracking - Track custom events with properties
  • 👤 User Identification - Identify users and update user properties
  • 📦 Batch Processing - Automatic batching of events for optimal performance
  • 💾 Local Storage - Events are persisted in browser storage
  • Auto-Flush - Configurable automatic sending of events
  • 🔄 Retry Logic - Failed requests are re-queued automatically
  • 📝 Full TypeScript Support - Complete type definitions included
  • 🎯 Simple API - Easy-to-use, intuitive interface

Installation

npm install bekender-analytics

or

yarn add bekender-analytics

Quick Start

Web / Next.js / Browser

import { createBekenderAnalytics } from 'bekender-analytics';

// Create analytics instance - automatically initialized and ready to use!
const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id',
  flushIntervalMs: 20000, // Optional: flush every 20 seconds (default)
  debug: false, // Optional: enable detailed logging
});

// Track an event immediately - no init() needed!
analytics.track('page_view', { page: '/home' });

// Identify a user
analytics.identify('user123', {
  name: 'John Doe',
  email: '[email protected]',
});

React Native / Expo

import { createBekenderAnalytics } from 'bekender-analytics';
import AsyncStorage from '@react-native-async-storage/async-storage';

// Create analytics instance with AsyncStorage - ready to use immediately!
const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id',
  storageAdapter: AsyncStorage, // Required for React Native
  flushIntervalMs: 20000,
});

// Start tracking immediately
analytics.track('app_opened', { platform: 'ios' });

Node.js (Server-side)

import { createBekenderAnalytics } from 'bekender-analytics';

// Create analytics instance without storage (memory only) - ready immediately!
const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id',
  disableStorage: true, // No persistent storage in Node.js
  flushIntervalMs: 10000, // Flush more frequently on server
});

// Start tracking immediately
analytics.track('api_request', { endpoint: '/api/users' });

Electron

import { createBekenderAnalytics } from 'bekender-analytics';

// Create analytics instance - works automatically with localStorage!
const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id',
});

// Start tracking immediately
analytics.track('desktop_app_launched', { version: '1.0.0' });

Configuration

interface BekenderAnalyticsConfig {
  apiKey: string;              // Required: API key for authentication
  appProjectId: string;        // Required: Analytics project identifier
  baseUrl?: string;            // Optional: Custom API URL (default: https://api.analytics.bekender.ru)
  flushIntervalMs?: number;    // Optional: Auto-flush interval in ms (default: 20000)
  maxBatchSize?: number;       // Optional: Max events per batch (default: 100)
  enableAutoFlush?: boolean;   // Optional: Enable auto-flush (default: true)
  storageAdapter?: StorageAdapter; // Optional: Custom storage (e.g., AsyncStorage for React Native)
  disableStorage?: boolean;    // Optional: Disable persistent storage (memory only)
  debug?: boolean;             // Optional: Enable debug logging (default: false)
}

Usage

import { createBekenderAnalytics } from 'bekender-analytics';

const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id',
  // ... other optional config
});

// Instance is automatically initialized and ready to use!
// No need to call init() - just start tracking

Storage Adapter Interface

For React Native or custom storage implementations:

interface StorageAdapter {
  setItem(key: string, value: string): Promise<void> | void;
  getItem(key: string): Promise<string | null> | string | null;
  removeItem(key: string): Promise<void> | void;
}

API Reference

Initialization

createBekenderAnalytics(config: BekenderAnalyticsConfig)

Creates and initializes a new analytics instance. The instance is automatically initialized and ready to track events immediately.

Returns: Initialized analytics instance

Example:

const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id'
});

Event Tracking

track(eventName: string, properties?: object, userId?: string): void

Tracks an analytics event.

analytics.track('button_clicked', { button_id: 'signup_btn' });
analytics.track('purchase', { amount: 99.99, currency: 'USD' }, 'user123');

User Management

identify(userId: string, properties?: object): void

Sets the current user and optionally updates user properties.

analytics.identify('user123', {
  name: 'John Doe',
  email: '[email protected]',
  plan: 'premium'
});

setUserProperties(userId: string, properties: object): void

Updates user properties without changing the current user.

analytics.setUserProperties('user123', {
  subscription: 'premium',
  last_login: '2025-10-08'
});

reset(): void

Clears the current user identifier.

analytics.reset();

getUserId(): string | null

Gets the current user identifier.

Data Management

flush(): Promise<void>

Manually sends all pending events and user properties to the server.

await analytics.flush();

getPendingEventsCount(): number

Returns the number of pending events in the queue.

getPendingUserPropsCount(): number

Returns the number of pending user property updates.

Lifecycle

destroy(): void

Stops automatic flushing and cleans up resources.

analytics.destroy();

Platform-Specific Examples

React Native Complete Example

// App.tsx
import React, { useEffect } from 'react';
import { createBekenderAnalytics } from 'bekender-analytics';
import AsyncStorage from '@react-native-async-storage/async-storage';

// Create analytics instance once outside component
const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id',
  storageAdapter: AsyncStorage,
});

export const App = () => {
  useEffect(() => {
    // Start tracking immediately - no init() needed!
    analytics.track('app_opened', { platform: 'react-native' });
    
    return () => {
      analytics.flush(); // Flush on unmount
    };
  }, []);

  const handleButtonPress = () => {
    analytics.track('button_pressed', { screen: 'home' });
  };

  return <YourAppComponents />;
};

Next.js (App Router) Example

// app/providers.tsx
'use client';

import { createBekenderAnalytics } from 'bekender-analytics';
import { createContext, useContext, useEffect } from 'react';

// Create analytics instance once - automatically initialized!
const analytics = createBekenderAnalytics({
  apiKey: process.env.NEXT_PUBLIC_ANALYTICS_API_KEY!,
  appProjectId: process.env.NEXT_PUBLIC_ANALYTICS_PROJECT_ID!,
});

const AnalyticsContext = createContext(analytics);

export const AnalyticsProvider = ({ children }) => {
  useEffect(() => {
    // Start tracking immediately - no init() needed!
    analytics.track('page_view', { page: window.location.pathname });
  }, []);

  return (
    <AnalyticsContext.Provider value={analytics}>
      {children}
    </AnalyticsContext.Provider>
  );
};

export const useAnalytics = () => useContext(AnalyticsContext);

Node.js Server Example

// server.ts
import express from 'express';
import { createBekenderAnalytics } from 'bekender-analytics';

// Create analytics instance - automatically initialized!
const analytics = createBekenderAnalytics({
  apiKey: process.env.ANALYTICS_API_KEY!,
  appProjectId: process.env.ANALYTICS_PROJECT_ID!,
  disableStorage: true, // No storage on server
  flushIntervalMs: 5000, // Flush every 5 seconds
});

const app = express();

app.get('/api/users', (req, res) => {
  // Track immediately - no init() needed!
  analytics.track('api_request', {
    endpoint: '/api/users',
    method: 'GET',
    ip: req.ip || 'unknown',
  });
  
  res.json({ users: [] });
});

// Graceful shutdown
process.on('SIGTERM', async () => {
  await analytics.flush();
  analytics.destroy();
  process.exit(0);
});

Electron Example

// main.ts (Electron main process)
import { app, BrowserWindow } from 'electron';
import { createBekenderAnalytics } from 'bekender-analytics';

// Create analytics instance - ready immediately!
const analytics = createBekenderAnalytics({
  apiKey: 'your-api-key',
  appProjectId: 'your-project-id',
});

app.on('ready', () => {
  // Track immediately - no init() needed!
  analytics.track('electron_app_started', {
    version: app.getVersion(),
    platform: process.platform,
  });
});

app.on('before-quit', async () => {
  await analytics.flush();
});

Usage Examples

Track Page Views

analytics.track('page_view', {
  page: window.location.pathname,
  referrer: document.referrer
});

Track User Actions

document.getElementById('signup-btn')?.addEventListener('click', () => {
  analytics.track('signup_clicked', {
    source: 'homepage',
    button_location: 'header'
  });
});

E-commerce Tracking

analytics.track('product_purchased', {
  product_id: 'prod_123',
  product_name: 'Premium Plan',
  price: '99.99',
  currency: 'USD'
});

User Lifecycle

// On user login
analytics.identify('user123', {
  email: '[email protected]',
  name: 'John Doe'
});

// Update user properties
analytics.setUserProperties('user123', {
  subscription: 'premium',
  last_activity: new Date().toISOString()
});

// On user logout
analytics.reset();

Manual Flush Before Navigation

// Ensure events are sent before page unload
window.addEventListener('beforeunload', async (e) => {
  await analytics.flush();
});

Platform Requirements

Web Browsers

  • Modern browsers supporting ES6+
  • LocalStorage API
  • Promises

React Native

  • React Native 0.60+
  • @react-native-async-storage/async-storage package required
npm install @react-native-async-storage/async-storage
# or
yarn add @react-native-async-storage/async-storage

Node.js

  • Node.js 14+ recommended
  • Works without storage (memory-only mode)

Electron

  • Electron 10+ recommended
  • Uses localStorage automatically

Error Handling

The SDK handles errors gracefully:

  • Failed requests are automatically re-queued
  • Events are persisted in localStorage to prevent data loss
  • All errors are logged to the console

Best Practices

  1. Create instance early - Call createBekenderAnalytics() as early as possible in your application
  2. Reuse instance - Create one instance and reuse it throughout your app (singleton pattern)
  3. Flush on navigation - Call flush() before page navigation to ensure data is sent
  4. Use meaningful event names - Use clear, descriptive names like user_signup instead of event1
  5. Keep properties simple - Store only string values in properties
  6. Enable debug mode - Use debug: true during development to see detailed logs
  7. Clean up - Call destroy() when the SDK is no longer needed

CDN Usage (No Build Required)

You can use Bekender Analytics directly in HTML without npm or build tools:

Production (Minified - 43KB)

<!-- Load from CDN - add before closing </body> tag -->
<script src="https://s3.timeweb.cloud/c14a1252-bekender-files/cdn_libraries/bekender-analytics.min.js"></script>

<script>
  // Create analytics instance - automatically initialized and ready!
  const analytics = BekenderAnalytics.createBekenderAnalytics({
    apiKey: 'your-api-key',
    appProjectId: 'your-project-id'
  });
  
  // Track immediately - no init() needed!
  analytics.track('page_view', {
    page: window.location.pathname
  });
  
  // Identify user on login
  analytics.identify('user123', {
    email: '[email protected]',
    name: 'John Doe'
  });
</script>

Development (Non-minified - 103KB)

For debugging, use the non-minified version:

<script src="https://s3.timeweb.cloud/c14a1252-bekender-files/cdn_libraries/bekender-analytics.js"></script>

Complete HTML Example

<!DOCTYPE html>
<html>
<head>
  <title>My App</title>
</head>
<body>
  <h1>Welcome to My App</h1>
  <button id="signup-btn">Sign Up</button>

  <!-- Load Bekender Analytics -->
  <script src="https://s3.timeweb.cloud/c14a1252-bekender-files/cdn_libraries/bekender-analytics.min.js"></script>
  
  <script>
    // Create analytics instance - automatically initialized!
    const analytics = BekenderAnalytics.createBekenderAnalytics({
      apiKey: 'your-api-key',
      appProjectId: 'your-project-id',
      flushIntervalMs: 20000
    });
    
    // Track immediately - no init() needed!
    analytics.track('page_loaded', {
      page: window.location.pathname,
      referrer: document.referrer
    });
    
    // Track button clicks
    document.getElementById('signup-btn').addEventListener('click', function() {
      analytics.track('signup_button_clicked', {
        button_location: 'home_page'
      });
    });
    
    // Track user session
    analytics.identify('user_' + Date.now(), {
      session_start: new Date().toISOString()
    });
    
    // Flush events before page unload
    window.addEventListener('beforeunload', function() {
      analytics.flush();
    });
  </script>
</body>
</html>

API Endpoints

For other platforms or custom integrations, you can use the REST API directly.

Authentication: All requests must include the API key in the x-bekender-api-key header.

Track Events

curl --location 'https://api.analytics.bekender.ru/analytics_upload_data/tracked_events_list' \
--header 'Content-Type: application/json' \
--header 'x-bekender-api-key: YOUR_API_KEY' \
--data '{
  "events": [
    {
      "analytics_event_name": "button_clicked",
      "user_id": "user123",
      "properties": {
        "button_id": "signup_btn"
      },
      "event_time": "2025-10-08T10:00:00.000Z"
    }
  ],
  "app_project_id": "your-project-id",
  "api_key": "your-api-key"
}'

Identify Users

curl --location 'https://api.analytics.bekender.ru/analytics_upload_data/identify_users_list' \
--header 'Content-Type: application/json' \
--header 'x-bekender-api-key: YOUR_API_KEY' \
--data '{
  "list": [
    {
      "user_id": "user123",
      "properties": {
        "email": "[email protected]",
        "name": "John Doe"
      }
    }
  ],
  "app_project_id": "your-project-id",
  "api_key": "your-api-key"
}'

FAQ

Where is the API key ("api_key")?

Where is the "app_project_id"?

  • Create a new analytics project in your BEKENDER dashboard: https://cloud.bekender.ru/analytics
  • Your project ID will be displayed after creation (e.g., 67185ba9262688a6********)

How do I get started?

  1. Sign up at BEKENDER.RU
  2. Create an analytics project in the Cloud Console
  3. Copy your API key from Settings
  4. Install the SDK and initialize it with your credentials
  5. Start tracking events!

What data is collected?

  • Event names and custom properties you send
  • User identifiers you provide (optional)
  • Event timestamps
  • No automatic data collection - you control everything

Is there a free tier?

  • Yes! Bekender Analytics offers a generous free tier for small projects
  • Check current pricing at https://bekender.ru

Can I see my data in real-time?

  • Yes! All events are processed in real-time and available immediately in your analytics dashboard

What about GDPR compliance?

  • Bekender Analytics is GDPR compliant
  • You control what data is collected
  • Users can request data deletion through your BEKENDER account

Contacts

No-Code & Business & Analytics Cloud Platform BEKENDER.RU

Platform Console CLOUD.BEKENDER.RU

Platform Documentation DOC.BEKENDER.RU

Support Email: [email protected]

Telegram: @bekender_support

License

MIT

Contributing

For issues, questions, or contributions, please visit our GitHub repository or contact support.