Skip to content

analytics — CONTEXT.md

Internal Angular 20 dashboard for syncc engineering/ops use only. Aggregates telemetry from all three client apps (web-admin, mobile-driver, passengers-app) across both city silos (Cochabamba and La Paz) into a single unified view. For global conventions (branding, Angular patterns), see /CLAUDE.md.


1. Purpose

The analytics app consumes the POST /analytics/events endpoint on each silo's API server. It does not replace the web-admin — it is a separate internal tool for monitoring product usage, HTTP errors, session durations, and device/platform breakdowns.


2. Routes

Path Component Guard
/login LoginComponent (lazy) Public
/dashboard DashboardComponent (lazy) authGuard
/ Redirects to /dashboard
** Redirects to /dashboard

3. Dual-Silo Auth

The app authenticates in parallel to both city API servers on login. Tokens are stored per silo in localStorage:

Key Value
analytics.token.cochabamba JWT for api.cbba.dev.syncc.me
analytics.token.lapaz JWT for api.lpz.dev.syncc.me
  • Login succeeds if at least one silo responds with a valid token.
  • AuthService.isLoggedIn is a signal(boolean) derived from whether any token exists.
  • authGuard redirects to /login when isLoggedIn() is false.
  • Tokens are cleared from localStorage on logout().

Credentials must be a SUPER_ADMIN account that exists in the target silo.


4. Services

Service Path Purpose
AuthService core/auth.service.ts Parallel silo login, token storage, isLoggedIn signal
AnalyticsService core/analytics.service.ts Fetches EventsReport from both silos and merges results

AnalyticsService.getReport(filters)

Queries GET /analytics/events/report on both silos in parallel via Promise.allSettled. If a city filter is set, only the matching silo is queried. Results are merged client-side via mergeReports() — sums for numeric fields, union+sort for arrays.

The EventsReport interface shape:

interface EventsReport {
  summary: { totalPageViews; totalErrors; totalSessions; avgSessionDurationMs };
  breakdown: {
    byDevice:   { device: string | null; count: number }[];
    byPlatform: { platform: string | null; count: number }[];
    byCity:     { city: string | null; count: number }[];
    byApp:      { app: string; count: number }[];
  };
  charts: {
    hourlyActivity: { hour: string; count: number }[];
    topPaths:  { path: string | null; app: string; views: number }[];
    topErrors: { path: string | null; code: number | null; app: string; count: number }[];
  };
}

5. Dashboard Component

pages/dashboard/dashboard.component.ts — all state via Angular signals.

Signal / Computed Purpose
filterApp, filterCity, startDate, endDate Bound to filter inputs (not applied until "Aplicar" click)
appliedFilters Private signal — only updated on applyFilters()
report resource<EventsReport, ...> — reloads when appliedFilters changes
avgSessionMin Derived from report.value()?.summary.avgSessionDurationMs
totalByApp report.value()?.breakdown.byApp
maxPathViews Max views across topPaths (used for bar chart scaling)
maxAppCount Max count across byApp (used for bar chart scaling)
hourlyBars Derived from hourlyActivity — includes heightPct for CSS bar height
deviceTotal Sum of byDevice[*].count (denominator for percentages)
platformTotal Sum of byPlatform[*].count

The resource() params option drives lazy loading — data only fetches when filters are explicitly applied, not on every keystroke.


6. Environment Config

File Used when
src/environments/environment.ts Dev build (ng serve)
src/environments/environment.prod.ts Production build (ng build --configuration=production)
// environment.ts (dev)
export const environment = {
  production: false,
  silos: {
    cochabamba: 'https://api.cbba.dev.syncc.me',
    lapaz:      'https://api.lpz.dev.syncc.me',
  },
  analyticsKey: 'syncc-analytics',
};

7. Dev Workflow

cd apps/analytics
npm install
npm start              # Dev server at http://localhost:4200
npm run build:prod     # Production build → dist/analytics/

No set-env.cjs script — environment files are edited directly.


8. Key File Paths

What Path
Routes src/app/app.routes.ts
App config src/app/app.config.ts
Auth service src/app/core/auth.service.ts
Auth guard src/app/core/auth.guard.ts
Analytics service + EventsReport interface src/app/core/analytics.service.ts
Dashboard page src/app/pages/dashboard/
Login page src/app/pages/login/
Environments src/environments/
Tailwind config tailwind.config.js
Global styles src/styles.css

Last updated: 2026-07-05.