@paczesny/analytics
v0.6.0
Published
Cookieless, privacy-first analytics tracker — one component, < 3KB.
Readme
@paczesny/analytics
Cookieless, privacy-first analytics tracker. One component, ~2.4 KB gzip, no cookies, no consent banner.
Install
pnpm add @paczesny/analyticsUsage (Next.js App Router)
// app/layout.tsx
import { Analytics } from "@paczesny/analytics";
export default function RootLayout({ children }) {
return (
<html lang="pl">
<body>
{children}
<Analytics siteId="abc123" />
</body>
</html>
);
}That's it. Page views (including client-side route changes), scroll depth, clicks, rage/dead clicks, JS errors and outbound/download clicks are captured automatically and sent in batches.
Custom events
import { track } from "@paczesny/analytics";
track("signup", { plan: "pro" });Props
| Prop | Type | Default | Description |
| --------------- | --------- | ----------------------------- | -------------------------------------------- |
| siteId | string | — | Required. Public site identifier. |
| apiHost | string | hosted ingest URL | Ingestion endpoint. |
| sampleRate | number | 1 | 0..1 sampling for high-volume click events.|
| trackOutbound | boolean | true | Track outbound links and file downloads. |
| debug | boolean | false | Log captured events to the console. |
Non-React usage
import { init, track } from "@paczesny/analytics";
init({ siteId: "abc123" });
track("cta_click");Plain <script> tag (no bundler, no React) — recommended for arbitrary sites
For sites that are not built with a React bundler, use the standalone build instead of importing the ESM package off a public CDN. It is a single self-contained file — there is no React and no runtime import chain — so you can pin it with Subresource Integrity (SRI) and, ideally, host it from your own origin.
<script
defer
src="https://analytics.blonie.cloud/t/0.5.0/paczesny-analytics.min.js"
integrity="sha384-clMVel4vBqb1PqSU0oIpBaWQbPHRKJEngX4T7G3rz13j7pBRwdHQvK+ouYtI8+ub"
crossorigin="anonymous"
data-site-id="abc123"></script>Optional attributes: data-api-host, data-sample-rate,
data-track-outbound="false", data-debug="true". Custom events afterwards:
window.paczesny.track("signup", { plan: "pro" });Self-host (best for login / sensitive / regulated pages)
Loading any third-party script on a page that handles credentials or sensitive data is a credential-skimming risk. To avoid a third-party origin in your CSP entirely:
- Download
paczesny-analytics.min.js(the URL above) and serve it from your own origin, e.g./paczesny-analytics.min.js. - Reference that first-party path in the
<script>tag, keeping the sameintegrityhash. - Your CSP then only needs
script-src 'self'— no external script origin.
Do not load this via
https://esm.sh/@paczesny/analytics. That pullsreactas a version-ranged ESM sub-import, requires the wholeesm.shorigin in your CSP, and cannot be covered by SRI.
Privacy
- No cookies, no persistent identifiers.
sessionIdis generated in memory and resets when the tab closes.- The client never computes a visitor id and never sends the IP — the backend
derives a daily-rotating
visitorIdso users cannot be tracked across days.
What gets collected
pageview, scroll (25/50/75/100%), click (sampled, normalized coords +
stable selector), rage_click, dead_click, error, outbound, download,
custom, session_end.
Transport
Events are queued in memory and flushed every 5s or when the buffer hits 20
events. On pagehide/visibilitychange the batch is sent with
navigator.sendBeacon (falling back to fetch with keepalive). Analytics
never throws into the host page.
