Monitor Competitor Facebook Ad Campaigns Over Time (2026)
Track competitor Facebook and Instagram ad activity week over week. Detect new creative launches, retiring ads, and CTA shifts with structured Ad Library data.

Thirdwatch's Facebook Ad Library Scraper captures active ad snapshots from Meta's public Ad Library -- ad count, creative text, CTAs, start dates, and platform mix. Schedule weekly runs to build a time series of competitor ad activity. Detect new creative launches, retired ads, CTA shifts, and platform strategy changes without manual browsing. No Facebook account required.
Why monitor competitor Facebook ad campaigns
Competitive ad monitoring is one of the most direct signals available to growth teams. According to Statista's digital advertising report, Meta platforms account for over 20% of global digital ad spend, making Facebook and Instagram the largest single-vendor ad surface in the world. Knowing what competitors run on Meta is not optional intelligence -- it is table stakes for any team spending on the platform.
The gap is temporal. A one-time competitor audit shows you what ads are live today but tells you nothing about creative velocity, testing cadence, or messaging shifts. The real insight comes from comparing this week's snapshot to last week's. Did the competitor launch five new creatives? Did they retire their "Free Shipping" messaging? Did they shift from Facebook-heavy to Instagram-only placement? These week-over-week deltas reveal strategy, not just tactics. A scheduled scraping pipeline turns the Ad Library from a static window into a time-series intelligence feed.
How does this compare to the alternatives?
Three ways to monitor competitor ad campaigns:
| Approach | Pricing | Temporal depth | Setup time | Maintenance |
|---|---|---|---|---|
| Manual Ad Library check (weekly) | Free | Snapshot only, no history | Zero | 30-60 min/week per competitor |
| Pathmatics / Moat / Adbeat (enterprise) | $500-$2,000/month | Deep historical data | 1-2 weeks onboarding | Vendor-managed |
| Thirdwatch Facebook Ad Library Scraper (scheduled) | Pay per result | Build your own time series from weekly snapshots | 10 minutes | Thirdwatch tracks Meta changes |
Enterprise tools like Pathmatics offer deep historical data but at enterprise pricing that excludes most startups and mid-market teams. Manual checking is free but does not scale past three competitors without consuming analyst hours. The Thirdwatch actor gives you structured snapshots that accumulate into your own time series at pay-per-result pricing.
How to monitor competitor ad campaigns in 4 steps
Step 1: How do I set up my Apify API token?
Sign in at apify.com (free tier, no credit card), open Settings, then Integrations, and copy your API token:
export APIFY_TOKEN="apify_api_xxxxxxxxxxxxxxxx"Step 2: How do I capture a baseline snapshot of competitor ads?
Run the actor once to establish a baseline of what each competitor is running right now.
import os, requests, json
from datetime import datetime
ACTOR = "thirdwatch~fb-ad-library-scraper"
TOKEN = os.environ["APIFY_TOKEN"]
competitors = ["warby parker", "zenni optical", "eyebuydirect", "pair eyewear"]
resp = requests.post(
f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items",
params={"token": TOKEN},
json={
"brands": competitors,
"country": "ALL",
"adType": "all",
"maxCreatives": 50,
},
timeout=600,
)
snapshot = resp.json()
timestamp = datetime.utcnow().strftime("%Y-%m-%d")
# Save baseline
with open(f"ad_snapshot_{timestamp}.json", "w") as f:
json.dump(snapshot, f, indent=2)
for brand in snapshot:
print(f"{brand['brand']}: {brand['adCount']} active ads, {brand['creativeCount']} creatives")This baseline is your week-zero reference. Every subsequent run gets compared against it to compute deltas.
Step 3: How do I detect new launches and retired creatives?
Compare two snapshots to identify what changed between runs.
import json
def load_snapshot(path):
with open(path) as f:
return json.load(f)
def creative_key(brand_name, creative):
return f"{brand_name}|{creative.get('textSnippet', '')}|{creative.get('startDate', '')}|{creative.get('cta', '')}"
def diff_snapshots(old_data, new_data):
old_keys = {}
new_keys = {}
for brand in old_data:
for c in brand.get("creatives", []):
old_keys[creative_key(brand["brand"], c)] = c
for brand in new_data:
for c in brand.get("creatives", []):
new_keys[creative_key(brand["brand"], c)] = c
launched = {k: v for k, v in new_keys.items() if k not in old_keys}
retired = {k: v for k, v in old_keys.items() if k not in new_keys}
return launched, retired
old = load_snapshot("ad_snapshot_2026-05-19.json")
new = load_snapshot("ad_snapshot_2026-05-26.json")
launched, retired = diff_snapshots(old, new)
print(f"New creatives launched: {len(launched)}")
print(f"Creatives retired: {len(retired)}")
for key, creative in list(launched.items())[:5]:
brand = key.split("|")[0]
print(f" NEW: {brand} -- \"{creative.get('textSnippet', '')[:60]}...\" ({creative.get('cta')})")The diff function uses a composite key of brand, text snippet, start date, and CTA to identify unique creatives. New keys in the latest snapshot are launches; missing keys are retirements. Track the adCount delta per brand to see overall ad volume trends.
Step 4: How do I automate this into a weekly alert pipeline?
Schedule the actor on Apify and connect a webhook to your alerting system.
curl -X POST "https://api.apify.com/v2/schedules?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "competitor-ad-monitor-weekly",
"cronExpression": "0 7 * * 1",
"timezone": "America/New_York",
"isEnabled": true,
"actions": [{
"type": "RUN_ACTOR",
"actorId": "thirdwatch~fb-ad-library-scraper",
"runInput": {
"brands": ["warby parker", "zenni optical", "eyebuydirect", "pair eyewear"],
"country": "ALL",
"adType": "all",
"maxCreatives": 50
}
}]
}'Every Monday at 7 AM, the actor captures a fresh snapshot. Wire an ACTOR.RUN.SUCCEEDED webhook to a Python script that loads the previous snapshot from storage, runs the diff, and posts a Slack summary with new launches, retired creatives, and ad count changes per competitor.
Sample output
A weekly snapshot record for one competitor:
{
"brand": "warby parker",
"country": "ALL",
"adType": "all",
"url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=ALL&q=warby+parker",
"active": true,
"adCount": 156,
"creatives": [
{
"startDate": "May 20, 2026",
"platforms": ["Facebook", "Instagram"],
"cta": "Shop Now",
"textSnippet": "Starting at $95, including prescription lenses. Try 5 frames at home for free."
},
{
"startDate": "Apr 3, 2026",
"platforms": ["Instagram", "Audience Network"],
"cta": "Learn More",
"textSnippet": "Virtual try-on. See how they look before you buy."
}
],
"creativeCount": 50,
"scraped_at": "2026-05-26T07:00:00.000Z"
}The startDate field is critical for monitoring. A creative with a May 20 start date that was not in last week's snapshot is a confirmed new launch. A creative with an April 3 start date that has persisted across four weekly snapshots is a proven performer the competitor keeps running. The adCount of 156 compared to last week's 142 tells you Warby Parker is scaling up ad volume.
Common pitfalls
Three mistakes in ad campaign monitoring pipelines. Snapshot-only thinking -- a single scrape tells you what is live today but nothing about velocity or trends. The value of monitoring is in the diff between snapshots. Always store historical snapshots and compute week-over-week deltas. Confusing ad count with creative count -- adCount is Meta's reported total active ads for the brand. creativeCount is how many individual creative samples the actor captured (capped by maxCreatives). A brand with 500 active ads but 50 captured creatives is not missing data; the actor sampled 50 of 500. Country filter drift -- switching country between runs breaks your time series. If you start with country: "US" and later switch to ALL, the ad counts are not comparable. Lock your country parameter for the life of a monitoring pipeline.
Thirdwatch's actor handles the rendering and anti-bot complexity so your monitoring pipeline receives consistent structured JSON every run.
A fourth trap: treating all creatives equally in your analysis. Not every ad in a competitor's library is a performance ad. Some are brand awareness, some are retargeting, some are lead generation. The cta field distinguishes these — "Shop Now" signals a conversion-focused ad, "Learn More" signals top-of-funnel, and "Sign Up" signals lead generation. Segment your competitive analysis by CTA type to understand which part of the funnel your competitor is investing in. A spike in "Shop Now" creatives combined with aggressive new launches suggests they are pushing for revenue, not awareness.
A fifth pattern worth watching: platform mix shifts. A competitor moving creatives from Facebook to Instagram-only (visible in the platforms array) often signals a demographic strategy shift — Instagram skews younger. Track the ratio of Instagram-only to Facebook-only creatives per brand over time. A sustained shift in this ratio over 4-6 weeks is a deliberate platform strategy change, not a testing artifact.
Related use cases
- Facebook Ad Library Scraper on Apify Store
- Scrape Facebook Ad Library for competitive intel
- Build an ad creative database with Facebook ads
- Track political ad spend with Facebook Ad Library
- Monitor brand TikTok presence
- Track influencer follower growth on Instagram
- The complete guide to scraping social media data
- All Thirdwatch use-case guides
Frequently asked questions
How often should I scrape to detect new competitor ads?
Weekly captures most competitive shifts. Brands typically test new creatives every 1-3 weeks. For high-velocity categories like flash sales or political campaigns, daily scraping catches launches within 24 hours of going live.
Can I track when a competitor stops running an ad?
Yes, by diffing consecutive snapshots. An ad present in last week's scrape but missing this week was retired. Store each week's creatives with timestamps and compute the diff to detect both new launches and retired creatives.
Does the Ad Library show ad performance metrics?
No. Meta's Ad Library does not expose impressions, clicks, or conversion data. You can infer creative performance from longevity -- ads running for 30-plus days are likely performing well enough to justify continued spend.
Can I monitor ads across Facebook and Instagram separately?
The platforms field on each creative shows which Meta surfaces carry that ad. You can filter to Instagram-only or Facebook-only creatives in your analysis to track platform-specific strategy shifts.
Will this work for monitoring my own brand's ads?
Yes. Pass your own brand name in the brands parameter. This is useful for auditing your own active inventory, catching rogue creatives running longer than intended, or verifying that new launches are live.
Related
100 free credits, no credit card.
About 30 real searches. Add the MCP to Claude or Cursor in two minutes.