Official SitePong SDK for error tracking and monitoring
npm install sitepong
The complete observability platform for modern applications.
Error tracking, session replay, analytics, feature flags, and more — all in one SDK.
Installation •
Quick Start •
Features •
React •
Docs
---
``bash`
npm install sitepong
`javascript
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'));
`
---
Automatic error capture for uncaught exceptions and unhandled promise rejections. Works in both browser and Node.js environments.
`javascript
// 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' },
});
`
Record and replay user sessions to see exactly what happened before an error. Privacy-focused with automatic input masking.
`javascript
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();
`
Ship features with confidence using real-time feature flags and A/B testing.
`javascript
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();
`
Understand user behavior with event tracking and autocapture.
`javascript
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: 'john@example.com',
plan: 'pro',
});
// Group users
sitepong.group('company-456', {
name: 'Acme Inc',
industry: 'Technology',
});
// Manual page views
sitepong.trackPageView('/checkout');
`
Identify devices and detect fraudulent activity with advanced fingerprinting.
`javascript
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();
}
`
Track performance with Web Vitals, custom transactions, and distributed tracing.
`javascript
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),
});
`
Monitor scheduled jobs and get alerted when they fail or miss a schedule.
`javascript
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();
});
`
Track business and application metrics with counters, gauges, and histograms.
`javascript
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();
`
Monitor database performance and detect N+1 query patterns.
`javascript
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 }]
`
Profile your production code to identify performance bottlenecks.
`javascript
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();
`
---
First-class React support with components and hooks.
`bash`
import { ... } from 'sitepong/react';
`jsx
import { SitePongProvider, SitePongErrorBoundary } from 'sitepong/react';
function App() {
return (
config={{
environment: 'production',
analytics: { enabled: true, autocapturePageviews: true },
replay: { enabled: true },
}}
>
);
}
`
`jsx
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 (
onClick={handleClick}
style={{ background: variant === 'red' ? 'red' : 'blue' }}
>
{showNewDesign ? 'Complete Purchase' : 'Checkout'}
);
}
`
---
`javascript
// app/providers.tsx
'use client';
import { SitePongProvider } from 'sitepong/react';
export function Providers({ children }) {
return (
config={{
environment: process.env.NODE_ENV,
replay: { enabled: true },
}}
>
{children}
);
}
`
`javascript
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);
});
`
`javascript
import sitepong from 'sitepong';
sitepong.init({
apiKey: process.env.SITEPONG_KEY,
environment: process.env.NODE_ENV,
});
// Uncaught exceptions and unhandled rejections
// are automatically captured
`
---
`javascript
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,
},
});
`
---
| 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 |
| 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 |
| 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 |
| Method | Description |
|--------|-------------|
| startReplay() | Start recording |stopReplay()
| | Stop recording |isReplayRecording()
| | Check if recording |getReplaySessionId()
| | Get session ID |
| 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 |
| Method | Description |
|--------|-------------|
| getVisitorId() | Get visitor ID |getDeviceSignals()
| | Get device signals |getFraudCheck()
| | Run fraud check |
| 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 |
| Method | Description |
|--------|-------------|
| cronCheckin(slug, options?) | Simple check-in |cronStart(slug, environment?)
| | Start cron job |cronWrap(slug, fn, environment?)
| | Wrap async function |
| 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 |
| 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 |
|
---
For full documentation, visit sitepong.com/docs.
MIT