← Both skills · wildhorn-static-ads · 1-understand/research-playbook.md
Where to find ads that are winning, how to tell they are winning without spend data, how to study a
competitor end to end (ads → landing pages → product pages → offers → quizzes), how to mine the voice of
customer, and what each step costs. Everything runs on the VPS (ssh vps-claude), never in the Mac's
browser.
| Source | Best for | Cost | Main gotcha |
|---|---|---|---|
TrendTrack (REST https://api.trendtrack.io/v1, key in /etc/secrets/trendtrack_api_key; or the TrendTrack MCP) |
Ad search by domain, run-time filters, brand trackers, scaling ads, transcripts, shop search, landing pages | ~1 credit per row via REST (~1.5× via MCP); lookup = 0 credit |
Credits shared with scheduled jobs; sortBy=reach returns 0 for US ads; longestRunning returns empty; ~1-day lag on new ads; weak on cuts |
Meta Ad Library via Apify (apify~facebook-ads-scraper, token /etc/apify/token) |
Full ad lists for a domain, sorted by Meta's impressions order, with media and copy | Low (≈ $8.6 for 1,295 ads across 4 brands) | Monthly cap; US impression numbers aren't public, only the ORDER |
| Meta Ad Library direct from the VPS | Free spot checks, "N ads use this creative", exact active hours, cut dates | Free | ~30 results per query from a datacenter IP; soft block at ~100 requests / 23 min; never 2 scrapers at once |
Radar (radar.machineroom.app, /root/workspace/radar/) |
Daily life of one competitor's ads: launches, cuts, lifetimes, pages, products | TrendTrack ~250 credits/day | TrendTrack sees few cuts (lifetimes inflated) |
Scaling shops (scaling.machineroom.app, /root/workspace/scaling/) |
New shops whose active ads grow fast; product discovery | ~1 credit/row | Shop createdAt = TrendTrack indexing date, not launch |
Competitor list (brands.machineroom.app, /root/workspace/competitors/big-list-2026-09.md) |
Who to watch per brand (Minx, Wildhorn, big US supplement spenders) | — | Snapshot from early September |
Offers study (offers.machineroom.app, /root/workspace/competitors/offers/) |
Real landing pages, bundles, gifts, mobile captures of ~120 brands | Done | Rebuild only with a budget |
Annotated swipe (/root/claude-vault/knowledge/copywriting/swipe-annotated/, 197 winners) |
Video winners already decoded (DNA, beat map, steal-this, score) | Free | Mixed niches |
Template folders (/root/workspace/wh-remix/templates/: before-after, bold claim, feature-benefit, meme, negative hook, problem-solution, us vs them, offer/sales, statistic) |
Static templates by concept | Free | Sort into families before use |
Statics of a domain, newest and longest-running (/root/workspace/competitors/tt_statics.py
<domain> <slug>; tt_dl_only.py <slug> re-downloads without credits):
search=[domain], searchType="domain", mediaType="image", status="all", sortBy="newest", order="desc"
→ newest 30
same + minDaysRunning=<threshold> → the "most performing" proxy
Choose the threshold by probing totals (limit=1) at several minDaysRunning values until ~30–45 ads
remain. Thresholds used: Primal Viking ≥ 200 days (32 statics), Mars Men ≥ 200 (39), Ancestral ≥ 200
(44), Primal Storm ≥ 135 (29 — young brand).
Why run time and not reach: sortBy=reach returns 0 for US ads and sortBy=longestRunning returns
empty (API bug). Run time is the honest proxy.
MCP tools for a brand overview (Step 1B of the blueprint): search_advertisers / lookup (pages of
the competitor AND our brand) · search_ads / get_brandtracker_scaling_ads (active, past, scaling) ·
get_brandtracker_transcripts (video transcripts already indexed) · analyze_tracked_brand /
brief_competitor (strategic overview) · search_shops / analyze_brand_changes (traffic, trend, offers)
· search_emails / analyze_shop_emails (email sequences).
Freshness filter that works (product discovery): don't trust shop createdAt. Use the weekly
advertising.history: keep shops where ads ≈ 0–10 around 60 days ago and active ads ≥ 50 now; or
search_ads with created_after = today − 60 d + sort_by reachDelta7d (ad firstSeenAt = real first
run date).
Givenche's three hacks (ads > traffic; traffic data lags 30–60 days):
Scaling calculation (scaling-shops method): last 5 weekly points of advertising.history, ≥ 3
points, last > first, growth ≥ +50 %. Collapse mirror shops (identical ad history) into one card.
Actor apify~facebook-ads-scraper, parameters used (/root/workspace/competitors/adlib/collect.py):
active_status=all, ad_type=all, country=ALL, query = the landing DOMAIN, sort_data[mode] =
total_impressions, sort_data[direction] = desc, limit per set (e.g. 1,200 for small brands = all ads;
220–320 for big ones). Second set per big brand: the 100 most recent launches (sort_data[mode] =
time_active for "newest").
What you get: ad id, page, start/end, active flag, variants (DCO), copy, titles, link, media URLs.
Downstream (adlib pipeline): media.py (download, B2 copy), transcribe.py (videos via API),
analyze_ads.py (per-ad fields: hook, problem, root cause, mechanism, angle, proof, offer, summary),
lpscan.py (landing pages), site/classify.py (fixed taxonomy), site/build_data.py (site data).
Budget share estimate: Meta's impression ORDER is real (checked 29/29 against the live page) but US numbers are hidden. Weight each ad 1/rank^0.8 and sum by angle → "≈ % of budget". Always label it an estimate.
Never: run Meta keyword searches on generic words (they return 50,000 unrelated ads); run two Meta scrapers from the VPS at once.
Built for Resilia (/root/workspace/radar/, site radar.machineroom.app). Use when the goal is to learn
a competitor's STRATEGY over ~20 days: winners, cut speed, iterations, angles per product, pages,
funnels.
Rules learned:
Never base the footprint on pages. Search by the landing domain (q=resilia.shop, cross-checked
with the brand name), keep every ad whose REAL link (the l.facebook.com/l.php?u= href) points to the
domain. The brand ran ~17–38 pages, most disguised as health-review sites ("Vascular Wellness Report",
"The Blood Sugar Report"). Exclude resellers (Amazon, other shops) and homonyms.
Dedupe by creative (video hash), not by ad id: Meta runs the same video under many ids ("N ads use this creative" = N ads).
data/<domain>/tt_ledger.json.| Signal | Strength | How to read it |
|---|---|---|
| Top of Meta's impressions order | Strong | Real order; budget share by rank weighting |
| Run time ≥ 60 days (≥ 135–200 days for mature brands) | Strong for statics | Nobody keeps paying for a loser for months |
| Many duplicates / DCO variants / "N ads use this creative" | Strong | The advertiser is pushing it across ad sets/pages |
| Same creative on several pages | Strong | Scaling through page diversification |
| Relaunched / iterated versions (same headline, new visual) | Strong | They believe in that gene |
| A dedicated landing page for the angle | Strong | "One landing per villain" = investment |
| Rising weekly active-ad count (shop level) | Medium–strong | +50 % in 4 weeks = scaling shop |
| Launch cadence (new creatives/day) | Context | 150–220/day = big tester; few = extending winners |
| Cut speed (share of creatives cut < 7 days) | Context | Resilia: 1 in 4 cut creatives die in < 1 week; survivors of 2 weeks often last 1–2 months |
| Traffic trend (TrendTrack/SimilarWeb) | Weak, lagging | Use only to describe a brand's trajectory (e.g. Primal Edge −21 % in 30 days, live ads ÷5 since April) |
| Hook rate / likes | Weak | Soft metrics; can mislead |
Our own winners (account data): ROAS above break-even and ≥ 10–15 % of monthly spend (20–25 % = very big), confirmed by month-2 rebill. Never judge before 72 h.
Evolve's order: Reddit → YouTube → TikTok comments → Amazon reviews → post-purchase survey → AnswerThePublic. Actors that work from the VPS datacenter IP (no residential proxy):
| Platform | Actor | Notes |
|---|---|---|
fatihtahta~reddit-scraper-search-fast (API) |
The HTML scraper trudax~reddit-scraper-lite fails (403) |
|
| YouTube comments | apidojo~youtube-comments-scraper |
Competitor videos + niche searches |
| TikTok comments | clockworks~tiktok-comments-scraper |
Reactions to competitor ads |
| TikTok search/hashtags | clockworks~tiktok-scraper / tiktok-hashtag-scraper |
Find niche videos |
| Amazon reviews | web_wanderer~amazon-reviews-extractor (≤ 50/product) |
Ours + ALL competitors, 1★–3★ especially |
| Trustpilot | memo23~trustpilot-scraper-ppe |
Negative reviews = unsolved pains |
| Quora | fatihtahta~quora-scraper |
Beliefs, awareness |
| Google SERP | apify~google-search-scraper |
"X reddit", "X horror story" |
Script: python3 /root/research_scrape.py <slug> [platforms] reading
products/<slug>/research-config.json. Query patterns: desires "I want [outcome] reddit" · emotions
"[problem] makes me feel reddit" · product experience "anyone tried [solution] reddit" (capture the
OUTCOME) · demographics "at what age does [problem] start" · horror "[solution] gone wrong".
Capture in 3 columns: Desire | Customer language (verbatim) | Ad idea. Report every scraping failure
explicitly (blocked actor, aborted run, empty dataset); never hide it.
Process (blueprint 1A → 1B → 1C): (1A) for EACH ad one row: format · exact headline · sub-headline · video hook (first 3 s) · angle · mechanism · visual format · proof · offer · CTA; group by angle; rank by weight — give the per-ad table first, then the synthesis. (1B) TrendTrack cross-check with every number sourced. (1C) the report above. Get sign-off before step 2.
mr-archive).mr-transcribe (API). Beat-by-beat analysis only if asked (it's
expensive); full transcripts are enough for the global analysis.Classify into BIG angles with a taxonomy fixed before classifying. The testosterone taxonomy used for 1,295 ads: angles = libido · size · belly · man boobs · face/jaw · energy · hair · muscle · 40+ · generation · digestion · GLP-1 · alcohol · comparison · generic T · other; mechanisms = aromatase · cortisol · deficiency · absorption · endocrine disruptors · SHBG · nitric oxide · DHEA/precursors · age decline · none · other. Promo ads get the angle underlying the promo.
Weight angles (rank-weighted share, run time, variants, LPs).
_m.jpg for slow
networks, "Which landing page for which angle" section).Example costs: 4-brand Meta library study = Apify $8.63 + OpenAI ≈ $38 (analysis with a GPT model) for 1,295 ads, 67 LPs, 21 PDPs, 238 videos. 4-brand statics study ≈ 330 TrendTrack credits.
For each landing page (advertorial, listicle, quiz, PDP, comparison, VSL):
nice -n 19 ionice -c3), forcing US locale with Shopify
cookies (localization=US, cart_currency=USD) when the VPS IP geolocates elsewhere.Patterns seen: "one landing per villain" (Primal Viking) · one "10 reasons" listicle cloned per angle (Mars Men) · advertorial "I tested the 2 top-selling…" for comparison angles (Primal Edge, Elora) · persona-specific PDP headlines ("For Men With Man Boobs Who've Tried Everything") · proof ads → proof page · media co-branded listicles (don't copy).
Method (quizmap study): crawl the quiz end to end on a phone-sized screen; click EVERY answer of every question; screenshot every screen; draw the tree (a straight line if all answers lead to the same next screen, a branch otherwise); run several full profiles to the result and landing page; then compare word by word what each answer changes ("dead questions" = no visible effect). Intercept submissions so nothing is sent to the competitor.
What to record: opening promise · length (questions, loaders, proof screens) · question formats · branches · proof inside the quiz · result screen (verdict levels, named root causes, score, projection chart with a date) · offer screen · landing page and whether it uses the answers · email capture · data passed in the URL (persona) · live A/B tests (e.g. "SKIP QUIZ & BUY NOW") · mistakes.
Takeaways that generalise: ~10 one-tap questions; a verdict with 3 levels + a named root cause the product answers + a dated projection tied to the offer length; cheap "made for me" hooks (dream-body picture, event + date countdown); nobody passes the quiz; test a skippable email step; actually USE the persona on the landing page (both competitors collect it and throw it away); every question should change the result or feed a segment; avoid diagnosis wording.
mr-archive find before
re-downloading.competitor-case-studies.md) before paying for new data.