Media Buyer

Internal command center for tracking Meta ads and GoHighLevel performance across clients.

v1.0.0Updated Jul 11, 2026, 11:34 AM UTC

Media Buyer

📘 Operator SOP — docs/SOP.md

If you're using this tool, start here. The SOP covers first-time onboarding plus daily, weekly, and monthly routines in plain English. The rest of this README is the developer reference (env vars, storage adapters, API routes).


This is a Next.js project bootstrapped with create-next-app.

Getting Started

First, run the development server:

npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev

Open http://localhost:3000 with your browser to see the result.

You can start editing the page by modifying app/page.tsx. The page auto-updates as you edit the file.

This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.

Meta Command Center

Internal tool for tracking Meta ads performance across all clients.

Pages

  • /meta/overview — All clients, KPIs, health status, anomalies
  • /meta/clients/[clientId] — Client detail with charts and trends
  • /meta/anomalies — Red/yellow accounts with reasons
  • /meta/settings — Client mapping, connection status, mock data generation

Enabling

Add to your .env:

META_ENABLED=true        # Enable/disable (default: true)
STORAGE_ADAPTER=local    # local | memory | postgres (default: local)

If META_ENABLED=false, all Meta pages show a "Meta not connected" empty state.

Seeding Mock Data

  1. Start the dev server: npm run dev
  2. Navigate to /meta/settings
  3. Click "Generate Mock Data" — this creates 10 clients with 60 days of snapshots
  4. Or call the API directly: curl -X POST http://localhost:3000/api/meta/seed

Connecting the Meta API

The Meta API integration is stubbed in src/meta/services/metaService.ts. To connect:

  1. Set META_ACCESS_TOKEN in your .env
  2. Implement fetchMetaInsights() in src/meta/services/metaService.ts
  3. The function should call the Meta Marketing API /insights endpoint and return MetaDailySnapshot[]
  4. Call storage.bulkUpsertSnapshots() to persist the data

Switching Storage Adapters

The storage layer uses an adapter pattern (src/meta/storage/StorageAdapter.ts):

  • local (default) — Persists to /data/*.json files. Falls back to in-memory if filesystem is read-only.
  • memory — In-memory only. Data lost on restart.
  • postgres — Skeleton only. To implement:
    1. Install a Postgres client (@vercel/postgres, pg, Drizzle, or Prisma)
    2. Create the tables (schemas documented in src/meta/storage/PostgresAdapter.ts)
    3. Implement the adapter methods
    4. Set STORAGE_ADAPTER=postgres and DATABASE_URL in .env

Recommended upgrade path: Supabase Postgres (free tier) or SQLite via better-sqlite3 for local dev.

API Routes

MethodRouteDescription
GET/api/meta/overview?range=7dOverview KPIs + client table
GET/api/meta/client/[clientId]?range=30dClient detail + snapshots
POST/api/meta/health/evaluateRe-evaluate health (all or one)
POST/api/meta/seedGenerate mock data (dev only)
PATCH/api/meta/clients/[clientId]Update client fields

GHL Command Center

Internal tool for tracking GoHighLevel leads, appointments, and pipeline across all locations (sub-accounts).

Pages

  • /ghl/overview — All locations, KPIs (leads, appointments, show rate, booking rate, pipeline)
  • /ghl/locations/[locationId] — Location detail with 6 charts (leads, booked, showed, show rate, opps won, pipeline)
  • /ghl/anomalies — Red/yellow locations with reasons
  • /ghl/settings — OAuth connection status, location mapping, mock data generation

Enabling

Add to your .env:

GHL_ENABLED=true         # Enable/disable (default: true)
GHL_CLIENT_ID=xxx        # From your GHL Marketplace app
GHL_CLIENT_SECRET=xxx
GHL_ACCESS_TOKEN=xxx     # Obtained via OAuth flow

Seeding Mock Data

  1. Start the dev server: npm run dev
  2. Navigate to /ghl/settings
  3. Click "Generate Mock Data" — creates 10 locations with 60 days of data
  4. Or: curl -X POST http://localhost:3000/api/ghl/seed

Connecting the GHL API

The GHL API integration is stubbed in src/ghl/services/ghlService.ts. To connect:

  1. Create a Marketplace app at https://marketplace.gohighlevel.com/
  2. Implement OAuth 2.0 flow to get access tokens per location
  3. Implement fetchGhlContacts(), fetchGhlAppointments(), fetchGhlOpportunities() in the service file
  4. API base: https://services.leadconnectorhq.com

Health Rules

Compares last 7 days to previous 7 days:

  • RED: 0 leads in 7d, show rate < 30%, 0 appointments despite having leads
  • YELLOW: Leads down 25%+, show rate < 50%, booking rate down 20%+
  • GREEN: Everything else

GHL API Routes

MethodRouteDescription
GET/api/ghl/overview?range=7dOverview KPIs + location table
GET/api/ghl/location/[locationId]?range=30dLocation detail + snapshots
POST/api/ghl/health/evaluateRe-evaluate health (all or one)
POST/api/ghl/seedGenerate mock data (dev only)
PATCH/api/ghl/locations/[locationId]Update location fields

Learn More

To learn more about Next.js, take a look at the following resources:

You can check out the Next.js GitHub repository - your feedback and contributions are welcome!

Deploy on Vercel

The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.

Check out our Next.js deployment documentation for more details.