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.
| Need | Package | Reference |
|---|---|---|
| Analytics, Web Vitals and session replay in React / Next.js | @temps-sdk/react-analytics | React Analytics SDK, Session Replay |
| Analytics in plain HTML, Vue or Svelte | @temps-sdk/analytics-browser, vue-analytics, svelte-analytics | Sections below |
| Error tracking | Official Sentry SDKs, or ErrorTracking in @temps-sdk/node-sdk | Error Tracking |
| Calling the Temps API, feature flags | @temps-sdk/node-sdk | Node SDK |
| Key-value storage | @temps-sdk/kv | KV Storage |
| File storage | @temps-sdk/blob | Blob 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.
| Package | Use for | Install |
|---|---|---|
@temps-sdk/react-analytics | React / Next.js apps | npm install @temps-sdk/react-analytics |
@temps-sdk/analytics-browser | Plain HTML pages, Astro islands, non-React SPAs | npm install @temps-sdk/analytics-browser |
@temps-sdk/vue-analytics | Vue 3 apps | npm install @temps-sdk/vue-analytics |
@temps-sdk/svelte-analytics | Svelte 4 / 5 and SvelteKit apps | npm install @temps-sdk/svelte-analytics |
@temps-sdk/analytics-core | Building your own framework adapter | npm 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 declarativetemps-event-nameattribute - 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
enableSessionRecordingand tune it withsessionRecordingConfig:
<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:
| Attribute | Type | Description |
|---|---|---|
data-domain | string | Override window.location.hostname |
data-base-path | string | Endpoint path (default /api/_temps) |
data-disabled | true / false | Disable entirely |
data-ignore-localhost | true / false | Skip localhost (default true) |
data-auto-track-pageviews | true / false | Auto-track route changes |
data-auto-track-page-leave | true / false | Track page_leave events |
data-auto-track-speed-analytics | true / false | Track Web Vitals |
data-auto-track-engagement | true / false | Heartbeat engagement tracking |
data-session-recording | true / false | Enable rrweb session recording |
data-excluded-paths | comma list | Extra paths to skip for recording, supports * (added to the built-in sign-in, checkout and payment exclusions) |
data-session-sample-rate | 0–1 | Fraction of sessions to record |
data-mask-all-inputs | true / false | Mask input values in recordings (default true) |
data-page-leave-event-name | string | Custom name for the page-leave event |
data-heartbeat-interval | number (ms) | Heartbeat interval |
data-inactivity-timeout | number (ms) | Inactivity timeout |
data-engagement-threshold | number (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
nullif 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
-1if 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
Responseobject.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:
| SDK | Reads | Notes |
|---|---|---|
@temps-sdk/kv, @temps-sdk/blob | TEMPS_API_URL, TEMPS_TOKEN, TEMPS_PROJECT_ID | apiUrl 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 TempsClient | Nothing | Pass baseUrl (ending in /api) and apiKey explicitly. |
@temps-sdk/node-sdk flags | TEMPS_API_URL, TEMPS_API_TOKEN | Zero 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