# Google Ads Transparency Scraper + Creative Monitor (`produkdigitalali/google-ads-transparency-creative-intelligence-monitor`) Actor

Scrape public Google Ads Transparency creatives, group creative families, analyze competitor ad activity, and monitor new, updated, stopped, and newly observed ads across runs.

- **URL**: https://apify.com/produkdigitalali/google-ads-transparency-creative-intelligence-monitor.md
- **Developed by:** [ProdukDigitalAli](https://apify.com/produkdigitalali) (community)
- **Categories:** Automation, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 71.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 google ad processeds

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/actors/running/actors-in-store.md#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

## Google Ads Transparency Scraper + Creative Monitor

Scrape public Google Ads Transparency creatives, group related creatives into deterministic families, summarize competitor activity, and optionally monitor ad and exposed landing-page changes across runs.

### Why this Actor is different

This is not only another Google Ads Transparency row extractor. It combines three jobs:

1. **Discovery** — resolve keywords, domains, direct AR advertiser IDs, or full Ads Transparency URLs and collect public creatives.
2. **Creative intelligence** — group equivalent/related creative assets into stable creative families and calculate format mix, family concentration, launch recency, visible lifespan, and landing-domain concentration without an LLM.
3. **Monitoring** — persist advertiser state and classify new, updated, possibly stopped, confirmed stopped, reactivated, advertiser failures/recoveries, and optional landing-page changes.

### Creative-family fingerprinting

Every creative receives `creativeFamilyId`, `familyMethod`, and `familyConfidence`.

- text ads: normalized headline + description + landing host (`TEXT_COPY`, HIGH)
- image ads with media enrichment: exact asset SHA-256 or perceptual dHash (HIGH)
- image fallback: normalized public asset URL (MEDIUM)
- video: YouTube video ID when exposed (HIGH), otherwise normalized video URL (MEDIUM)
- final fallback: creative ID only (LOW; never merges different creatives)

This helps distinguish **many creative IDs** from **many genuinely different creative concepts/assets**.

#### Stable change hashing

Google can regenerate preview wrapper callback identifiers on every request. The Actor canonicalizes those volatile render parameters before comparing creatives, so callback churn and observation-date roll-forward do not produce false `AD_UPDATED` events. Meaningful asset/copy/destination changes remain detectable.

### Conservative monitoring semantics

A partial Google result window is not treated as a complete advertiser inventory. The Actor distinguishes a creative that is *proven new* from one that is merely *newly observed* in a rotating partial window.

- `NEW_AD` — the creative was absent from a previous **complete** advertiser baseline, so it is safe to call it new relative to that baseline
- `NEWLY_OBSERVED_AD` — the creative ID was not in the stored state, but the previous advertiser crawl was incomplete, so the Actor does **not** claim it was newly launched
- first complete-crawl miss: `POSSIBLY_STOPPED`
- N complete consecutive misses (default 2): `AD_STOPPED`
- later return: `AD_REACTIVATED`
- incomplete/truncated/failed crawl: **no missing-ad inference**

Direct AR advertiser IDs are recommended for scheduled monitoring because keyword/domain resolution can legitimately return multiple advertiser accounts.

For high-volume collection, the Actor paginates `SearchCreatives` conservatively (40 creatives per RPC page in the current implementation) and treats Google redirects or suspicious empty continuation pages as incomplete rather than as proof that an advertiser inventory ended.

### Optional landing-page monitoring

When Google publicly exposes/decodes a destination URL, `auditLandingPages` can inspect bounded public HTTP/HTML signals: HTTP status, final URL, title, meta description, canonical, noindex, H1, and visible-content hash.

Monitoring can emit `LANDING_PAGE_CHANGED`, `LANDING_PAGE_BROKEN`, and `LANDING_PAGE_RECOVERED`. Landing-page and media requests block localhost/private/link-local/reserved targets and revalidate redirect destinations.

### Example

```json
{
  "domains": ["nike.com"],
  "region": "US",
  "maxAdsPerAdvertiser": 100,
  "includeDetails": true,
  "includeAdvertiserSummary": true,
  "fingerprintMedia": false,
  "auditLandingPages": false
}
```

Scheduled monitor:

```json
{
  "advertiserIds": ["AR1234567890"],
  "maxAdsPerAdvertiser": 500,
  "monitorMode": true,
  "emitChangesOnly": true,
  "baselineOnly": true,
  "monitorKey": "competitor-daily",
  "stopConfirmationRuns": 2
}
```

`baselineOnly` only suppresses the first baseline for an empty advertiser state; later runs continue normally. If a baseline is incomplete, later unseen IDs are reported as `NEWLY_OBSERVED_AD` until a complete baseline has established the full public inventory.

### Output

The dataset can contain:

- `ADVERTISER_RESOLUTION` — candidates, scores, ambiguity, selected advertiser IDs
- `AD` — structured public creative record
- `ADVERTISER_SUMMARY` — deterministic creative/activity intelligence
- `CHANGE` — monitoring events
- `ERROR` — explicit reader-mode errors

Run-level diagnostics are written to `RUN_SUMMARY` in the default key-value store.

### Important limitations

- Google Ads Transparency is a public transparency surface, but the web RPC used by this Actor is not a documented stable Google API. Google can change response shapes or rate limits; the Actor fails explicitly rather than fabricating missing fields.
- `firstShown` / `lastShown` are best-effort fields from the current public response shape and must be Cloud-validated against real live responses after each protocol change.
- Ordinary commercial ads do **not** universally expose spend, impressions, audience targeting, conversion performance, or every landing URL. This Actor does not invent those metrics.
- Destination URL, text decoding, media URLs, and dates can be absent depending on creative format and what Google exposes.
- Optional media fingerprinting and landing-page auditing add network work and can be slower than creative-only collection.
- Apify Proxy is enabled by default. Sticky proxy sessions are unique per Actor run, and the client rotates to a fresh proxy session when Google responds with `google.com/sorry` or HTTP 429. Users can still provide their own proxy configuration.
- Transient HTTP transport/protocol failures (including incomplete chunked reads, proxy errors, connection/read/write errors, and timeouts) are normalized into retryable errors; Google session/RPC failures reinitialize the public session and rotate the proxy when available instead of crashing the Actor.
- No CAPTCHA solving or authenticated/private Google account access is implemented. If all retry/proxy rotations remain blocked, the Actor reports `GOOGLE_BLOCKED` explicitly.

### Security and reliability

- bounded ads, targets, concurrency, response bytes, redirects, retries, and timeouts
- private/local network blocking for public enrichment requests
- redirect target revalidation
- per-advertiser persistent KVS state
- failure-state preservation
- duplicate advertiser processing avoided within one run
- no stop inference on incomplete crawls

### Validation

The packaged release is subjected to unit/integration tests, JSON-schema/project validation, parser/HTML fuzzing, monitoring-state tests, public-network tests, and synthetic stress checks. Live Google RPC compatibility, Apify Proxy behavior, Cloud KVS persistence, real-world rate limits, throughput, and cost are deliberately left for the small Cloud validation gates because this environment has no outbound DNS access.

### Pricing

The Actor is designed for Pay Per Event pricing with one simple primary custom event:

- `ad-processed` — **$0.0008 per successfully processed creative** ($0.80 / 1,000)
- `apify-actor-start` — use Apify's synthetic start event at the default **$0.00005** in Console

A creative is billable when its public Google creative record is successfully processed. Monitoring runs still charge for unchanged creatives because the Actor must fetch and compare them. Failed creative-detail fetches are not charged. Resolution, summaries, advertiser errors, and monitoring change rows do not create extra custom charges.

The billing guard checks the user's remaining PPE budget before starting an advertiser, caps work when needed, charges successful creatives individually, and keeps a paid prefix only if a concurrent/race condition exhausts the limit mid-run. Any billing-truncated monitoring crawl is treated as incomplete so unseen previous ads remain preserved and cannot become false `AD_STOPPED` events. Billing diagnostics are included in `RUN_SUMMARY`.

Cloud full-detail benchmark evidence from the validation advertiser:

| Creatives | Dataset results | Runtime | Displayed platform cost |
|---:|---:|---:|---:|
| 10 | 11 | ~6 s | ~$0.001 |
| 50 | 51 | ~18 s | ~$0.002 |
| 100 | 101 | ~38 s | ~$0.005 |

The displayed platform cost is rounded by Apify and is not a guarantee for other advertisers, regions, proxies, optional media downloads, or landing-page audits.

# Actor input Schema

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

Mixed public search targets. Domains, AR advertiser IDs, full Ads Transparency URLs, and brand keywords are detected automatically.

## `domains` (type: `array`):

Domains to resolve to public Google Ads Transparency advertisers.

## `advertiserIds` (type: `array`):

Direct AR-prefixed Google Ads Transparency advertiser IDs. Recommended for stable scheduled monitoring.

## `targets` (type: `array`):

Optional explicit target objects with query, target type, stable targetId, and label.

## `maxTargets` (type: `integer`):

Maximum unique target definitions processed in one run.

## `resolutionPolicy` (type: `string`):

best\_match processes the highest-scoring advertiser; all\_matches processes several visible candidates.

## `maxAdvertisersPerTarget` (type: `integer`):

Maximum advertiser candidates processed for one target when all\_matches is selected.

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

Google Ads Transparency region filter. Use anywhere for no built-in region filter; regionTargetId can cover additional markets.

## `regionTargetId` (type: `integer`):

Optional Google geo-target ID overriding the built-in region mapping.

## `maxAdsPerAdvertiser` (type: `integer`):

Hard cap on creative IDs collected for each advertiser. Stop detection is conservative when this limit truncates a crawl.

## `includeDetails` (type: `boolean`):

Fetch per-creative detail pages/RPC data. Disable only for fast creative-ID discovery.

## `includeAdRecords` (type: `boolean`):

Emit one structured AD record per collected creative in normal reader mode.

## `includeAdvertiserSummary` (type: `boolean`):

Emit deterministic activity metrics such as format mix, creative-family count, launch velocity, visible lifespan, and landing-domain concentration.

## `includeResolutionRecords` (type: `boolean`):

Emit the visible advertiser candidates, scores, ambiguity flag, and selected advertiser IDs for each non-direct target.

## `fingerprintMedia` (type: `boolean`):

Download public image assets when available and compute exact SHA-256 plus a 64-bit perceptual dHash for stronger creative-family grouping.

## `auditLandingPages` (type: `boolean`):

When a destination URL is publicly exposed, audit bounded HTTP/SEO signals and monitor landing-page changes, breaks, and recoveries.

## `monitorMode` (type: `boolean`):

Persist per-advertiser creative and landing-page state across runs and classify newly observed, proven-new, updated, stopped, reactivated, broken, changed, and recovered signals.

## `emitChangesOnly` (type: `boolean`):

When monitoring, suppress unchanged creative rows and return only meaningful ad/landing/status changes.

## `baselineOnly` (type: `boolean`):

On the first monitoring run for an advertiser, save current ads without emitting first-observation creative events.

## `monitorKey` (type: `string`):

Namespace for persistent monitoring state. Reuse the same value across related scheduled runs.

## `stopConfirmationRuns` (type: `integer`):

Number of complete consecutive misses required before AD\_STOPPED. The first miss can emit POSSIBLY\_STOPPED.

## `concurrency` (type: `integer`):

Maximum concurrent creative-detail/media/landing requests inside one advertiser pipeline.

## `targetConcurrency` (type: `integer`):

Maximum advertiser target pipelines processed concurrently.

## `requestTimeoutSeconds` (type: `integer`):

Per-request timeout for Google/public HTTP requests.

## `maxRetries` (type: `integer`):

Retries transient network, rate-limit, and 5xx Google RPC responses with bounded backoff.

## `maxRedirects` (type: `integer`):

Maximum redirects followed for public media/landing requests; every redirect target is revalidated against private-network SSRF.

## `maxMediaBytes` (type: `integer`):

Maximum bytes downloaded for one image fingerprint operation.

## `maxLandingPageBytes` (type: `integer`):

Maximum bytes downloaded for one exposed landing-page audit.

## `proxyConfiguration` (type: `object`):

Optional Apify Proxy configuration. A proxy is recommended for higher-volume Google requests and rate-limit resilience.

## Actor input object example

```json
{
  "queries": [],
  "domains": [],
  "advertiserIds": [
    "AR16735076323512287233"
  ],
  "targets": [],
  "maxTargets": 20,
  "resolutionPolicy": "best_match",
  "maxAdvertisersPerTarget": 3,
  "region": "anywhere",
  "maxAdsPerAdvertiser": 10,
  "includeDetails": true,
  "includeAdRecords": true,
  "includeAdvertiserSummary": true,
  "includeResolutionRecords": true,
  "fingerprintMedia": false,
  "auditLandingPages": false,
  "monitorMode": false,
  "emitChangesOnly": false,
  "baselineOnly": false,
  "monitorKey": "default",
  "stopConfirmationRuns": 2,
  "concurrency": 10,
  "targetConcurrency": 3,
  "requestTimeoutSeconds": 30,
  "maxRetries": 3,
  "maxRedirects": 5,
  "maxMediaBytes": 5242880,
  "maxLandingPageBytes": 2097152,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Structured advertiser-resolution, AD, ADVERTISER\_SUMMARY, CHANGE, and ERROR records.

## `runSummary` (type: `string`):

Target, advertiser, creative, monitoring, landing-page, and error counts for the run.

# 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 = {
    "advertiserIds": [
        "AR16735076323512287233"
    ],
    "maxAdsPerAdvertiser": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("produkdigitalali/google-ads-transparency-creative-intelligence-monitor").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 = {
    "advertiserIds": ["AR16735076323512287233"],
    "maxAdsPerAdvertiser": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("produkdigitalali/google-ads-transparency-creative-intelligence-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "advertiserIds": [
    "AR16735076323512287233"
  ],
  "maxAdsPerAdvertiser": 10
}' |
apify call produkdigitalali/google-ads-transparency-creative-intelligence-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,produkdigitalali/google-ads-transparency-creative-intelligence-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/u5Yci57qMgqd6Qvoq/builds/fKeAADazrdatM2IYU/openapi.json
