UNPKG

@cruxstack/browser-sdk

Version:

A lightweight, privacy-focused JavaScript SDK for web analytics and event tracking. Built with TypeScript, featuring automatic event capture, event-time environment snapshots, intelligent queuing, and robust error handling.

96 lines (95 loc) 3.31 kB
import { SENSITIVE_SELECTORS, PRIVACY_SETTINGS } from './constants'; // Check if an element should be ignored for tracking export const shouldIgnoreElement = (element) => { // Check if element matches sensitive selectors if (element.matches(SENSITIVE_SELECTORS)) { return true; } // Check if element is inside a sensitive container if (element.closest(SENSITIVE_SELECTORS)) { return true; } // Check for data attributes that indicate sensitive content if (element.hasAttribute('data-sensitive') || element.hasAttribute('data-private') || element.hasAttribute('data-no-track')) { return true; } return false; }; // Redact sensitive values from form inputs export const redactSensitiveValue = (element, value) => { if (!PRIVACY_SETTINGS.REDACT_INPUT_VALUES) { return value; } const input = element; const type = input.type?.toLowerCase(); const name = input.name?.toLowerCase(); // Always redact password fields if (type === 'password') { return '[REDACTED_PASSWORD]'; } // Redact email fields if (type === 'email' || name?.includes('email')) { return '[REDACTED_EMAIL]'; } // Redact phone numbers if (type === 'tel' || name?.includes('phone') || name?.includes('tel')) { return '[REDACTED_PHONE]'; } // Redact credit card fields if (name?.includes('card') || name?.includes('credit') || type?.includes('cc')) { return '[REDACTED_CARD]'; } // Redact SSN or social security if (name?.includes('ssn') || name?.includes('social')) { return '[REDACTED_SSN]'; } // For other inputs, return limited info if (input.tagName === 'INPUT') { return value.length > 0 ? `[${value.length} chars]` : null; } return value; }; // Clean data object by removing or redacting sensitive information export const cleanEventData = (data) => { const cleaned = { ...data }; // Remove sensitive fields const sensitiveFields = ['password', 'ssn', 'social', 'creditCard', 'cvv']; sensitiveFields.forEach(field => { if (cleaned[field]) { delete cleaned[field]; } }); // Redact URLs that might contain sensitive info if (cleaned.url && typeof cleaned.url === 'string') { try { const url = new URL(cleaned.url); // Remove sensitive query parameters const sensitiveParams = ['token', 'key', 'password', 'secret', 'auth']; sensitiveParams.forEach(param => { url.searchParams.delete(param); }); cleaned.url = url.toString(); } catch (e) { // Invalid URL, keep as is } } return cleaned; }; // Check if we should rate limit this event let eventCounts = new Map(); export const shouldRateLimit = (eventType, limit = 100, windowMs = 60000) => { const now = Date.now(); const key = eventType; const current = eventCounts.get(key) || { count: 0, lastReset: now }; // Reset counter if window has passed if (now - current.lastReset > windowMs) { current.count = 0; current.lastReset = now; } current.count++; eventCounts.set(key, current); return current.count > limit; };