Documentation

Complete guide to integrating Serla analytics into your application.

Getting Started

Serla is a privacy-focused analytics platform designed for developers. No cookies, no fingerprinting, no consent banners required.

Quick Start

  1. Create an account at serla.dev/signup
  2. Create a project and copy your API key from the dashboard
  3. Install the SDK or use the REST API directly
  4. Start tracking events with a single line of code

Your First Event

const serla = new Serla('sk_live_your_api_key');
serla.track('page_view', { page: '/home' });

Authentication

All API requests require authentication using an API key.

API Key Format

sk_live_Live keys - use in production
sk_test_Test keys - events marked as test data

Using Your API Key

curl -X POST https://serla.dev/api/v1/events \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name": "test_event"}'

Security Best Practices

  • Never expose API keys in client-side code for web apps (use a proxy)
  • Rotate keys periodically from the dashboard
  • Use test keys during development
  • Set up IP allowlists for server-side integrations

Installation

Download the SDK for your preferred language. Each SDK is a single file with no dependencies.

JavaScript
serla.js - Browser & Node.js
Download
TypeScript
serla.ts - Full type definitions
Download
Python
serla.py - Python 3.7+
Download

Browser Installation

HTML
<script src="/serla.js"></script>
<script>
const serla = new Serla('sk_live_your_api_key');
serla.trackPageView();
</script>

ES Modules

import { Serla } from './serla.js';
const serla = new Serla('sk_live_your_api_key');

SDK Configuration

Customize SDK behavior with configuration options.

const serla = new Serla('sk_live_your_api_key', {
// API endpoint (default: https://serla.dev/api/v1)
endpoint: 'https://serla.dev/api/v1',
// Enable debug logging (default: false)
debug: true,
// Batch size before auto-flush (default: 10)
batchSize: 10,
// Flush interval in ms (default: 5000)
flushInterval: 5000,
// Auto-track page views (default: false)
autoTrackPageViews: true,
// Respect Do Not Track header (default: true)
respectDoNotTrack: true,
// Session timeout in minutes (default: 30)
sessionTimeout: 30
});

SDK Methods

MethodDescription
track(name, options?)Queue event for batched sending
send(name, options?)Send event immediately (no batching)
identify(userId, props?)Identify a user
trackPageView(props?)Track a page view
flush()Send all queued events
reset()Clear user identity and session
getSessionId()Get current session ID
getUserId()Get current user ID
setDebug(enabled)Enable/disable debug mode

track() vs send()

track()

Queues events locally and sends them in batches. More efficient for high-volume tracking. Events are sent when the batch size is reached (default: 10) or flush interval elapses (default: 5 seconds).

send()

Sends a single event immediately without batching. Use for critical events that must be recorded instantly, like purchases or signups.

// Batched - efficient for high volume
serla.track('page_view', { page: '/home' });
serla.track('button_click', { button: 'cta' });
// Immediate - for critical events
await serla.send('purchase', {
distinctId: 'user_123',
properties: { revenue: 99.99 }
});

Tracking Events

Track any user action with custom properties. Events are the core of Serla analytics.

Basic Event

// Simple event
serla.track('button_click');
// Event with properties
serla.track('purchase', {
properties: {
product_id: 'prod_123',
product_name: 'Pro Plan',
price: 49.99,
currency: 'USD'
}
});
// Event with user ID
serla.track('signup', {
distinctId: 'user_456',
properties: {
plan: 'pro',
source: 'google_ads'
}
});

Revenue Tracking

Serla automatically recognizes and aggregates these revenue properties: revenue, amount, value, price

serla.track('purchase_completed', {
distinctId: 'user_123',
properties: {
revenue: 149.99,
quantity: 2,
product: 'Pro Plan',
currency: 'USD'
}
});

Tracking Best Practices

  • Use snake_case for event names: button_click, not buttonClick
  • Be consistent with naming across your app
  • Keep properties flat - avoid deeply nested objects
  • Use standard names for common events: signup, login, purchase

Identifying Users

Associate events with a user to track them across sessions and devices.

// Basic identification
serla.identify('user_123', {
email: 'john@example.com',
name: 'John Doe'
});
// Full user profile
serla.identify('user_123', {
// Contact info
email: 'john@example.com',
name: 'John Doe',
phone: '+1234567890',
// Account info
plan: 'pro',
created_at: '2024-01-15T10:30:00Z',
// Company info (B2B)
company: 'Acme Inc',
company_size: '50-100',
industry: 'Technology',
// Custom properties
lifetime_value: 499.99
});

Reset Identity

Clear user identity on logout:

serla.reset();
// Generates new anonymous session ID

Sessions & Page Views

Sessions are created automatically and track user activity over time.

How Sessions Work

  • Sessions are created automatically on first event
  • Sessions expire after 30 minutes of inactivity (configurable)
  • Session ID format: sess_abc123...
  • New session created after timeout, reset(), or new browser tab

Tracking Page Views

// Basic page view
serla.trackPageView();
// With custom properties
serla.trackPageView({
title: 'Pricing Page',
section: 'marketing'
});

SPA Integration

import { useLocation } from 'react-router-dom';
function App() {
const location = useLocation();
useEffect(() => {
serla.trackPageView();
}, [location.pathname]);
}

Properties & Schema

Understanding the data schema and auto-enriched properties.

Reserved Properties

These properties are auto-detected from the request:

PropertyDescription
$browserBrowser name
$osOperating system
$deviceDevice type (desktop, mobile, tablet)
$countryCountry code
$cityCity name
$referrerReferrer URL
$utm_sourceUTM source
$utm_mediumUTM medium
$utm_campaignUTM campaign

Property Limits

  • Max 100 properties per event
  • Property names: max 100 characters
  • String values: max 1000 characters
  • Arrays: max 100 items
  • Nested objects: max 3 levels deep

