From b91f9da2f4e2023e9c845db88f06aa70a81253d3 Mon Sep 17 00:00:00 2001 From: autocommit Date: Mon, 18 May 2026 22:15:12 -0700 Subject: [PATCH] =?UTF-8?q?docs(ai-copilot):=20=F0=9F=93=9D=20Update=20ana?= =?UTF-8?q?lytics=20dashboard=20documentation=20with=20cross-surface=20agg?= =?UTF-8?q?regation=20and=20attribution=20tracking=20details?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../docs/T-analytics-dashboard.brief.md | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/@platform/codebase/@features/ai-copilot/docs/T-analytics-dashboard.brief.md b/@platform/codebase/@features/ai-copilot/docs/T-analytics-dashboard.brief.md index e19973f..4319b02 100644 --- a/@platform/codebase/@features/ai-copilot/docs/T-analytics-dashboard.brief.md +++ b/@platform/codebase/@features/ai-copilot/docs/T-analytics-dashboard.brief.md @@ -93,6 +93,105 @@ The dashboard is the **strategist's front-window**, not a separate specialist. I - Per-city historical performance (cities Quinn has visited multiple times — what's the trend?). - Tour vs home-base revenue split. +## Cross-surface aggregation + attribution + +The panels above (T1 revenue, T2 funnel, T3 per-surface, T4 cohort, T5 tour ledger) all draw on cross-surface data. Three concerns govern how that data is rolled up + how prospect-funnel paths across surfaces get credit. **Owned UX-side here; engineering owned at [_engineering-surface-metrics.md](./_engineering-surface-metrics.md)** (schemas + scheduler + attribution model implementations). + +### §T-aggregate — Aggregation across surfaces + +**What aggregates and what doesn't**: + +| Panel | Aggregate-canonical? | Sources | +|---|---|---| +| T1 Revenue | **Yes** — sum across all surfaces with revenue signal | OF subs/tips, Tryst-driven bookings (per [surface-tryst.brief.md §9](./surface-tryst.brief.md)), Fansly, manual ledger entries, content PPV | +| T2 Funnel stage counts | **Yes** — counts roll across surfaces; per-source breakdown is a drilldown | Tryst profile-views, X impressions, OF subs, iMessage replies, etc. | +| T3 Per-surface | **No** — per-surface by definition; tier-gated empty-states honored per surface's `§canonical-facts` | Single-surface raw | +| T4 Cohort warmth | **Yes** — cohort defined by *first cross-surface touchpoint*; warmth weighted by all subsequent touchpoints | All touchpoints | +| T5 Tour ledger | **Yes** — per-leg revenue rolls across surfaces in the tour window | All revenue sources during leg dates | + +**Read path**: panels read from `metric_aggregates` (the materialized rollup table). Engineering's rollup cadence: 15 min active window, 1h recent, daily older, immutable past 90 days. + +**Freshness UI**: each aggregate panel shows a "computed N min ago" stamp in compact gray text (12pt). Tap to manually re-trigger rollup — `strategist` re-runs over the underlying surface_metrics. Per [T6b](#t6b--refresh-model), the pull-to-refresh affordance is intentionally low-affordance because inference costs real money. + +**Per-surface contribution breakdown**: every aggregate panel has a `surface_breakdown` chip stack (e.g. T1 revenue: `OF 62% · Tryst 21% · Fansly 17%`). Tap a chip → drilldown filters to that surface. + +**Tier-gating implication**: if Quinn is on Tryst Basic (no native analytics per [§canonical-facts](./surface-tryst.brief.md)), Tryst contributes nothing to view-count aggregates and shows `—` in surface_breakdown rather than `0` (zero would falsely suggest "no views" — `—` means "unmeasured"). T3 Tryst row shows the upgrade nudge; T1/T2/T4 aggregates honor the absence cleanly. + +**Insight chip (strategist)**: +> Revenue's up 18% — OF carrying it (62% share). Tryst views aren't measured at your tier; jumping to Standard would let me tell you whether Tryst's quietly contributing. + +### §T-attribution — Cross-surface touchpoint funnel + +**Where**: lives inside T2 funnel as an additional view-mode toggle (`Funnel · Top paths`). Default view is stage-counts (T2 above); `Top paths` switches to multi-surface chain visualization. + +**Top paths view**: +``` +Top funnel paths this week +───────────────────────────── +Tryst → iMessage → OF subscription · 8 conversions · $312 revenue +X → OF subscription · 5 conversions · $185 revenue +Eros → iMessage → booking · 3 conversions · $1,800 revenue +Tryst → Signal → booking · 2 conversions · $1,200 revenue +(11 single-touch paths consolidated) · 11 conversions · $267 revenue +``` + +Each path is a clickable row → opens chat with strategist scoped to "explain this path; tell me what works." + +**Per-prospect view** (in `prospect-detail.screen.md` — companion to brief B3): +``` +Felix · first-touch Tryst (Apr 8, 14:02) + ↓ 19 hours + iMessage (Apr 9, 09:14) + ↓ 13 hours + OF subscription (Apr 9, 22:11) + ↓ ongoing + 3 tips totaling $47 + +Attribution credit (time-decay default): + Tryst 60% + X 0% + OF 40% +Lifetime revenue: $89 +``` + +**Privacy** (per [_engineering-surface-metrics §9](./_engineering-surface-metrics.md)): +- Anonymous touchpoints (profile_view with no identifier match) **aggregate only** — they count in T2 funnel top-of-funnel totals, never appear in per-prospect paths. +- Per-prospect paths are Quinn-only — never visible to coop peers (per [brief N](./N-provider-coop.brief.md)), never shared org-wide pre-explicit-consent (W §W4 deferred). +- Brief V data-export covers Quinn's full attribution graph as her data. + +**Insight chip (strategist)**: +> Your warmest path this month is Tryst → iMessage → OF. The Tryst-first prospects who DM within 48h convert at 3× the rate of cold OF subs. Want me to draft a Tryst-bio nudge to point more of them to iMessage faster? + +### §T-attribution-model — Model picker + +A small chrome control in T2 + on prospect-detail.screen.md that selects which attribution model is in use for the displayed numbers: + +``` +Attribution: [ Time-decay ▾ ] (?) + ├─ First-touch + ├─ Last-touch + ├─ Time-decay (default) + └─ Position-based (40/40/20) +``` + +**Model semantics** (per [_engineering-surface-metrics §8](./_engineering-surface-metrics.md)): +- **First-touch** — 100% credit to the earliest surface. Brand-discovery view. +- **Last-touch** — 100% credit to the surface that hosted the conversion. Conversion view. +- **Time-decay** (default) — exponential decay, 7-day half-life. Balanced; favors recent-but-not-only-recent. +- **Position-based** — 40% first / 40% last / 20% middle. Surfaces middle-funnel value. + +**(?) info popover** explains the choice in plain voice: +> Different attribution models tell different stories. Time-decay is the balanced default — Cocotte gives more credit to recent touches without ignoring the first one. Switch to First-touch when you want to see what's bringing prospects in; Last-touch when you want to see what's closing. Same data, different lens. + +**Persistence**: per-Quinn preference, stored in `users.attribution_model_pref`. Model selection updates instantly (no recompute — engineering computes all four models in parallel; the picker just selects which is displayed). + +**Tap the (?)** → opens chat with strategist scoped to "help me pick an attribution model." + +**Insight chip (strategist, when Quinn switches model)**: +> Switched to First-touch — Tryst's credit jumped to 78%. That's where prospects discover you. Switch back to Time-decay (default) to see what's actively warming them right now. + +--- + ## T6 — Dashboard chrome and access ### T6a — Where the dashboard lives @@ -159,6 +258,9 @@ The dashboard is **operator-facing only**. Never exported, never embedded in out - **T-Q3** Anomaly threshold — what counts as worth a chat surfacing vs just an insight-chip change? Lean: ±20% revenue WoW, ±10pp funnel-stage conversion shift, cohort flatline >2 weeks. Engineering-tunable. `[engineering]` - **T-Q4** "Tell me more" handoff continuity — does the chat thread that opens from a panel keep that panel pinned at the top while strategist explains? Lean: yes, the panel pins as a card-style reference while the conversation flows below it. `[nice-to-have]` - **T-Q5** Per-cohort experiments — when Quinn approves a strategist-proposed price test or DM-cluster from the dashboard, where does that action's progress surface afterward? Lean: in the dashboard panel that spawned it, with a "test running, day 3 of 7" status. `[nice-to-have]` +- **T-Q6** Attribution model default — Time-decay proposed (7-day half-life); confirm half-life against Quinn's actual sales cycle (SM-Q3 in `_engineering-surface-metrics.md`). `[engineering]` +- **T-Q7** Attribution per coop — should cross-coop revenue attribution be visible at all, or strictly per-coop-isolated? Lean: per-coop-isolated unless explicit coop-data-share consent. `[blocking once P5 multi-org lands]` +- **T-Q8** "Top paths" view — how many paths to show before consolidating to "(N single-touch paths)"? Lean: top 8 multi-touch + consolidated single-touch tail. `[nice-to-have]` ## Related @@ -170,3 +272,7 @@ The dashboard is **operator-facing only**. Never exported, never embedded in out - [strategist contract](./specialist-strategist.contract.md) — T is strategist's front-window. - [voice](./00-system-voice.md) §V4 — strategist voice lean (working). - [brief K](./K-safety-blocklist.brief.md) — revenue figures never echoed outward. +- [_engineering-surface-metrics.md](./_engineering-surface-metrics.md) — schemas + ingestion + scheduler + attribution model implementations powering §T-aggregate / §T-attribution / §T-attribution-model. +- [_engineering-talent-scout-port.md §0.2](./_engineering-talent-scout-port.md) — design rationale for cross-surface aggregation + attribution. +- [specialist-prospect-resolver.contract.md](./specialist-prospect-resolver.contract.md) — touchpoint linking (resolves which touchpoints belong to which prospect). +- [surface-tryst.brief.md §canonical-facts](./surface-tryst.brief.md) — tier-gating example (Basic tier shows `—` not `0` in surface_breakdown).