Spaces:
Sleeping
04 - Analytics Layer
Analytics is derived from structured runtime metadata. It does not read raw chat text from
ape_messages.
Access
The /analytics SPA route can load without a token. All /analytics/* API
routes require the admin token:
X-APE-Admin-Token: <APE_ADMIN_TOKEN>
The frontend prompts for the token when it is missing and sends it through the
shared request() helper.
Source Collections
| Collection | Used for |
|---|---|
ape_turn_record |
Turns, rewards, signals, selected/rendered formats, topics |
ape_user_bandit_state |
Strategy performance and cognitive facets |
ape_user_topic_interest |
Precomputed user-topic interest |
ape_topic_trend_daily |
Precomputed daily topic trends |
ape_user_directory |
Optional display names and outreach gates |
ape_messages is intentionally excluded.
Page Scope
The dashboard has one search input:
| Input | Mode | Behavior |
|---|---|---|
| Empty | Global | Platform overview, trends, active customers, global facets |
| Raw user id | Single user | Server hashes it and returns that user's profile |
u_<hex> hash |
Single user | Server passes it through without double-hashing |
Clicking an active-customer row fills the search input with that user's hash.
Main Sections
Platform Overview
Cross-user macro view:
- top topics
- top strategies
- stage funnel
- readiness funnel
- intent mix
- signal mix
- platform time series
- customer health
- RAG and instruction quality summaries
Active Customers
Outreach roster, sorted by readiness. Each row includes:
- display name if available
- user hash
- strongest topic
- interest score
- recent turn counts
- positive/negative engagement
- compliance status
- narrative reason
The outreach gate is:
interest_score >= threshold
AND compliance_eligible
AND NOT do_not_contact
Cognitive Facets
Global mode aggregates by (intent, topic, strategy) across users. Single-user
mode shows one user's cells and strategy preferences.
Topic Interest
Per-user topic scores:
interest_score =
weight_frequency * frequency_score
+ weight_recency * recency_score
+ weight_engagement * engagement_score
+ weight_followup * followup_depth_score
Recommended Outreach
Uses offer_policy rows plus user-topic interest scores. Endpoint path still
uses /analytics/offers/{user_id} for compatibility, but the UI label is
Outreach.
Recompute
POST /analytics/recompute?days=N rebuilds:
ape_user_topic_interestape_topic_trend_daily
It reads ape_turn_record only. It does not scan raw messages.
Use cases:
- after demo seeding
- after heavy chat activity
- scheduled cron refresh
- before screenshots or stakeholder review
The UI separates:
| Button | Work |
|---|---|
| Reload | Re-fetch current aggregate collections |
| Recompute now | Rebuild aggregates, then reload |
Endpoint Families
| Endpoint | Purpose |
|---|---|
POST /analytics/recompute?days=N |
Rebuild derived aggregate collections |
GET /analytics/platform-overview?days=N&top_n=K |
Cross-user dashboard summary |
GET /analytics/platform-timeseries?days=N |
Daily platform trend data |
GET /analytics/topics-timeseries?days=N&top_n=K |
Daily data for top topics |
GET /analytics/trends?days=N&limit=K&refresh=bool |
Trending topics |
GET /analytics/topic-timeseries?topic=X&days=N |
Daily counts for one topic |
GET /analytics/topic-users?topic=X&limit=K&min_score=Y |
Users interested in a topic |
GET /analytics/active-users?days=N&min_interest=X&limit=K |
Outreach roster |
GET /analytics/user-profile?user_id=X&domain=Y |
12-facet profile |
GET /analytics/cognitive-facets?user_id=X&min_interactions=N |
Per-cell facets; omit user_id for global |
GET /analytics/user-interests?user_id=X&limit=K&refresh=bool |
Per-user topic interest |
GET /analytics/user-timeseries?user_id=X&days=N |
Per-user daily activity |
GET /analytics/offers/{user_id}?domain=Y |
Recommended outreach actions |
GET /analytics/strategy-performance?user_id=X&min_pulls=N |
Strategy ranking and tiers |
GET /analytics/customer-health?days=N&cohort_weeks=K |
Satisfaction and retention style health metrics |
GET /analytics/rag-quality?days=N&min_turns=K&sample_limit=S |
Content correction and answer quality signals |
GET /analytics/instruction-quality?days=N&min_turns=K&sample_limit=S |
Format compliance and instruction issues |
Signal Interpretation
The signal mix should count both:
- entries in
pending_signals[] - the final resolved
signallabel, especially composite labels
That is why analytics can still show thumbs_up and thumbs_down even though
they do not directly update the format bandit.