# Competitor Ad Intel — All Platforms Ad Library (Google + Bing) (`mochiboo/competitor-ad-intel-all-platforms`) Actor

One advertiser or domain in — every ad it runs on Google AND Microsoft/Bing back, in ONE normalized schema. Cross-platform competitor ad research / ad intelligence API: creative, format, first/last-shown, region. Filter by region & date, toggle platforms. Clean JSON/CSV, company-level only.

- **URL**: https://apify.com/mochiboo/competitor-ad-intel-all-platforms.md
- **Developed by:** [mochi](https://apify.com/mochiboo) (community)
- **Categories:** Developer tools, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Competitor Ad Intel — All Platforms · Cross-Platform Ad Library & Ad Intelligence API

**One advertiser in — every ad it runs on Google *and* Microsoft/Bing back, in ONE unified schema.**
Give a brand or domain (e.g. `nike.com`) and get a single, flat, normalized table of its ads across
the **Google Ads Transparency Center** and the **Microsoft / Bing Ads Library** — no stitching three
tools together. Built for **competitor ad research across all platforms**, **cross-platform ad
library** pulls, **ad intelligence API** pipelines, and **AI agents** that want one tool, not many.

> **Keywords:** competitor ads all platforms, cross-platform ad library, ad intelligence api,
> competitor ad research, multi-platform ad spy, Google ads transparency, Bing ads library,
> Microsoft ads transparency, competitor ad monitoring, ad library api.

### Why this actor

- **One tool, both platforms.** Nobody on the shelf aggregates Google + Bing ad intel into a single
  normalized output. Query once; pivot Google and Bing side by side by `advertiserName` and `adFormat`.
- **AI-agent-friendly.** Flat schema, identical top-level keys on every row (only `platform` and the
  nested `platformData` differ), short input descriptions, and a fast small default so an agent can
  probe cheaply before a full pull.
- **Streams results live.** Each ad is written to your dataset the moment it's normalized — an
  interrupted run keeps everything found so far; you never wait until the end.
- **Never a silent gap.** If one platform is down or errors, the run still returns the other's ads
  plus a `warnings` note in the run summary — graceful partial results, not a whole-run failure.
- **Reuses two proven scrapers** as in-process libraries (not sub-actor calls, so you're never
  double-charged): the Google Ads Transparency and Bing Ads Library actors.

### Coverage — read this (honest scope)

| Platform | Geography | Notes |
|---|---|---|
| **Google Ads Transparency** | **Global** | Search/Shopping/Display/YouTube creatives; region filter supported. |
| **Microsoft / Bing Ads Library** | **EEA only** | Bing's Ad Library is an EU-compliance transparency tool, so it contains ads served in the European Economic Area — **not the US**. |

So: a **US** region returns **Google-only** results (Bing has no US data) — and the run tells you so
in `warnings`. For EEA markets you get both. We do not oversell Bing coverage.

### Input

| Field | Type | Description |
|---|---|---|
| `queries` | array | One advertiser per line — a brand name or domain (`nike.com`, `Bosch`). Searched on both platforms. |
| `searchMode` | select | `auto` (brand/domain search, default) · `keyword` (words in ad copy / advertiser) · `advertiserId` (exact platform IDs; Google `AR…`, Bing numeric — mixed IDs are auto-routed). |
| `platforms` | array | `["google","bing"]` by default. Turn one off to run a single platform. |
| `region` | string | Country name/code (`US`, `DE`, `United Kingdom`) or `anywhere`. Applied per platform (Bing = EEA only). |
| `dateFrom` / `dateTo` | string | `YYYY-MM-DD` active-window bounds. |
| `includeBingAdDetails` | boolean | Bing only: fetch per-ad impressions range / by-country / targeting (one extra request per Bing ad; off by default). |
| `maxResultsPerPlatform` | integer | Stop after N ads **per platform** (default **20** for a fast preview; `0` = no limit). |

#### Example

```json
{
  "queries": ["nike.com"],
  "searchMode": "auto",
  "platforms": ["google", "bing"],
  "region": "DE",
  "maxResultsPerPlatform": 50
}
```

### Output — one unified row per ad

Every row has the **same top-level fields** regardless of platform. A field a platform genuinely
does not expose is `null` (never invented). Platform-unique extras live under `platformData`.

```json
{
  "platform": "google",
  "advertiserName": "Nike, Inc.",
  "advertiserDomain": "nike.com",
  "advertiserId": "AR16735076323512287233",
  "adId": "CR03002423070389436417",
  "adFormat": "image",
  "title": null,
  "bodyText": null,
  "destinationUrl": null,
  "displayUrl": null,
  "imageUrl": "https://s0.2mdn.net/…_300x250_EN.jpg",
  "creativeUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?…",
  "firstShown": "2021-10-26T07:00:00.000Z",
  "lastShown": "2026-05-24T23:54:27.000Z",
  "advertiserVerified": null,
  "region": "US",
  "adLibraryUrl": "https://adstransparency.google.com/advertiser/AR…/creative/CR…",
  "matchedQuery": "nike.com",
  "searchMode": "domain",
  "source": "adstransparency.google.com",
  "scrapedAt": "2026-07-27T00:00:00.000Z",
  "platformData": {
    "variantCount": 466,
    "advertiserAdCount": null,
    "advertiserCountry": null,
    "firstShownTs": 1635231600,
    "lastShownTs": 1779663267
  }
}
```

A Bing row is the same shape — `platform: "bing"`, `title`/`bodyText`/`destinationUrl` populated,
`adFormat`/`creativeUrl`/`advertiserDomain` = `null`, and Bing extras under `platformData`
(`totalImpressionsRange`, `impressionsByCountry`, `targets`, `assetJson`).

#### Normalization mapping (the contract)

How each platform's native field maps to the unified schema:

| Unified field | Google (Ads Transparency) | Bing (Ads Library) |
|---|---|---|
| `platform` | `"google"` | `"bing"` |
| `advertiserName` | advertiser name (org) | advertiser name (funding org) |
| `advertiserDomain` | verified domain | — (`null`) |
| `advertiserId` | `AR…` id | numeric id |
| `adId` | **creative id** (`CR…`) | ad id |
| `adFormat` | text / image / video | — (`null`, untyped) |
| `title` | — (`null`) | ad title |
| `bodyText` | — (`null`) | ad description |
| `destinationUrl` | — (`null`, not exposed) | landing URL |
| `displayUrl` | — (`null`) | display URL |
| `imageUrl` | direct image (image creatives) | first image in `AssetJson` |
| `creativeUrl` | rendered-creative preview URL | — (`null`) |
| `firstShown` / `lastShown` | ISO **datetime** | ISO **date** (needs `includeBingAdDetails`) |
| `advertiserVerified` | — (`null`) | verified flag |
| `region` | region scoped to | advertiser country (EEA) |
| `adLibraryUrl` | deep-link to Google | deep-link to Bing |
| `matchedQuery` / `searchMode` / `source` / `scrapedAt` | carried from the run | carried from the run |
| `platformData` | `variantCount`, `advertiserAdCount`, `advertiserCountry`, `firstShownTs`, `lastShownTs` | `totalImpressionsRange`, `impressionsByCountry`, `targets`, `assetJson`, `displayUrl` |

**On `platformData`:** these are the fields unique to one platform with no cross-platform twin, so
they'd be misleading as top-level columns. Keeping them nested means the aggregate loses **nothing**
versus the single-platform actors — Google's breadth/enrichment and Bing's impressions/targeting are
all still there.

*Note on Google `variantCount`:* a **relative breadth proxy** (served variants/placements Google
reports per creative), **not** impressions or spend — the public Center exposes neither. Bing's
`totalImpressionsRange` is a real (ranged) impressions figure Microsoft publishes.

### Run summary

Each run writes a `RUN_SUMMARY` to the key-value store: `adsReturned`, a `byPlatform` breakdown
(pushed / pages / errors), `resultCapReached` + `cappedPlatforms` (raise `maxResultsPerPlatform` for
full coverage), `complete` (clean, exhaustive across the selected platforms), and `warnings` — so a
partial or capped result set is never silent.

### Compliance

- **Company / advertiser-level only.** Both sources disclose the *funding organisation*, not a
  person — there is no personal-data field in the output. PDPA / GDPR-friendly by design.
- Reads only public, no-login ad-transparency data (Google's Ads Transparency Center and Microsoft's
  public Ad Library API). Use responsibly and in line with each platform's terms.

### Pricing

Pay per result (per ad returned). No subscription — you only pay for the data you pull.

# Actor input Schema

## `queries` (type: `array`):

One advertiser per line — a brand name or domain (e.g. "nike.com", "Bosch"). The actor searches BOTH Google and Bing for each and returns every ad it finds, in one unified schema. For an exact-ID lookup instead, set Search mode to 'advertiserId' and paste platform IDs (Google AR..., Bing numeric).

## `searchMode` (type: `string`):

How to read each query. 'auto' (default) = brand/domain search on both platforms — the usual choice. 'keyword' = find ads whose copy or advertiser matches the term. 'advertiserId' = exact platform advertiser IDs (Google AR..., Bing numeric); mixed IDs are routed to the right platform automatically.

## `platforms` (type: `array`):

Which ad libraries to query. Default = both. Turn one off to run a single platform. If one platform errors, the run still returns the other's results plus a warning (never a whole-run failure).

## `region` (type: `string`):

Restrict ads to where they were shown. Country name/code (e.g. "US", "United Kingdom", "DE") or "anywhere". Applied per platform: Google is global; Bing covers the EEA only, so a non-EEA region returns Google-only results. Unknown values fall back to anywhere (never a wrong-country leak).

## `dateFrom` (type: `string`):

Only ads whose active period overlaps on/after this date. Format YYYY-MM-DD. Leave blank for no lower bound.

## `dateTo` (type: `string`):

Only ads whose active period overlaps on/before this date. Format YYYY-MM-DD. Leave blank for no upper bound.

## `includeBingAdDetails` (type: `boolean`):

Bing only: fetch per-ad impressions range, impressions-by-country and targeting (one extra request per Bing ad, slower). Off by default. Google's public Center does not expose these.

## `maxResultsPerPlatform` (type: `integer`):

Stop after this many ads PER platform (so a 2-platform run returns up to 2x this). Kept low (20) for a fast, cheap preview; raise for full pulls. 0 = no limit.

## Actor input object example

```json
{
  "queries": [
    "nike.com"
  ],
  "searchMode": "auto",
  "platforms": [
    "google",
    "bing"
  ],
  "region": "anywhere",
  "includeBingAdDetails": false,
  "maxResultsPerPlatform": 20
}
```

# 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 = {
    "queries": [
        "nike.com"
    ],
    "region": "anywhere"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mochiboo/competitor-ad-intel-all-platforms").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 = {
    "queries": ["nike.com"],
    "region": "anywhere",
}

# Run the Actor and wait for it to finish
run = client.actor("mochiboo/competitor-ad-intel-all-platforms").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 '{
  "queries": [
    "nike.com"
  ],
  "region": "anywhere"
}' |
apify call mochiboo/competitor-ad-intel-all-platforms --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=mochiboo/competitor-ad-intel-all-platforms",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/dgd2OqVldLnyJALod/builds/ZilciwvhBahpzFAUj/openapi.json
