Temps SDKs

Temps has three kinds of SDK: browser analytics SDKs (React, Vue, Svelte, plain JavaScript), the Node.js SDK for the Temps API and server-side error tracking, and KV and Blob storage clients. Browser error tracking uses the official Sentry SDKs pointed at your Temps DSN. This page helps you pick a package; each section links to its full reference.

NeedPackageReference
Analytics, Web Vitals and session replay in React / Next.js@temps-sdk/react-analyticsReact Analytics SDK, Session Replay
Analytics in plain HTML, Vue or Svelte@temps-sdk/analytics-browser, vue-analytics, svelte-analyticsSections below
Error trackingOfficial Sentry SDKs, or ErrorTracking in @temps-sdk/node-sdkError Tracking
Calling the Temps API, feature flags@temps-sdk/node-sdkNode SDK
Key-value storage@temps-sdk/kvKV Storage
File storage@temps-sdk/blobBlob storage

Analytics SDKs overview

Temps provides analytics SDKs for every major frontend runtime. They all capture the same signals — pageviews, custom events, Web Vitals, engagement heartbeats, page-leave events, and optional session recording — and send them to the same /api/_temps endpoints on your Temps instance.

PackageUse forInstall
@temps-sdk/react-analyticsReact / Next.js appsnpm install @temps-sdk/react-analytics
@temps-sdk/analytics-browserPlain HTML pages, Astro islands, non-React SPAsnpm install @temps-sdk/analytics-browser
@temps-sdk/vue-analyticsVue 3 appsnpm install @temps-sdk/vue-analytics
@temps-sdk/svelte-analyticsSvelte 4 / 5 and SvelteKit appsnpm install @temps-sdk/svelte-analytics
@temps-sdk/analytics-coreBuilding your own framework adapternpm install @temps-sdk/analytics-core

Every SDK builds on the framework-agnostic @temps-sdk/analytics-core, so the payload shape, localhost detection and retry logic are the same across frameworks. One difference: the script tag (and other core-based recorders) skips a built-in list of sign-in, checkout and payment paths during session recording, while the React provider (0.0.4) uses its own recorder with no built-in exclusions. Pick the package that matches your stack.

What gets tracked by default? Pageviews (on route change), Web Vitals (the Core Web Vitals LCP, INP and CLS, plus FCP, TTFB and the deprecated FID), engagement heartbeats (every 30s while active), and a page_leave event on unload. Session recording is opt-in via enableSessionRecording.


React analytics

Track pageviews, custom events, performance metrics, and session replays in your React applications.

Installation

npm install @temps-sdk/react-analytics

Quick Start

import { TempsAnalyticsProvider, useTrackEvent } from '@temps-sdk/react-analytics';

function App() {
  return (
    <TempsAnalyticsProvider>
      <YourApp />
    </TempsAnalyticsProvider>
  );
}

function YourComponent() {
  const trackEvent = useTrackEvent();

  const handleClick = () => {
    trackEvent('button_clicked', {
      buttonId: 'cta-button',
      location: 'homepage'
    });
  };

  return <button onClick={handleClick}>Click me</button>;
}

What it covers

  • Pageviews and page exits, tracked automatically on route changes (autoTrackPageviews, autoTrackPageLeave)
  • Custom events with useTrackEvent() or the declarative temps-event-name attribute
  • Web Vitals: the Core Web Vitals (LCP, INP, CLS) plus FCP, TTFB and the deprecated FID (autoTrackSpeedAnalytics, on by default)
  • Engagement heartbeats and element visibility (useEngagementTracking, useScrollVisibility)
  • Session replay, off by default. Turn it on with enableSessionRecording and tune it with sessionRecordingConfig:
<TempsAnalyticsProvider
  enableSessionRecording
  sessionRecordingConfig={{ sessionSampleRate: 0.1 }} // record 10% of sessions
>
  {children}
</TempsAnalyticsProvider>

Inputs are masked by default (maskAllInputs: true), and replay records DOM snapshots and input only, not console or network activity. Privacy controls and consent patterns are in Session Replay.

