# Meta Ads Competitive Intelligence (`automation-lab/meta-ads-competitive-intelligence`) Actor

📊 Turn public Meta Ads Library URLs into ranked competitor briefs with ad evidence, transparent angle scoring, and optional Shopify product enrichment.

- **URL**: https://apify.com/automation-lab/meta-ads-competitive-intelligence.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Meta Ads Competitive Intelligence

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](https://apify.com/automation-lab/facebook-ads-library), 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:

1. validates that every URL is a real Meta Ads Library path;
2. invokes our maintained Facebook Ads Library Actor;
3. reads and deduplicates the returned ad records;
4. calculates observed run duration from public start and end dates;
5. normalizes public reach or impression ranges when available;
6. classifies a bounded persuasion angle from ad text;
7. copies matching text snippets as classification evidence;
8. optionally reads a public Shopify product JSON endpoint;
9. scores each ad with visible duration, reach, and evidence components;
10. writes ranked rows to the default dataset;
11. writes an aggregate JSON report to the `REPORT` KVS 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](https://apify.com/automation-lab/facebook-ads-library) 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

1. Open Meta Ads Competitive Intelligence in Apify Console.
2. Open the public Meta Ads Library in another tab.
3. Configure a keyword or advertiser-page search.
4. Copy the complete results URL from your browser.
5. Paste it into **Meta Ads Library URLs**.
6. Set **Maximum ads to analyze**.
7. Leave Shopify enrichment enabled when product research matters.
8. Click **Start**.
9. Review **Ranked ad evidence** in the dataset.
10. 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

```json
{
  "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:

```json
{
  "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

```json
{
  "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](https://apify.com/automation-lab/google-ads-scraper) and [LinkedIn Ad Library Scraper](https://apify.com/automation-lab/linkedin-ad-library-scraper).
Join by advertiser, destination domain, creative text, and reporting date.

### Using the Apify API with JavaScript

```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

```python
import os
from apify_client import ApifyClient

client = 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().items
print(items)
```

### Using the Apify API with cURL

```bash
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:

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true"
```

Fetch the report summary:

```bash
curl "https://api.apify.com/v2/key-value-stores/STORE_ID/records/REPORT"
```

### Use with Apify MCP

Expose the Actor to Claude Code:

```bash
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:

```json
{
  "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:

1. compare `adId` values with the previous run;
2. flag newly observed IDs;
3. compare `isActive`, `runDays`, copy, and destination;
4. preserve removed rows in your own history;
5. 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](https://apify.com/automation-lab/facebook-ads-library) — raw Meta ad records.
- [Facebook Ads Transcript Scraper](https://apify.com/automation-lab/facebook-ads-transcript-scraper) — spoken creative transcript enrichment.
- [Google Ads Scraper](https://apify.com/automation-lab/google-ads-scraper) — Google Ads Transparency Center research.
- [LinkedIn Ad Library Scraper](https://apify.com/automation-lab/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 `reachSource` says 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.

# Actor input Schema

## `adsLibraryUrls` (type: `array`):

Paste public facebook.com/ads/library/ search or advertiser-result URLs. Filters embedded in each URL are preserved by the source scraper. Maximum 10 URLs.

## `maxAds` (type: `integer`):

Limit the combined report size. Use a small value for a quick brief and a larger value for recurring competitor research.

## `enrichShopify` (type: `boolean`):

Fetch public /products/{handle}.json endpoints when an ad destination is a Shopify-style product URL. Other destinations remain in the report without enrichment.

## `maxEnrichmentConcurrency` (type: `integer`):

Maximum simultaneous product endpoint requests. Lower this if destination stores rate-limit requests.

## `adRecords` (type: `array`):

Optional JSON array of rows previously exported by automation-lab/facebook-ads-library. This avoids launching the source scraper again and can be combined with URLs.

## Actor input object example

```json
{
  "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": 5,
  "enrichShopify": true,
  "maxEnrichmentConcurrency": 2,
  "adRecords": []
}
```

# Actor output Schema

## `rankedAds` (type: `string`):

Default dataset rows sorted by transparent duration, reach, and angle-evidence score components.

## `report` (type: `string`):

Aggregate angle counts, top ads, methodology, source run ID, and interpretation caveats.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "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": 5,
    "enrichShopify": true,
    "maxEnrichmentConcurrency": 2,
    "adRecords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/meta-ads-competitive-intelligence").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "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": 5,
    "enrichShopify": True,
    "maxEnrichmentConcurrency": 2,
    "adRecords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/meta-ads-competitive-intelligence").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "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": 5,
  "enrichShopify": true,
  "maxEnrichmentConcurrency": 2,
  "adRecords": []
}' |
apify call automation-lab/meta-ads-competitive-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/meta-ads-competitive-intelligence",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Meta Ads Competitive Intelligence",
        "description": "📊 Turn public Meta Ads Library URLs into ranked competitor briefs with ad evidence, transparent angle scoring, and optional Shopify product enrichment.",
        "version": "0.1",
        "x-build-id": "RZpIaZKfdSbGnWl2i"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~meta-ads-competitive-intelligence/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-meta-ads-competitive-intelligence",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/automation-lab~meta-ads-competitive-intelligence/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-meta-ads-competitive-intelligence",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/automation-lab~meta-ads-competitive-intelligence/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-meta-ads-competitive-intelligence",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "adsLibraryUrls": {
                        "title": "🔗 Meta Ads Library URLs",
                        "maxItems": 10,
                        "type": "array",
                        "description": "Paste public facebook.com/ads/library/ search or advertiser-result URLs. Filters embedded in each URL are preserved by the source scraper. Maximum 10 URLs.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxAds": {
                        "title": "Maximum ads to analyze",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Limit the combined report size. Use a small value for a quick brief and a larger value for recurring competitor research.",
                        "default": 25
                    },
                    "enrichShopify": {
                        "title": "🛍️ Enrich Shopify product links",
                        "type": "boolean",
                        "description": "Fetch public /products/{handle}.json endpoints when an ad destination is a Shopify-style product URL. Other destinations remain in the report without enrichment.",
                        "default": true
                    },
                    "maxEnrichmentConcurrency": {
                        "title": "Enrichment concurrency",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Maximum simultaneous product endpoint requests. Lower this if destination stores rate-limit requests.",
                        "default": 4
                    },
                    "adRecords": {
                        "title": "Existing ad records (advanced)",
                        "maxItems": 200,
                        "type": "array",
                        "description": "Optional JSON array of rows previously exported by automation-lab/facebook-ads-library. This avoids launching the source scraper again and can be combined with URLs.",
                        "items": {
                            "type": "object"
                        },
                        "default": []
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