Batch Events

Events are automatically batched for efficiency. The queue flushes when batch size is reached, interval elapsed, or manually.

i
Automatic batching: Events queue locally and flush every 5 seconds or when 10 events are queued, whichever comes first.

Manual Flush

// Send all queued events immediately
await serla.flush();
// Flush before page unload (handled automatically)
window.addEventListener('beforeunload', () => {
serla.flush();
});

API Batch Endpoint

curl -X POST https://serla.dev/api/v1/events/batch \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"events": [
{ "name": "page_view", "properties": { "page": "/home" } },
{ "name": "button_click", "properties": { "button": "cta" } }
]
}'

API Reference

Base URL: https://serla.dev/api/v1

POST/events

Track a single event.

Request

{
"name": "purchase",
"distinctId": "user_123",
"sessionId": "sess_abc",
"timestamp": "2024-01-15T10:30:00Z",
"properties": {
"product_id": "prod_123",
"price": 49.99
}
}

Response

{
"success": true,
"eventId": "evt_abc123",
"sessionId": "sess_abc"
}
POST/events/batch

Track multiple events (max 100 per request).

Request

{
"events": [
{ "name": "page_view", "properties": { "page": "/home" } },
{ "name": "button_click", "properties": { "button": "cta" } }
]
}

Response

{
"success": true,
"count": 2,
"eventIds": ["evt_abc", "evt_def"]
}
POST/identify

Identify a user and set properties.

Request

{
"distinctId": "user_123",
"properties": {
"email": "john@example.com",
"name": "John Doe",
"plan": "pro"
}
}
GET/export

Export events as JSON or CSV.

Query Parameters

formatjson or csv (default: json)
startDateISO 8601 date
endDateISO 8601 date
eventNameFilter by event name
limitMax results (default: 1000, max: 10000)
DELETE/users/:distinctId

Delete all data for a user (GDPR right to deletion).

Example

curl -X DELETE https://serla.dev/api/v1/users/user_123 \
-H "Authorization: Bearer sk_live_..."

Rate Limits

Limits by Plan

PlanEvents/secEvents/month
Free1025,000
Hobby50500,000
Pro2002,500,000
Max1000Unlimited

Rate Limit Headers

X-RateLimit-Limit: 50
X-RateLimit-Remaining: 49
X-RateLimit-Reset: 1705312800

Handling 429 Errors

async function trackWithRetry(event, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await serla.track(event);
} catch (error) {
if (error.status === 429) {
const delay = Math.pow(2, i) * 1000;
await new Promise(r => setTimeout(r, delay));
} else {
throw error;
}
}
}
}

Webhooks

Receive real-time notifications when events occur.

Setup

  1. Go to Dashboard > Settings > Webhooks
  2. Click "Add Webhook"
  3. Enter your endpoint URL
  4. Select events to receive
  5. Copy the signing secret

Webhook Payload

{
"id": "wh_abc123",
"type": "event.created",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"event": {
"id": "evt_xyz",
"name": "purchase",
"distinctId": "user_123",
"properties": { "price": 49.99 }
}
}
}

Webhook Events

EventDescription
event.createdNew event tracked
user.identifiedUser identified
goal.completedGoal conversion
threshold.exceededCustom alert triggered

Signature Verification

const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

Dashboard Features

Funnels

Create conversion funnels to see where users drop off.

Example funnel:

  1. page_view (page=/pricing)
  2. signup_started
  3. signup_completed
  4. purchase

Goals

Track conversion events and assign monetary values.

  • Event-based: Track any event as a conversion
  • Pageview-based: Track specific page visits
  • Revenue-based: Track events with revenue properties

Retention

Analyze user retention with cohort analysis.

  • Group users by signup date
  • View retention by day, week, or month
  • Define custom retention events

Segments

Create saved segments for filtering data.

Example Segment
Country = United States
AND Browser = Chrome
AND Plan = pro

Attribution

Understand how users find you with attribution models.

  • First-touch: Credit first interaction
  • Last-touch: Credit last interaction before conversion
  • Linear: Equal credit to all touchpoints
  • Time-decay: More credit to recent touchpoints

Journeys

Analyze user navigation patterns through your site.

  • User paths: See top navigation patterns
  • Drop-off points: Identify where users leave
  • Session analysis: Understand user flow

Built automatically from page views. Enable autoTrackPageViews: true or call trackPageView().

Privacy & Compliance

No Cookies

Serla does not use cookies. Session tracking uses in-memory storage or optional localStorage.

No Fingerprinting

We never fingerprint users. Identification is explicit via identify() or session-based for anonymous users.

IP Addresses

IPs are used for geolocation only and are never stored. Geolocation is resolved at ingestion time.

Data Retention

PlanRetention
Free7 days
Hobby60 days
Pro180 days
Max3 years

User Opt-Out

// Check opt-out before initializing
if (!localStorage.getItem('serla_optout')) {
const serla = new Serla('sk_live_...');
}
// Opt-out function for privacy settings
function optOut() {
localStorage.setItem('serla_optout', 'true');
serla.reset();
}

Error Handling

Error Codes

CodeStatusDescription
invalid_request400Malformed request body
unauthorized401Invalid or missing API key
forbidden403Key does not have permission
not_found404Resource not found
rate_limit_exceeded429Too many requests
internal_error500Server error

SDK Error Handling

try {
await serla.track('event');
} catch (error) {
if (error.code === 'rate_limit_exceeded') {
// Wait and retry
} else if (error.code === 'unauthorized') {
// Check API key
} else {
console.error('Serla error:', error.message);
}
}

Debug Mode

const serla = new Serla('sk_live_...', { debug: true });
// Or toggle at runtime
serla.setDebug(true);