Diroku frontend SDK - lightweight event capture and batching
npm install @diroku/sdkbash
npm install @Diroku/sdk
`
$3
`html
`
š Quick Start
$3
`typescript
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: 'user@example.com',
plan: 'pro',
})
// Track errors
try {
// your code
} catch (error) {
sdk.trackError(error, { context: 'checkout' })
}
`
$3
`html
`
āļø Configuration
`typescript
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.
$3
Automatically captures all click events with:
- Element CSS selector
- Element tag name
- Element text content (truncated to 100 chars)
- Click coordinates (x, y)
`typescript
// Automatically captured event:
{
event_type: 'click',
element_selector: '#signup-button',
element_tag: 'button',
element_text: 'Sign Up Now',
click_x: 450,
click_y: 320
}
`
$3
Automatically captures:
- JavaScript errors (window.onerror)
- Unhandled promise rejections
- Error stack traces
- Source file and line numbers
`typescript
// 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 }
}
`
$3
Captures scroll events (debounced to once per second):
- Scroll position in pixels
- Scroll depth as percentage (0-100%)
`typescript
// Automatically captured:
{
event_type: 'scroll',
scroll_y: 1250,
scroll_depth: 45
}
`
$3
Automatically captures form submissions with:
- Form ID and name
- Number of form fields
- Validation errors (invalid fields)
`typescript
// Automatically captured on submit:
{
event_type: 'form.submit',
form_id: 'checkout-form',
form_fields: 8,
form_errors: ['email', 'phone'] // Invalid fields
}
`
$3
Automatically tracks single-page application navigation:
- history.pushState()
- history.replaceState()
- popstate events (back/forward)
`typescript
// Automatically captured:
{
event_type: 'navigation',
from_url: 'https://app.example.com/products',
to_url: 'https://app.example.com/checkout'
}
`
$3
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)
`typescript
// 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:
`typescript
{
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)
}
`
$3
You can selectively disable auto-capture features:
`typescript
// 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
},
})
`
$3
Protect sensitive user data using maskSelectors:
`typescript
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-private attribute for sensitive elements
`html
Sensitive information
123-45-6789
`
š API Reference
$3
#### init(config: SDKConfig): Diroku
Initialize and start the SDK.
`typescript
const sdk = init({
projectId: 'proj_123',
debug: true,
samplingRate: 0.5, // Track 50% of events
})
`
$3
#### capture(eventType: string, eventData?: Partial
Capture a custom event.
`typescript
sdk.capture('video.played', {
video_id: 'abc123',
duration: 120,
quality: '1080p',
})
`
#### track(eventName: string, properties?: Record
Simplified tracking method.
`typescript
sdk.track('purchase.completed', {
amount: 99.99,
currency: 'USD',
items: ['item1', 'item2'],
})
`
#### trackPageView(url?: string)
Track page view (automatically captures current URL).
`typescript
sdk.trackPageView()
// or
sdk.trackPageView('/custom/path')
`
#### identify(userId: string, metadata?: Record
Identify the current user.
`typescript
sdk.identify('user-456', {
email: 'user@example.com',
name: 'John Doe',
plan: 'enterprise',
})
`
#### trackError(error: Error | string, metadata?: Record
Track errors and exceptions.
`typescript
try {
dangerousOperation()
} catch (err) {
sdk.trackError(err, {
operation: 'user_signup',
step: 'payment',
})
}
`
$3
#### flush(): Promise
Immediately flush queued events.
`typescript
await sdk.flush()
`
#### stop()
Stop the SDK and flush remaining events.
`typescript
sdk.stop()
`
#### getQueueSize(): number
Get current queue size (in-memory + persisted).
`typescript
const size = sdk.getQueueSize()
console.log(${size} events queued)
`
#### getSessionId(): string
Get current session ID.
`typescript
const sessionId = sdk.getSessionId()
`
šØ Advanced Usage
$3
Reduce data volume by sampling events:
`typescript
const sdk = init({
projectId: 'proj_123',
samplingRate: 0.1, // Track only 10% of events
})
`
$3
Events are automatically queued when offline and sent when connection is restored:
`typescript
const sdk = init({
projectId: 'proj_123',
persistQueue: true, // default
maxRetries: 5, // retry up to 5 times
})
`
$3
`typescript
const sdk = init({
projectId: 'proj_123',
maxRetries: 3,
retryDelayMs: 2000, // Start with 2s delay
// Exponential backoff: 2s, 4s, 8s
})
`
$3
`typescript
const sdk = init({
projectId: 'proj_123',
debug: true, // Logs all events to console
})
`
šļø Development
$3
The SDK can be built for different environments. Each build bakes in the correct API endpoint:
`bash
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 dev
`
> Note: Each environment build overwrites the dist/ files. The API endpoint is baked into the bundle at build time, so customers only need to provide projectId and apiKey.
$3
`bash
Build the SDK first
npm run build:local
Open customer-example/index.html in your browser
or start a local server:
npx serve customer-example
`
$3
`
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:
`typescript
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
tags?: string[]
}
`
$3
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 |