@diroku/sdk
v0.1.1
Published
Diroku frontend SDK - lightweight event capture and batching
Maintainers
Readme
🎯 Diroku Frontend SDK
Lightweight, production-ready browser SDK for capturing events, errors, and user interactions with automatic batching, offline support, and retry logic.
✨ Features
- 🚀 Lightweight - < 6KB gzipped
- 🤖 Auto-Capture - Automatic tracking of clicks, errors, forms, scroll, navigation, and performance
- � Core Web Vitals - LCP, FID, CLS, FCP, TTFB automatically captured
- 📦 Smart Batching - Efficient event bundling with configurable size and interval
- 💾 Offline Support - Persistent queue using localStorage, automatic retry on reconnect
- 🔄 Exponential Backoff - Smart retry logic for failed requests
- 🎲 Sampling - Configurable sampling rate to reduce data volume
- 🔒 Privacy First - Data masking capabilities for sensitive information
- 📱 Cross-browser - Works on all modern browsers (Chrome 90+, Firefox 88+, Safari 14+)
- 🌐 Multiple Formats - ESM, CJS, and UMD builds for any environment
- 📝 TypeScript - Full type definitions included
- ⚡ Performance - Uses PerformanceObserver API, minimal impact on page performance
📦 Installation
Via NPM
npm install @Diroku/sdkVia CDN
<script src="https://cdn.diroku.dev/sdk/Diroku.min.js"></script>🚀 Quick Start
Basic Usage
import { init } from '@Diroku/sdk'
// Initialize SDK
const sdk = init({
projectId: 'your-project-id',
apiKey: 'your-api-key', // optional
endpoint: 'https://api.example.com/v1/ingest/batch',
})
// Track page view
sdk.trackPageView()
// Track custom event
sdk.track('button.clicked', {
button_id: 'signup',
page: '/pricing',
})
// Identify user
sdk.identify('user-123', {
email: '[email protected]',
plan: 'pro',
})
// Track errors
try {
// your code
} catch (error) {
sdk.trackError(error, { context: 'checkout' })
}HTML/Script Tag Usage
<script src="dist/Diroku.min.js"></script>
<script>
const sdk = Diroku.init({
projectId: 'your-project-id',
})
sdk.trackPageView()
</script>⚙️ Configuration
interface SDKConfig {
projectId: string // Required: Your project ID
apiKey?: string // Optional: API key for authentication
endpoint?: string // Optional: Custom ingestion endpoint
batchSize?: number // Optional: Events per batch (default: 25)
batchIntervalMs?: number // Optional: Batch interval in ms (default: 5000)
maxRetries?: number // Optional: Max retry attempts (default: 3)
retryDelayMs?: number // Optional: Initial retry delay (default: 1000)
persistQueue?: boolean // Optional: Enable localStorage queue (default: true)
samplingRate?: number // Optional: 0.0 to 1.0 (default: 1.0 = 100%)
debug?: boolean // Optional: Enable debug logging (default: false)
maskSelectors?: string[] // Optional: CSS selectors to mask
autoCapture?: boolean | { // Optional: Auto-capture configuration (default: true)
clicks?: boolean // Auto-capture click events (default: true)
errors?: boolean // Auto-capture JavaScript errors (default: true)
scroll?: boolean // Auto-capture scroll events (default: true)
forms?: boolean // Auto-capture form submissions (default: true)
navigation?: boolean // Auto-capture SPA navigation (default: true)
performance?: boolean // Auto-capture performance metrics (default: true)
}
}🤖 Auto-Capture Features
Diroku automatically captures user interactions and performance metrics without any manual instrumentation. All auto-capture features are enabled by default.
Click Tracking
Automatically captures all click events with:
- Element CSS selector
- Element tag name
- Element text content (truncated to 100 chars)
- Click coordinates (x, y)
// Automatically captured event:
{
event_type: 'click',
element_selector: '#signup-button',
element_tag: 'button',
element_text: 'Sign Up Now',
click_x: 450,
click_y: 320
}Error Tracking
Automatically captures:
- JavaScript errors (
window.onerror) - Unhandled promise rejections
- Error stack traces
- Source file and line numbers
// Automatically captured on error:
{
event_type: 'error.javascript',
severity: 'error',
error_message: 'Cannot read property of undefined',
error_stack: '...',
error_type: 'TypeError',
metadata: { line: 42, column: 15 }
}Scroll Tracking
Captures scroll events (debounced to once per second):
- Scroll position in pixels
- Scroll depth as percentage (0-100%)
// Automatically captured:
{
event_type: 'scroll',
scroll_y: 1250,
scroll_depth: 45
}Form Tracking
Automatically captures form submissions with:
- Form ID and name
- Number of form fields
- Validation errors (invalid fields)
// Automatically captured on submit:
{
event_type: 'form.submit',
form_id: 'checkout-form',
form_fields: 8,
form_errors: ['email', 'phone'] // Invalid fields
}SPA Navigation
Automatically tracks single-page application navigation:
history.pushState()history.replaceState()popstateevents (back/forward)
// Automatically captured:
{
event_type: 'navigation',
from_url: 'https://app.example.com/products',
to_url: 'https://app.example.com/checkout'
}Performance Metrics
Automatically captures Core Web Vitals and timing metrics:
Core Web Vitals
- LCP (Largest Contentful Paint) - Loading performance
- FID (First Input Delay) - Interactivity
- CLS (Cumulative Layout Shift) - Visual stability
- FCP (First Contentful Paint)
// Automatically captured:
{
event_type: 'performance.lcp',
lcp: 2450 // milliseconds
}
{
event_type: 'performance.fid',
fid: 85 // milliseconds
}
{
event_type: 'performance.cls',
cls: 0.0234 // score
}Navigation Timing
Captures comprehensive page load timing using Navigation Timing API:
{
event_type: 'performance.navigation',
dns_time: 45, // DNS lookup time (ms)
tcp_time: 120, // TCP connection time (ms)
ttfb: 230, // Time to First Byte (ms)
request_time: 230, // Request time (ms)
response_time: 180, // Response download time (ms)
dom_processing_time: 450, // DOM processing time (ms)
page_load_time: 2340, // Total page load time (ms)
time_to_interactive: 1850, // Time to interactive (ms)
fcp: 1200 // First Contentful Paint (ms)
}Disabling Auto-Capture
You can selectively disable auto-capture features:
// Disable all auto-capture
const sdk = init({
projectId: 'proj_123',
autoCapture: false,
})
// Or selectively enable/disable features
const sdk = init({
projectId: 'proj_123',
autoCapture: {
clicks: true,
errors: true,
scroll: false, // Disable scroll tracking
forms: true,
navigation: true,
performance: false, // Disable performance tracking
},
})Privacy & Data Masking
Protect sensitive user data using maskSelectors:
const sdk = init({
projectId: 'proj_123',
maskSelectors: [
'[data-private]', // Custom data attribute
'input[type="password"]', // Password fields
'.ssn', // Social security numbers
'.credit-card', // Credit card fields
],
})Elements matching these selectors will have their text content replaced with [MASKED] in captured events.
Best Practices:
- Always mask password fields
- Mask financial data (credit cards, SSN)
- Mask personal identifiable information (PII)
- Use
data-privateattribute for sensitive elements
<!-- This text will be masked -->
<div data-private>Sensitive information</div>
<input type="password" name="password" />
<span class="ssn">123-45-6789</span>📚 API Reference
Initialization
init(config: SDKConfig): Diroku
Initialize and start the SDK.
const sdk = init({
projectId: 'proj_123',
debug: true,
samplingRate: 0.5, // Track 50% of events
})Core Methods
capture(eventType: string, eventData?: Partial<FrontendEvent>)
Capture a custom event.
sdk.capture('video.played', {
video_id: 'abc123',
duration: 120,
quality: '1080p',
})track(eventName: string, properties?: Record<string, any>)
Simplified tracking method.
sdk.track('purchase.completed', {
amount: 99.99,
currency: 'USD',
items: ['item1', 'item2'],
})trackPageView(url?: string)
Track page view (automatically captures current URL).
sdk.trackPageView()
// or
sdk.trackPageView('/custom/path')identify(userId: string, metadata?: Record<string, any>)
Identify the current user.
sdk.identify('user-456', {
email: '[email protected]',
name: 'John Doe',
plan: 'enterprise',
})trackError(error: Error | string, metadata?: Record<string, any>)
Track errors and exceptions.
try {
dangerousOperation()
} catch (err) {
sdk.trackError(err, {
operation: 'user_signup',
step: 'payment',
})
}Utility Methods
flush(): Promise<void>
Immediately flush queued events.
await sdk.flush()stop()
Stop the SDK and flush remaining events.
sdk.stop()getQueueSize(): number
Get current queue size (in-memory + persisted).
const size = sdk.getQueueSize()
console.log(`${size} events queued`)getSessionId(): string
Get current session ID.
const sessionId = sdk.getSessionId()🎨 Advanced Usage
Sampling
Reduce data volume by sampling events:
const sdk = init({
projectId: 'proj_123',
samplingRate: 0.1, // Track only 10% of events
})Offline Support
Events are automatically queued when offline and sent when connection is restored:
const sdk = init({
projectId: 'proj_123',
persistQueue: true, // default
maxRetries: 5, // retry up to 5 times
})Custom Retry Logic
const sdk = init({
projectId: 'proj_123',
maxRetries: 3,
retryDelayMs: 2000, // Start with 2s delay
// Exponential backoff: 2s, 4s, 8s
})Debug Mode
const sdk = init({
projectId: 'proj_123',
debug: true, // Logs all events to console
})🏗️ Development
Build
The SDK can be built for different environments. Each build bakes in the correct API endpoint:
# Install dependencies
npm install
# Build for local development (http://localhost:8080/v1/ingest/batch)
npm run build:local
# Build for staging (https://staging-api.diroku.dev/v1/ingest/batch)
npm run build:staging
# Build for production (https://api.diroku.dev/v1/ingest/batch)
npm run build
# Development build with watch
npm run devNote: Each environment build overwrites the dist/ files. The API endpoint is baked into the bundle at build time, so customers only need to provide
projectIdandapiKey.
Demo
# Build the SDK first
npm run build:local
# Open customer-example/index.html in your browser
# or start a local server:
npx serve customer-exampleProject Structure
sdk-js/
├── src/
│ ├── index.ts # Main SDK class
│ ├── types.ts # TypeScript interfaces
│ └── queue.ts # Persistent queue implementation
├── dist/ # Built files (generated)
│ ├── index.esm.js # ES Module
│ ├── index.cjs.js # CommonJS
│ ├── Diroku.min.js # UMD (browser)
│ └── index.d.ts # Type definitions
├── demo.html # Interactive demo
├── package.json
├── tsconfig.json
└── vite.config.ts📊 Event Schema
Events captured by the SDK follow this structure:
interface FrontendEvent {
// Core fields
event_id: string // Auto-generated UUID
event_type: string // Event type/name
timestamp: string // ISO 8601 timestamp
session_id: string // Browser session ID
severity?: string // debug | info | warning | error | critical
user_id?: string // User identifier (from identify())
// Browser context (auto-captured)
user_agent?: string
url?: string
referrer?: string
viewport_width?: number
viewport_height?: number
screen_width?: number
screen_height?: number
// Error tracking (auto-captured)
error_message?: string
error_stack?: string
error_type?: string // Error constructor name
// Performance - Navigation Timing (auto-captured)
page_load_time?: number // Total page load time (ms)
time_to_interactive?: number // Time to interactive (ms)
dns_time?: number // DNS lookup time (ms)
tcp_time?: number // TCP connection time (ms)
request_time?: number // Request time (ms)
response_time?: number // Response time (ms)
dom_processing_time?: number // DOM processing time (ms)
// Performance - Core Web Vitals (auto-captured)
lcp?: number // Largest Contentful Paint (ms)
fid?: number // First Input Delay (ms)
cls?: number // Cumulative Layout Shift (score)
fcp?: number // First Contentful Paint (ms)
ttfb?: number // Time to First Byte (ms)
// Click tracking (auto-captured)
element_selector?: string // CSS selector
element_text?: string // Element text content
element_tag?: string // HTML tag name
click_x?: number // X coordinate
click_y?: number // Y coordinate
// Scroll tracking (auto-captured)
scroll_depth?: number // Scroll percentage (0-100)
scroll_y?: number // Scroll position in pixels
// Form tracking (auto-captured)
form_id?: string // Form ID attribute
form_name?: string // Form name attribute
form_fields?: number // Number of form fields
form_errors?: string[] // Invalid field names
// Navigation tracking (auto-captured)
from_url?: string // Previous URL
to_url?: string // New URL
// Custom metadata
metadata?: Record<string, any>
tags?: string[]
}Event Types
The SDK automatically captures these event types:
| Event Type | Description | Auto-Captured |
|------------|-------------|---------------|
| click | User click events | ✅ Yes |
| error.javascript | JavaScript errors | ✅ Yes |
| error.promise | Unhandled promise rejections | ✅ Yes |
| scroll | Scroll events (debounced) | ✅ Yes |
| form.submit | Form submissions | ✅ Yes |
| navigation | SPA route changes | ✅ Yes |
| performance.lcp | Largest Contentful Paint | ✅ Yes |
| performance.fid | First Input Delay | ✅ Yes |
| performance.cls | Cumulative Layout Shift | ✅ Yes |
| performance.navigation | Navigation timing | ✅ Yes |
| page.view | Page views | Manual |
| user.identified | User identification | Manual |
| Custom events | Your custom events | Manual |
🔧 Browser Compatibility
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Opera 76+
📄 License
MIT
🤝 Contributing
Contributions welcome! Please open an issue or PR.
📝 Changelog
v0.2.0 (Current)
- ✅ Auto-capture features
- Automatic click tracking with element info
- Automatic error and promise rejection tracking
- Automatic scroll tracking (debounced)
- Automatic form submission tracking
- Automatic SPA navigation tracking
- ✅ Performance monitoring
- Core Web Vitals (LCP, FID, CLS, FCP)
- Navigation Timing API metrics
- Time to First Byte (TTFB)
- Time to Interactive (TTI)
- ✅ Privacy features
- Element text masking with CSS selectors
- Configurable auto-capture (enable/disable per feature)
- ✅ Enhanced event schema
- 20+ new event fields for performance and interactions
- Comprehensive error tracking with stack traces
- Form validation error tracking
v0.1.0
- ✅ Initial release
- ✅ Automatic batching
- ✅ Offline support with localStorage
- ✅ Exponential backoff retry
- ✅ TypeScript support
- ✅ Multiple build formats (ESM, CJS, UMD)
- ✅ Interactive demo page
- ✅ Sampling support
- ✅ Session management
🆘 Support
For issues and questions:
- GitHub Issues: [Link to repo]
- Documentation: [Link to docs]
- Email: [email protected]