Full reference → every provider prop, hook and default is documented in the React Analytics SDK reference.

Next.js Integration

App Router:

// app/layout.tsx
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <TempsAnalyticsProvider>
          {children}
        </TempsAnalyticsProvider>
      </body>
    </html>
  );
}

Pages Router:

// pages/_app.tsx
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';

export default function App({ Component, pageProps }) {
  return (
    <TempsAnalyticsProvider>
      <Component {...pageProps} />
    </TempsAnalyticsProvider>
  );
}

Vanilla JS analytics

Framework-free analytics for plain HTML pages, Astro islands, Alpine.js, htmx, or any JS runtime without a framework wrapper.

Installation

npm install @temps-sdk/analytics-browser

Quick Start (programmatic)

import { init, trackEvent } from '@temps-sdk/analytics-browser';

// Boot once, typically in your entry file
init({
  autoTrackPageviews: true,
  autoTrackSpeedAnalytics: true,
  autoTrackEngagement: true,
});

// Later, anywhere
trackEvent('signup_clicked', { plan: 'pro' });

init() returns an AnalyticsApi and also attaches it to window.temps so other scripts can call window.temps.trackEvent(...) without importing.

Quick Start (script tag)

Drop-in for static sites — no bundler required. The CDN bundle reads optional data-* attributes from its own <script> tag and boots on DOMContentLoaded:

<script
  defer
  src="https://unpkg.com/@temps-sdk/analytics-browser@0.0.6/dist/temps.min.js"
></script>

By default, the script sends events to the current site's relative /api/_temps/* endpoints. For apps deployed on Temps, the proxy handles those endpoints automatically. For apps hosted elsewhere, add a same-origin rewrite for /api/_temps/* to your Temps instance.

Enable session replay or other overrides with data-* attributes:

<script
  defer
  src="https://unpkg.com/@temps-sdk/analytics-browser@0.0.6/dist/temps.min.js"
  data-session-recording="true"
  data-excluded-paths="/admin/*,/internal/*"
></script>

Supported data-* attributes:

AttributeTypeDescription
data-domainstringOverride window.location.hostname
data-base-pathstringEndpoint path (default /api/_temps)
data-disabledtrue / falseDisable entirely
data-ignore-localhosttrue / falseSkip localhost (default true)
data-auto-track-pageviewstrue / falseAuto-track route changes
data-auto-track-page-leavetrue / falseTrack page_leave events
data-auto-track-speed-analyticstrue / falseTrack Web Vitals
data-auto-track-engagementtrue / falseHeartbeat engagement tracking
data-session-recordingtrue / falseEnable rrweb session recording
data-excluded-pathscomma listExtra paths to skip for recording, supports * (added to the built-in sign-in, checkout and payment exclusions)
data-session-sample-rate0–1Fraction of sessions to record
data-mask-all-inputstrue / falseMask input values in recordings (default true)
data-page-leave-event-namestringCustom name for the page-leave event
data-heartbeat-intervalnumber (ms)Heartbeat interval
data-inactivity-timeoutnumber (ms)Inactivity timeout
data-engagement-thresholdnumber (ms)When a session becomes "engaged"

API

import {
  init,
  getAnalytics,
  trackEvent,
  trackPageview,
  destroy,
} from '@temps-sdk/analytics-browser';

init(options);                // Boot. Safe to call once per page.
getAnalytics();               // Returns the current AnalyticsApi; throws if init() wasn't called.
trackEvent(name, data?);      // Async — fires and forgets.
trackPageview();              // Manual pageview. Usually not needed with auto-tracking.
destroy();                    // Tear down listeners, timers, and session recorder.

Vue analytics

First-class Vue 3 support via a plugin + composables. Works with Nuxt, Vite, and any Vue 3 SPA.

Installation

npm install @temps-sdk/vue-analytics

Quick Start

// main.ts
import { createApp } from 'vue';
import { TempsAnalyticsPlugin } from '@temps-sdk/vue-analytics';
import App from './App.vue';

