Security
This page outlines what TraceLog protects automatically, what it does not handle, and what you are responsible for as the integrator.
What TraceLog Guarantees
Input Value Protection
TraceLog never captures values from <input>, <textarea>, or <select> elements. Click events on form fields only capture element metadata (tag name, id, class) -- never the value attribute.
PII Sanitization
Sensitive data patterns in error messages and click text are automatically redacted:
| Pattern | Example | Result |
|---|---|---|
| Email addresses | user@example.com | [REDACTED] |
| Phone numbers (US) | (555) 123-4567 | [REDACTED] |
| Credit card numbers | 4111 1111 1111 1111 | [REDACTED] |
| API keys / tokens | sk_live_abc123... | [REDACTED] |
| Bearer tokens | Bearer eyJhbG... | [REDACTED] |
| IBAN numbers | DE89 3704 0044 0532 0130 00 | [REDACTED] |
This sanitization runs client-side before any data leaves the browser.
URL Parameter Filtering
TraceLog strips 14 sensitive query parameters from all tracked URLs by default:
token, auth, key, session, reset, password, api_key, apikey, secret, access_token, refresh_token, verification, code, otp
You can extend this list with custom parameters via sensitiveQueryParams in your configuration. Common parameters like email and user are not filtered by default because they have legitimate uses in confirmation links and attribution.
Client-Side Controls
All sampling, deduplication, and validation happen in the browser. Privacy controls work even without a backend connection. Rate limiting (200 events/sec) prevents abuse and accidental event floods.
XSS Protection
All string metadata is sanitized against common XSS patterns. HTML entities are encoded automatically before being included in event payloads.
Data Retention
Server-side analytics data is retained according to your subscription plan and automatically deleted after the retention period:
| Plan | Retention |
|---|---|
| Free | 30 days |
| Growth | 90 days |
| Pro | 180 days |
| Business | 365 days |
| Enterprise | 365 days |
Client-side event data in the browser expires after 2 hours in localStorage regardless of plan.
What TraceLog Does NOT Do
- No form submission tracking -- form data is never captured automatically. You must explicitly send form data via
tracelog.event(). - No fingerprinting -- no canvas fingerprinting, browser fingerprinting, or cross-site tracking. User IDs are optional and entirely under your control.
- No long-term client storage -- events expire after 2 hours in localStorage. Session recovery windows are configurable (default: 2x session timeout).
Your Responsibilities
TraceLog is a tool, not a compliance solution. The following areas require your attention.
GDPR Consent Management
You must obtain user consent before calling tracelog.init(). See the Consent & GDPR page for implementation details and code examples.
Protecting Sensitive UI
Mark sensitive elements with data-tlog-ignore to exclude them from tracking entirely:
<div data-tlog-ignore>
<input type="text" name="card_number">
<input type="text" name="cvv">
</div>
This prevents TraceLog from capturing any interaction data -- including element metadata -- from the marked elements and their children.
Custom Event Data Sanitization
TraceLog automatically sanitizes error messages and click text, but you are responsible for sanitizing data passed to tracelog.event().
Do this:
// Hash sensitive IDs before sending
const hashedId = await hashUserId(user.id);
tracelog.event('purchase_completed', {
user_id: hashedId, // Hashed, not raw
amount: 99.99,
currency: 'USD'
});
Not this:
// DO NOT send PII in custom events
tracelog.event('user_registered', {
email: user.email, // PII leak
phone: user.phone, // PII leak
address: user.address, // PII leak
credit_card: user.card // Critical PII leak
});
URL Parameter Configuration
Extend the default sensitive parameter list with any application-specific parameters:
await tracelog.init({
sensitiveQueryParams: ['affiliate_id', 'promo_code', 'referral'],
integrations: {
tracelog: { projectId: 'your-project-id' }
}
});
Responsibility Matrix
| Aspect | TraceLog handles | You handle |
|---|---|---|
| Input value protection | Never captured automatically | Verify in testing |
| PII in text and errors | Auto-redacted (email, phone, cards, tokens) | Extend for domain-specific PII |
| URL parameters | 14 default parameters filtered | Add app-specific parameters |
| Consent management | Not handled | Implement before init() |
| Sensitive UI elements | data-tlog-ignore support provided | Mark all sensitive elements |
| Custom event data | Not sanitized | Sanitize before sending |
| Data retention | Client: 2-hour auto-cleanup. Server: per plan | Server: configure per your policy |
Advanced Security Patterns
User ID Anonymization with SHA-256
Instead of sending raw user IDs, hash them before passing to TraceLog:
import { tracelog } from '@tracelog/lib';
async function setAnonymousUser(userId: string) {
const encoder = new TextEncoder();
const data = encoder.encode(userId + 'your-secret-salt');
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashedId = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
tracelog.identify(hashedId);
}
This uses the native Web Crypto API, available in all modern browsers. No additional dependencies are required.
Secure Custom Backend
When sending events to your own backend, enforce HTTPS and configure credentials carefully:
await tracelog.init({
integrations: {
custom: {
collectApiUrl: 'https://your-api.com/collect',
allowHttp: false, // Never enable in production
fetchCredentials: 'include' // Use 'omit' if cookies are not needed
}
}
});
Setting allowHttp: true transmits analytics data over unencrypted connections. This should only be used for local development.
Transformer Security
Transformers let you modify events before they are sent to a custom backend. Use them for additional PII sanitization, but be careful not to introduce leaks.
Sanitize PII in transformers:
tracelog.setTransformer('beforeSend', (data) => {
if ('type' in data && data.custom_event?.metadata) {
const sanitized = { ...data.custom_event.metadata };
delete sanitized.email;
delete sanitized.phone;
delete sanitized.ssn;
return {
...data,
custom_event: { ...data.custom_event, metadata: sanitized }
};
}
return data;
});
Validate external input:
tracelog.setTransformer('beforeSend', (data) => {
if ('type' in data) {
// Validate and sanitize before merging
const validated = validateExternalData(window.externalData);
const sanitized = sanitizePII(validated);
return {
...data,
custom_event: {
...data.custom_event,
metadata: { ...data.custom_event?.metadata, ...sanitized }
}
};
}
return data;
});
Transformers are applied for custom backend integrations and ignored for TraceLog SaaS (schema protection). In multi-integration setups, the SaaS integration receives the original event while the custom backend receives the transformed version.