Skip to main content

Knowledge > Products > Growth Command Center

Growth Command Center (GCC)

The GCC is the founder-facing growth dashboard — NOT a customer product. It gives the founder one place to work the 28K+ unified leads model (which had no UI before 2026-06-09), run campaign preflight, watch ads attribution, monitor list health, and compare email variants. Shipped as four stacked PRs in one session — #840 (core: portfolio overview, leads CRM, tasks), #841 (campaign detail, preflight center, pipeline, demo readiness), #843 (ads attribution, GA4/Meta tags, conversion fan-out, list health), #844 (contact logging, org history, what-they-received, variant performance) — all merged 2026-06-09 and Playwright-verified on deployed preview + production.

Design rule: GCC has ZERO send/approve endpoints. Sending stays in the existing outreach-engine flows with founder press (CASL). Bulk actions on leads are suppress-only (DNC).

Route & Auth

  • UI: churchwiseai.com/founder/[token]/growth (sub-routes per tab below; pill nav in GrowthNav.tsx)
  • API: /api/founder/growth/* — founder token auth (founder-auth.ts, ?token=)
  • Detail pages outside the nav: growth/campaigns/[id] (campaign detail) and growth/orgs/[id] (org-level combined history)

Surfaces (nav tabs)

TabRoute segmentWhat it does
Overview/growthPer-property rollups + risk flags + Property→Vertical→Product→Campaign matrix (PortfolioOverview, PortfolioMatrix). Campaign property backfilled in PR #863 so CWA/SermonWise cards show true campaign + sent counts.
Leads/growth/leadsCRM over leads (28K+ rows, server-paginated). Bulk DNC (suppress-only), status, task, CSV export. LeadDrawer shows merged timeline, manual contact logging (call/email/meeting/sms → append-only lead_events), and "what they received" — exact draft subject/body + demo /s/<slug> + kit /p/<token> links in a sandboxed viewer.
Pipeline/growth/pipelineMRR-estimated pipeline board (PipelineBoard).
Preflight/growth/preflightPreflight Center wraps the 11-gate runCampaignPreflight verbatim + a GCC warning layer with acknowledgements stored in growth_settings (preflight_ack:<campaignId>).
Demos/growth/demosDemo readiness view (DemoReadiness).
Demo Leads/growth/demo-leadsInbox of demo-lead captures (quote wizard / chat / voice) from /s/{slug} demos — added for local-business demos with founder alert in PR #868 (2026-06-11).
Variants/growth/variantsA/B/C email-variant + demo-segment performance comparison (VariantPerformance).
List Health/growth/list-healthSuppression breakdown + live MailerLite status (MAILERLITE_API_KEY set).
Tasks/growth/tasksMarketing task queue (marketing_tasks table, TasksQueue).

Campaign detail gained send controls in PR #862 (2026-06-10): CampaignSendPanel — dry-run, typed SEND gate, live progress, Stop, auto-attach to a running durable send — plus per-member draft preview modal. PR #863 (2026-06-10) added SendReadyPanel (whole-DB real-gate send-ready scan, one-click into the send modal).

Ads attribution (PR #843 + follow-ups)

  • AttributionCapture sets cwa_attr_first (set-once) / cwa_attr_last (always) cookies for utm/gclid/wbraid/gbraid/fbclid + fbp/fbc; consent-gated like PostHog; excluded on /s/ /p/ /preview/; persisted to leads.first_touch/last_touch jsonb via upsertLead.
  • MetaPixel.tsx replaced the old inline pixel (which fired on /s/ church pages with no consent gating).
  • GA4 LIVE since 2026-06-10, measurement ID G-NJ89LPGHFX (PR #845) — required three stacked fixes: imperative gtag bootstrap, BOM/CRLF-proof env handling, CSP allowlisting of googletagmanager.com + GA collect domains.
  • ad-conversions.ts fan-out fires from outreach-attribution.ts post-conversion: Meta CAPI live; Google Ads fan-out is a stub awaiting GOOGLE_ADS_* credentials. PR #869 (2026-06-11) added paid-ads prerequisites: GA4 key events + purchase, click-ID persistence, conversion fan-out. PostHog remains the analytics source of truth; platform tags exist for ad-network conversion signals.

Code conventions

  • Lib in src/lib/growth/ — server modules import 'server-only', return null on error with console.warn('[gcc]...'); pure logic lives in client-safe *-shared.ts files testable via node --import tsx --test.
  • Portfolio registry layers on existing src/lib/property-registry.ts — do not duplicate it.
  • lead_events is append-only (founder_note / stage_change / contact_logged).
  • Additive migrations only (applied via Supabase MCP): marketing_tasks, growth_settings (kv: domain_health:<domain>, preflight_ack:<campaignId>), leads.first_touch/last_touch jsonb.
  • Stacked-PR lesson (from the 4-PR ship): after squash-merging a base PR, reconcile the next stacked branch by merging origin/main INTO it (never force-push); add/add conflicts on GCC-only files resolve --ours; vercel ls "Ready" is the prod-deploy signal — SSR-content marker probes gave a false positive mid-build.

Data sources

leads (+ first_touch/last_touch), lead_events, lead_organizations, marketing_tasks, growth_settings, outreach_campaigns, campaign_members, outreach_contacts, outreach_send_audit, email_unsubscribers, local_businesses (demo-leads surface). List Health additionally calls the MailerLite API live.

How to verify

  1. Open https://churchwiseai.com/founder/<founder-token>/growth — 9 nav pills render (Overview … Tasks) with a "← Dashboard" link back.
  2. Overview shows per-property cards with non-zero campaign/sent counts (CWA showed 19 campaigns / 1,917 sent after the #863 backfill).
  3. Leads tab paginates the leads table; opening a lead shows timeline + "what they received" links that resolve 200.
  4. Preflight tab runs against a real campaign and reports the 11 gates.
  5. GA4: any marketing page fires /g/collect 204 with G-NJ89LPGHFX; GA and Meta pixels are ABSENT on /s/ demo pages.

Open follow-ups

  • Google Ads conversion fan-out stub — blocked on GOOGLE_ADS_* credentials.
  • Per-tab Playwright coverage exists from ship sessions (7/7 on #862, 4/4 on #863, 12/12 on #841/#844) but there is no single recurring GCC regression suite.

Verified: 2026-06-11 (route files + tables confirmed against origin/main; PR numbers/dates from git history and DECISION_LOG 2026-06-09/10/11 entries).