Medium Dashboards system

Campaign Performance View

A campaign-level view that ties leads and bookings back to the campaign/UTM that drove them and reports volume, cost-aware efficiency (if spend is provided), and downstream quality — booked rate and completed rate per campaign — so spend follows what converts, not just what clicks. It joins captured UTM campaign data to lead outcomes and optionally an imported spend table. Strictly an analytics view over campaign metadata; it does not run ads.

5 to 9 days
timeline
Medium
complexity
5
tools
4
steps

Built with real HMX dashboard tool paths

Supabase PostgresUTM captureSQL joinsCSV/table spend importNext.js 16 server componentsSupabase PostgresUTM captureSQL joinsCSV/table spend importNext.js 16 server components

01 // System facts

System facts

Campaign Performance View uses a reporting model and review layer for Dashboards. A campaign-level view that ties leads and bookings back to the campaign/UTM that drove them and reports volume, cost-aware efficiency (if spend is... The architecture connects ensure campaign metadata is, supabase postgres, utm capture, and owner review with an explicit control path.

Outcome

Owners can see which campaigns produce booked, qualifying leads versus just traffic — directing budget toward what actually converts and flagging campaigns that look busy but don't book.

Main risk

Lost UTMs (direct/null) and a large unattributed bucket make per-campaign conclusions unreliable, especially with low per-campaign volume.

Prevention

Surface the unattributed bucket explicitly, suppress rate rankings below a minimum-volume threshold, and reconcile campaign counts against total leads so nothing is silently dropped.

Fallback

If spend data isn't available, ship the volume-and-quality view (booked/completed rate per campaign) without cost metrics, and add efficiency once a spend source exists.

System architecture

Campaign Performance View Architecture

6 nodes
Ensure campaign metadata is
SQL joining leads ->
Supabase Postgres
UTM capture
Review Queue
Owner Review
  1. 01Ensure campaign metadata is

    A campaign-level view that ties leads and bookings back to the campaign/UTM that drove them and reports volume, cost-aware efficiency (if spend is...

  2. 02SQL joining leads ->

    Write SQL joining leads -> campaign with counts, booked/completed rates per campaign, and, if spend is present, cost-per-lead and cost-per-booked.

  3. 03Supabase Postgres

    Supabase Postgres contributes the trusted model for Campaign Performance View so metrics are defined before they are visualized.

  4. 04UTM capture

    Build a campaign table/panel (server component) sortable by volume or efficiency, with downstream quality columns so a high-volume low-quality campaign is obvious.

  5. 05Review Queue

    If spend data isn't available, ship the volume-and-quality view (booked/completed rate per campaign) without cost metrics, and add efficiency once...

  6. 06Owner Review

    Owners can see which campaigns produce booked, qualifying leads versus just traffic — directing budget toward what actually converts and flagging c...

How it is built

Build steps

A campaign-level view that ties leads and bookings back to the campaign/UTM that drove them and reports volume, cost-aware efficiency (if spend is provided), and downstream quality — booked rate and completed rate per campaign — so spend follows what converts, not just what clicks. It joins captured UTM campaign data to lead outcomes and optionally an imported spend table. Strictly an analytics view over campaign metadata; it does not run ads.

  1. 01Ensure campaign metadata (utm_campaign/source/medium) is captured per lead and define how to optionally import spend per campaign (a small CSV/table the owner maintains).
  2. 02Write SQL joining leads -> campaign with counts, booked/completed rates per campaign, and, if spend is present, cost-per-lead and cost-per-booked.
  3. 03Build a campaign table/panel (server component) sortable by volume or efficiency, with downstream quality columns so a high-volume low-quality campaign is obvious.
  4. 04Add a 'thin data' guard so campaigns with too few leads aren't ranked on noisy rates, and an 'unattributed' row so totals reconcile.

Tools

Workflow surface

  • Supabase Postgres
  • UTM capture
  • SQL joins
  • CSV/table spend import
  • Next.js 16 server components
  • Inputs layer: Ensure campaign metadata (utm_campaign/source/medium) is captured per lead and define how to optionally import spend per campaign (a small CSV/table the owner maintains).
  • Transform layer: Write SQL joining leads -> campaign with counts, booked/completed rates per campaign, and, if spend is present, cost-per-lead and cost-per-booked.
  • Metrics layer: Supabase Postgres contributes the trusted model for Campaign Performance View so metrics are defined before they are visualized.
  • Visualization layer: UTM capture handles refresh, review, or reporting delivery while surface the unattributed bucket explicitly, suppress rate rankings below a minimum-volume threshold, and reconcile campaign counts against total le...
  • Action layer: Owners can see which campaigns produce booked, qualifying leads versus just traffic — directing budget toward what actually converts and flagging c...

Data flow

  1. 01Ensure campaign metadata (utm_campaign/source/medium) is captured per lead and define how to optionally import spend per campaign (a small CSV/table the owner maintains).
  2. 02Write SQL joining leads -> campaign with counts, booked/completed rates per campaign, and, if spend is present, cost-per-lead and cost-per-booked.
  3. 03Build a campaign table/panel (server component) sortable by volume or efficiency, with downstream quality columns so a high-volume low-quality campaign is obvious.
  4. 04Add a 'thin data' guard so campaigns with too few leads aren't ranked on noisy rates, and an 'unattributed' row so totals reconcile.

Controls and fallbacks

  • Lost UTMs (direct/null) and a large unattributed bucket make per-campaign conclusions unreliable, especially with low per-campaign volume.
  • Surface the unattributed bucket explicitly, suppress rate rankings below a minimum-volume threshold, and reconcile campaign counts against total le...
  • If spend data isn't available, ship the volume-and-quality view (booked/completed rate per campaign) without cost metrics, and add efficiency once...