const app = createApp(App);

app.use(TempsAnalyticsPlugin, {
  basePath: '/api/_temps',
  autoTrackPageviews: true,
  enableSessionRecording: false,
});

app.mount('#app');

Composables

<script setup lang="ts">
import {
  useTempsAnalytics,
  useTrackEvent,
  useTrackPageview,
  usePageLeave,
  useEngagementTracking,
  useScrollVisibility,
  useSessionRecording,
} from '@temps-sdk/vue-analytics';

// Raw API
const analytics = useTempsAnalytics();

// Convenience helpers
const trackEvent = useTrackEvent();
const trackPageview = useTrackPageview();

function onCtaClick() {
  trackEvent('cta_clicked', { location: 'hero' });
}

// Track when the current page is about to be left
usePageLeave((data) => {
  console.log('Leaving with engagement:', data.engagement_time_seconds);
});

// Reactive engagement signal
const { engagement, isEngaged } = useEngagementTracking();

// Scroll visibility for a ref
import { ref } from 'vue';
const pricingSection = ref<HTMLElement | null>(null);
useScrollVisibility(pricingSection, () => {
  trackEvent('pricing_viewed');
});

// Session recording toggle
const { isEnabled, enable, disable, toggle } = useSessionRecording();
</script>

<template>
  <button @click="onCtaClick">Get started</button>
  <section ref="pricingSection">…</section>
</template>

Global property

The plugin also registers $temps as a global property for Options API components:

<script>
export default {
  methods: {
    handleClick() {
      this.$temps.trackEvent('legacy_button');
    },
  },
};
</script>

Nuxt 3

In plugins/temps.client.ts:

import { TempsAnalyticsPlugin } from '@temps-sdk/vue-analytics';

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(TempsAnalyticsPlugin, {
    basePath: '/api/_temps',
  });
});

Svelte analytics

Store-based analytics for Svelte 4, Svelte 5 runes mode, and SvelteKit.

Installation

npm install @temps-sdk/svelte-analytics

Quick Start

// src/lib/analytics.ts
import { initTempsAnalytics } from '@temps-sdk/svelte-analytics';

export const analytics = initTempsAnalytics({
  basePath: '/api/_temps',
  autoTrackPageviews: true,
  autoTrackSpeedAnalytics: true,
});

Call initTempsAnalytics() once in your root layout (browser-only — wrap in if (browser) on SvelteKit):

<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { browser } from '$app/environment';
  import { onMount } from 'svelte';
  import { initTempsAnalytics } from '@temps-sdk/svelte-analytics';

  onMount(() => {
    if (browser) {
      initTempsAnalytics({ basePath: '/api/_temps' });
    }
  });
</script>

<slot />

Tracking events

<script lang="ts">
  import { getTempsAnalytics } from '@temps-sdk/svelte-analytics';

  function onClick() {
    getTempsAnalytics()?.trackEvent('hero_cta_clicked', { variant: 'a' });
  }
</script>

<button on:click={onClick}>Get started</button>

The trackVisibility action

Fire an event when an element scrolls into view:

<script lang="ts">
  import { trackVisibility } from '@temps-sdk/svelte-analytics';
</script>

<section
  use:trackVisibility={{
    eventName: 'pricing_viewed',
    once: true,
    threshold: 0.5,
    data: { section: 'pricing' },
  }}
>
  <h2>Pricing</h2>
</section>

Engagement store

<script lang="ts">
  import { engagementStore } from '@temps-sdk/svelte-analytics';
  const engagement = engagementStore();
</script>

