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

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

Additional Resources

Was this page helpful?