Spoar

Overview

Privacy-first web analytics you host yourself, with a typed SDK and one API for ingest, reads and sign-in.

Spoar records pageviews, custom events, errors and Core Web Vitals from your sites and apps, and stores them in a Postgres database you run. It sets no cookies for visitors and never stores raw IP addresses.

It has three parts:

PartWhat it is
SDK@spoar/sdk: a browser client, plugins, and React, Next, server and proxy entries. ESM only
APIOne Elysia service under /v2: ingest, aggregate and visitor-level reads, speed insights, error tracking, a read-only SQL console, sign-in, projects and tokens
DatabasePostgres (Neon in production). Every read goes through the API

What it runs on

The browser core has no framework dependency. Anything that bundles ES modules can use it, and the framework entries add conveniences on top. Frameworks has a setup page per stack.

StackWhat you use
Next.js 15 or laterThe core, /react and /next for route templates, /proxy for the /_ra route, /server in route handlers and server actions
React 19 with any routerThe core and /react. Pageviews follow pushState routers without extra code
Vite, vanilla TypeScript or JavaScriptThe core and plugins
Vue, Svelte and SvelteKit, AstroThe core and plugins
Solid, PreactThe core and plugins. Dedicated guides are coming soon
Node, Bun, Deno, Vercel Functions, Cloudflare Workers/server and /proxy, on any runtime with fetch and the standard Request and Response
Any other languagePOST /v2/events with a secret key, as described in the API reference

There is no <script src> snippet and no CommonJS build.

How data flows

  1. The SDK batches events in the browser and sends them to /v2/events, directly or through a same-origin proxy path such as /_ra.
  2. The API checks the key and origin, scores bots, enriches the event with geo, device and channel, and stores it. Raw IP addresses are never stored; a daily salted hash is used for rate limits and visitor counting.
  3. Reads, exports and the SQL console answer from the same tables, with access decided per project and per caller.

How it works describes each step in detail.

Where to start

On this page