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

sitepong

v0.0.15

Published

Official SitePong SDK for error tracking and monitoring

Readme


Installation

npm install sitepong

Quick Start

import sitepong from 'sitepong';

sitepong.init({
  apiKey: 'your-api-key',
  environment: 'production',
  release: '1.0.0',
});

// Errors are automatically captured!
// Or capture manually:
sitepong.captureError(new Error('Something went wrong'));

Features

Error Tracking

Automatic error capture for uncaught exceptions and unhandled promise rejections. Works in both browser and Node.js environments.

// Automatic capture - just initialize!
sitepong.init({ apiKey: 'your-api-key' });

// Manual capture with context
try {
  riskyOperation();
} catch (error) {
  sitepong.captureError(error, {
    tags: { component: 'checkout' },
    extra: { orderId: '12345' },
  });
}

// Capture messages
sitepong.captureMessage('User signed up', 'info', {
  user: { id: 'user-123' },
});

Session Replay

Record and replay user sessions to see exactly what happened before an error. Privacy-focused with automatic input masking.

sitepong.init({
  apiKey: 'your-api-key',
  replay: {
    enabled: true,
    maskInputs: true,           // Mask sensitive inputs
    blockSelector: '.private',  // Block specific elements
    sampleRate: 0.5,            // Record 50% of sessions
    recordNetwork: true,        // Capture XHR/fetch requests
    recordConsole: true,        // Capture console logs
  },
});

// Manual control
sitepong.startReplay();
sitepong.stopReplay();
const sessionId = sitepong.getReplaySessionId();

Feature Flags

Ship features with confidence using real-time feature flags and A/B testing.

sitepong.init({
  apiKey: 'your-api-key',
  enableFlags: true,
});

// Wait for flags to load
await sitepong.waitForFlags();

// Boolean flags
if (sitepong.getFlag('new-checkout', false)) {
  showNewCheckout();
}

// Multivariate flags / A/B tests
const variant = sitepong.getVariant('button-color', 'blue');
const payload = sitepong.getVariantPayload('pricing-test');

// Get all flags
const allFlags = sitepong.getAllFlags();

Product Analytics

Understand user behavior with event tracking and autocapture.

sitepong.init({
  apiKey: 'your-api-key',
  analytics: {
    enabled: true,
    autocapturePageviews: true,
    autocaptureClicks: true,
    autocaptureForms: true,
  },
});

// Track custom events
sitepong.track('Purchase Completed', {
  product: 'Pro Plan',
  revenue: 99,
});

// Identify users
sitepong.identify('user-123', {
  name: 'John Doe',
  email: '[email protected]',
  plan: 'pro',
});

// Group users
sitepong.group('company-456', {
  name: 'Acme Inc',
  industry: 'Technology',
});

// Manual page views
sitepong.trackPageView('/checkout');

Device Intelligence & Fraud Detection

Identify devices and detect fraudulent activity with advanced fingerprinting.

sitepong.init({
  apiKey: 'your-api-key',
  fingerprint: {
    enabled: true,
    extendedSignals: true,
  },
});

// Get stable visitor ID
const { visitorId, confidence } = await sitepong.getVisitorId();

// Get device signals
const signals = await sitepong.getDeviceSignals();

// Fraud detection
const fraud = await sitepong.getFraudCheck();
if (fraud.riskScore > 0.8) {
  blockTransaction();
}

Performance Monitoring

Track performance with Web Vitals, custom transactions, and distributed tracing.

sitepong.init({
  apiKey: 'your-api-key',
  performance: {
    enabled: true,
    webVitals: true,
    navigationTiming: true,
    resourceTiming: true,
    sampleRate: 1.0,
  },
});

// Get Web Vitals
const vitals = sitepong.getWebVitals();
// { LCP: 1200, FID: 50, CLS: 0.1, FCP: 800, TTFB: 200 }

// Custom transactions
const txId = sitepong.startTransaction('checkout-flow');
const spanId = sitepong.startSpan(txId, 'validate-cart');
// ... do work
sitepong.endSpan(txId, spanId);
sitepong.endTransaction(txId);

// Distributed tracing
import { createTraceContext, propagateTrace } from 'sitepong';

const trace = createTraceContext();
fetch('/api/order', {
  headers: propagateTrace(trace),
});

Cron Monitoring

Monitor scheduled jobs and get alerted when they fail or miss a schedule.

sitepong.init({
  apiKey: 'your-api-key',
  crons: { enabled: true },
});

// Simple check-in
await sitepong.cronCheckin('daily-backup');

