Meta Ads Competitive Intelligence
Pricing
Pay per event
Meta Ads Competitive Intelligence
π Turn public Meta Ads Library URLs into ranked competitor briefs with ad evidence, transparent angle scoring, and optional Shopify product enrichment.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Turn public Meta Ads Library searches into a ranked, evidence-backed competitor ad report.
This Actor collects ads through the maintained Facebook Ads Library Scraper, analyzes every creative with an auditable persuasion taxonomy, enriches supported Shopify product destinations, and produces both spreadsheet-ready rows and a report summary.
No Facebook login is required. No OpenAI key is required. No Supabase database is required.
Use it to answer practical questions:
- π Which competitor ads have stayed active longest?
- π Which ads have the strongest public reach or impression evidence?
- π§ Which persuasion angles appear most often?
- ποΈ Which products, offers, prices, and destinations are promoted?
- π Which ads deserve a closer look in the next creative brief?
Every score is explainable. Every classified angle includes copied evidence when a taxonomy phrase matches. Missing source evidence stays missing instead of being invented.
What does Meta Ads Competitive Intelligence do?
The Actor accepts one or more public facebook.com/ads/library/ result URLs.
These can be keyword searches or advertiser-page result URLs.
It then:
- validates that every URL is a real Meta Ads Library path;
- invokes our maintained Facebook Ads Library Actor;
- reads and deduplicates the returned ad records;
- calculates observed run duration from public start and end dates;
- normalizes public reach or impression ranges when available;
- classifies a bounded persuasion angle from ad text;
- copies matching text snippets as classification evidence;
- optionally reads a public Shopify product JSON endpoint;
- scores each ad with visible duration, reach, and evidence components;
- writes ranked rows to the default dataset;
- writes an aggregate JSON report to the
REPORTKVS record.
The result is useful competitive research, not a black-box prediction.
Who is it for?
Ecommerce growth teams
Track active competitor offers, product destinations, price ranges, and recurring creative angles. Schedule the same input weekly to refresh a category brief.
Performance marketing agencies
Build evidence-backed client reports without manually copying dozens of Ads Library cards. Compare brands with a stable output contract.
Creative strategists
Find durable ads, study headlines and CTAs, group evidence by angle, and create a short list for human review.
Founders and product marketers
Research how adjacent brands frame problems, discounts, guarantees, novelty, convenience, and aspiration.
Data and automation teams
Send ranked rows to Sheets, Airtable, BigQuery, Snowflake, Slack, Make, Zapier, or an internal dashboard.
If you only need raw ads, use Facebook Ads Library Scraper instead.
Why use a separate report Actor?
Raw ad exports and competitive reports solve different jobs.
The source scraper preserves a stable extraction contract. This Actor adds cross-record ranking, taxonomy evidence, product enrichment, risks, and a summary artifact without changing that raw-data contract.
Benefits include:
- π repeatable weekly or monthly reporting;
- π transparent scoring instead of unexplained AI labels;
- πΎ exportable evidence at the row level;
- π§© direct reuse of an existing raw Ads Library dataset;
- π no mandatory third-party AI or vector-database credentials;
- β οΈ explicit caveats about what public ad evidence cannot prove.
What data can I extract?
| Field group | Example fields | Meaning |
|---|---|---|
| Identity | rank, adId, adLibraryUrl | Stable row identity and source link |
| Advertiser | advertiserName, advertiserPageUrl | Public advertiser context |
| Creative | copy, headline, cta, creativeType, mediaUrls | Message and creative assets |
| Delivery | platforms, isActive, startDate, endDate, runDays | Public delivery metadata |
| Destination | destinationUrl, destinationDomain | Normalized landing destination |
| Product | productTitle, productVendor, productType, price range, availability | Public Shopify JSON enrichment |
| Reach | reachLower, reachUpper, reachMidpoint, reachSource | Source transparency evidence when present |
| Angle | angle, angleConfidence, angleEvidence | Auditable bounded classification |
| Score | scoreRunDuration, scoreReach, scoreEvidence, scoreTotal | Visible ranking components |
| Safety | risks, enrichmentStatus | Missing evidence and enrichment limitations |
Optional fields are omitted when the public source does not expose them. Numbers remain numbers and booleans remain booleans for clean exports.
How are competitor ads ranked?
The maximum score is 100 points:
- Run duration: 45 points. Increases through 90 observed days, then caps.
- Reach evidence: 35 points. Uses a logarithmic normalization of a public reach or impression midpoint.
- Angle evidence: 20 points. Requires a matched phrase and scales with classification confidence.
Missing reach receives zero reach points. Missing or invalid start dates receive zero duration points. Unclassified copy receives zero angle-evidence points.
This prevents the Actor from silently inventing performance evidence.
A high score does not mean high ROAS, conversions, revenue, or profit. It means the ad has stronger observable research signals under the documented formula.
Which persuasion angles are detected?
The deterministic v1 taxonomy includes:
discount_value;scarcity_urgency;social_proof;problem_solution;authority;novelty;aspiration;convenience;risk_reversal;unclassified.
Evidence snippets come from the ad headline, body, or CTA. The Actor does not send your records to an external language model.
Because the taxonomy is bounded, teams can compare repeated reports without model drift.
How does Shopify product enrichment work?
When a normalized destination contains /products/{handle}, the Actor requests the public /products/{handle}.json endpoint.
Supported fields can include:
- product title and handle;
- vendor and product type;
- minimum and maximum variant price;
- whether any variant is available.
Requests are cached by normalized destination URL within the run. Concurrency is bounded by input. The ad row is still emitted if enrichment fails or is not applicable.
The endpoint does not reliably expose store currency, so prices are not mislabeled with an invented currency.
How much does it cost to analyze Meta competitor ads?
The Actor uses pay-per-event pricing:
- report start: $0.005;
- each analyzed ad on the BRONZE plan: $0.00025721 before plan discounts.
A 5-ad starter report is approximately $0.0063 at BRONZE pricing. A 25-ad research report is approximately $0.0114. A 100-ad category report is approximately $0.0307.
Apify plan tiers can reduce the per-ad price. The input prefill uses only 5 ads to keep the first run small.
The composed source Actor has its own platform charges, which are paid by the calling account and shown in Apify usage. Always review the run estimate in Console before large scheduled jobs.
How to run the Actor
- Open Meta Ads Competitive Intelligence in Apify Console.
- Open the public Meta Ads Library in another tab.
- Configure a keyword or advertiser-page search.
- Copy the complete results URL from your browser.
- Paste it into Meta Ads Library URLs.
- Set Maximum ads to analyze.
- Leave Shopify enrichment enabled when product research matters.
- Click Start.
- Review Ranked ad evidence in the dataset.
- Open Report summary for aggregate angle counts and the top-ad list.
For EU transparency fields, use a country such as Ireland in the source Ads Library search. Availability still depends on Meta's public response for each ad.
Input parameters
| Parameter | Type | Default | Limits | Description |
|---|---|---|---|---|
adsLibraryUrls | string array | Ireland Allbirds search prefill | 10 URLs | Public search or advertiser results URLs |
maxAds | integer | 25, prefill 5 | 1-200 | Combined unique ads in the report |
enrichShopify | boolean | true | β | Attempt supported public product JSON enrichment |
maxEnrichmentConcurrency | integer | 4, prefill 2 | 1-10 | Parallel product endpoint requests |
adRecords | object array | empty | 200 rows | Existing output from our source scraper |
Provide at least one URL or one direct ad record. Direct records and URL results can be combined.
Invalid hosts or paths fail closed. A total source extraction failure exits non-zero instead of returning a misleading successful run.
Input example
{"adsLibraryUrls": ["https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=IE&media_type=all&q=allbirds&search_type=keyword_unordered"],"maxAds": 25,"enrichShopify": true,"maxEnrichmentConcurrency": 4}
To re-analyze a prior export without another source run:
{"adRecords": [{"adArchiveId": "123456789012345","pageName": "Example Brand","isActive": true,"startDate": "2026-05-01","bodyText": "Try it free. Cancel anytime.","title": "A simpler way to work","ctaText": "Start free trial","linkUrl": "https://example.com/products/demo"}],"maxAds": 1,"enrichShopify": false}
Output example
{"rank": 1,"adId": "123456789012345","adLibraryUrl": "https://www.facebook.com/ads/library/?id=123456789012345","advertiserName": "Example Brand","isActive": true,"headline": "A simpler way to work","cta": "Start free trial","creativeType": "image","mediaUrls": ["https://scontent.example/creative.jpg"],"platforms": ["facebook", "instagram"],"destinationUrl": "https://example.com/products/demo","enrichmentStatus": "not_found","startDate": "2026-05-01","runDays": 82,"reachSource": "unavailable","angle": "risk_reversal","angleConfidence": 0.84,"angleEvidence": ["Try it free. Cancel anytime."],"scoreRunDuration": 41,"scoreReach": 0,"scoreEvidence": 16.8,"scoreTotal": 57.8,"risks": ["Ranking is not a performance or ROAS estimate.","Public reach/impression evidence is unavailable."],"analyzedAt": "2026-07-22T16:00:00.000Z"}
The exact values depend on the public source at run time.
Report summary
The key-value store record named REPORT contains:
- generation time;
- source Actor and source run ID;
- ads analyzed and products enriched;
- angle frequency counts;
- a compact top-10 ad list;
- methodology statements;
- caveats for responsible interpretation.
Use dataset rows for analysis and exports.
Use REPORT for Slack messages, dashboards, briefs, or downstream agents.
Tips for better competitor research
- π― Use advertiser-page result URLs for precise brand research.
- π Repeat the same search by country to compare market-specific creative.
- π Schedule weekly runs and compare ad IDs with the previous dataset.
- π§ͺ Start with 5-25 ads before expanding a category report.
- ποΈ Keep enrichment on for direct product destinations.
- π Preserve the full Ads Library URL so embedded filters reach the source Actor.
- π§ Review evidence snippets before using an angle in client-facing copy.
- β οΈ Treat duration and reach as observable signals, not outcomes.
Integrations and workflows
Google Sheets or Airtable brief
Schedule the Actor weekly.
Export the default dataset.
Sort by scoreTotal, filter by brand, and assign top rows to strategists.
Slack competitor digest
Use a run-finished webhook.
Fetch the REPORT record.
Post angle counts and top-ad links to a channel.
BigQuery or Snowflake history
Append dataset rows with analyzedAt.
Deduplicate by adId and reporting date.
Track when an ad first appears or disappears from successive public snapshots.
Make, Zapier, or n8n
Trigger the Actor from a client or category list. Route enriched products to ecommerce research and unclassified rows to manual review.
Cross-channel research
Pair reports with Google Ads Scraper and LinkedIn Ad Library Scraper. Join by advertiser, destination domain, creative text, and reporting date.
Using the Apify API with JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/meta-ads-competitive-intelligence').call({adsLibraryUrls: ['https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=IE&q=allbirds&search_type=keyword_unordered'],maxAds: 25,enrichShopify: true,maxEnrichmentConcurrency: 4,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Using the Apify API with Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/meta-ads-competitive-intelligence').call(run_input={'adsLibraryUrls': ['https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=IE&q=allbirds&search_type=keyword_unordered'],'maxAds': 25,'enrichShopify': True,'maxEnrichmentConcurrency': 4,})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(items)
Using the Apify API with cURL
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~meta-ads-competitive-intelligence/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"adsLibraryUrls": ["https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=IE&q=allbirds&search_type=keyword_unordered"],"maxAds": 25,"enrichShopify": true}'
Fetch dataset items after the run succeeds:
$curl "https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true"
Fetch the report summary:
$curl "https://api.apify.com/v2/key-value-stores/STORE_ID/records/REPORT"
Use with Apify MCP
Expose the Actor to Claude Code:
$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/meta-ads-competitive-intelligence"
Claude Desktop, Cursor, and VS Code can use this JSON configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/meta-ads-competitive-intelligence"}}}
Example prompts:
- βRun a 25-ad Meta competitor report for this Ads Library URL and summarize the top three evidence-backed angles.β
- βWhich ranked ads have product enrichment and have run for more than 30 days?β
- βDraft a creative research brief from the report, but repeat every caveat about reach and ROAS.β
MCP can invoke the Actor and retrieve its structured output. It does not change the Actor's deterministic scoring method.
Scheduling a weekly ads report
Create an Apify schedule with a stable input. Choose a weekly cadence appropriate for your market. Store each run's dataset ID and date in your destination system.
For change tracking:
- compare
adIdvalues with the previous run; - flag newly observed IDs;
- compare
isActive,runDays, copy, and destination; - preserve removed rows in your own history;
- review top-score changes with a person.
This Actor creates snapshots and analysis. It does not maintain a permanent cross-run monitor database by itself.
Data quality and limitations
Meta controls what the public Ads Library exposes. Fields vary by geography, category, advertiser, and time.
Important limitations:
- public reach or impression evidence may be absent;
- source ads can disappear or change;
- redirected destinations can become invalid;
- only recognizable
/products/{handle}paths are enriched; - some stores disable public product JSON;
- Shopify prices may not identify currency;
- pattern-based classification cannot capture every creative nuance;
- identical copy can support more than one persuasion angle;
- the highest-confidence matched angle is returned as the primary label.
Review source links before making material decisions.
Is scraping Meta Ads Library legal?
Meta Ads Library is a public transparency surface. However, legality depends on jurisdiction, purpose, data handling, and contractual obligations.
Users are responsible for:
- following applicable laws and Meta terms;
- respecting intellectual property and trademarks;
- avoiding deceptive reuse of competitor creative;
- not using output for unlawful profiling or discrimination;
- applying appropriate retention and security controls;
- reviewing Shopify store terms before downstream use.
This Actor does not bypass a login or request private account data. It composes a maintained public-data Actor and reads supported public product endpoints.
Troubleshooting
Why did the run fail with an invalid URL message?
The Actor accepts only facebook.com, www.facebook.com, or m.facebook.com with the exact /ads/library/ path.
Open the Ads Library results page and copy the complete browser URL.
Do not paste a normal Facebook post or advertiser profile URL.
Why is reachSource set to unavailable?
Meta did not expose a usable public reach or impression range in that source row. Try a supported EU country such as Ireland, but do not assume every ad will include transparency data. The Actor intentionally does not infer a missing number.
Why is product enrichment not_product_url?
The destination does not contain a recognized /products/{handle} path.
Category pages, homepages, custom landing pages, and non-Shopify stores remain valid ad rows but are not product-enriched.
Why is product enrichment fetch_error or not_found?
The store may block the endpoint, remove the product, redirect differently, or disable public JSON. Reduce concurrency and retry later. The ad analysis remains complete.
Why did the source return no ads?
Open the original URL in Meta Ads Library and check its filters. Try an active keyword with a country selected. A true total extraction failure exits non-zero so schedules can alert you.
Frequently asked questions
Does this Actor use AI?
The baseline does not call an external LLM. It uses a deterministic persuasion taxonomy, evidence phrases, and a transparent score formula.
Can it write ad copy?
It produces evidence a human or downstream agent can use in a brief. It does not automatically imitate competitor copy or claim generated copy will perform.
Does a long-running ad mean it is profitable?
No. Run duration is observable; profitability is not. Use it only as one research signal.
Can I analyze an existing dataset?
Yes.
Pass rows exported by automation-lab/facebook-ads-library in adRecords.
This is useful when you already paid for and stored the raw extraction.
Can I mix direct records and new URLs?
Yes.
The Actor combines and deduplicates rows by ad ID up to maxAds.
Are product prices converted?
No. Prices are emitted as public variant numbers without an invented currency. Perform conversion only after resolving store currency in your own workflow.
Is this a stateful ads monitor?
No. Schedule it and store successive datasets if you need historical change tracking.
Related Facebook and advertising Actors
- Facebook Ads Library Scraper β raw Meta ad records.
- Facebook Ads Transcript Scraper β spoken creative transcript enrichment.
- Google Ads Scraper β Google Ads Transparency Center research.
- LinkedIn Ad Library Scraper β B2B LinkedIn creative research.
Choose the raw source Actor when you need full export flexibility. Choose Meta Ads Competitive Intelligence when you need ranked cross-record evidence and a report summary.
Responsible interpretation checklist
Before sharing a report:
- confirm the Ads Library URLs and countries;
- open the source links for top-ranked ads;
- distinguish reach from impressions when
reachSourcesays so; - repeat that score is not ROAS;
- verify product currency independently;
- inspect angle evidence, not only the label;
- preserve missing evidence as missing;
- timestamp the snapshot;
- avoid copying protected creative;
- add human judgment to any client recommendation.
That discipline turns public ad records into useful, defensible research rather than unsupported performance claims.