Analytics
Verified Against source code
Last updated: September 2026
AquaDealers uses PostHog for product analytics and Sentry for error tracking and session replays. Both are initialized in src/lib/telemetry.ts via the initTelemetry() function, called at app startup in src/main.tsx.
Environment variables required: VITE_POSTHOG_KEY, VITE_POSTHOG_HOST (optional, defaults to https://app.posthog.com), and VITE_SENTRY_DSN. If any are missing, the respective SDK silently skips initialization with a console warning.
PostHog (Product Analytics)
Configuration
| Setting | Value | Notes |
| Package | posthog-js ^1.376.0 | Client-side JS SDK |
| API Key | VITE_POSTHOG_KEY | Environment variable |
| API Host | VITE_POSTHOG_HOST | Defaults to https://app.posthog.com if unset |
| Autocapture | false | Disabled for privacy — no automatic click/pageview tracking |
| Capture mode | Manual only | Explicit trackEvent() calls required |
Exported API
Two functions are exported from src/lib/telemetry.ts:
| Function | Signature | Purpose |
trackEvent |
(name: string, properties?: object) |
Capture a named event with optional properties |
identifyUser |
(userId: string, traits?: object) |
Associate the current session with a dealer ID |
Not instrumented: Neither trackEvent nor identifyUser are called anywhere in the application code. The hooks are defined and exported, but zero feature files import or invoke them. PostHog currently receives no events from AquaDealers. This means product analytics is effectively non-functional.
Privacy Design
- Autocapture disabled: PostHog does not capture clicks, page views, or form submissions automatically
- Manual-only: When instrumented, only explicitly tracked events would be sent
- User identification: Designed to use dealer UUID, not personal information
Sentry (Error Tracking)
Configuration
| Setting | Value | Notes |
| Package | @sentry/react ^10.53.1 | React-specific SDK with ErrorBoundary support |
| DSN | VITE_SENTRY_DSN | Sentry project identifier (env var) |
| Browser Tracing | Enabled | Sentry.browserTracingIntegration() |
| Session Replay | Enabled | Sentry.replayIntegration() |
tracesSampleRate | 1.0 | 100% of transactions sampled |
replaysSessionSampleRate | 0.1 | 10% of all sessions get a replay (even without errors) |
replaysOnErrorSampleRate | 1.0 | 100% of error sessions get a replay |
| ErrorBoundary | Wraps entire app | src/main.tsx — branded crash fallback with captureException |
| Source Maps | Enabled | vite.config.ts — sourcemap: true for readable stack traces |
Cost warning: tracesSampleRate: 1.0 samples every transaction. replaysSessionSampleRate: 0.1 records 10% of all sessions even without errors. At scale, this generates significant Sentry billing. Consider reducing tracesSampleRate to 0.1–0.3 as the user base grows.
What Sentry Captures
- Unhandled exceptions: JavaScript errors, promise rejections — caught by the app-wide
Sentry.ErrorBoundary in src/main.tsx
- Performance traces: Page load times, navigation timing, API call durations (100% sampled)
- Session replays: DOM recording on 100% of error sessions and 10% of all sessions — allows replaying exactly what the user did before an error
- Breadcrumbs: Automatic trail of user actions (clicks, navigation, console logs) leading up to an error
- Source maps: Stack traces resolve to original TypeScript sources, not minified bundles
Error Boundary
The entire app is wrapped in <Sentry.ErrorBoundary> in src/main.tsx. When an unhandled React error occurs:
- Sentry captures the exception with full stack trace
- A branded crash fallback screen is shown to the user (
CrashFallback component)
- The user can reload the page to recover
Instrumentation Status
Current Gap
The telemetry infrastructure is in place but product analytics is not wired up:
| Capability | Status | Notes |
| PostHog SDK initialization | Ready | Initializes when env var is present |
trackEvent() function | Exported | Available in src/lib/telemetry.ts |
identifyUser() function | Exported | Available in src/lib/telemetry.ts |
| Event instrumentation | Missing | Zero call sites in the codebase — no events are tracked |
| User identification | Missing | Never called — sessions are anonymous |
| Sentry error tracking | Active | Fully functional with ErrorBoundary + replays |
| Sentry performance tracing | Active | 100% sample rate |
Recommended Instrumentation
High-value events to instrument when enabling product analytics:
| Event | Where to Add | Properties |
bill_created | useCheckout.ts after successful save | item_count, total, payment_type, is_offline |
payment_collected | Payment collection flow | amount, method, farmer_id |
whatsapp_sent | whatsAppService.ts | message_type, method (api/wa.me) |
report_exported | Report export handlers | report_type, format, date_range |
user_identified | Auth store on login | plan, branch_count, staff_count |
Architecture
File Map
| File | Purpose |
src/lib/telemetry.ts | PostHog + Sentry initialization, trackEvent(), identifyUser() |
src/main.tsx | Calls initTelemetry(), wraps app in Sentry.ErrorBoundary |
vite.config.ts | sourcemap: true for Sentry stack traces |
.env | VITE_SENTRY_DSN, VITE_POSTHOG_KEY, VITE_POSTHOG_HOST |