<p>Engagement: {$engagement.engagement_time_seconds}s</p>
{#if $engagement.is_engaged}
  <span>Active visitor</span>
{/if}

Session recording store

<script lang="ts">
  import { sessionRecordingStore } from '@temps-sdk/svelte-analytics';
  const recording = sessionRecordingStore();
</script>

<button on:click={recording.toggle}>
  {$recording.enabled ? 'Stop' : 'Start'} recording
</button>

analyticsStore readable

A Svelte readable that resolves to the current AnalyticsApi (or null before init completes). Handy for reactive templates:

<script lang="ts">
  import { analyticsStore } from '@temps-sdk/svelte-analytics';
</script>

{#if $analyticsStore}
  <p>Analytics ready on {$analyticsStore.enabled ? 'prod' : 'local'}</p>
{/if}

Analytics core

@temps-sdk/analytics-core is the framework-agnostic engine behind the React, Vue, Svelte, and vanilla packages. Use it directly only when building a custom integration (Solid, Qwik, Preact, Web Components, etc.).

Installation

npm install @temps-sdk/analytics-core

API

import {
  createAnalytics,
  EngagementTracker,
  SpeedTracker,
  SessionRecorder,
  sendAnalytics,
  sendAnalyticsReliable,
  DEFAULT_BASE_PATH,
  type AnalyticsApi,
  type AnalyticsOptions,
  type EngagementData,
  type SpeedMetric,
} from '@temps-sdk/analytics-core';

const analytics: AnalyticsApi = createAnalytics({
  basePath: DEFAULT_BASE_PATH, // "/api/_temps"
  autoTrackPageviews: true,
  autoTrackSpeedAnalytics: true,
  autoTrackEngagement: true,
  enableSessionRecording: false,
});

analytics.trackEvent('custom_event', { foo: 'bar' });
analytics.trackPageview();
analytics.enableSessionRecording();
// When your app unmounts
analytics.destroy();

Building your own adapter

The individual trackers are standalone classes:

import { EngagementTracker, SpeedTracker, SessionRecorder } from '@temps-sdk/analytics-core';

const engagement = new EngagementTracker({
  basePath: '/api/_temps',
  heartbeatInterval: 30000,
  onHeartbeat: (data) => console.log('beat', data),
});

const speed = new SpeedTracker({ basePath: '/api/_temps' });

const session = new SessionRecorder({
  basePath: '/api/_temps',
  enabled: true,
  excludedPaths: ['/admin/*'],
});
session.start();

// Later
engagement.destroy();
speed.destroy();
session.destroy();

All trackers are safe to call in SSR contexts — they no-op when window is undefined.


Node.js SDK

@temps-sdk/node-sdk is the server-side SDK for Node.js and Bun. It has a typed client for the Temps REST API (25 namespaces, generated from the OpenAPI spec), a Sentry-compatible ErrorTracking client and a feature-flag reader.

Installation

npm install @temps-sdk/node-sdk

Quick Start

import { TempsClient } from '@temps-sdk/node-sdk';

const client = new TempsClient({
  baseUrl: 'https://your-temps-instance.com/api', // include the /api prefix
  apiKey: process.env.TEMPS_API_KEY,
});

// List projects (calls return { data, error, response } and don't throw on HTTP errors)
const { data: projects } = await client.projects.list();

// Trigger a deployment of the main branch
await client.projects.triggerPipeline({
  path: { id: 1 },
  body: { branch: 'main' },
});

Every method takes one options object with path, query and body fields that mirror the REST endpoint. baseUrl must end in /api, because the client's paths (such as /projects/{id}) are served under that prefix. TempsClient reads no environment variables: pass baseUrl and apiKey yourself. Apps deployed on Temps get TEMPS_API_URL (already ending in /api) and a project-scoped TEMPS_API_TOKEN injected, which you can pass straight through.

Full reference → the namespace list, ErrorTracking options, visitor enrichment and feature flags are documented in the Node SDK reference.


Error tracking

Temps error tracking speaks the Sentry protocol, so there is no separate Temps error SDK for the browser: point the official Sentry SDK for your platform (@sentry/react, @sentry/nextjs, sentry-sdk for Python, sentry-go and so on) at your project's DSN. Setup, source maps and grouping are covered in Error Tracking.

For server-side Node.js and Bun code you can use the ErrorTracking namespace in @temps-sdk/node-sdk instead:

import { ErrorTracking } from '@temps-sdk/node-sdk';

ErrorTracking.init({ dsn: process.env.SENTRY_DSN!, environment: 'production' });

try {
  await riskyOperation();
} catch (error) {
  ErrorTracking.captureException(error);
}

See Node SDK: error tracking for every option.


Key-value store

@temps-sdk/kv is a small client for Temps KV, a Redis-style key-value store for caching, sessions and counters. Full reference → the HTTP API, limits and setup are documented in KV Storage.

Installation

npm install @temps-sdk/kv

Quick Start

import { kv, createClient } from '@temps-sdk/kv';

// Using default client (uses env vars)
await kv.set('user:123', { name: 'John', email: 'john@example.com' });
const user = await kv.get('user:123');
await kv.del('user:123');

// With expiration
await kv.set('session:abc', sessionData, { ex: 3600 }); // 1 hour

// Increment counter
const count = await kv.incr('page:views');

// Pattern matching
const keys = await kv.keys('user:*');

Custom Client

import { createClient } from '@temps-sdk/kv';

const client = createClient({
  apiUrl: 'https://your-temps-instance.com',
  token: 'your-deployment-token',
  projectId: 1 // Required for API keys, optional for deployment tokens
});

await client.set('key', 'value');
const value = await client.get('key');

API Reference

  • Name
    get<T>(key)
    Description

    Get the value of a key. Returns null if key doesn't exist.

    const value = await kv.get<string>('my-key');
    
  • Name
    set(key, value, options?)
    Description

    Set a key-value pair. Supports expiration.

    await kv.set('key', 'value');
    await kv.set('key', 'value', { ex: 60 }); // Expire in 60 seconds
    
  • Name
    del(...keys)
    Description

    Delete one or more keys. Returns count of deleted keys.

    await kv.del('key1', 'key2', 'key3');
    
  • Name
    incr(key)
    Description

    Increment a numeric value. Returns new value.

    const count = await kv.incr('counter');
    
  • Name
    expire(key, seconds)
    Description

    Set expiration on an existing key.

    await kv.expire('key', 3600); // Expire in 1 hour
    
  • Name
    ttl(key)
    Description

    Get time-to-live of a key. Returns seconds remaining or -1 if no expiration.

    const ttl = await kv.ttl('key');
    
  • Name
    keys(pattern)
    Description

    Find keys matching a pattern (supports * wildcard).

    const userKeys = await kv.keys('user:*');
    

Use Cases

Session Storage:

// Store session
await kv.set(`session:${sessionId}`, sessionData, { ex: 86400 }); // 24 hours

// Retrieve session
const session = await kv.get(`session:${sessionId}`);

Rate Limiting:

const key = `rate:${userId}`;
const count = await kv.incr(key);
if (count === 1) {
  await kv.expire(key, 60); // Set expiration on first increment
}
if (count > 100) {
  throw new Error('Rate limit exceeded');
}

Caching:

const cacheKey = `cache:${query}`;
let result = await kv.get(cacheKey);

if (!result) {
  result = await expensiveOperation();
  await kv.set(cacheKey, result, { ex: 300 }); // Cache for 5 minutes
}

Blob storage

SDK for Temps Blob storage—upload, download, and manage files and binary data.

Installation

npm install @temps-sdk/blob

Quick Start

import { blob, createClient } from '@temps-sdk/blob';

// Upload a file
const result = await blob.put('uploads/image.jpg', fileBuffer, {
  contentType: 'image/jpeg'
});
console.log(result.url); // Public URL

// Download a file
const response = await blob.download(result.url);
const data = await response.arrayBuffer();

// List files
const list = await blob.list({ prefix: 'uploads/', limit: 10 });

// Delete files
await blob.del(result.url);

Custom Client

import { createClient } from '@temps-sdk/blob';

const client = createClient({
  apiUrl: 'https://your-temps-instance.com',
  token: 'your-deployment-token',
  projectId: 1 // Required for API keys
});

await client.put('path/to/file.txt', 'content');

API Reference

  • Name
    put(pathname, body, options?)
    Description

    Upload a blob. Returns URL and metadata.

    const result = await blob.put('uploads/file.txt', 'content', {
      contentType: 'text/plain',
      addRandomSuffix: false
    });
    

    Body types: string, Uint8Array, Blob, ArrayBuffer

  • Name
    download(url)
    Description

    Download a blob. Returns Response object.

    const response = await blob.download(url);
    const text = await response.text();
    const buffer = await response.arrayBuffer();
    
  • Name
    head(url)
    Description

    Get blob metadata without downloading content.

    const metadata = await blob.head(url);
    console.log(metadata.size, metadata.contentType);
    
  • Name
    list(options?)
    Description

    List blobs with pagination and filtering.

    const result = await blob.list({
      prefix: 'uploads/',
      limit: 50,
      cursor: 'next-page-token'
    });
    
  • Name
    del(urls)
    Description

    Delete one or more blobs by URL.

    await blob.del(url);
    await blob.del([url1, url2, url3]);
    
  • Name
    copy(fromUrl, toPathname)
    Description

    Copy a blob to a new location.

    const newBlob = await blob.copy(oldUrl, 'new/path/file.txt');
    

Use Cases

File Upload:

// Upload from form
const formData = new FormData();
formData.append('file', fileInput.files[0]);

const file = await fileInput.files[0].arrayBuffer();
const result = await blob.put(`uploads/${filename}`, file, {
  contentType: fileInput.files[0].type
});

Image Processing:

// Upload image
const imageResult = await blob.put('images/photo.jpg', imageBuffer, {
  contentType: 'image/jpeg'
});

// Later, copy to processed folder
await blob.copy(imageResult.url, 'processed/photo.jpg');

File Management:

// List all files in a directory
const files = await blob.list({ prefix: 'documents/' });

// Delete old files
const oldFiles = files.blobs.filter(f =>
  new Date(f.uploadedAt) < new Date('2026-01-01')
);
await blob.del(oldFiles.map(f => f.url));

Environment Variables

Each server-side SDK reads configuration differently:

SDKReadsNotes
@temps-sdk/kv, @temps-sdk/blobTEMPS_API_URL, TEMPS_TOKEN, TEMPS_PROJECT_IDapiUrl is the instance root, without /api (the SDK adds /api/kv/... or /api/blob/...). TEMPS_PROJECT_ID is only needed with an API key.
@temps-sdk/node-sdk TempsClientNothingPass baseUrl (ending in /api) and apiKey explicitly.
@temps-sdk/node-sdk flagsTEMPS_API_URL, TEMPS_API_TOKENZero configuration on Temps.

Apps deployed on Temps get TEMPS_API_URL (ending in /api) and TEMPS_API_TOKEN, a deployment token for the project, injected automatically. The KV and Blob SDKs look for TEMPS_TOKEN and an instance root without /api, so on Temps pass the values explicitly:

import { createClient } from '@temps-sdk/kv';

const kv = createClient({
  apiUrl: process.env.TEMPS_API_URL!.replace(/\/api$/, ''),
  token: process.env.TEMPS_API_TOKEN,
});

Error Handling

The KV and Blob SDKs throw typed errors with an optional code and HTTP status:

import { kv, KVError } from '@temps-sdk/kv';
import { BlobError } from '@temps-sdk/blob';

try {
  await kv.set('key', 'value');
} catch (error) {
  if (error instanceof KVError) {
    console.error('KV Error:', error.message, error.status, error.code);
  }
}

TempsClient in the Node SDK does not throw on HTTP errors; it returns { data, error, response }. See API Errors.


TypeScript Support

All SDKs are written in TypeScript and ship their type definitions:

// KV values are typed by the caller
const user = await kv.get<{ name: string; email: string }>('user:123');
// user is { name: string; email: string } | null

// Node SDK request and response types are generated from the OpenAPI spec
const { data: project } = await client.projects.get({ path: { id: 1 } });
// project is ProjectResponse | undefined

Last updated

Was this page helpful?