Analytics & Observability
Temps includes a comprehensive analytics and observability platform built-in—no external services required. Track visitors, replay sessions, monitor performance, and analyze user behavior all in one place.
Overview
Unlike Vercel and other platforms that require third-party integrations, Temps provides production-ready analytics out of the box:
What's Included
- Real-time visitor analytics
- Custom event tracking
- Session replay with DOM recording
- Core Web Vitals monitoring
- Funnel analysis
- Geographic tracking
- User session stitching
- Performance metrics
Why It Matters
- Zero external dependencies
- No data leaves your infrastructure
- Unlimited page views (no pricing tiers)
- Complete data ownership
- GDPR/CCPA compliant by default
- Sub-second query performance
Architecture
Temps analytics is powered by:
- TimescaleDB: Time-series database for high-throughput event ingestion
- PostgreSQL: Hypertables for automatic data partitioning
- In-Memory Caching: Sub-100ms query performance
- Event Batching: Efficient network usage
Visitor Analytics
Track and analyze visitor behavior with detailed metrics and geographic data.
Metrics Tracked
- Name
Page Views- Description
Total page views with time-series charts, breakdown by path, referrer tracking
- Name
Unique Visitors- Description
IP-based unique visitor identification, session stitching, returning vs new visitor ratio
- Name
Session Duration- Description
Average session length, time on page, engagement metrics
- Name
Bounce Rate- Description
Single-page session tracking, exit page analysis
- Name
Geographic Data- Description
Country, region, city detection using MaxMind GeoIP, timezone tracking
- Name
Device & Browser- Description
User agent parsing, browser version, OS, device type (mobile/desktop/tablet)
- Name
Referrer Sources- Description
Traffic source tracking, UTM parameter parsing, campaign attribution
- Name
Real-Time Visitors- Description
Live visitor count, currently active pages
Dashboard Views
Access analytics data via the dashboard. View real-time metrics, historical trends, and detailed visitor insights all in one place.
Time-Series Charts
View trends over time with customizable date ranges:
- Last 24 hours (hourly breakdown)
- Last 7 days (daily breakdown)
- Last 30 days (daily breakdown)
- Last 90 days (weekly breakdown)
- Custom date range
Event Tracking
Track custom events to understand user interactions and behavior.
Built-in Events
Temps automatically tracks:
- Page views
- Page exits
- Link clicks (external)
- Form submissions
- File downloads
- 404 errors
- JavaScript errors
Custom Events
Track any custom event in your application:
Track Custom Events
import { useTrackEvent } from '@temps-sdk/react-analytics';
function CheckoutButton() {
const trackEvent = useTrackEvent();
const handleCheckout = () => {
trackEvent('checkout_completed', {
orderId: '12345',
amount: 99.99,
currency: 'USD',
items: 3
});
};
return <button onClick={handleCheckout}>Complete Purchase</button>;
}
Event Properties
- Name
Event Name- Description
String identifier for the event (e.g., 'signup_completed', 'video_played')
- Name
Properties- Description
Custom JSON object with event metadata (any structure)
- Name
User ID- Description
Optional user identifier to link events across sessions
- Name
Timestamp- Description
Automatic timestamp (or custom for backfilling)
- Name
Session ID- Description
Automatically generated session identifier
- Name
Context- Description
Automatic context (IP, user agent, referrer, page URL)
Querying Events
Query and filter events in the dashboard or via API:
Dashboard
// Filter events in dashboard
{
"event": "purchase_completed",
"dateRange": "last_30_days",
"filters": {
"properties.amount": { "gte": 100 },
"properties.currency": "USD"
},
"groupBy": "properties.plan"
}
Session Replay
Record and replay user sessions to understand how users interact with your application.
Features
- Name
DOM Recording- Description
Captures DOM snapshots and mutations, CSS styles, input events (with privacy controls)
- Name
Event Timeline- Description
Visual timeline of all interactions (clicks, scrolls, navigation, errors)
- Name
Console Logs- Description
Captures browser console output during session
- Name
Network Activity- Description
Records API requests and responses (optional)
- Name
Performance Metrics- Description
FPS, memory usage, page load times
- Name
Error Correlation- Description
Links sessions to error events for debugging
Privacy Controls
Automatic Redaction
- Password inputs (always masked)
- Credit card fields (always masked)
- Email addresses (configurable)
- Phone numbers (configurable)
- Custom selectors
User Consent
- Opt-in mode (user consent required)
- Opt-out mode (user can disable)
- Geo-based rules (GDPR compliance)
- Sampling rate (record % of sessions)
Configure Session Replay
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';
function App() {
return (
<TempsAnalyticsProvider
enableSessionRecording={true}
sessionRecordingConfig={{
sessionSampleRate: 0.1, // Record 10% of sessions
maskAllInputs: false,
blockClass: 'sensitive-data',
maskTextSelector: 'input[type="password"], input[type="email"]'
}}
>
<YourApp />
</TempsAnalyticsProvider>
);
}
Replay Player
The replay player includes:
- Playback controls (play, pause, speed adjustment)
- Timeline scrubber
- Event markers (clicks, navigation, errors)
- Console panel
- Network panel
- Device viewport emulation
Storage Optimization: Session recordings are compressed using efficient algorithms. Average session (~5 minutes) uses ~500KB storage.
Performance Monitoring
Track Core Web Vitals and performance metrics to optimize user experience.
Core Web Vitals
- Name
Largest Contentful Paint (LCP)- Description
Measures loading performance. Target: < 2.5 seconds
- Name
First Input Delay (FID)- Description
Measures interactivity. Target: < 100 milliseconds
- Name
Cumulative Layout Shift (CLS)- Description
Measures visual stability. Target: < 0.1
- Name
First Contentful Paint (FCP)- Description
Time to first content render. Target: < 1.8 seconds
- Name
Time to First Byte (TTFB)- Description
Server response time. Target: < 600 milliseconds
- Name
Interaction to Next Paint (INP)- Description
Measures responsiveness. Target: < 200 milliseconds
Automatic Collection
Performance metrics are automatically collected when you use the Temps SDK:
Enable Performance Monitoring
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';
function App() {
return (
<TempsAnalyticsProvider
autoTrackSpeedAnalytics={true}
>
<YourApp />
</TempsAnalyticsProvider>
);
}
Performance Insights
View performance trends in the dashboard:
- Historical performance scores (Lighthouse-style)
- Performance by page/route
- Performance by device/browser
- Performance by geography
- Percentile distributions (P50, P75, P95, P99)
Performance Budgets
Set performance budgets and get alerts when exceeded:
// Configure performance budgets
{
"budgets": {
"LCP": { "target": 2500, "alert": 3000 },
"FID": { "target": 100, "alert": 200 },
"CLS": { "target": 0.1, "alert": 0.25 }
},
"notifications": {
"email": "devteam@example.com",
"slack": "https://hooks.slack.com/..."
}
}
Funnel Analysis
Track multi-step conversion funnels to optimize user flows.
Create a Funnel
Define a sequence of events that represent a user journey:
Define Funnel
// Create funnel via dashboard
{
"name": "Signup Funnel",
"steps": [
{
"name": "Landing Page View",
"event": "pageview",
"filters": { "path": "/" }
},
{
"name": "Signup Page View",
"event": "pageview",
"filters": { "path": "/signup" }
},
{
"name": "Form Submitted",
"event": "signup_form_submit"
},
{
"name": "Email Verified",
"event": "email_verified"
},
{
"name": "Onboarding Completed",
"event": "onboarding_complete"
}
],
"timeWindow": "24h" // Max time between steps
}
Funnel Metrics
- Name
Conversion Rate- Description
Percentage of users who complete all steps
- Name
Drop-off Rate- Description
Percentage of users who exit at each step
- Name
Time to Convert- Description
Average time between first and last step
- Name
Step Conversion- Description
Conversion rate between consecutive steps
- Name
Cohort Analysis- Description
Compare funnels across different user segments
Funnel Visualization
The dashboard provides:
- Visual funnel chart with drop-off indicators
- Step-by-step conversion rates
- Time-to-convert distribution
- User segmentation (device, location, traffic source)
- Historical trends
Sending Analytics from React
Send analytics events from your React application using the official React SDK.
Installation
npm install @temps-sdk/react-analytics
Setup
React Setup
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';
function App() {
return (
<TempsAnalyticsProvider
domain="example.com"
autoTrackPageviews={true}
ignoreLocalhost={true}
autoTrackSpeedAnalytics={true}
enableSessionRecording={true}
sessionRecordingConfig={{
sessionSampleRate: 0.1
}}
>
<YourApp />
</TempsAnalyticsProvider>
);
}
Hooks
React Hooks
import { useTrackEvent } from '@temps-sdk/react-analytics';
function SignupButton() {
const trackEvent = useTrackEvent();
const handleSignup = async () => {
// Track event
trackEvent('signup_started', {
source: 'hero',
plan: 'pro'
});
// Your signup logic
};
return <button onClick={handleSignup}>Sign Up</button>;
}
Complete React Example
Here's a complete example showing how to send analytics from a React app:
Complete Example
// app/layout.tsx (Next.js App Router)
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';
export default function RootLayout({ children }) {
return (
<html>
<body>
<TempsAnalyticsProvider
basePath="/api/_temps"
autoTrackPageviews={true}
autoTrackSpeedAnalytics={true}
enableSessionRecording={true}
sessionRecordingConfig={{
sessionSampleRate: 0.1
}}
>
{children}
</TempsAnalyticsProvider>
</body>
</html>
);
}
// components/CheckoutButton.tsx
import { useTrackEvent, useAnalytics } from '@temps-sdk/react-analytics';
export function CheckoutButton() {
const trackEvent = useTrackEvent();
const analytics = useAnalytics();
const handleCheckout = async (userId: string) => {
// Identify the user
analytics.identify(userId, {
email: 'user@example.com',
plan: 'pro'
});
// Track checkout event
trackEvent('checkout_completed', {
orderId: '12345',
amount: 99.99,
currency: 'USD',
items: 3,
paymentMethod: 'credit_card'
});
};
return <button onClick={() => handleCheckout('user-123')}>Checkout</button>;
}
Declarative Tracking
Track events using data attributes (no JavaScript required):
<button data-temps-event="button_click" data-temps-button="signup">
Sign Up
</button>
<a
href="/pricing"
data-temps-event="link_click"
data-temps-destination="pricing"
>
View Pricing
</a>
Enriching Visitors with Node SDK
Enrich visitor data with custom metadata from your backend using the Node SDK. This allows you to add user information, subscription details, or any custom data to visitor records.
Why Enrich Visitors?
Visitor enrichment lets you:
- Link anonymous visitors to known users
- Add business context (subscription tier, customer segment)
- Store custom metadata for segmentation
- Improve analytics insights with user data
Enrich Visitor Example
Node.js/TypeScript
import { TempsClient } from '@temps-sdk/node-sdk';
const client = new TempsClient({
baseUrl: 'https://your-temps-instance.com',
apiKey: 'your-api-key'
});
// After user logs in, enrich their visitor record
async function enrichVisitorAfterLogin(
visitorId: string | number, // Can be GUID, numeric ID, or encrypted GUID (enc_xxx)
projectId: number,
userId: string,
userEmail: string
) {
try {
const result = await client.analytics.enrichVisitor({
path: {
visitor_id: typeof visitorId === 'number' ? visitorId : visitorId
},
query: { project_id: projectId },
body: {
custom_data: {
userId: userId,
email: userEmail,
subscriptionTier: 'pro',
signupDate: '2024-01-15',
customerSegment: 'enterprise',
tags: ['vip', 'beta-tester']
}
}
});
console.log('Visitor enriched:', result);
// Response: { success: true, visitor_id: string, message: string }
} catch (error) {
console.error('Failed to enrich visitor:', error);
}
}
Getting Visitor ID from Frontend
To enrich a visitor, you need their visitor ID from the frontend. The visitor ID can be:
- A GUID (e.g.,
"550e8400-e29b-41d4-a716-446655440000") - A numeric ID (e.g.,
123) - An encrypted GUID (e.g.,
"enc_xxx")
React - Get Visitor ID
import { useAnalytics } from '@temps-sdk/react-analytics';
function UserProfile() {
const analytics = useAnalytics();
useEffect(() => {
// Get current visitor ID (returns GUID or numeric ID)
const visitorId = analytics.getVisitorId();
// Send to your backend when user logs in
if (visitorId && user) {
fetch('/api/enrich-visitor', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
visitorId, // Can be string GUID or numeric ID
userId: user.id,
email: user.email
})
});
}
}, [user, analytics]);
return <div>Profile</div>;
}
Backend Integration
Complete example of enriching visitors from your backend:
Backend API Route
// api/enrich-visitor.ts (Next.js API route)
import { TempsClient } from '@temps-sdk/node-sdk';
import type { NextApiRequest, NextApiResponse } from 'next';
const tempsClient = new TempsClient({
baseUrl: process.env.TEMPS_API_URL!,
apiKey: process.env.TEMPS_API_KEY!
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
const { visitorId, userId, email } = req.body;
// Fetch user data from your database
const user = await db.users.findUnique({ where: { id: userId } });
try {
// Enrich visitor with user data
// visitorId can be string (GUID) or number (numeric ID)
const result = await tempsClient.analytics.enrichVisitor({
path: {
visitor_id: typeof visitorId === 'string' ? visitorId : parseInt(visitorId)
},
query: {
project_id: parseInt(process.env.TEMPS_PROJECT_ID!)
},
body: {
custom_data: {
userId: user.id,
email: user.email,
name: user.name,
subscriptionTier: user.subscription?.tier || 'free',
signupDate: user.createdAt.toISOString(),
lastLogin: new Date().toISOString(),
tags: user.tags || []
}
}
});
res.json({
success: true,
message: result.message,
visitorId: result.visitor_id
});
} catch (error: any) {
console.error('Failed to enrich visitor:', error);
res.status(error.status || 500).json({
error: error.message || 'Failed to enrich visitor'
});
}
}
Use Cases
- Name
User Identification- Description
Link anonymous visitors to known users after login:
const result = await client.analytics.enrichVisitor({ path: { visitor_id: visitorId // string GUID or number }, query: { project_id: 1 }, body: { custom_data: { userId: user.id, email: user.email, name: user.name } } }); // Returns: { success: true, visitor_id: string, message: string }
- Name
Subscription Context- Description
Add subscription information for segmentation:
await client.analytics.enrichVisitor({ path: { visitor_id: visitorId }, query: { project_id: 1 }, body: { custom_data: { subscriptionTier: 'enterprise', subscriptionStatus: 'active', monthlySpend: 999.99, features: ['analytics', 'api-access', 'priority-support'] } } });
- Name
Customer Segmentation- Description
Add tags and segments for analysis:
await client.analytics.enrichVisitor({ path: { visitor_id: visitorId }, query: { project_id: 1 }, body: { custom_data: { segment: 'high-value', tags: ['enterprise', 'beta', 'early-adopter'], acquisitionChannel: 'organic', lifetimeValue: 5000 } } });
Querying Enriched Visitors
After enriching visitors, you can query them to see the custom data:
Query Enriched Visitors
// Get specific visitor details (includes custom_data)
const visitor = await client.analytics.getVisitorDetails({
path: {
visitor_id: 'visitor-guid' // or numeric ID
},
query: { project_id: 1 }
});
// Access enriched custom data
console.log(visitor.custom_data);
// Output: { userId: '123', email: 'user@example.com', ... }
// Get visitor by numeric ID
const visitorById = await client.analytics.getVisitorById({
path: { id: 123 },
query: { project_id: 1 }
});
// Get visitor by GUID
const visitorByGuid = await client.analytics.getVisitorByGuid({
path: { visitor_id: '550e8400-e29b-41d4-a716-446655440000' },
query: { project_id: 1 }
});
// List all visitors (with pagination)
const visitors = await client.analytics.getVisitors({
query: {
project_id: 1,
limit: 50,
offset: 0
}
});
// Each visitor in the list includes custom_data if enriched
visitors.forEach(v => {
if (v.custom_data) {
console.log(`Visitor ${v.visitor_id}:`, v.custom_data);
}
});
Privacy & Compliance
Temps analytics is designed with privacy in mind and complies with GDPR, CCPA, and other regulations.
Data Ownership
- Name
Self-Hosted- Description
All data stays on your infrastructure—no data sent to third parties
- Name
No Cookies- Description
IP-based tracking (no tracking cookies required)
- Name
Anonymization- Description
IP address hashing and anonymization options
- Name
Data Retention- Description
Configurable retention policies (30/90/180/365 days, or custom)
- Name
Right to Erasure- Description
User data deletion via API or dashboard
- Name
Data Export- Description
Export user data in JSON/CSV format
GDPR Compliance
GDPR Configuration
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';
function App() {
const [consent, setConsent] = useState(false);
return (
<TempsAnalyticsProvider
disabled={!consent} // Only track if user consents
>
<CookieBanner onAccept={() => setConsent(true)} />
<YourApp />
</TempsAnalyticsProvider>
);
}
Compliance Features
GDPR
- User consent management
- Right to access data
- Right to erasure
- Data portability
- Privacy by design
CCPA
- Do Not Sell disclosure
- Opt-out mechanisms
- Data access requests
- Data deletion requests