# Changelog of Google Ads Scraper - Transparency Monitor (`vortex_data/google-ads`) Actor

- **URL**: https://apify.com/vortex\_data/google-ads/changelog.md
- **Full Actor documentation**: https://apify.com/vortex\_data/google-ads.md

## Changelog

### 2026-06-17

- Improved zero-result run reports: when no Google advertiser is resolved for the input target, `OUTPUT` now says `0 advertisers found` and suggests exact `AR...` IDs, Transparency Center URLs, or spaced brand names for joined domains.
- Cleaned Google preview UI labels such as Vietnamese `Được tài trợ` and generic `website` from decoded ad copy so they do not become `headline`, `description`, or `textLines`.
- Rebuilt the public README around Apify Store guidance: clear introduction, use cases, quick start, input options, output example, optional extras, monitoring, API/integration examples, benchmarks, limitations, FAQ, and support notes.
- Fixed the Output tab date presentation for `firstShown` and `lastShown`: Apify Console now displays the Actor's stable `YYYY-MM-DD` strings instead of reformatting them into mixed UTC date-time cells.
- Fixed output data correctness for `daysActive`: it now matches the visible `firstShown` / `lastShown` dates instead of being one day short when Google's raw timestamps are not exactly midnight UTC.
- Fixed downloaded creative and landing archive links by generating pre-signed Apify key-value store URLs instead of raw API URLs that can return 403 outside authenticated API contexts.
- Improved keyword/domain advertiser resolution: exact or start-of-name brand matches and higher Google-exposed volume now outrank weaker matches where the brand appears later in the name, so inputs like `adobe.com` resolve to the main Adobe advertiser instead of a small unrelated advertiser.
- Replaced one-RPC-one-session routing with a warmed sticky Google RPC session pool. Individual hot proxy sessions now cool down or retire without making the whole cheap route fail, reducing unnecessary 429 churn in rich enrichment runs.
- Improved large all-extras runs by caching OCR results per image URL and avoiding duplicate image OCR on video rows when video OCR is already enabled.
- Reduced wasted all-extras CPU work: image OCR now runs on image creatives, not text/video rows that already have structured copy or video OCR, and YouTube video OCR fallback scans one representative thumbnail.
- Increased the creative-detail deadline for large all-extras runs so temporary Google 429 cooldown plus route/session rotation can complete the enriched row instead of dropping it early.
- Disabled removed-ad detection on limited monitor windows. Limited scheduled runs now track new/seen safely; true removed rows are emitted only when monitoring the full advertiser window with `resultsLimit=0` and `maxPages=0`.
- Added limited-monitor guidance to the run report so users understand that `new`/`seen` are sampled-window statuses unless the monitor scans the full advertiser.
- Matched the current Google Ads Transparency Center UI RPC context for `SearchCreatives` and `GetCreativeById`, keeping our payload shape aligned with the live product instead of older minimal calls.
- Reworked LookupService 429 recovery again: direct detail calls now cool down and get re-probed later instead of being disabled for the whole run; current requests rotate through Apify's cheaper proxy sessions before Residential rescue.
- Increased the creative-detail retry budget so rich enrichment has enough attempts to rotate direct -> datacenter -> residential without surfacing temporary Google 429s to the user.
- Improved all-extras throughput: creative asset downloads now run concurrently per ad, image OCR has one additional worker lane, and video OCR no longer lets one slow frame extraction serialize the whole run.
- Added hard deadlines for optional OCR, video OCR, creative-file downloads, landing-page archives, and per-creative detail lookup so one slow external resource cannot hold the whole run.
- Improved OCR quality filtering so very short noisy fragments are not promoted into `ocrText` or `videoOcrText`.
- Reduced unnecessary Residential Proxy use: SearchService 429 recovery no longer proactively disables direct LookupService detail calls; Lookup switches route only after its own rate-limit or network signal.
- Added a narrow direct LookupService probe lane so a hot Google detail endpoint cannot receive a burst of simultaneous direct retries before the route circuit breaker reacts.
- Increased `SearchCreatives` page size from 40 to Google's accepted 100-result page window, reducing pagination RPCs for 100+ ad exports.
- Added automatic large-window format rescue: when a broad ALL-format query appears truncated below Google's reported result window, the Actor collects TEXT, IMAGE, and VIDEO shards and deduplicates them for fuller coverage.
- Improved SearchService 429 recovery: repeated search throttling now gets more bounded attempts and keeps using fresh Residential sessions while cheaper routes cool down instead of bouncing straight back to throttled routes.
- Added cross-service Google RPC throttling: when SearchService is already rate-limited on direct traffic, LookupService detail calls avoid direct during the same cooldown window instead of stampeding the same throttled route.
- Heavy enrichment runs now flush dataset rows in smaller batches so users see partial results sooner when OCR, asset download, landing archive, and reach stats are all enabled.
- Added a simple visible `includeReachStats` option for Google-exposed regions, platforms, impression ranges, and targeting flags. This replaces the need to know the internal `deepEnrichment` switch.
- Improved full-enrichment routing for speed and cost: healthy direct detail lookups no longer proactively switch to Residential Proxy; Residential is reserved for actual 429/network recovery.
- Increased the adaptive RPC starting rate and retry budgets so temporary Google throttling rotates route/session more often before a run fails.
- Removed hidden enriched-mode overfetch. Reach stats now respects `resultsLimit` as the network-work limit instead of fetching reserve candidates.
- Added dynamic Actor memory in `actor.json` so small runs stay light while OCR, asset downloads, landing archives, reach stats, and large exports get more CPU automatically.
- Removed hidden API-only controls from the public input schema. The Actor input UI now contains only the user-facing workflow fields.
- Renamed the visible scheduled-monitor field to `monitorName` so Apify quality checks do not treat the monitor label as a sensitive secret key.

