From integration to per-practice operating surface across the organic channel stack.
TL;DR. We just unlocked 30 Gen4 (PromoRepublic) tools from the original 6 by re-OAuthing with the right scopes. The warehouse already lands 83 practice locations and the network-wide rollups every night. This roadmap turns that into a per-practice and per-region operating surface across five phases over about seven weeks.
Per-practice data is the rate-limiting step. Every downstream phase depends on Phase 3 closing the practice ↔ Gen4 location bridge.
marketing.gen4_snapshots · raw JSON-API payloads, one row per tool call, JSONB data columnmarketing.gen4_sync_runs · audit log, status, errorsmarketing.gen4_locations · 83 locations cataloged with raw attributesmarketing.gen4_oauth_state · rotated refresh tokens persist across service restarts/admin/gen4 · sync trigger, runs table, snapshot drawer, live tool catalog/marketing/gen4 · network-wide social audience, content, top postsscripts/gen4-oauth.py · self-contained DCR + PKCE + RFC 8707 helperGoal. Close the location bridge so every single-location tool call lands keyed to a known SGA practice. This is the foundation for every downstream phase.
name + city + state against shared.practices with a confidence score. Wire as a one-shot endpoint POST /api/v1/gen4/locations/auto-match./admin/gen4/locations. Three tabs: matched (≥80 confidence), needs review (40–79), unmatched (<40). Manual confirm or reassign per row.location_id on each snapshot row.GET /api/v1/gen4/snapshots?practice_id=X returns rowsGoal. Click any practice → see its organic performance at a glance. Audience, posts, GBP, reviews, reputation. Plain answers to "how are we doing?"
/marketing/practices/:practiceId — add an "Organic Channels" section between existing KPI tiles and the campaign breakdown.
| Card | Tool source | What you see |
|---|---|---|
| Social Performance | get_social_performance_single_location | Audience by network with sparkline + delta. Engagement total + breakdown. |
| Content Performance | get_social_content_performance_single_location | Posts published + top performing post with thumbnail + publishing rhythm. |
| Google Business Profile | get_gbp_performance_single_location | Views, calls, direction requests, photo views. |
| Local Visibility | get_local_visibility_single_location | Average ranking, ranked keywords count, search engines visible on. |
| Review Performance | get_review_performance_single_location | Average rating, review velocity, recent reviews list. |
| Reputation | get_reputation_insights_single_location | Sentiment trend, top topics, alerts. |
Practice without Gen4 mapping shows a "This practice doesn't have Gen4 coverage. Request setup →" CTA that links to the admin map page.
Goal. Marketing leadership can answer "which practices need a call this week" in under 2 minutes.
Upgrade existing /marketing/gen4 from "stats wall" to "decision surface."
Goal. Korrine stops opening individual Gen4 dashboards per practice.
New /tasks-app/social-ops — lives next to standup + sprints in the tasks shell.
| Section | Tool source | Action |
|---|---|---|
| Centralized inbox | get_inbox_conversations | All DMs across all locations, sort by unread |
| Failed posts triage | get_failed_posts_all_locations | Queue per practice with error + retry/dismiss |
| Low publishing alerts | get_low_publishing_locations | List of practices below threshold posts/week |
| Scheduled posts calendar | get_scheduled_posts_all_locations | Cross-practice month view, filter by network |
| Phase | Length | Cumulative | Depends on |
|---|---|---|---|
| 3 · Practice bridge | 1 week | Week 1 | Phase 1+2 shipped |
| 4 · Practice surface | 1.5 weeks | Week 2.5 | Phase 3 |
| 5 · Network intelligence | 1 week | Week 3.5 | Phase 4 (uses per-practice data) |
| 6 · Ops tools | 1.5 weeks | Week 5 | Phase 3 (location mapping) |
| 7 · AI insights | 2 weeks | Week 7 | Phases 3 + 4 + 5 |
Phases 5 and 6 can run in parallel once Phase 4 is shipped, shaving ~1 week if needed.
invalid_grant.Begin Phase 3 immediately. It's the rate-limiting step for every downstream phase, and the work is mechanical (matcher + admin page + cron). Ship a canary sync before committing the full nightly cron.