Privacy-first analytics platform for React applications. Track user behavior, monitor errors, and gain insights without compromising privacy.
🚀 Get Started Instantly: Visit reactanalytics.app for a fully managed, hosted solution.
⚙️ Self-Host: This project is open source and self-hostable. Built with modern web technologies and designed for developers who want full control over their analytics data.
- Node.js 22+ (uses NVM:
nvm use 24) - Docker & Docker Compose
- Yarn package manager
# Clone the repository
git clone https://github.com/jvidalv/react-analytics.git
cd react-analytics/web
# Use correct Node version
nvm use 24
# Install dependencies
yarn install
# Copy environment file
cp .env.example .env.local
# Edit .env.local with your credentials (see Environment Variables below)
# Start PostgreSQL database
yarn db
# Run database migrations
yarn db:migrate
# Start development server (includes Next.js + cron watchers)
yarn devOpen http://localhost:3000 to access the dashboard.
The project uses Drizzle migrations for all schema changes:
# Generate new migration from schema.ts changes
yarn db:generate
# Apply pending migrations
yarn db:migrate
# Visual database browser
yarn db:studio
# Reset database (⚠️ DESTRUCTIVE - drops all tables)
yarn db:resetImportant: Never bypass the migration system. Always use yarn db:generate → yarn db:migrate for schema changes. See DATABASE_SETUP.md for complete database documentation.
React Analytics is built with privacy at its core:
- Self-Hosted - Your data stays on your infrastructure, never shared with third parties
- Open Source - Fully auditable code, no hidden tracking
- Data Ownership - Complete control over your analytics data
- GDPR-Friendly - Designed to support compliance when properly configured
- No External Dependencies - All data processing happens on your servers
If you collect user identities (name, email) using the identify() method, you MUST:
- ✅ Obtain explicit user consent before tracking
- ✅ Implement data access and deletion mechanisms
- ✅ Maintain a data retention policy
- ✅ Provide clear privacy notices to users
- ✅ Honor user rights (access, deletion, portability)
Documentation:
- PRIVACY.md - Technical privacy features and data collection details
- GDPR.md - GDPR compliance implementation guide with code examples
- DISCLAIMER.md - Legal disclaimer and responsibilities
- LICENSE - MIT License with data protection notice
| Feature | React Analytics | Google Analytics | Mixpanel |
|---|---|---|---|
| Self-Hosted | ✅ Yes | ❌ No | ❌ No |
| Open Source | ✅ Yes | ❌ No | ❌ No |
| Full Data Ownership | ✅ Yes | ❌ No | ❌ No |
| No Third-Party Sharing | ✅ Yes | ❌ No | ❌ No |
| Your Infrastructure | ✅ Yes | ❌ No | ❌ No |
- Next.js 16 - React framework with App Router
- React 19 - Latest React with concurrent features
- PostgreSQL - Primary database (via Docker locally, Neon in production)
- Drizzle ORM - Type-safe database queries with migrations
- NextAuth v5 - Authentication (Google, GitHub, Apple)
- Elysia - Backend API framework with type safety
- Stripe - Payment processing
- Tailwind CSS 4 - Styling
- TypeScript 5 - Full type safety
- Vitest - Testing framework (analytics package)
📦 NPM Package: @jvidalv/react-analytics
This monorepo includes the @jvidalv/react-analytics package in packages/analytics. This is the open source npm package that enables analytics tracking in React applications.
# Install the package
npm install @jvidalv/react-analytics
# or
yarn add @jvidalv/react-analytics- Universal - Works with React, React Native, Expo, and Next.js
- Auto-detection - Automatically detects routing framework
- Event Batching - Efficient 5-second batching with configurable intervals
- Storage Adapters - localStorage (web), AsyncStorage (React Native)
- Device Detection - Platform, OS, browser, device info
- TypeScript - Full type safety
cd packages/analytics
# Build CJS + ESM bundles
yarn build
# Run tests
yarn test
# Watch mode
yarn test:watch
# Publish to npm
npm publishCreate a .env.local file in the root directory. You can copy .env.example as a starting point:
cp .env.example .env.local# Database (local development)
DATABASE_URL=postgresql://postgres:postgres@localhost:5434/postgres
# Authentication
AUTH_SECRET=your-secret-key-here # Generate: openssl rand -base64 32
NEXT_PUBLIC_APP_URL=http://localhost:3000
# OAuth (configure at least one provider)
# GitHub: https://github.com/settings/developers
AUTH_GITHUB_ID=your-github-client-id
AUTH_GITHUB_SECRET=your-github-client-secret
# Google: https://console.cloud.google.com
AUTH_GOOGLE_ID=your-google-client-id
AUTH_GOOGLE_SECRET=your-google-client-secret# Cron secret for materialized view refresh
CRON_SECRET=your-cron-secret # Generate: openssl rand -base64 32
# Base URL (defaults to http://localhost:3000)
BASE_URL=https://your-production-domain.com# Email service (Resend)
RESEND_API_KEY=re_...
# AI features (OpenAI)
OPENAI_API_KEY=sk-...
# Payment processing (Stripe)
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET_KEY=whsec_...
PRODUCT_PRO_PLAN_ID=prod_...
PRODUCT_STARTER_PLAN_ID=prod_...
NEXT_PUBLIC_FREE_PLAN=https://...
NEXT_PUBLIC_STARTER_PLAN=https://...
NEXT_PUBLIC_PRO_PLAN=https://...react-analytics/
├── packages/analytics/ # @jvidalv/react-analytics NPM package
│ ├── src/ # Universal analytics library
│ ├── test/ # Vitest tests
│ └── dist/ # Build output (CJS + ESM)
├── src/ # Next.js application
│ ├── app/ # App Router pages
│ ├── api/ # Elysia API routes
│ ├── domains/ # Business logic
│ ├── db/ # Database (schema, migrations)
│ └── components/ # UI components
├── drizzle/ # Database migrations
│ ├── 0000_*.sql # Migration files
│ └── meta/ # Migration metadata
├── scripts/ # Utility scripts
│ ├── reset-database.ts # Reset database
│ ├── run-cron.ts # Run cron tasks manually
│ └── watch-crons.ts # Cron watcher for dev
└── CLAUDE.md # AI reference guide
- CLAUDE.md - Comprehensive AI reference guide
- AGENTS.md - AI agent documentation hub
- BUGBOT.md - Debugging & troubleshooting guide
- DATABASE_SETUP.md - Database setup and seed data guide
Always use migrations for database schema changes:
# 1. Edit src/db/schema.ts
export const myTable = pgTable("my_table", {
id: uuid().primaryKey().defaultRandom(),
name: text("name").notNull(),
});
# 2. Generate migration
yarn db:generate
# 3. Review generated SQL
cat drizzle/XXXX_*.sql
# 4. Edit if needed (e.g., for materialized views)
# Replace CREATE TABLE with CREATE MATERIALIZED VIEW if needed
# 5. Apply migration
yarn db:migrate
# 6. Commit both files
git add src/db/schema.ts drizzle/
git commit -m "feat: add my_table"The project uses materialized views for optimized analytics queries:
analytics_identified_users_mv- Production identified usersanalytics_test_identified_users_mv- Test identified users
These are refreshed every minute by a cron job. In development:
# Cron runs automatically with yarn dev
# Manual refresh:
yarn cron:refresh-viewscd packages/analytics
yarn test # Run tests
yarn test:watch # Watch mode
yarn test:coverage # Coverage report- Connect repository to Vercel
- Set environment variables (see Environment Variables above)
- Migrations run automatically via
vercel-buildscript - Set up cron job for materialized view refresh:
- Path:
/api/cron/refresh-views - Schedule:
* * * * *(every minute) - Set
CRON_SECRETenvironment variable
- Path:
- Build application:
yarn build - Run migrations:
yarn db:migrate - Start server:
yarn start - Set up cron job for view refresh (use
scripts/run-cron.ts)
Contributions are welcome! Please follow these guidelines:
- Use semantic commit messages (
feat:,fix:,docs:, etc.) - Always use migrations for database changes
- Run tests before submitting PR
- Follow TypeScript and ESLint conventions
- Update documentation when adding features
See CLAUDE.md for detailed development guidelines.
MIT License - feel free to use this project for personal or commercial purposes.