All work / 05 of 07 · AI engineering

GHL Automation Scorecard.

A self-service dashboard that shows the hours saved per month (and dollar value) by every automation running across four brands — embedded as a widget inside each brand’s GoHighLevel sub-account, same pattern as the live TOFAC uptime widget.

Client
Internal (Remodeling Concepts, Ryann Reed, Wood Lane, TOFAC)
Role
Architect + solo engineer
Year
2026
Status
Architecture locked, RC adapter in build
GHL Scorecard overview tab shown on a monitor — marketing mockup
01 · Context

“What is Mike actually doing for us this month?”

As the automation footprint grew, “what is Mike actually doing for us this month?” became a real question. Hours-saved was the right answer; nobody had numbers.

The data is all in GHL — calendar events, conversation messages, contact creation, tag history — it just needed someone to count it and put a multiplier on each event type.

02 · Problem

One number, four shapes of data.

  • Each brand uses GHL differently (RC = native calendar; RR = custom-field appointments; WL = mixed).
  • A naive solution would be three one-off dashboards that drift apart.
  • The widget has to live inside GHL so the audience sees it without leaving their CRM.
  • Numbers also have to be portfolio-credible — “I save my clients X hours/month” is a sales line for me.
03 · What I built

One scorecard view, one adapter per brand.

A brand-adapter pattern in the existing TOFAC Next.js app: one shared scorecard view, one per-brand adapter class that knows how to query that brand’s GHL data (calendar vs. custom field vs. mixed). Three headline cards — Hours Saved MTD, $ Value Saved, Top Driver — rendered behind a signed embed token so it can drop into any GHL dashboard via iframe.

Architecture

GHL: RC GHL: RR (custom fields) GHL: WL TOFAC: Supabase │ │ │ │ ▼ ▼ ▼ ▼ adapter:RC adapter:RR adapter:WL adapter:TOFAC │ │ │ │ └────────────────────── normalized event stream ─────────────────────┘ │ ▼ Σ (event_count × min/event) │ ▼ [HOURS SAVED MTD] [$ VALUE SAVED] [TOP DRIVER] │ ▼ Signed embed → iframe inside each GHL dashboard

Stack

Next.js 16 GHL API (Private Integration Tokens) Supabase Signed embed tokens (HMAC) Per-brand adapter classes Config-driven multipliers Vercel

Key decisions

  • Brand-adapter pattern from day one. Considered RC-only first then refactor — rejected because the cost of writing one shared scorecard view is ~half a day and pays back the first time RR plugs in.
  • RC ships first, RR second, WL third. RC uses native GHL Calendar (standard API path) and has the most data — biggest, most credible launch number. RR uses custom fields for appointments — bespoke adapter — better as brand #2 to validate the pattern works.
  • Same embed pattern as TOFAC uptime widget, which is already in production at golf.ryannreed.com/uptime/embed. Reused signed-token + iframe approach. Independent secrets per surface.
  • Multipliers live in a config file, not hard-coded. Self-booked appointment = 12 min, auto-reply = 3 min, form contact = 3 min, tag from workflow = 1 min. Easy to tune as the model gets more honest.
  • Read-only GHL scopes only. This thing reports. It does not touch.
  • Phase 2 = portfolio-level “all-brands aggregate” — the sales-material money shot (“Saved $X across 4 clients last month”). Same adapters, one extra view.
04 · Selects

One scorecard, five lenses on the brand.

Each tab answers a different operator question: am I selling enough, are leads moving through, is marketing converting, is social driving discovery, is email landing? Same widget pattern, swapped data adapter underneath. (Numbers and names below are scrubbed for portfolio display.)

Sales tab
Sales · pipeline + funnel
Marketing tab
Marketing · traffic + sources
Social tab
Social · channel metrics
Email tab
Email · engagement + deliverability
05 · Outcome

Architecture locked, RC adapter in build.

Targets below are planning-stage estimates for the RC + RR launch window.

4
Brands on one shared scorecard
~127h
Estimated hours saved per month (target, RC + RR combined)
~$3,175
Estimated dollar value per month (target, at $25/hr)

Architecture is locked, RC adapter is in build. The TOFAC uptime widget already proves the embed pattern works inside GHL; this just swaps the data source. The interesting design constraint turned out to be honesty — the multipliers have to under-promise or the number stops being credible to the people whose time it represents.

06 · Lessons

What I’d do the same. What I’d do differently.

Keep: Pick the boring multiplier. Better to be conservative and trusted than aggressive and questioned.

Keep: Lift the embed token pattern from the prior surface instead of inventing a second one. Same security model, separate secrets.

Change (planning): The standalone repo / shared-with-Marketing-Dashboard split took longer to decide than it should have. Worth ~30 minutes of architecture discussion up front next time.