NWS · Live
Spend (30D)$24,165·
Leads289·
CPL$84·
Closed Deals9·
CPA$2,685·
Revenue$28,358·
Cash Collected$21,361·
ROAS1.17x·
CTR1.88%·
Meta Spend$18,984·
Spend (30D)$24,165·
Leads289·
CPL$84·
Closed Deals9·
CPA$2,685·
Revenue$28,358·
Cash Collected$21,361·
ROAS1.17x·
CTR1.88%·
Meta Spend$18,984·
Settings · Data Sources & Sync

Where the numbers come from.

Manage the connections that power this dashboard. Sync jobs run hourly via Vercel Cron; trigger them manually from API Status.

Reporting Period
No syncs yet · syncs hourly
Sources Connected
4 / 4
Sync Frequency
Every hour
Architecture
ETL → Supabase
No direct API calls from frontend

Data Flow


  ┌─────────────────────────────────────────────────────────┐
  │  SOURCES                                                 │
  │                                                          │
  │   Google Ads ─┐                                          │
  │              ├──→ SyncWith ──→ Google Sheet (Ad Spend)  │
  │   Meta Ads ──┘                          │                │
  │                                         │                │
  │   NWS Sales Sheet ──────────────────────┤                │
  │   (Sold Data tab)                       │                │
  └─────────────────────────────────────────┼────────────────┘
                                            ▼
  ┌─────────────────────────────────────────────────────────┐
  │  Vercel Cron Jobs (hourly)                               │
  │    /api/sync/sheet              — sales sheet            │
  │    /api/sync/google-ads-sheet   — Google via SyncWith    │
  │    /api/sync/meta-sheet         — Meta via SyncWith      │
  └────────────────────┬────────────────────────────────────┘
                       ▼
  ┌─────────────────────────────────────────────────────────┐
  │  Supabase (nws_* tables)                                 │
  │    nws_campaigns       nws_leads                         │
  │    nws_ad_spend_daily  nws_sync_log                      │
  └────────────────────┬────────────────────────────────────┘
                       ▼
  ┌─────────────────────────────────────────────────────────┐
  │  Dashboard (Next.js Server Components)                   │
  │    Reads only via SQL — no direct API calls              │
  └─────────────────────────────────────────────────────────┘
            

Connected Sources

Supabase

LiveBackend database

Stores all synced data. Cron jobs write here. Dashboard reads from here. Tables prefixed nws_*.

Sales Sheet — Closed Deals

LiveGoogle Sheets API (service account)

NWS's 'Sold Data' tab. Closed deals, sale value, cash collected, UTM attribution. Read hourly.

Google Ads — Daily Spend

LiveSyncWith → Google Sheet → Supabase

SyncWith pulls Google Ads campaign data into a Google Sheet hourly. The dashboard reads that sheet via the same service account as Sales. No Developer Token or MCC needed.

Meta Ads — Daily Spend

LiveMeta Marketing API (direct)

Pulls campaign insights (spend, impressions, clicks, lead conversions) directly from the Meta Marketing API using a system-user token. Synced hourly.

Sync Schedule

Sales Sheet
0 * * * *
Every hour, on the hour
Google Ads (SyncWith)
5 * * * *
Every hour, 5 past
Meta Ads (SyncWith)
10 * * * *
Every hour, 10 past — when configured
SyncWith handles platform-side authentication (Google Ads, Meta) on its end. Our cron job just reads the populated Google Sheets via service account — same simple pipeline for all sources.

Required Environment Variables

Live in D:\AdSpendDashboard\.env.local (local) and Vercel project settings (production). Never commit secrets to git.

Supabase
NEXT_PUBLIC_SUPABASE_URLset
NEXT_PUBLIC_SUPABASE_ANON_KEYset
SUPABASE_SERVICE_ROLE_KEYset
Sales Sheet — Closed Deals
GOOGLE_SERVICE_ACCOUNT_PATHunset
LEADS_SHEET_IDset
LEADS_SHEET_RANGEset
Google Ads — Daily Spend
GOOGLE_SERVICE_ACCOUNT_PATHunset
Meta Ads — Daily Spend
META_ACCESS_TOKENset
META_AD_ACCOUNT_IDset