Skip to Content
API ReferenceDashboard API

Dashboard API

File: app/api/analytics/dashboard/route.ts

GET /api/analytics/dashboard

Returns aggregated analytics data from PostHog via HogQL queries.

Parameters

ParameterRequiredDescription
passwordYesMust match ANALYTICS_PASSWORD env var
periodNoTime range: all (default), year, 90d, month, week, day

Response

{ "routes": [ { "id": "bassegoda-fau", "name": "Falda Bassegoda i La Fau", "gpxUrl": "http://...", "views": 42, "downloads": 12, "shares": 3, "articleUrl": "https://www.bttpirineus.org/..." } ], "core": { "views": 100, "downloads": 50, "shares": 20, "shareModalOpens": 15, "openRouteStartClicks": 8 }, "shareChannels": [ { "channel": "facebook", "count": 10 } ], "timeSeries": [ { "date": "2026-02-20", "views": 10, "downloads": 5, "shares": 2, "actions": 3 } ], "granularity": "day", "comparison": { "views": 80, "downloads": 40, "shares": 15, "shareModalOpens": 12, "openRouteStartClicks": 6 }, "topPages": [ { "page": "https://www.bttpirineus.org/...", "views": 10 } ], "source": "posthog" }

HogQL queries

The endpoint runs 6 parallel queries against PostHog:

  1. Core totals: countIf(event = 'track_viewed'), etc.
  2. Per-route breakdown: Group by properties.gpx_url
  3. Time-series: Group by toDate(timestamp) or toStartOfWeek(timestamp)
  4. Share channels: Group by properties.share_channel where event = track_shared
  5. Top pages: Group by properties.page_url, limit 20
  6. Comparison: Same queries for the previous equivalent period

All queries exclude events where properties.is_internal = true.

Error codes

StatusCondition
401Invalid or missing password
500PostHog not configured (POSTHOG_PERSONAL_API_KEY missing)