Skip to content

Phase 6 — Advanced Analytics & Platform Hardening

Goal: Reporting, custom branding, API access tier, and operational hardening.


6.1 Backend — Analytics Endpoints

All gated by org.featureSnapshot.advancedAnalytics.

GET /v1/analytics/pipeline-funnel?jobId=:id   — stage drop-off rates
GET /v1/analytics/time-to-hire?jobId=:id      — avg days per stage
GET /v1/analytics/question-effectiveness      — screening question pass/fail correlation
GET /v1/analytics/interviewer-activity        — interviews conducted per recruiter

Gate: if (!org.featureSnapshot.advancedAnalytics) return res.status(403).json({...})


6.2 Backend — Custom Branding

Organization.brandingConfig (added to Organization model):

typescript
brandingConfig?: {
  primaryColor: string;
  logoUrl: string;
  emailFooterText: string;
  candidatePortalDomain?: string;  // custom domain support
};

Candidate-facing emails and session pages (screening, DSA, AI sessions) read brandingConfig from the org. Custom colors applied via CSS variables — no per-org frontend builds.

Gate: org.featureSnapshot.customBranding


6.3 Backend — Rate Limiting & Operational Hardening

  • Rate limiting: express-rate-limit on token-gated public endpoints (screening, DSA) — 60 req/min per IP
  • Request ID tracing: x-request-id middleware on all requests for log correlation
  • AI evaluation queue: Move inline-async AI eval calls to BullMQ + Redis job queue for reliability (survives server restart)
  • Health check: GET /health returning { status: 'ok', db: 'connected', queue: { depth: n } }

BullMQ Migration for AI Evaluation

typescript
// screeningEvaluationService.ts: instead of inline async call
await evaluationQueue.add('evaluate-screening', { interviewId: interview._id });

// evaluationWorker.ts: BullMQ worker processes jobs
evaluationQueue.process('evaluate-screening', async (job) => {
  const { interviewId } = job.data;
  await runScreeningEvaluation(interviewId);
});

6.4 Frontend — Analytics Dashboard

Route: /analytics

src/pages/recruiter/Analytics.tsx:

  • Pipeline funnel chart (per-stage conversion rates)
  • Time-to-hire breakdown
  • Gated by featureSnapshot.advancedAnalytics — show upgrade prompt if false

6.5 Frontend — Candidate Portal Branding

Load Organization.brandingConfig at session start for public session pages. Apply via CSS variables:

css
:root {
  --brand-primary: v-bind(brandingConfig.primaryColor);
}

No per-org frontend builds required.


Phase 6 — Acceptance Criteria

  • [ ] Analytics endpoints return 403 for orgs on plans without advancedAnalytics: true
  • [ ] Candidate-facing session pages show org logo + brand color when set
  • [ ] Screening session endpoint rate-limited to 60 req/min per IP
  • [ ] AI evaluation queued via BullMQ — survives server restart without lost jobs
  • [ ] Health check returns 200 with DB + queue status
  • [ ] x-request-id header present on all API responses for log tracing