### 2026-06-13

- Improved full deep enrichment routing at that stage with a direct soft limit, controlled route escalation, and batch dataset writes. The 100-row deep benchmark then was 82.5s actor time / 94.9s full Apify run time.
- Added adaptive rich overfetch: small runs no longer enrich 20 extra candidates just to save 1-5 rows, reducing unnecessary `GetCreativeById` pressure and 429 cascades.
- Added zero-network preview snippet decoding. When listing/detail HTML already exposes copy, landing URLs, images, or YouTube IDs, the Actor uses it before fetching preview JS.
- Made Quick scan a fast preview-rich ad table by default. Full per-row `GetCreativeById` stats now live behind API-only `deepEnrichment=true` and the Full audit preset.
- Increased concurrency for the preview-rich path separately from Google RPC concurrency, so large default exports can fetch public preview assets faster without increasing `GetCreativeById` 429 risk.
- Added batch dataset writes for the default preview-rich path to avoid slow per-row pushes on 500+ result runs.
- Reworked route recovery into per-service route circuit breakers. Search stayed cheap direct/datacenter-first, while deep detail lookup used a controlled direct + Residential profile at that stage.
- Reworked rich enrichment from fixed chunks to a worker-pool pipeline so slow preview/OCR/archive work no longer blocks the next batch of `GetCreativeById` lookups.
- Benchmarked higher rich-run concurrency and Google RPC pacing, then kept a stable direct-first profile because aggressive 100-row tests produced more Google 429s and worse total time. Route switching and residential fallback remain reserved for detail lookups after cheaper routes fail.
- Added `maxPreviewUrlsPerAd` as an API-only speed/quality control. The default now decodes one preview URL per ad for faster rich output; API users can raise it to 2-3 when variant completeness matters more than speed.
- Added optional video OCR with `extractVideoOcrText`, direct video frame sampling via `ffmpeg`, YouTube thumbnail fallback, dataset fields (`videoOcrText`, `videoOcrLines`, `videoOcrSourceUrls`, `videoOcrFramesCount`, `videoOcrStatus`), and an Ads table `Video text` column.
- Added optional landing-page archiving with `archiveLandingPages`, one archived HTML copy per unique landing URL, `LANDING_*` key-value store records, dataset fields (`landingPageKey`, `landingPageUrl`, `landingPageStatus`, `landingPageBytes`), and an Ads table `Archived landing page` column.
- Added optional image OCR with `extractOcrText`, Tesseract/Pillow runtime dependencies, dataset fields (`ocrText`, `ocrLines`, `ocrSourceUrls`, `ocrImagesCount`, `ocrStatus`), and an Ads table `Image text` column.
- Updated the public speed benchmark section with real fast bulk, 20-row rich, 100-row rich, and small video-OCR/landing-archive verification runs.
- Added Clay and n8n integration instructions, including an importable `integrations/n8n-google-ads-monitor.json` workflow.
- Simplified the public input UI for normal users: hidden workflow presets and API-only controls, made rich 50-ad competitor scans the default, and kept only competitor input, result limit, simple filters, creative-file download, monitoring, and fast-export toggle visible.
- Rewrote the public README around buyer workflows and clean outputs instead of internal run modes, following the simpler packaging used in the Google Maps and Google News Actors.
- Reduced the Output tab to one Ads table plus Run report. Removed extra landing-page, creative-file, advertiser, and changes views from the primary Console experience; raw columns remain available through Apify's automatic All fields view and exports.
- Updated the Actor title and Store description to sell competitor creatives, landing pages, downloaded assets, and new/removed ad monitoring directly.

### 2026-06-05

