Skip to content

Revenue Tracking

Mission Control's revenue tracking system aggregates earnings across 5 revenue sources toward a $25M annual goal. Data flows from automated collectors to a real-time dashboard display.

System Architecture

Data Collection

Collector Script

Location: /Users/aurora/.openclaw/workspace/scripts/revenue_collector.py
Schedule: Daily at 6am CT via cron
Manual run: cd /Users/aurora/.openclaw/workspace && python3 scripts/revenue_collector.py

The collector:

  1. Fetches data from all 5 sources
  2. Calculates YTD totals, last 30 days, and projected annual
  3. Posts snapshot to Convex database
  4. Logs detailed results for debugging

Data Flow

Revenue Sources → Collector Script → Convex Snapshot → Dashboard Display

Revenue Sources

1. Close CRM (Sponsorship Deals)

Purpose: Won sponsorship opportunities
API: GET https://api.close.com/api/v1/opportunity/
Credentials: .secrets/close_api_key.txt
Migration: Switched from Copper to Close on 2026-03-12/13

Query parameters:

  • status_type=won — only closed deals
  • date_won__gte=2026-01-01 — YTD filter
  • date_won__lte=today — current date

Data extracted:

  • Field: value (in cents, divided by 100 for USD)
  • Pagination: _skip parameter with has_more flag
  • Authentication: HTTP Basic (API key as username, empty password)

2. Impact (Affiliate Network)

Purpose: Affiliate network earnings across all campaigns
API: GET https://api.impact.com/Mediapartners/{account_sid}/Reports/partner_performance_by_day
Credentials: .secrets/impact_account_sid.txt, .secrets/impact_api_key.txt

Important: Uses the Reports endpoint, not /Actions. The Actions endpoint only returns pending actions (~$83K), while Reports returns the complete picture (~$454K).

Query parameters:

  • START_DATE=2026-01-01 (YYYY-MM-DD format required)
  • END_DATE=today
  • PageSize=1000

Data extracted:

  • Field: Total_Cost (includes action earnings + bonuses)
  • Date format: Strict YYYY-MM-DD (other formats rejected with 400 error)

3. RedVentures

Purpose: Commission from RV Media Network
API: OAuth2 + GET https://reporting-api.rvmedianetwork.com/overview
Credentials: .secrets/redventures_client_id.txt, .secrets/redventures_api_key.txt, .secrets/redventures_property_id.txt

Authentication flow:

  1. POST client credentials → bearer token
  2. GET overview data with token

Limitations:

  • Max 31-day window per API call
  • Collector makes multiple calls to cover full YTD period

Data extracted:

  • Field: commission from overviewReporting.page[]

4. AdsByMoney (CPC/Publisher Earnings)

Purpose: YTD publisher earnings from AdsByMoney campaigns
Method: Automated scraping with session authentication
Credentials: .secrets/adsbymoney_creds.json

Scraping process:

  1. GET /sign_in → extract CSRF token from meta tag
  2. POST credentials → establish session cookie
  3. GET /admin/publisher_campaigns?start_date=2026-01-01&end_date=TODAY&date_range_index=10 → set YTD range
  4. GET /admin/publisher_overviews?pubid=418&status=active → fetch earnings JSON
  5. Filter by Unix timestamp to current year, sum totals

Date range indices:

  • 10 — custom date range (uses start_date/end_date params)
  • 9 — last 12 months (ignores start/end params)
  • 6 — current month
  • 7 — last month

Fallback: If scraping fails, reads data/revenue/adsbymoney_manual.json

5. MSN (Manual Monthly Revenue)

Purpose: Manual monthly revenue entered by Apple
Storage: data/revenue/msn_monthly.json
Format: {"2026-01": 32250.00, "2026-02": ...}

Update process:

  1. revenue-manual-check-in cron fires on the 21st of each month
  2. Asks Apple for MSN + AdsByMoney numbers via message
  3. Ari logs both values and reruns collector
  4. Dashboard shows $0 until first report around the 21st

No API: Fully manual entry system

Data Storage

Convex Database

Table: revenue_snapshots

Schema:

typescript
{
  snapshotDate: string,       // "2026-02-19"
  totalYtdUsd: number,        // Sum of all sources
  projectedAnnualUsd: number, // (YTD_total / days_elapsed) * 365
  last30dUsd: number,         // Last 30 days across sources
  sources: {
    close: number | null,     // (renamed from 'copper' on 2026-03-13)
    impact: number | null,
    redventures: number | null,
    adsbymoney: number | null,
    msn: number,
  },
  createdAt: number,          // Date.now()
}

Convex Endpoints

  • Write: POST {CONVEX_SITE_URL}/revenue/snapshot
  • Read: GET {CONVEX_SITE_URL}/revenue/latest (used by dashboard)
  • Functions: revenue.tssaveSnapshot mutation + getLatest query

Dashboard Display

Progress Bar

  • Goal: $25M annually
  • Calculation: (totalYtdUsd / 25000000) * 100
  • Visual: Green progress bar with percentage

Source Pills

Individual pills showing contribution by source:

  • Close CRM (Won): $XXX,XXX
  • Impact: $XXX,XXX
  • RedVentures: $XXX,XXX
  • AdsByMoney: $XXX,XXX
  • MSN: $XXX,XXX

Key Metrics

  • YTD Total: Current year earnings
  • Last 30 Days: Rolling 30-day total
  • Projected Annual: (YTD_total / days_elapsed) * 365

Active Crons

CronSchedulePurpose
revenue-collector6am CT dailyRun collector script, update Convex
revenue-manual-check-in9am on the 21stRequest MSN + AdsByMoney from Apple

Troubleshooting

If Numbers Look Wrong

  1. Run collector manually:

    bash
    cd /Users/aurora/.openclaw/workspace
    python3 scripts/revenue_collector.py
  2. Check source-specific issues:

    • AdsByMoney: Verify date range setting (should be YTD, not last 3 days)
    • Impact: Confirm using partner_performance_by_day + Total_Cost, not /Actions + Payout
    • Close: Check date format is M/D/YYYY as expected
    • RedVentures: May need additional 31-day windows as year progresses
  3. Review logs: Each source logs what it found for debugging

Migration Notes

Close CRM Migration (2026-03-12/13):

  • Migrated from Copper to Close API
  • Convex key renamed from sources.copper to sources.close
  • Dashboard API route may still reference sources.copper for compatibility
  • Live test confirmed 67 YTD deals working correctly

Data Validation

The collector outputs detailed logs showing:

  • Number of records found per source
  • Dollar amounts calculated
  • Any errors or warnings
  • Final totals and projections

Example output:

Close CRM (Won): 67 deals → $XXX,XXX USD
Impact (Performance by Day): 50 days → $454,893.42 USD YTD
RedVentures: $3,368.54 USD YTD
AdsByMoney (manual): $31,854.33 USD YTD (updated 2026-02-19)
MSN: YTD total 32250.00 USD
Totals — YTD: $X,XXX,XXX | Last 30d: $XXX,XXX | Projected: $X.XM
Snapshot written: 200