Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Preparing Ring Platform content
Preparing Ring Platform content
Preparing Ring Platform content
Filter with Founder / Developer in the docs sidebar. Monitoring truth lives in app/api/health, app/api/analytics/*, lib/logger.ts, public/scripts/analytics.js + RingAnalyticsBeacon, and the admin analytics UI. No separate features/analytics doc page — this article is the ring-wide analytics overview.
Ring Platform ships first-party telemetry into PostgreSQL JSONB tables, a container-friendly health endpoint, and structured server logs. External APM (Sentry, Vercel Analytics) is optional via env vars — not required for core operation.
| Layer | Mechanism | Primary signal |
|---|---|---|
| Liveness | GET /api/health (+ HEAD) | Process up, env warnings, memory |
| UX performance | WebVitalsProvider → POST /api/analytics/web-vitals | LCP, CLS, INP, TTFB, FCP |
| Product events | analytics.js + RingAnalyticsBeacon → POST /api/analytics/app | Sessions, page loads, custom events (analytics_events) |
| Personal profiles | recordPersonalPageView → personal_page_view | Unique visits 24h/7d by role on /{username} |
| Client errors | POST /api/analytics/errors | Stack traces, component, severity |
| Admin dashboard | /admin/analytics | getPlatformAnalytics() incl. personalPages |
| Realtime connectivity | /api/tunnel/ping, /api/tunnel/heartbeat | Tunnel latency / session health |
| Server logs | lib/logger.ts | JSON lines to stdout (LOG_LEVEL) |
| Optional infra | Docker profile monitoring | Prometheus + Grafana (local dev only) |
A Ring clone combines auth, marketplace data, payments, and realtime notifications. Silent failure shows up as “the site loads but orders don’t sync” — not as a red error page. Personal-page unique visits tell you whether member trust faces are getting traffic without counting owners refreshing their own pages.
Same-workflow: personal_page_view unique visit stats and owner skip.
Next-step: restore after incidents detected here.
See-also: Web Vitals tuning and performance ops.
Depends-on: CRON_SECRET, LOG_LEVEL, ANALYTICS_DISABLE_STORAGE, optional Sentry.
Filter with Founder / Developer in the docs sidebar. Monitoring truth lives in app/api/health, app/api/analytics/*, lib/logger.ts, public/scripts/analytics.js + RingAnalyticsBeacon, and the admin analytics UI. No separate features/analytics doc page — this article is the ring-wide analytics overview.
Ring Platform ships first-party telemetry into PostgreSQL JSONB tables, a container-friendly health endpoint, and structured server logs. External APM (Sentry, Vercel Analytics) is optional via env vars — not required for core operation.
| Layer | Mechanism | Primary signal |
|---|---|---|
| Liveness | GET /api/health (+ HEAD) | Process up, env warnings, memory |
| UX performance | WebVitalsProvider → POST /api/analytics/web-vitals | LCP, CLS, INP, TTFB, FCP |
| Product events | analytics.js + RingAnalyticsBeacon → POST /api/analytics/app | Sessions, page loads, custom events (analytics_events) |
| Personal profiles | recordPersonalPageView → personal_page_view | Unique visits 24h/7d by role on /{username} |
| Client errors | POST /api/analytics/errors | Stack traces, component, severity |
| Admin dashboard | /admin/analytics | getPlatformAnalytics() incl. personalPages |
| Realtime connectivity | /api/tunnel/ping, /api/tunnel/heartbeat | Tunnel latency / session health |
| Server logs | lib/logger.ts | JSON lines to stdout (LOG_LEVEL) |
| Optional infra | Docker profile monitoring | Prometheus + Grafana (local dev only) |
A Ring clone combines auth, marketplace data, payments, and realtime notifications. Silent failure shows up as “the site loads but orders don’t sync” — not as a red error page. Personal-page unique visits tell you whether member trust faces are getting traffic without counting owners refreshing their own pages.
Same-workflow: personal_page_view unique visit stats and owner skip.
Next-step: restore after incidents detected here.
See-also: Web Vitals tuning and performance ops.
Depends-on: CRON_SECRET, LOG_LEVEL, ANALYTICS_DISABLE_STORAGE, optional Sentry.
Filter with Founder / Developer in the docs sidebar. Monitoring truth lives in app/api/health, app/api/analytics/*, lib/logger.ts, public/scripts/analytics.js + RingAnalyticsBeacon, and the admin analytics UI. No separate features/analytics doc page — this article is the ring-wide analytics overview.
Ring Platform ships first-party telemetry into PostgreSQL JSONB tables, a container-friendly health endpoint, and structured server logs. External APM (Sentry, Vercel Analytics) is optional via env vars — not required for core operation.
| Layer | Mechanism | Primary signal |
|---|---|---|
| Liveness | GET /api/health (+ HEAD) | Process up, env warnings, memory |
| UX performance | WebVitalsProvider → POST /api/analytics/web-vitals | LCP, CLS, INP, TTFB, FCP |
| Product events | analytics.js + RingAnalyticsBeacon → POST /api/analytics/app | Sessions, page loads, custom events (analytics_events) |
| Personal profiles | recordPersonalPageView → personal_page_view | Unique visits 24h/7d by role on /{username} |
| Client errors | POST /api/analytics/errors | Stack traces, component, severity |
| Admin dashboard | /admin/analytics | getPlatformAnalytics() incl. personalPages |
| Realtime connectivity | /api/tunnel/ping, /api/tunnel/heartbeat | Tunnel latency / session health |
| Server logs | lib/logger.ts | JSON lines to stdout (LOG_LEVEL) |
| Optional infra | Docker profile monitoring | Prometheus + Grafana (local dev only) |
A Ring clone combines auth, marketplace data, payments, and realtime notifications. Silent failure shows up as “the site loads but orders don’t sync” — not as a red error page. Personal-page unique visits tell you whether member trust faces are getting traffic without counting owners refreshing their own pages.
Same-workflow: personal_page_view unique visit stats and owner skip.
Next-step: restore after incidents detected here.
See-also: Web Vitals tuning and performance ops.
Depends-on: CRON_SECRET, LOG_LEVEL, ANALYTICS_DISABLE_STORAGE, optional Sentry.
Owners see unique 24h/7d visit stats on their personal page widget.
degraded — missing critical env after deploy; check secrets before blaming Postgres.poor ratings climb — CDN, image weight, or SSR regression; correlate with a release tag (BUILD_DATE / GIT_COMMIT on health JSON when set).analytics_errors — broken client bundle or third-party script; admin dashboard lists recent messages.Define who gets paged (operator vs developer) and what “down” means for your clone — Ring OSS does not ship PagerDuty wiring; you attach health checks to your provider.
public/scripts/app-analytics.js| Route | Method | Auth | Persists to |
|---|---|---|---|
/api/analytics/web-vitals | POST | Optional session | web_vitals |
/api/analytics/web-vitals | GET | Admin | Query web_vitals or ?scope=platform summary |
/api/analytics/app | POST | Optional session | analytics_events |
/api/analytics/errors | POST | Optional session | analytics_errors |
/api/analytics/errors | GET | Admin | List errors |
/api/analytics/device | POST | Session required | user_device_telemetry |
/api/analytics/platform-stats | GET | Admin | Counts: users, entities, opportunities |
Implementation: features/analytics/lib/analytics-db.ts (insertAnalyticsEventBatch). Client Web Vitals: lib/web-vitals.tsx (INP replaces FID).
| Piece | Path |
|---|---|
| Event type | personal_page_view |
| Writer | features/analytics/lib/personal-page-analytics.ts → recordPersonalPageView |
| Call site | app/[locale]/[username]/page.tsx — skips owners |
| Owner widget | getPersonalPageViewStats (features/auth/services/personal-page-stats.ts) |
| Admin | getPersonalPagePlatformStats → PlatformAnalyticsSummary.personalPages |
| Engagement | personal_page_view joins docs_page_view / page_view / app_load in admin pageViews aggregates |
Details and unique-by-role math: Public Profile Pages.
Included in data/schema.sql and migration 017_ring_analytics_schema.sql:
analytics_events — batched client telemetry and server personal_page_view rowsweb_vitals — Core Web Vitals batchesanalytics_errors — client-side error logWhen set, ingest routes acknowledge payloads but skip DatabaseService writes (isAnalyticsStorageDisabled()). Personal-page recorder also no-ops.
Env: LOG_LEVEL (debug | info | warn | error, default info in production), LOG_SILENT=true to mute.
Commented/optional in env.local.template / docker.env.template:
SENTRY_DSN — wire via your Sentry Next.js integration (not auto-enabled in repo)NEXT_PUBLIC_ANALYTICS_ID, VERCEL_ANALYTICS_ID — Vercel-hosted clones only| Route | Purpose |
|---|---|
POST /api/tunnel/ping | Authenticated pong + timestamp |
POST /api/tunnel/heartbeat | Connection keep-alive |
See Tunnel protocol.
Cron routes (/api/cron/*) fail closed without CRON_SECRET. Example: GET /api/cron/email-analytics runs ProcessConductor pipeline email-analytics.
Services: ring-prometheus (:9090), ring-grafana (:3001). Config: docker/prometheus/prometheus.yml.
The bundled Prometheus job references /api/metrics, which is not implemented in this tree, and scrapes /api/health as JSON (not Prometheus exposition format). Treat the profile as a starting scaffold.
Server page: app/[locale]/admin/analytics/page.tsx — requires isPlatformAdmin, loads getPlatformAnalytics('7d') including personalPages.
Deep-dive: tunnel transports and heartbeat behavior.
Owners see unique 24h/7d visit stats on their personal page widget.
degraded — missing critical env after deploy; check secrets before blaming Postgres.poor ratings climb — CDN, image weight, or SSR regression; correlate with a release tag (BUILD_DATE / GIT_COMMIT on health JSON when set).analytics_errors — broken client bundle or third-party script; admin dashboard lists recent messages.Define who gets paged (operator vs developer) and what “down” means for your clone — Ring OSS does not ship PagerDuty wiring; you attach health checks to your provider.
public/scripts/app-analytics.js| Route | Method | Auth | Persists to |
|---|---|---|---|
/api/analytics/web-vitals | POST | Optional session | web_vitals |
/api/analytics/web-vitals | GET | Admin | Query web_vitals or ?scope=platform summary |
/api/analytics/app | POST | Optional session | analytics_events |
/api/analytics/errors | POST | Optional session | analytics_errors |
/api/analytics/errors | GET | Admin | List errors |
/api/analytics/device | POST | Session required | user_device_telemetry |
/api/analytics/platform-stats | GET | Admin | Counts: users, entities, opportunities |
Implementation: features/analytics/lib/analytics-db.ts (insertAnalyticsEventBatch). Client Web Vitals: lib/web-vitals.tsx (INP replaces FID).
| Piece | Path |
|---|---|
| Event type | personal_page_view |
| Writer | features/analytics/lib/personal-page-analytics.ts → recordPersonalPageView |
| Call site | app/[locale]/[username]/page.tsx — skips owners |
| Owner widget | getPersonalPageViewStats (features/auth/services/personal-page-stats.ts) |
| Admin | getPersonalPagePlatformStats → PlatformAnalyticsSummary.personalPages |
| Engagement | personal_page_view joins docs_page_view / page_view / app_load in admin pageViews aggregates |
Details and unique-by-role math: Public Profile Pages.
Included in data/schema.sql and migration 017_ring_analytics_schema.sql:
analytics_events — batched client telemetry and server personal_page_view rowsweb_vitals — Core Web Vitals batchesanalytics_errors — client-side error logWhen set, ingest routes acknowledge payloads but skip DatabaseService writes (isAnalyticsStorageDisabled()). Personal-page recorder also no-ops.
Env: LOG_LEVEL (debug | info | warn | error, default info in production), LOG_SILENT=true to mute.
Commented/optional in env.local.template / docker.env.template:
SENTRY_DSN — wire via your Sentry Next.js integration (not auto-enabled in repo)NEXT_PUBLIC_ANALYTICS_ID, VERCEL_ANALYTICS_ID — Vercel-hosted clones only| Route | Purpose |
|---|---|
POST /api/tunnel/ping | Authenticated pong + timestamp |
POST /api/tunnel/heartbeat | Connection keep-alive |
See Tunnel protocol.
Cron routes (/api/cron/*) fail closed without CRON_SECRET. Example: GET /api/cron/email-analytics runs ProcessConductor pipeline email-analytics.
Services: ring-prometheus (:9090), ring-grafana (:3001). Config: docker/prometheus/prometheus.yml.
The bundled Prometheus job references /api/metrics, which is not implemented in this tree, and scrapes /api/health as JSON (not Prometheus exposition format). Treat the profile as a starting scaffold.
Server page: app/[locale]/admin/analytics/page.tsx — requires isPlatformAdmin, loads getPlatformAnalytics('7d') including personalPages.
Deep-dive: tunnel transports and heartbeat behavior.
Owners see unique 24h/7d visit stats on their personal page widget.
degraded — missing critical env after deploy; check secrets before blaming Postgres.poor ratings climb — CDN, image weight, or SSR regression; correlate with a release tag (BUILD_DATE / GIT_COMMIT on health JSON when set).analytics_errors — broken client bundle or third-party script; admin dashboard lists recent messages.Define who gets paged (operator vs developer) and what “down” means for your clone — Ring OSS does not ship PagerDuty wiring; you attach health checks to your provider.
public/scripts/app-analytics.js| Route | Method | Auth | Persists to |
|---|---|---|---|
/api/analytics/web-vitals | POST | Optional session | web_vitals |
/api/analytics/web-vitals | GET | Admin | Query web_vitals or ?scope=platform summary |
/api/analytics/app | POST | Optional session | analytics_events |
/api/analytics/errors | POST | Optional session | analytics_errors |
/api/analytics/errors | GET | Admin | List errors |
/api/analytics/device | POST | Session required | user_device_telemetry |
/api/analytics/platform-stats | GET | Admin | Counts: users, entities, opportunities |
Implementation: features/analytics/lib/analytics-db.ts (insertAnalyticsEventBatch). Client Web Vitals: lib/web-vitals.tsx (INP replaces FID).
| Piece | Path |
|---|---|
| Event type | personal_page_view |
| Writer | features/analytics/lib/personal-page-analytics.ts → recordPersonalPageView |
| Call site | app/[locale]/[username]/page.tsx — skips owners |
| Owner widget | getPersonalPageViewStats (features/auth/services/personal-page-stats.ts) |
| Admin | getPersonalPagePlatformStats → PlatformAnalyticsSummary.personalPages |
| Engagement | personal_page_view joins docs_page_view / page_view / app_load in admin pageViews aggregates |
Details and unique-by-role math: Public Profile Pages.
Included in data/schema.sql and migration 017_ring_analytics_schema.sql:
analytics_events — batched client telemetry and server personal_page_view rowsweb_vitals — Core Web Vitals batchesanalytics_errors — client-side error logWhen set, ingest routes acknowledge payloads but skip DatabaseService writes (isAnalyticsStorageDisabled()). Personal-page recorder also no-ops.
Env: LOG_LEVEL (debug | info | warn | error, default info in production), LOG_SILENT=true to mute.
Commented/optional in env.local.template / docker.env.template:
SENTRY_DSN — wire via your Sentry Next.js integration (not auto-enabled in repo)NEXT_PUBLIC_ANALYTICS_ID, VERCEL_ANALYTICS_ID — Vercel-hosted clones only| Route | Purpose |
|---|---|
POST /api/tunnel/ping | Authenticated pong + timestamp |
POST /api/tunnel/heartbeat | Connection keep-alive |
See Tunnel protocol.
Cron routes (/api/cron/*) fail closed without CRON_SECRET. Example: GET /api/cron/email-analytics runs ProcessConductor pipeline email-analytics.
Services: ring-prometheus (:9090), ring-grafana (:3001). Config: docker/prometheus/prometheus.yml.
The bundled Prometheus job references /api/metrics, which is not implemented in this tree, and scrapes /api/health as JSON (not Prometheus exposition format). Treat the profile as a starting scaffold.
Server page: app/[locale]/admin/analytics/page.tsx — requires isPlatformAdmin, loads getPlatformAnalytics('7d') including personalPages.
Deep-dive: tunnel transports and heartbeat behavior.