Watch competitor Facebook ads on a 24h schedule (auto-refresh + New badge)
One click to star a brand. KOLens then auto-scrapes their Meta Ad Library every 24h and badges every new creative the moment it appears.
Quick answer
The boring loop ad spy actually is
Watching a competitor's paid creative is high-leverage research — the ad they kept running for 8 weeks converted; the one they killed in 3 days didn't. But manually visiting the Meta Ad Library every morning to spot what's new is exactly the kind of repetitive admin work marketing teams quietly drop after week 3.
KOLens' original Ad Spy already let you scrape any brand's full creative wall in one click. What was missing: a passive loop that does the daily check for you and tells you when something actually changes.
How the watchlist works
- 1Open any advertiser detail page.Either scrape a fresh brand on /ad-spy, or click into one already in the workspace data store from
/ad-spy/watchlist. - 2Click 'Watch · 24h refresh' next to the page name.The toggle adds a per-user row in the watchlist table. Re-clicking unwatches. Optimistic UI — feels instant; rollback on error.
- 3Wait — KOLens re-runs the scrape every 24h.The scheduler picks any watch row whose
last_refreshed_atis older than 24 hours, calls Apify against the advertiser's page URL, and stamps the timestamp. Capped at 5 refreshes per scheduler tick so a single tick stays bounded. - 4On your next visit, new ads light up.Each ad card whose
first_seen_atis later than your per-userlast_viewed_atgets a small New pill in the corner. After one second on the page the timestamp bumps forward, so badges only clear after you've had a chance to see them.
The aggregate view
/ad-spy/watchlist rolls every watched advertiser into one list with a per-row "N new" pill. The page header sums them across the whole watchlist:
- 3 advertisers · 14 new ads since you last looked — the headline number you actually want when triaging the morning.
- Per-card last-refresh timestamp so you can spot a watch that's stuck (e.g. an advertiser that deleted their Facebook page → no more ads to scrape).
- Pause / resume from the same row when a brand goes quiet for the season.
Design choices that actually mattered
Free for the user, on the platform's dime
Charging credits per auto-refresh would have made the Watch button feel adversarial — "do you really want this?" anchored against an increasing bill. We made it free instead. The Apify cost is real and bounded (24h cadence × small refresh batches) and the watchlist is a sticky retention feature, so it pays for itself.
Apify errors don't bump the timestamp
When Apify hiccups (~1% of runs, usually a captcha rotation), we log the failure but leave last_refreshed_at alone. That way the next scheduler tick picks the row up again instead of creating a 24-hour data hole when the actor was down for an hour.
"New" is per-user, not global
Two users on the same workspace shouldn't see each other's New badges. Each watch row carries its own last_viewed_at — opening the page bumps your timestamp, leaving everyone else's intact. Same advertiser, two private notification states.
vs alternatives
- AdSpy / BigSpy / Magic Ads — large indexed libraries with subscription billing. KOLens doesn't compete on breadth; we compete on freshness + watch-friction (one click to star, one click to disconnect, no annual contract).
- Manual Meta Ad Library — Meta's free tool. Fine for one-time research; doesn't loop, doesn't diff, doesn't notify.
- Apify alone — viable if you're an engineer who wants to roll your own. KOLens packages the scrape + deduplication + per-user New tracking + UI so a marketer can use it without writing scheduler code.
Coming next
On the roadmap (tracked as AS-5 follow-ups): push the New events out via the same email + webhook delivery we just shipped for KOL alerts. Star a brand → first new creative drops → Slack ping the same minute KOLens detects it.
Frequently asked
- How fresh is the data — is it real-time?
- Refresh is on a 24h cadence per watched advertiser. The cadence is conservative because each Apify scrape takes 30-90 seconds — running it every minute would burn through quota without giving you faster intel. New ads typically appear in the next 24h refresh after Meta publishes them.
- What does the 'New' badge consider 'new'?
- Per-user. Each user has a private last_viewed_at timestamp on every advertiser they watch. Any DBFbAd whose first_seen_at is later than your last_viewed_at gets badged. Open the advertiser page → after one second the timestamp bumps forward, so the badges only clear after you've actually had a chance to see them.
- Does it cost credits?
- No. Watchlist auto-refresh is a free feature. The original ad-library scrape that puts an advertiser in your data store costs 1 credit per 10 ads (the same rate as the manual one-shot scrape); the recurring auto-refresh after that is on the platform.
- Can I share a watchlist with a teammate?
- Watchlists are per-user in v1 — each Supabase user account sees their own. Shared workspace watchlists are on the roadmap for the team-tier pricing once that ships.
- What's the difference between Ad Spy watchlist and the KOL watchlist?
- Same idea, different platform. The KOL watchlist tracks TikTok creator accounts (follower deltas, engagement, posting cadence). The Ad Spy watchlist tracks Facebook advertisers (new creatives, longevity, EU DSA spend buckets).
Read next
Facebook Ad Spy — scrape any brand's live ad creatives in 30s
KOLens crawls the Meta Ad Library and pulls every creative — video, image, carousel — for any Facebook page. Watch it inline, see the CTA, body copy, and run dates. 1 credit per 10 ads.
TikTok audience snapshot — see where a creator's followers actually live (coming soon)
Sampled country / language / activity / niche signals for any TikTok creator. Honest confidence intervals, no fake demographics. Coming to KOLens.