- Reworked Output tab UX so the Ads table is the first link, the run report moved to a secondary link, and the main dataset view shows a compact set of practical columns instead of technical/enrichment fields.
- Improved input form copy and sectioning so users can understand workflow choice, competitor inputs, result limits, filters, monitoring, creative-file downloads, and advanced/API-only controls.
- Changed `resultsLimit` to a run-level cap on saved dataset rows across all competitors. Positive limits now stop remaining advertisers instead of making extra requests that cannot be saved.
- Reworked proxy escalation to use direct requests first, Apify automatic/datacenter proxy as the cheap fallback, and Residential Proxy only as the last detail-lookup fallback after cheaper routes are blocked.
- Network route failures now switch route immediately without an extra sleep: Search moves direct to datacenter, while detail Lookup can move direct to datacenter to Residential.
- Removed automatic detail-to-listing fallback from enriched workflows. Detail-heavy modes now skip rows whose details cannot be fetched after retries instead of returning degraded listing-only rows.
- Hid `filterPlatform` from the normal input UI and documented it as an API-only strict filter, because Google often omits platform stats from creative detail responses. The Actor now avoids selling inferred platform matches as real data.
- Made workflow presets respect explicit non-default user/API overrides for scope and advanced fields, so users can run cheap 20-row tests without switching to Custom mode while Apify schema defaults no longer break preset behavior.
- Added adaptive LookupService routing: detail calls stay direct-first while healthy, then switch subsequent Lookup calls to managed proxy routes for a short window after Google 429s.
- Made `FAST_EXPORT` the default workflow and raised its preset to 1,000 listing-only ads per run for large, fast exports.
- Switched `MONITOR_CHANGES` to listing-based diffing by default so scheduled monitors do not re-enrich every historical ad.
- Added adaptive Google RPC throttling: the Actor starts faster, reacts to 429 globally, retries with fresh sessions, and avoids long per-request 429 sleep loops.
- Made SearchService direct-first with proxy fallback, which avoids burning the bulk path on shared proxy exit-IP throttling.
- Stopped pinning Apify Proxy to US for Google RPC calls; automatic rotating countries give the bulk path a larger proxy pool while RPC payload filters still control ad regions.
- Kept Residential Proxy off the normal bulk path; it is reserved for detail lookups after direct and cheaper proxy routes fail.
- Kept detail-heavy runs on the detail path instead of automatically downgrading rows to listing-only data.
- Skipped advertiser metadata lookup in platform-filter runs to save one extra LookupService call.
- Added fail-fast protection for platform-filter runs when Google throttles detail lookups, preventing long timeouts with no output.
- Added `dataDepth` to dataset rows and OUTPUT breakdowns so users can see `listing`, `preview`, and `enriched` rows.
- Added run-level RPC performance stats to `OUTPUT.run.performance`.
- Reduced one extra advertiser metadata RPC in listing-only workflows.
- Added a product polish pass across Store copy, input form labels, output tabs, dataset views, README, and OUTPUT report cards.
- Added emoji-led workflow labels and next actions to make the Actor easier to understand on the first run.
- Repositioned the Actor as Google Ads Competitor Monitor with clearer product copy.
- Added `runMode` presets: Quick scan, Monitor changes, Swipe file, Fast export, Full audit, and Custom.
- Reworked input UX so normal users choose one workflow instead of combining low-level switches.
- Added a human-readable `OUTPUT.summary` line and included `runMode` in the run report.
- Added an official key-value store schema with Run reports, Monitor state, and Creative files collections.
- Added `monitorMode` and `stateKey` for automatic new / seen / removed creative detection across scheduled runs.
- Moved monitor state persistence into the named key-value store `google-ads-monitor-state`, with a run-local `STATE_...` snapshot for UI visibility.
- Added `downloadAssets` to save direct media assets into the default key-value store and return `assetKey`, `assetUrl`, `assetKeys`, `assetUrls`, `assets`, and `mediaDownloaded`.
- Fixed downloaded asset links to use the public Apify API base URL instead of the platform-internal API URL.
- Reduced Google 429 stalls by lowering the default RPC rate, shortening SearchCreatives retry budgets, bounding 429 backoff, and logging the first rate-limit warning immediately.
- Added `monitorOutputMode`; `CHANGES_ONLY` saves only new/removed rows and skips detail decoding for already-seen ads when no platform filter is used.
- Added a run-level `OUTPUT` summary with totals, status counts, top formats, top platforms, top landing domains, top advertisers, long-running ads, and asset download totals.
- Added dataset fields and views for monitor status, advertisers, landing pages, and downloaded assets.
- Kept legacy `excludeCreativeIds` support for manual diffing outside monitor mode.

### 2026-05-29

- Simplified the Output tab to one Results entry and removed the duplicate Full data view.
- Improved full-enrichment throughput by separating preview CDN fetches from Google RPC concurrency and fetching public preview assets directly first, with proxy fallback on rate limits.
- Added Actor output schema links for preview and raw API dataset access.
- Added a public changelog reference in `.actor/actor.json`.
- Removed user-configurable proxy settings; proxy handling is managed internally.
- Improved input schema labels and defaults for non-technical users.
- Added richer output fields: ad copy, CTA, landing URL, media URLs, platform and region breakdowns, impression ranges, targeting summary, and preview thumbnails.
- Added API aliases for search inputs such as `searchQuery`, `keywords`, `domains`, and `advertiserIds`.
- Kept `resultsLimit=0` as unlimited output and `maxPages=0` as no page cap by default.
- Improved stability around proxy fallback, boolean parsing, country normalization, and already-seen creative skipping.
