Ad Network as a first class section: what to review โ
| Field | Value |
|---|---|
| Branch | feat/admin-and-merchant-portals, draft PR #976: feat(admin): portal navigation, financials and monitoring, plus the agent-process work behind them, not merged |
| Project | README.md |
| Issue | #986: feat(admin): promote Ad Network to a first class section with Delivery, Placements and Review tabs |
| Servers you need | Admin portal on http://localhost:3001 (npm run admin:dev). Admin Storybook on http://localhost:6008 (npm run storybook:admin) |
| Local origins | Required for the Delivery tab. The Review tab needs merchants-api, which already proxies locally |
| Test plan | docs/engineering/testing/runs/ad-network-first-class/README.md, 8 of 10 scenarios passed, 2 blocked on data |
Why does the Delivery row say "needs the local origins"? โ
The Delivery tab reads analytics-api, which the admin portal proxies to the DEPLOYED service by default. โ
.env.localpointsANALYTICS_API_ORIGINat Cloud Run, so the chart shows whatever last merged todev.- Restart the admin dev server after the
.env.localorigin change lands. Tracked as#1002: fix(dev-env): local dev proxies venues and analytics to Cloud Run, so branch backend changes are invisible locally.
What changed here? โ
Ad Network became a top-level Platform item beside Venues and Merchants. โ
- Your words on 2026-08-24: it needs its own dedicated considerations. It used to be
/admin/analytics/dashboards/ads, one tab among five, two clicks deep. - Option B was chosen: a section with tabs, not a bare promotion.
Three tabs, which are the ad lifecycle. โ
| Tab | What it is | Where it came from |
|---|---|---|
| Delivery | The existing Ad Delivery dashboard | Moved from analytics/dashboards/ads |
| Placements | The inventory view | New. The concept existed in the data with no surface owning it |
| Review | The gate an offer passes to enter the network | Moved from merchants/offer-review |
Merchants changes meaning as a result. โ
- With Offer review gone, Merchants is accounts and applications only. That is a real change to a section nobody asked to change, so it is named here rather than left to be discovered.
A defect was waiting at the destination, and its second half is the important one. โ
- The Offer review queue read empty on localhost regardless of what was in the database, with no error and no failed request. Two causes:
vite.config.mjsproxied no/api/adminroute, andparseResponseturned a non-JSON 200 (the app shell answering) into an empty list. - Both fixed. Verified rather than inferred: an unauthenticated request went from
200 text/htmlto401 application/json. - This is why the 2026-08-24 design survey recorded the queue as empty and reasoned about it as a product state. It was not a product state.
Where do I look, and what am I looking for? โ
The section and its tab strip http://localhost:3001/admin/ad-network โ
- It should redirect to
/admin/ad-network/delivery. - Three tabs: Delivery, Placements, Review. The sidebar entry should be top level under Platform, one click, beside Venues and Merchants.
Delivery http://localhost:3001/admin/ad-network/delivery โ
- Needs the local origins.
- It should render inside the section chrome rather than as a standalone analytics dashboard.
- The old path
/admin/analytics/dashboards/adsshould redirect here. - The chart still segments Hero, Inline, Feed and Unknown. Unknown is a data-quality bucket for rollup rows whose placement did not match the vocabulary, and it stays on the chart deliberately.
Placements http://localhost:3001/admin/ad-network/placements โ
- The inventory half is real: three surfaces, where each appears, how contended each is, with copy taken from the placement table in
docs/economics/AD_PLACEMENT_ECONOMICS.mdso the portal and the economics model use the same words. - The three per-surface figures (fill rate, eligible offers, CTR) render through
Scaffold, dated, pointing at an issue. They are not faked and they are not zeroes. A zero would have lied: it reads as "nothing is delivering" when the truth is "nothing has been asked". Unknownis deliberately absent from this tab. It is not inventory anyone can buy.
Review http://localhost:3001/admin/ad-network/review โ
- The queue should read
{"offers":[],"count":0}: genuinely empty in dev, which is a different claim from the one the survey made. - The old path
/admin/merchants/offer-reviewshould redirect here. - If it reads empty with no error at all, that is now the true state rather than the swallowed-error state. A failed request should now throw and show.
Storybook http://localhost:6008 โ
- Section, Delivery tab, Placements tab, Review tab.
- Placements and Ad Delivery on their own.
- Static captures in
screenshots/; live signed-in captures share../admin-venues-section/screenshots/live/.
What is deliberately NOT done? โ
The Offer review redesign. This project does the MOVE, not the redesign. โ
- You named that redesign separately. Keeping the two apart is what stops one build turning into three.
The per-placement aggregate behind the three figures. โ
- Filed before the surface was built, so the
Scaffoldnumber points at real tracked work rather than at a placeholder for a placeholder:#998: feat(analytics): expose a per-placement aggregate so the Ad Network Placements tab can show fill rate, eligible offers and CTR.
Pacing and fill rules. โ
- The Ad Delivery copy already gestures at them with nothing behind it. Out of scope for the move, named so it is not lost.
What open findings touch this project? โ
Cross-referenced from ../merchant-and-venue-dashboards/branch-review-0828.md.
AdDeliveryDashboard.jsxgot a diff read, not a line-by-line pass. It is one of four large rewrites the reviewer named as reviewed at a shallower depth than the rest.- The non-JSON 200 hardening was applied to
merchantsApi.jsand NOT toanalyticsApi.js. That is finding 7 in the review, and it belongs to the analytics surfaces rather than this one, but the Delivery tab reads through the unhardened path. - No finding in the review targets the Placements or Review tab directly.
What issue does each piece close? โ
| Piece | Issue | State |
|---|---|---|
| The section, its three tabs, and the moves | #986: feat(admin): promote Ad Network to a first class section with Delivery, Placements and Review tabs | Built on branch |
| The empty Offer review queue on localhost | #981: bug(admin): the Offer review queue reads empty on localhost, because vite proxies no /api/admin route | Closed, both halves fixed |
| The three per-surface figures on Placements | #998: feat(analytics): expose a per-placement aggregate so the Ad Network Placements tab can show fill rate, eligible offers and CTR | Open, scaffolded and dated |
The Scaffold component the figures render through | #991: feat(admin): a shared Scaffold component whose required props make a placeholder declare its age and its wiring issue | Built on branch |