This is a how-it-works outline so you can build/integrate your own version. You run your own infrastructure and your own API keys (Meta app, RedTrack, OpenAI, etc.) — nothing here needs Ryan's credentials. It just describes the architecture and the gotchas worth copying.
Media-buying bizopp on Facebook. The structure: a stack of ad accounts (workhorse "MAIN" accounts + "DFU" done-for-you stacks + a separate Business-Manager stack) running across a large pool of fan pages (2 pages per ad — one male, one female persona). Traffic → RedTrack (cloaking + attribution) → JVZoo affiliate offers (bizopp pays ~$90/conversion). Two offers run side by side: the real bizopp VSL and a safe Amazon fallback used for non-English language cloaking.
Goal: a self-running machine ("MOTHER") that generates creative, builds/tests ads, auto-kills losers, and scales winners — so the operator focuses on offers/backend/capital.
cost_per_inline_link_click (CPC-link) and inline_link_click_ctr, never raw cpc/ctr (they count image/profile clicks = meaningless).api.redtrack.io/report) = the conversion/revenue truth. Group reports by a sub dimension.convtype1 / revenuetype1 for real-time sales + revenue. conversions/revenue are lagged. convtype5 = InitiateCheckout (IC).sub6 = campaign name. This is the ONLY stable per-creative signal.sub4 — it's the cloak word "magic" on ~every ad, so it collapses ~$466k of revenue into one bucket. Useless for attribution.sub1 (ad.id) — it churns whenever ads are rebuilt.cost, plus roas/profit/cpa/cpc natively — so you can compute true per-campaign ROAS entirely inside RT without joining Meta. Winner = ROAS, never cost-per-IC.sub_id1) but NOT for LSP links (hardcoded sub_id1=rp) — LSP revenue is aggregate-only.peak-system/scripts/| Script | Cadence | Job |
|---|---|---|
spend_pacer.py |
every 20m | sets spend_cap = max(lifetime,today)+$500 buffer; dayparting + bid-backoff; $10k/day circuit-breaker |
kill_monitor.py |
every 30m | RT-truth pause rules (no-IC/no-sale/high-CPA) + reviver + dead-winner alert |
health_monitor.py |
every 30m | scans for DISAPPROVED/WITH_ISSUES ads, swaps creative to a safe puppy image |
comment_moderation.py |
every 30m | Claude classifies post comments, auto-hides negatives (feedback-score/CPM lever), drafts replies |
product_research.py (NBRT) |
every 3h | reads TG steering, mines Reddit, ranks true winners (RT sub6/ROAS), Claude generates 5 fresh brief ideas |
morning_digest.py |
8am Thailand | per-CBO spend/sales/CPA/ROAS + killed-ads recap |
update_status.py / ops_report.py / spend_snapshot.py |
2–10m | refresh live state files the dash reads |
All run detached/cron, never agent-babysat. Telegram bot (@terrenceisabot) = mobile control + alerts.
Two Flask/gunicorn web apps reading the same JSON state + live API pulls:
- Main dash — gunicorn-served, simple auth. Blueprint-per-tab structure (smm.py, auth.py). Has an SMM tab: fan pages + post-IDs + comment viewer/approve.
- Picker / creative dash — separate service. Routes like /dash (creatives), /dash/smm (pages+ads+winners), /dash/comments (live comment viewer via page tokens), /briefs/... (gallery pages).
- ⚠️ Display convention to copy: any Meta "Checkouts" column over-reports; the RedTrack Conv / RT Rev columns are the truth. Label them so nobody trusts the Meta number.
data/page_name_map.json (159+ pages), /tmp/all_pages_by_gender.json (283-page gender map — every ad runs on 1 male + 1 female page)data/creative_manifest.json (151 creatives), all hosted on R2 (pub-…r2.dev/catalog/)data/comment_drafts.json (reply drafts awaiting one-tap approve), data/comment_seen.jsondata/kills_log.jsonl, data/brief_steer.json (NBRT taste-learning)The op keeps a few flat markdown/JSON state files as the single source of truth, so any operator or script can pick up context instantly: - a live status file auto-refreshed every ~10m (what's running now), - a stable handoff brief (architecture + account map — credentials kept out of band), - a one-page playbook diagram. The principle: the chat/agent is disposable, the state files ARE the system.