// Start/end pattern
const cron = sitepong.cronStart('nightly-sync');
try {
  await performSync();
  await cron.ok();
} catch (error) {
  await cron.error();
}

// Wrap async functions
await sitepong.cronWrap('hourly-cleanup', async () => {
  await cleanupOldRecords();
});

Custom Metrics

Track business and application metrics with counters, gauges, and histograms.

sitepong.init({
  apiKey: 'your-api-key',
  metrics: { enabled: true },
});

// Counters
sitepong.metricIncrement('api.requests', 1, { tags: { endpoint: '/users' } });

// Gauges
sitepong.metricGauge('queue.size', 42);

// Histograms
sitepong.metricHistogram('response.size', 1024);

// Distributions
sitepong.metricDistribution('payment.amount', 99.99);

// Timing
await sitepong.metricTime('db.query', async () => {
  return await db.query('SELECT * FROM users');
});

// Manual timer
const timer = sitepong.metricStartTimer('operation.duration');
// ... do work
timer.stop();

Database Query Tracking

Monitor database performance and detect N+1 query patterns.

sitepong.init({
  apiKey: 'your-api-key',
  database: {
    enabled: true,
    slowQueryThreshold: 100,  // Log queries over 100ms
    redactParams: true,       // Redact sensitive parameters
  },
});

// Track queries
const users = await sitepong.dbTrack(
  'SELECT * FROM users WHERE id = ?',
  () => db.query('SELECT * FROM users WHERE id = ?', [userId])
);

// Detect N+1 patterns
const patterns = sitepong.getDbNPlusOnePatterns();
// [{ query: 'SELECT * FROM orders WHERE user_id = ?', count: 50 }]

Production Profiling

Profile your production code to identify performance bottlenecks.

sitepong.init({
  apiKey: 'your-api-key',
  profiling: {
    enabled: true,
    sampleRate: 0.1,    // Profile 10% of operations
    maxDuration: 30000, // Max 30s profiles
  },
});

// Profile async operations
const result = await sitepong.profile('processOrder', async () => {
  return await processOrder(orderId);
});

// Manual spans
const endSpan = sitepong.startProfileSpan('validate');
// ... validation logic
endSpan();

React Integration

First-class React support with components and hooks.

import { ... } from 'sitepong/react';

Provider & Error Boundary

import { SitePongProvider, SitePongErrorBoundary } from 'sitepong/react';

function App() {
  return (
    <SitePongProvider
      apiKey="your-api-key"
      config={{
        environment: 'production',
        analytics: { enabled: true, autocapturePageviews: true },
        replay: { enabled: true },
      }}
    >
      <SitePongErrorBoundary fallback={<ErrorPage />}>
        <YourApp />
      </SitePongErrorBoundary>
    </SitePongProvider>
  );
}

Hooks

import {
  // Core
  useSitePong,
  useCaptureException,
  useSetUser,

  // Feature Flags
  useFeatureFlag,
  useExperiment,

  // Analytics
  useTrack,
  useIdentify,

  // Fingerprinting
  useVisitorId,
  useFraudCheck,

  // Performance
  useWebVitals,
  usePerformanceTransaction,

  // Replay
  useReplay,
} from 'sitepong/react';

function CheckoutButton() {
  const track = useTrack();
  const showNewDesign = useFeatureFlag('new-checkout-design', false);
  const { variant } = useExperiment('button-color');

  const handleClick = () => {
    track('Checkout Started', { items: cart.length });
    // ...
  };

  return (
    <button
      onClick={handleClick}
      style={{ background: variant === 'red' ? 'red' : 'blue' }}
    >
      {showNewDesign ? 'Complete Purchase' : 'Checkout'}
    </button>
  );
}

Framework Integration

Next.js

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

import { SitePongProvider } from 'sitepong/react';

export function Providers({ children }) {
  return (
    <SitePongProvider
      apiKey={process.env.NEXT_PUBLIC_SITEPONG_KEY}
      config={{
        environment: process.env.NODE_ENV,
        replay: { enabled: true },
      }}
    >
      {children}
    </SitePongProvider>
  );
}

Express

import express from 'express';
import sitepong from 'sitepong';

const app = express();

sitepong.init({
  apiKey: process.env.SITEPONG_KEY,
  environment: 'production',
});

// Error handling middleware
app.use((err, req, res, next) => {
  sitepong.captureError(err, {
    extra: {
      url: req.url,
      method: req.method,
      userId: req.user?.id,
    },
  });
  next(err);
});

Node.js

import sitepong from 'sitepong';

sitepong.init({
  apiKey: process.env.SITEPONG_KEY,
  environment: process.env.NODE_ENV,
});

