# @shipabase/js > Privacy-first product analytics SDK (GDPR, no cookies, no localStorage, EU-hosted). Zero dependencies, ~2 kB gzipped. Four functions: `init(appKey, options?)`, `trackEvent(name, props?)`, `trackPageview(path?)`, `flush()`. Browser/universal entry: `@shipabase/js`. Node entry: `@shipabase/js/node`. Follow these rules when adding Shipabase to a project. ## Install - Use the project's package manager: `npm i @shipabase/js`, `pnpm add @shipabase/js`, `yarn add @shipabase/js` or `bun add @shipabase/js`. - The app key looks like `SB-EU-` followed by 10 lowercase letters or digits. Read it from an env var and never hardcode a guess. If the user hasn't given one, ask for it or leave a clearly named env var (it comes from the Shipabase dashboard). ## Where to call init (exactly once) - Next.js App Router: create `app/providers.tsx` with `"use client"`. Call `init(process.env.NEXT_PUBLIC_SHIPABASE_KEY!, { appVersion })` inside `useEffect(() => {...}, [])`, and wrap `{children}` in `app/layout.tsx` with ``. Don't call `init` or `trackEvent` in Server Components, route handlers or during render. Importing the package on the server is safe, though. - Next.js Pages Router: call it in `useEffect` in `pages/_app.tsx`. - Vite (React/Vue/Svelte/Solid): call `init(import.meta.env.VITE_SHIPABASE_KEY)` at the top of `src/main.ts(x)`, before rendering. - React Native / Expo: call `init(process.env.EXPO_PUBLIC_SHIPABASE_KEY)` once at startup (root layout), then `trackPageview(pathname)` on every screen change (Expo Router: `usePathname()` in a `useEffect`; React Navigation: `onStateChange` of `NavigationContainer`). - Node (servers, CLIs, workers, scripts): `import { init, trackEvent, flush } from "@shipabase/js/node"`. Call `init(process.env.SHIPABASE_KEY)` at startup. In short-lived processes, `await flush()` before exit. - Options: `{ host?, appVersion?, isDebug?, flushInterval?, pageviews? }`. `isDebug` is set automatically on localhost and when `NODE_ENV=development`, so don't set it manually unless asked. ## Event naming - Use `snake_case` in `object_verb` form, past tense: `timer_started`, `project_created`, `invoice_sent`, `checkout_completed`, `signup_completed`. - Allowed characters are `[A-Za-z0-9_.:-]`, up to 64 chars. Names must be constant strings, never built from user data. - Track meaningful user actions (activation, core feature usage, conversion). Don't track every click or render. 5–15 events is typical. - Page views are automatic in the browser: the SDK sends `page_viewed` with the current path on load and on every route change. Don't track them yourself, and don't add a `path` prop (every event already carries its page). Disable with `init(key, { pageviews: false })`; for hash routers or mobile screens, call `trackPageview(path)`. The server drops query strings and replaces IDs in paths with `:id`. ## Props - Max 20 keys. Keys are at most 40 chars. Values are string (≤ 200 chars), finite number or boolean. No nested objects or arrays; invalid props are silently dropped. - Good props: `plan: "pro"`, `minutes: 25`, `source: "onboarding"`, `success: true`, `count: 3`. - NEVER put personal data in props, because GDPR forbids it: no emails, names, usernames, user IDs, account IDs, phone numbers, IP addresses, addresses, tokens, or free text typed by users. The server already derives an anonymous daily visitor hash and country. - Never add cookies, localStorage or custom identifiers alongside this SDK. ## Behavior - `trackEvent` never throws, so there's no need for try/catch. Calls before `init` are ignored. - Events are batched (25 max per request), sent every 5 s, and sent with `navigator.sendBeacon` when the page is hidden or closed. ## Verify 1. Run the app locally and trigger one tracked action. Local events are flagged `isDebug: true`. 2. Open the Shipabase dashboard, then the app's **Setup** page. It shows the first event as soon as it arrives. In other views, enable the "debug" toggle to see local events. 3. If nothing shows up, check the browser console for a `[shipabase]` warning (an invalid key or event name) and the Network tab for a `POST /v1/events` returning `202`. ## Docs - [README](https://www.npmjs.com/package/@shipabase/js): full API reference and privacy notes ## All docs pages (Markdown) Full docs in one file: https://shipabase.dev/llms-full.txt ### Get started - [Introduction](https://shipabase.dev/docs.md): Privacy-first product analytics for the apps you ship. Add it by hand in five minutes, or let your coding agent do it. - [Quickstart](https://shipabase.dev/docs/quickstart.md): Install the SDK, call init once, and see your first event. Five minutes, no cookie banner. - [For AI agents](https://shipabase.dev/docs/ai-agents.md): Shipabase is built to be installed by a coding agent. Give it one prompt, it reads the rules, you review the diff. ### Frameworks - [Next.js](https://shipabase.dev/docs/nextjs.md): Add Shipabase to a Next.js App Router project. - [React (Vite)](https://shipabase.dev/docs/react.md): Add Shipabase to a React app built with Vite. - [Vue & Svelte](https://shipabase.dev/docs/vue-svelte.md): Add Shipabase to a Vue or Svelte app built with Vite, or to SvelteKit. - [React Native & Expo](https://shipabase.dev/docs/react-native.md): Track screens and events in a mobile app built with Expo or React Native. - [Node.js](https://shipabase.dev/docs/node.md): Track events from API servers, CLIs, scripts and cron jobs. ### Guides - [Page views](https://shipabase.dev/docs/page-views.md): Pages are tracked automatically in the browser. Screens in mobile apps take one line. - [Naming events](https://shipabase.dev/docs/naming-events.md): Short, stable names make every chart readable. - [Props & privacy](https://shipabase.dev/docs/props.md): Add context to events without collecting personal data. - [Sessions](https://shipabase.dev/docs/sessions.md): How visits are grouped, and how conversions are counted. - [Verify your setup](https://shipabase.dev/docs/verify.md): See your first event, and fix it when nothing shows up. ### Reference - [API reference](https://shipabase.dev/docs/api.md): Three functions. None of them throw, and calls before init are ignored. ### Privacy - [Privacy](https://shipabase.dev/docs/privacy.md): What the SDK sends, how visitors are counted, and what you should never send. ## Blog (Markdown) - [Analytics MCP server for Claude Code, Cursor and Codex](https://shipabase.dev/blog/analytics-mcp-server.md): Connect an analytics MCP server to Claude Code or Cursor. Your agent installs cookieless tracking, checks the first event and reads your stats. - [How to add analytics to a Lovable app](https://shipabase.dev/blog/add-analytics-lovable-app.md): Two ways to track what users do in an app built with Lovable: one prompt, or three lines of code. Cookieless, no consent banner for the SDK. - [Why your AI traffic shows up as “Direct”](https://shipabase.dev/blog/ai-traffic-direct.md): ChatGPT, Claude and Gemini send you visitors your analytics can’t see. Why the source disappears, and what you can still measure. - [How to know if ChatGPT sends you traffic](https://shipabase.dev/blog/chatgpt-traffic-analytics.md): Referrers, utm_source and what AI assistants don’t tell you. And how to see AI traffic in one card. - [Cookieless analytics for Next.js in 2 minutes](https://shipabase.dev/blog/cookieless-analytics-nextjs.md): Add privacy-first product analytics to a Next.js App Router project: install, init once, track what matters. ## Blog en français - [Serveur MCP d’analytics pour Claude Code, Cursor et Codex](https://shipabase.dev/fr/blog/serveur-mcp-analytics): Connectez un serveur MCP d’analytics à Claude Code ou Cursor : votre agent installe un suivi sans cookies, vérifie le premier événement et lit vos stats. - [Comment ajouter des analytics à une app Lovable](https://shipabase.dev/fr/blog/ajouter-analytics-app-lovable): Deux façons de suivre ce que font les utilisateurs d’une app Lovable : un prompt ou 3 lignes de code. Sans cookies, sans bandeau de consentement pour le SDK. - [Pourquoi votre trafic IA apparaît en « Direct »](https://shipabase.dev/fr/blog/trafic-ia-direct): ChatGPT, Claude et Gemini vous envoient des visiteurs que vos analytics ne voient pas. Pourquoi la source disparaît, et ce que vous pouvez encore mesurer. - [Comment savoir si ChatGPT vous envoie du trafic](https://shipabase.dev/fr/blog/trafic-chatgpt-analytics): Referrer, utm_source et ce que les assistants IA ne vous disent pas : comment repérer le trafic ChatGPT et voir tout votre trafic IA dans une seule carte. - [Analytics sans cookies pour Next.js en 2 minutes](https://shipabase.dev/fr/blog/analytics-sans-cookies-nextjs): Ajoutez des analytics produit sans cookies à un projet Next.js (App Router) : installation, un seul appel à init, puis le suivi des événements qui comptent. ## Blog en español - [Servidor MCP de analítica para Claude Code, Cursor y Codex](https://shipabase.dev/es/blog/servidor-mcp-analitica): Conecta un servidor MCP de analítica a Claude Code o Cursor. Tu agente instala el tracking sin cookies, comprueba el primer evento y lee tus estadísticas. - [Cómo añadir analítica a una app de Lovable](https://shipabase.dev/es/blog/anadir-analitica-app-lovable): Dos formas de medir lo que hacen los usuarios en una app de Lovable: un prompt o tres líneas de código. Sin cookies ni banner de consentimiento para el SDK. - [Por qué tu tráfico de IA aparece como «Directo»](https://shipabase.dev/es/blog/trafico-ia-directo): ChatGPT, Claude y Gemini te envían visitantes que tu analítica no ve. Por qué se pierde la fuente del tráfico de IA y qué puedes seguir midiendo. - [Cómo saber si ChatGPT te envía tráfico](https://shipabase.dev/es/blog/trafico-chatgpt-analitica): Referrers, utm_source y lo que los asistentes de IA no te cuentan: cómo saber si ChatGPT te envía tráfico y ver todo tu tráfico de IA en una sola tarjeta. - [Analítica sin cookies para Next.js en 2 minutos](https://shipabase.dev/es/blog/analitica-sin-cookies-nextjs): Añade analítica de producto sin cookies y centrada en la privacidad a tu proyecto Next.js (App Router): instala, llama a init una vez y mide lo que importa.