Google Ads Brand Bidding Monitor
Pricing
from $3.50 / 1,000 branded search checkeds
Google Ads Brand Bidding Monitor
Monitor branded Google searches to detect competitor ads, affiliate brand bidding, unauthorized resellers, new paid-search bidders, and ad-copy changes across countries and devices.
Pricing
from $3.50 / 1,000 branded search checkeds
Rating
0.0
(0)
Developer
Furkan Toluç
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
16 days ago
Last modified
Categories
Security
Limited permissionsShare
Monitor branded Google searches across countries and devices. Detect known competitors, unrecognized advertisers, authorized partners, repeated bidders, new landing domains, and ad-copy changes over time.
This Actor is a branded paid-search monitoring and compliance-signal product. It uses Apify's maintained apify/google-search-scraper as its collection primitive and adds deterministic normalization, evidence, classification, compact history, and conservative change detection. It is not a general Google scraper, an ad-spend estimator, or a legal trademark detector.
What it does
For one brand per run, the Actor:
- Checks up to ten branded terms in as many as five countries, on desktop and/or mobile.
- Performs one to three independent observations per country-device market.
- Extracts paid Google results and normalizes their registrable landing domains.
- Classifies advertisers as
OFFICIAL,AUTHORIZED,KNOWN_COMPETITOR, orUNRECOGNIZEDfrom your lists. - Measures check coverage, landing-domain coverage, observation depth, and evidence strength.
- Compares every successful market with its previous successful baseline under the same
monitorId. - Writes one Dataset item per market, a run-level
REPORT.md, anOUTPUTrecord, measuredCOSTS.json, and compact named-store state.
It is designed for paid search teams, affiliate managers, performance marketers, brand protection teams, agencies, and SaaS or ecommerce brands.
Why repeated observations matter
Google Ads are probabilistic: auctions, targeting, budgets, and personalization cause results to vary. A duplicate ad row within one SERP is not repeated evidence. REPEATED_BIDDER requires the same landing domain in at least two independent observations of the current country-device market.
Most monitors should use the default of two observations. A single observation remains useful, but cannot produce strong repeated evidence.
Google paid-search observations depend on an external upstream Actor and can occasionally be slow or unavailable. Each observation is protected by a bounded runtime and charge ceiling. The parent makes one child call per logical observation and does not add a retry loop on top of the upstream Actor's own behavior. Failed observations are treated as missing evidence rather than as evidence that no ads exist.
Input
{"monitorId": "acme-brand-monitor","brandName": "Acme","brandTerms": ["acme", "acme pricing", "acme coupon", "acme login"],"officialDomains": ["acme.com"],"authorizedDomains": ["partner-a.com"],"competitorDomains": ["competitor-one.com", "competitor-two.com"],"countries": ["US", "GB", "DE"],"devices": ["desktop", "mobile"],"observationsPerMarket": 2,"languageCode": "en","debug": false,"resetState": false}
monitorId is the stable identity for a monitoring configuration. If you leave it empty, it is derived from the brand name. It is normalized and hashed before being used in a named Key-Value Store; arbitrary input is never used directly as a storage name. resetState removes only this monitor's STATE record.
The field was previously called monitorKey. Existing tasks, schedules, and API calls that still send monitorKey keep working and keep the same monitoring history; output records keep the monitorKey field name for compatibility.
The Store's example input (Squarespace, two branded terms, US, desktop, one observation) is a deliberately small demo that usually finishes in under a minute. Ads are probabilistic, so a single demo run may or may not observe sponsored results.
Domains may be entered as domains, subdomains, or URLs. They are reduced with Public Suffix List-aware logic, so store.partner.co.uk becomes partner.co.uk rather than co.uk.
Output
The default Dataset contains one item per brand + country + device report—not one item per ad. A report includes a flat Store-friendly summary plus complete nested evidence:
{"brandName": "Acme","country": "US","device": "mobile","reportStatus": "SUCCESS","baselineStatus": "EXISTING_BASELINE","evidenceStrength": 100,"coverage": {"expectedChecks": 8,"successfulChecks": 8,"successfulCheckRate": 1,"landingDomainCoverage": 1},"summary": {"sponsoredAdsObserved": 6,"uniqueAdvertiserDomains": 3,"knownCompetitorsObserved": 1,"unrecognizedDomainsObserved": 1,"repeatedBidders": 2,"newLandingDomains": 1,"newAdCopies": 1},"advertisers": [],"findings": [],"changes": {"newDomains": ["competitor-two.com"],"newAdFingerprints": ["..."],"previouslyObservedDomainsNotSeenThisRun": ["coupon-example.com"]}}
Evidence strength measures data quality, not advertiser severity. Its documented formula is:
round(60 × successful-check coverage+ 20 × effective landing-domain coverage+ 20 × observation depth)
When successfully collected SERPs contain no ads, paid-ad parsing and landing-domain coverage are reported as null (not applicable) and do not penalize evidence strength. When no checks succeed, evidence strength is zero. Observation depth is 0.5 for one usable observation and 1 for two or more.
Report status thresholds are SUCCESS at 90%+ successful checks, PARTIAL from 50% through below 90%, and INSUFFICIENT_EVIDENCE below 50%. Absence-based signals require at least 80% coverage.
Signals
COMPETITOR_ON_BRAND_TERM: a landing domain matches your known competitor list.AUTHORIZED_PARTNER_OBSERVED: a landing domain matches your authorized list.NEW_UNRECOGNIZED_ADVERTISER: an unrecognized domain is new relative to a prior successful baseline.REPEATED_BIDDER: a domain appeared in at least two independent current-run observations.TRADEMARK_IN_AD_COPY_SIGNAL: monitored brand wording appeared in title or description; this is not a legal determination.POTENTIAL_AFFILIATE_POLICY_RISK: an unrecognized advertiser appeared on a coupon, promo, discount, or deal-oriented branded query; no affiliate relationship is asserted.NEW_LANDING_DOMAINandNEW_AD_COPY: changes from the previous successful baseline.OWN_AD_NOT_OBSERVED,PREVIOUS_BIDDER_NOT_OBSERVED, andNO_SPONSORED_ADS_OBSERVED: conservative absence observations, emitted only with adequate check coverage.INSUFFICIENT_EVIDENCE: missing SERPs make absence-based conclusions unsafe.
Monitoring over time
The first successful run establishes a baseline and never calls all current advertisers “new.” Later successful runs compare domains and normalized ad-copy fingerprints with the preceding successful market state. Incomplete markets do not overwrite a healthy baseline.
Save the Actor input as an Apify Task and schedule it daily or weekly to turn one-time branded SERP observations into a monitoring history. Reuse exactly the same monitorId for that monitor. This repeated use is the product's recurring-value mechanism.
Pricing
The Actor uses Apify Pay Per Event pricing with one search-checked event: $0.005 per branded Google search results page checked on the Apify Free plan, with lower prices on paid Apify plans (down to $0.0035). One page is one brand term in one country on one device in one observation, so a run costs:
terms × countries × devices × observations per market × $0.005
For example, the Store's demo input (2 terms × 1 country × 1 device × 1 observation) is two search checks ($0.01). Three terms in two countries on desktop and mobile with two observations each is 24 search checks ($0.12). Market reports, advertisers, ads, and findings are not charged separately, and pages that the upstream Actor fails to return are not charged.
Google results are collected by Apify's apify/google-search-scraper, whose own usage (about $0.0045 per results page at the time of writing) is billed separately to your account by that Actor. A small Actor start fee is also charged per run.
Before each observation starts, the Actor checks that your run's spending limit can cover every results page of that observation. When the limit is reached, it stops starting new observations, writes the reports collected so far, and finishes with the status SUCCEEDED_BUDGET_LIMIT_REACHED. COSTS.json records child run IDs, charged event counts, and actual upstream usageTotalUsd when Apify exposes it; otherwise it explicitly reports cost as unavailable. The OUTPUT record includes searchPagesChecked and searchChecksCharged.
Integrations
Consume Dataset and Key-Value Store output through Apify's normal API and integration ecosystem, including schedules, webhooks, Make, Zapier, Google Sheets, and other standard platform connections. This Actor intentionally does not build custom Slack, email, CRM, or dashboard integrations.
Limitations and interpretation
- Google Ads are probabilistic. Not observed does not mean stopped bidding.
- Missing upstream results are missing evidence, never evidence that no ads existed.
- Advertiser classifications depend on user-supplied official, authorized, and competitor domain lists.
UNRECOGNIZEDdoes not mean fraudulent, unauthorized, illegal, or infringing.- Brand wording in ad copy is an observation, not a legal trademark conclusion.
- The Actor does not crawl landing pages, follow redirects, estimate ad spend, or estimate lost revenue.
- Country targeting follows the upstream Actor's country-level search controls; it is not proof of every user's experience within that country.
Development and deployment
The child-observation safety policy is centralized in src/config/child-observation-policy.ts. Its initial calibration ceilings are 240 seconds and $0.50 per child observation. Before starting a child run, the Actor reads the upstream Actor's current pricing metadata. If the configured ceiling is below the upstream minimalMaxTotalChargeUsd, preflight fails explicitly and does not start a run or silently raise the ceiling. These are maximum safety bounds, not expected costs or a per-keyword pricing formula; revisit them after additional controlled live probes.
npm cinpm run validateapify push
A paid live probe runs only when both APIFY_TOKEN is available and LIVE_TEST=1 is explicitly set. Keep it to one country, one device, one or two terms, one observation, and a maximum total charge of $0.50 where supported. Zero observed ads is a valid probe outcome.
Post-launch product metrics
Targets: at least 10 external testers, 100 successful market reports, 3 users creating schedules, 30% or higher seven-day repeat-run rate, at least 95% deterministic classification precision, at least 90% landing-domain coverage, and zero false stopped-bidding claims. The leading behavioral metric is reuse of the same monitorId.
Reconsider further investment if known-positive branded queries rarely expose ads, landing-domain coverage stays below 80%, current upstream economics prevent a healthy margin, repeat behavior remains below 15% after 100+ reports, classification errors exceed 5%, support becomes excessive, or users consistently require a standalone dashboard.