// Uncaught exceptions and unhandled rejections
// are automatically captured

Configuration Reference

sitepong.init({
  // Required
  apiKey: 'your-api-key',

  // Core
  endpoint: 'https://ingest.sitepong.com',
  environment: 'production',
  release: '1.0.0',
  autoCapture: true,
  maxBatchSize: 10,
  flushInterval: 5000,
  debug: false,

  // Feature Flags
  enableFlags: false,
  flagsEndpoint: undefined,

  // Analytics
  analytics: {
    enabled: false,
    autocapturePageviews: false,
    autocaptureClicks: false,
    autocaptureForms: false,
  },

  // Session Replay
  replay: {
    enabled: false,
    maskInputs: true,
    blockSelector: undefined,
    maskSelector: undefined,
    sampleRate: 1.0,
    maxSessionDuration: 3600000,
    recordNetwork: false,
    recordConsole: false,
  },

  // Performance
  performance: {
    enabled: false,
    webVitals: true,
    navigationTiming: true,
    resourceTiming: false,
    sampleRate: 1.0,
  },

  // Fingerprinting
  fingerprint: {
    enabled: false,
    extendedSignals: false,
  },

  // Cron Monitoring
  crons: {
    enabled: false,
  },

  // Custom Metrics
  metrics: {
    enabled: false,
    flushInterval: 10000,
    maxBatchSize: 100,
  },

  // Database Tracking
  database: {
    enabled: false,
    slowQueryThreshold: 100,
    redactParams: true,
  },

  // Profiling
  profiling: {
    enabled: false,
    sampleRate: 0.1,
    maxDuration: 30000,
  },
});

API Reference

Core

| Method | Description | |--------|-------------| | init(config) | Initialize the SDK | | captureError(error, context?) | Capture an error | | captureMessage(message, level?, context?) | Capture a message | | setUser(user) | Set user context | | setTags(tags) | Set tags | | setContext(context) | Set additional context | | flush() | Flush the error queue |

Feature Flags

| Method | Description | |--------|-------------| | getFlag(key, defaultValue?) | Get boolean flag | | getVariant(key, defaultValue?) | Get variant key | | getVariantPayload(key, defaultValue?) | Get variant payload | | getAllFlags() | Get all flags | | waitForFlags() | Wait for flags to load | | areFlagsReady() | Check if flags are loaded | | refreshFlags() | Refresh flags from server |

Analytics

| Method | Description | |--------|-------------| | track(event, properties?) | Track custom event | | trackPageView(url?, properties?) | Track page view | | identify(userId, traits?) | Identify user | | group(groupId, traits?) | Group users | | resetAnalytics() | Reset analytics state |

Session Replay

| Method | Description | |--------|-------------| | startReplay() | Start recording | | stopReplay() | Stop recording | | isReplayRecording() | Check if recording | | getReplaySessionId() | Get session ID |

Performance

| Method | Description | |--------|-------------| | startTransaction(name, data?) | Start transaction | | endTransaction(id, status?) | End transaction | | startSpan(txId, name, data?) | Start span | | endSpan(txId, spanId, status?) | End span | | getWebVitals() | Get Web Vitals |

Fingerprinting

| Method | Description | |--------|-------------| | getVisitorId() | Get visitor ID | | getDeviceSignals() | Get device signals | | getFraudCheck() | Run fraud check |

Metrics

| Method | Description | |--------|-------------| | metricIncrement(name, value?, options?) | Increment counter | | metricGauge(name, value, options?) | Set gauge | | metricHistogram(name, value, options?) | Record histogram | | metricDistribution(name, value, options?) | Record distribution | | metricTime(name, fn, options?) | Time async function | | metricStartTimer(name, options?) | Start manual timer |

Cron Monitoring

| Method | Description | |--------|-------------| | cronCheckin(slug, options?) | Simple check-in | | cronStart(slug, environment?) | Start cron job | | cronWrap(slug, fn, environment?) | Wrap async function |

Database

| Method | Description | |--------|-------------| | dbTrack(query, fn, source?) | Track async query | | dbTrackSync(query, fn, source?) | Track sync query | | getDbQueryCount() | Get query count | | getDbNPlusOnePatterns() | Get N+1 patterns |

Profiling

| Method | Description | |--------|-------------| | profile(name, fn, metadata?) | Profile async function | | startProfileSpan(name, metadata?) | Start profile span | | getProfiles() | Get all profiles | | getLatestProfile() | Get latest profile | | flushProfiles() | Flush profiles |


Documentation

For full documentation, visit sitepong.com/docs.

License

MIT