Analytics
Measurement and intelligence — what happened, what competitors are doing, and what the system should learn from both.
Back to the workflows index.
What this vertical means here
Analytics OS is the fifth spoke off Mktg OS on page 1. Page 3 adds
Deep Analytics / Call Analytics and Competition Research; page 5 lists
Dashboard / Analytics as deliverable ⑤.
The live surfaces here are strong — competitor analysis and the learning profile are among the more sophisticated things in the product — but they are intelligence, feeding content decisions. The measurement half, reporting on outcomes, is thin.
Workflows
| Workflow | Status | Where |
|---|---|---|
| Competitor analysis — competitors, reels, comparison | ✅ Live | Competitor Analysis |
| Reel topic derivation — per-reel topic + summary, vision retry | ✅ Live | Competitors tab, Discovery + Daily Studio |
| Instagram learning profile (v2) — OAuth → metric sync → analysis | ✅ Live | Learning |
| Platform admin dashboard — activity + token analytics | ✅ Live | Admin → Dashboard |
| Feed scoring — authority, authenticity, relevance, brand fit | ✅ Live | Discovery |
| Health checks | ✅ Live | /health, Admin → Health |
| Unified Dashboard / Analytics | 🟡 Partial | Deliverable ⑤ — admin dashboard exists; no tenant-facing marketing dashboard |
| Deep Analytics / Call Analytics | ⬜ Planned | Page 3 |
| Program measurement | ⬜ Planned | A6 on page 2 |
| Attribution | ⬜ Planned | Implied, never drawn |
What's live, in detail
Competitor analysis
Two separate stores, bridged rather than merged:
- Your own account lives in the learning store — connections, reels, metric snapshots, written by the Instagram Graph sync.
- Competitors live in the
ops_ca_*store.
buildComparison bridges them: it refreshes the own-profile row when it's older
than 6 hours, in parallel with the competitor reads and behind an 8-second
timeout, so a slow Instagram call can never blank the comparison. Competitors
refresh in batches of 3.
Own-profile sync prefers the Meta provider (real Graph data via the stored OAuth token) and falls back to Apify only when Meta returns no follower count — i.e. a personal account.
Reel topics
Genuinely careful work, and worth understanding before changing:
- Captions are stripped of promo boilerplate first — "follow for more" describes the account, not the reel.
- Candidate topics are rejected by a promo filter at every exit: deterministic fallback, LLM output, and hashtag pick alike.
- Unresolved reels report a
NO_TOPICsentinel rather than inventing a category. - Only those get one cover-frame vision retry, capped per refresh, SSRF-guarded.
The same vision call returns a 1–2 sentence summary of what the reel covers, overwriting the deterministic one — which describes the caption's shape (hook, style, CTA) and reads as boilerplate on topic cards. Both are persisted, so changing the prompt requires a refresh to take effect.
This is deliberately not the learning page's media pipeline, which downloads the video and needs ffmpeg + Whisper — far too heavy for a per-refresh path.
Learning profile
OAuth connect → cron metric sync → reel analysis → learning profile (v2). Feeds hook formulas and creator voice into ATL script generation.
Token analytics
The platform admin dashboard tracks usage by feature and operation — every agent
call is attributed (feed, compliance, blogs, with operations like
draft_generation, quality_repair, feed_review, blog_review).
This is the one place the system measures itself well.
What's missing
A tenant-facing marketing dashboard. Deliverable ⑤ on page 5 is
Dashboard / Analytics. What exists is a platform admin dashboard — activity
and token spend. A marketing lead has no view of what their content did.
Content performance. The system knows what it produced. It does not report on how any of it performed after publishing. Instagram metrics sync for learning, not for reporting.
Deep analytics / call analytics. Page 3 names it twice. Nothing exists.
Program measurement (A6). Page 2 sets rupee targets per play; nothing
measures against them. See Program.
The feedback loops. Page 6 tags three as end-state, all of them analytics work:
- Learn from what we have done →
ES- Scan competition to get insights →
ES- Scan category to get insights →
ES
The second is partially served by competitor analysis. The first and third are not started. Notably, the Discovery Agent never learns which enriched items a human actually queued — so the feed does not improve with use.
Dependencies
| Needs | For |
|---|---|
| Meta / Instagram Graph OAuth | Own-profile metrics, learning |
| Apify | Competitor scraping, personal-account fallback |
| OpenAI vision | Reel cover-frame topic + summary |
Coolify cron → /api/internal/instagram-sync | Metric sync |
Coolify cron → /api/internal/news-fetch | Daily sweep, competitor refresh |
| ffmpeg + Whisper | Learning-page media pipeline only |
The daily sweep fires competitor refresh per modules.competitors.enabled
tenant and does not await it — it is a paid Apify scrape plus an LLM topic
pass that can run for minutes. That module flag is the cost control.
Workflow specs in this folder
- Competitor Analysis
- Instagram Learning Profile
- Marketing Dashboard
- Reel Topic Derivation
- Token & Activity Analytics
Roadmap source
Pages 1 (Analytics OS spoke), 3 (Deep Analytics, Competition Research,
monitoring/optimization), 5 (deliverable ⑤), 6 (the three ES feedback loops).
See ../../roadmap_ref_extracted.md.