# Google Maps Lead Finder for SEO & PPC Agencies (`feeng/google-maps-agency-lead-finder`) Actor

📍 Google Maps agency leads from $4 per 1,000. Qualify prospects and get structured sales-pipeline, CRM contact, PPC audit, and website-opportunity views with scores and evidence-based outreach angles.

- **URL**: https://apify.com/feeng/google-maps-agency-lead-finder.md
- **Developed by:** [Daniel S.](https://apify.com/feeng) (community)
- **Categories:** Lead generation, Marketing, Business
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 basic qualified leads

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 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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## Google Maps Lead Finder for SEO & PPC Agencies

Find local businesses with weak websites, missing conversion tracking, and visible reputation gaps. Get ranked agency prospects, local competitor benchmarks, public contacts, evidence-backed outreach, screenshots, and a downloadable sales audit report in one run. 📍

This is not a generic Google Maps export. The Actor searches Google Maps, audits each public website for tracking, conversion, technical, contact, and social signals, then prioritizes businesses most likely to benefit from PPC, SEO, web design, or reputation services.

### Quick Start: Your First Useful Run 🚀

You only need a business type and a location. Everything else has a safe default.

1. Add one **Search term**, such as `dentists`, `roofers`, or `med spas`.
2. Add one **Location**, such as `Austin, TX`. You can leave it empty only if every search term already contains a location.
3. Set **Number of places** to `5–10` for a quick first run.
4. Keep qualification filters unchanged until you have inspected the first result set.
5. Choose an enrichment level:
   - **Basic:** inexpensive Google Maps prospect validation.
   - **Contacts:** public email and social discovery for a CRM list.
   - **Website audit:** PPC, conversion, technical, and web-design analysis.
   - **Full:** contacts and the complete website audit together.
6. Choose the **Service you want to sell**. Keep competitor benchmark and sales report enabled.
7. Click **Save & Start**, then open the **Sales pipeline** dataset view for the ranked call list.

For a proper PPC or web-design analysis, use `Website audit` or `Full`. Basic mode cannot inspect website tags, conversion tracking, performance, forms, or technical problems.

#### Recommended Setup by Use Case

| Goal | Enrichment | Focus service | Useful filters | Sort by |
| --- | --- | --- | --- | --- |
| PPC and tracking leads | Website audit or Full | PPC | Keep website availability on All | Best agency opportunity |
| Website redesign leads | Website audit or Full | Web design | All or Only without a website | Website opportunity score |
| Reputation leads | Basic or Contacts | Reputation | Minimum 20 reviews, maximum rating 4.3 | Best agency opportunity |
| SEO prospects | Website audit or Full | Local SEO | Keep broad filters initially | Best agency opportunity |
| CRM contact list | Contacts or Full | Balanced | Optional category filters | Lead gap score |

All score thresholds are optional. Leave them at `0` for the first run, inspect the results, and only then raise them to produce a smaller list.

### What One Result Looks Like 📊

Instead of only returning a business name and phone number, the Actor produces an actionable row like this:

| Field | Example |
| --- | --- |
| Business | Example Local Dentist |
| Priority | Hot lead |
| Agency opportunity | 86/100 |
| PPC opportunity / readiness | 91/100 / 48/100 |
| Recommended service | PPC tracking and landing-page improvement |
| Evidence | No Ads conversion tag observed; weak CTA; competitors have stronger review volume |
| Contact | Public phone, email, website, and discovered social links |
| Outreach | Evidence-backed email draft, discovery questions, and call opener |

The dataset contains the complete structured evidence and scores. When **Generate sales audit report** is enabled, the run key-value store also contains `SALES_AUDIT_REPORT.html` and `SALES_AUDIT_REPORT.pdf`. Optional screenshots can be included as point-in-time website evidence.

### Why use this instead of a general Google Maps scraper? 🧭

A broad Google Maps scraper is the better choice when you need large raw place datasets, reviews, images, questions, or exhaustive place attributes. This Actor is purpose-built for the step after data collection: deciding which businesses an agency should contact and what it can credibly offer.

| Workflow | General Maps scraper | Agency Lead Finder |
| --- | --- | --- |
| Multiple business searches | Raw place records | One deduplicated prospect list |
| Website inspection | Usually optional raw fields | Technical, tracking, CTA, contact, and social audit |
| PPC qualification | Manual review | Separate Ads, conversion tracking, readiness, and opportunity signals |
| Local benchmark | Build it yourself | Same-search peer comparison with explicit sample size |
| Sales prioritization | Build it yourself | Combined score plus hot/warm/monitor tier |
| Outreach preparation | Manual research | Suggested service, email, call opener, evidence table, and PDF report |

The value is not simply another copy of the same Maps fields. It is a smaller, sales-ready list that can save an agency from manually opening and auditing every business website.

### Pricing 💵

There is a **$0.007 start fee per run**. Every exported lead is then charged at exactly one mutually exclusive tier:

| Result tier | When it applies | Price per lead | Price per 1,000 |
| --- | --- | ---: | ---: |
| Basic lead | Website audit, email search, and social search are not performed | $0.004 | $4 |
| Contact-enriched lead | Public email or social search is performed without the website audit | $0.006 | $6 |
| Website-audited lead | Technical, PPC tracking, and conversion audit is performed without contact search | $0.012 | $12 |
| Fully enriched lead | Website audit and public contact search are both performed | $0.014 | $14 |

Raw Google Maps candidates removed by qualification or score filters are not charged as result events. A business without a website remains a basic lead because no website enrichment can be performed.

### Why agencies use it ✨

- **🎯 Prioritized prospects:** agency, lead-gap, PPC opportunity, PPC readiness, website, and competitor-gap scores make the next call list obvious.
- **🔎 Evidence, not guesses:** each lead includes the public signals behind the suggested service and outreach angle.
- **📈 PPC-ready audit:** inspects rendered pages and browser network traffic for Google Ads, GTM, Analytics, Meta Pixel, call tracking, CTAs, forms, and landing-page weaknesses.
- **🖥️ Web-design qualification:** scores technical age, mobile metadata, titles, descriptions, headings, structured data, broken resources, JavaScript errors, page weight, image alt text, and conversion UX.
- **📬 Contactability:** finds public email addresses and social profiles from the business website when available.
- **🏁 Local context:** compares each business only with peers collected for the same search term and location.
- **📄 Sales deliverables:** produces structured outreach data plus print-ready HTML and PDF reports; optional screenshots preserve point-in-time website evidence.

### What It Collects 📦

For each business, the dataset includes:

- `businessName`
- `category`
- `address`
- `phoneNumber`
- `website`
- `emailAddress`
- `facebookUrl`
- `instagramUrl`
- `linkedinUrl`
- `googleMapsUrl`
- `rating`
- `reviewCount`
- `coordinates`
- `openingHours`
- `leadScore`
- `leadScoreReasons`
- `ppcOpportunityScore`
- `ppcReasons`
- `ppcReadinessScore`, strengths, and gaps
- `websiteOpportunityScore`
- `websiteOpportunityReasons`
- `competitorGapScore` and `localBenchmark`
- `advertisingIntelligence`, which explicitly separates active-ad verification from conversion technology
- `salesAuditReport` with evidence, discovery questions, email copy, and call opener
- `auditEvidence` with audited URLs and an optional screenshot record key
- `googleAdsStatus`: `detected`, `possible-via-gtm`, `not-observed`, or `audit-incomplete`
- `googleAdsConfidence` and concrete tracking evidence
- PPC tracking signals such as Google Tag Manager, Google Analytics, Google Ads conversion tags, Meta Pixel, LinkedIn Insight, and call tracking
- conversion signals such as forms, phone links, booking CTAs, quote CTAs, and weak CTA detection
- website technical signals such as HTTPS, viewport meta, old copyright year, and outdated layout hints

The Actor also saves `OUTPUT.json`, `OUTPUT.csv`, `RUN_SUMMARY.json`, `SALES_AUDIT_REPORT.json`, `SALES_AUDIT_REPORT.html`, and `SALES_AUDIT_REPORT.pdf` to the default key-value store when report generation is enabled.

### Structured Dataset Views 🧩

The default dataset includes flat, filterable columns while retaining the complete nested audit objects for API compatibility. Apify Console provides seven purpose-built views:

- **Sales pipeline:** priority, score, recommended service, outreach angle, and primary contact fields.
- **CRM contact list:** email, phone, website, social profiles, address, and Maps URL.
- **PPC & conversion opportunities:** active-ads verification status, conversion-tracking status, landing-page readiness, Consent Mode, paid-click handling, GTM, Analytics, pixels, forms, and CTAs.
- **Website opportunities:** dedicated website score, CMS, HTTPS, outdated-site signal, metadata, structured data, browser load time, broken resources, image alt coverage, forms, and evidence.
- **Local competitor benchmark:** peer gap score, cohort summary, concrete gaps, ratings, reviews, and digital-readiness comparisons.
- **Sales audit & outreach:** recommended offer, evidence, benchmark summary, email copy, call opener, contacts, and screenshot key.
- **All core fields:** broad flat export for advanced automation and integrations.

`RUN_SUMMARY.json` also reports counts by priority, result tier, and recommended service, average scores, and contact coverage.

### Input ⚙️

This sample performs a complete PPC-focused analysis. For a cheaper trial, change `enrichmentMode` to `basic` and reduce `maxResultsPerSearch` to `5`.

```json
{
  "searchTerms": ["dentists", "orthodontists"],
  "location": "Austin, TX",
  "maxResultsPerSearch": 10,
  "maxTotalResults": 20,
  "language": "en",
  "minReviews": 0,
  "maxReviews": 1000000,
  "minRating": 0,
  "maxRating": 5,
  "websiteFilter": "all",
  "enrichmentMode": "full",
  "focusService": "ppc",
  "includeCompetitorBenchmark": true,
  "benchmarkCompetitorCount": 3,
  "generateSalesReport": true,
  "includeAuditScreenshots": false,
  "minimumAgencyOpportunityScore": 0,
  "minimumPpcOpportunityScore": 0,
  "sortBy": "agencyOpportunity",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
````

#### Input Fields

- `searchTerms`: Up to 10 business types or services searched in one run.
- `location`: City, region, or country appended to each search term.
- `maxResultsPerSearch` and `maxTotalResults`: Per-query and whole-run safety limits.
- `language`: Google Maps and browser language.
- `minReviews`, `maxReviews`, `minRating`, and `maxRating`: Qualification ranges applied before website enrichment.
- `websiteFilter`: Keep all businesses, only businesses with a website, or only website-less prospects.
- `categoryIncludes` and `categoryExcludes`: Optional case-insensitive category filters.
- `excludeIrrelevantResults`: Remove obvious category/name mismatches and unrelated sponsored Maps results before paid enrichment; enabled by default.
- `enrichmentMode`: Choose Basic, Contacts, Website audit, or Full with the exact per-result price shown in the form.
- `websiteTimeoutSecs`: Timeout for each website enrichment request.
- `maxWebsitePages`: Number of pages to fetch per website, including likely contact/about pages.
- `websiteConcurrency`: Number of websites audited in parallel.
- `focusService`: Prioritize PPC, SEO, web design, reputation, or balanced agency opportunities.
- `includeCompetitorBenchmark`: Compare a lead only with businesses collected for the same search term and location.
- `benchmarkCompetitorCount`: Include 1-5 concrete comparison businesses per lead.
- `generateSalesReport`: Save structured JSON plus printable HTML and PDF sales reports.
- `includeAuditScreenshots` and `maxEvidenceScreenshots`: Optionally preserve capped viewport screenshots in the key-value store.
- `minimumLeadScore`, `minimumPpcOpportunityScore`, `minimumWebsiteOpportunityScore`, and `minimumAgencyOpportunityScore`: Remove weak prospects before export.
- `minimumPriorityTier`: Export all, warm-and-hot, or hot-only prospects.
- `sortBy`: Rank by agency opportunity, PPC opportunity, PPC readiness, website gap, competitor gap, lead gap, or review count.
- `proxyConfiguration`: Optional Apify Proxy config. Direct cloud browsing works for smoke tests; for larger runs or blocked regions, use a suitable Apify Proxy group, ideally residential.

Legacy API inputs `searchQuery`, `maxResults`, `requireWebsite`, `includeWebsiteAudit`, `includeEmailSearch`, and `includeSocialLinks` remain supported, but the Console form uses the new batch-search and enrichment-tier fields.

### Lead Scoring 🎯

`leadScore` is calculated from agency opportunity signals:

- Many reviews with weak or average rating.
- No website on Google Maps.
- Website uses plain HTTP instead of HTTPS.
- No public email found.
- No social media links found.
- Website appears technically outdated.
- Website returns HTTP errors.

The final dataset is sorted by the selected `sortBy` mode; combined agency opportunity is the default.

### PPC Opportunity Scoring 📈

`ppcOpportunityScore` estimates whether the business is a commercially relevant prospect for paid ads services. `ppcReadinessScore` separately measures whether the public website is ready to convert paid traffic. A high opportunity score is a sales signal; a high readiness score is a website strength.

Higher PPC scores come from:

- PPC-friendly category such as dentist, clinic, lawyer, home services, restaurant, cafe, gym, salon, hotel, auto repair, or real estate.
- High review count or strong rating, which indicates demand and trust.
- Website exists, so PPC traffic has somewhere to go.
- Missing Google Ads conversion tag.
- Missing or uncertain conversion measurement and Analytics evidence.
- Missing Meta Pixel, LinkedIn Insight, or call tracking.
- Weak website CTA signals, such as no form, no phone link, no booking CTA, and no quote CTA.
- Outdated website signals where a campaign could be sold together with a better landing page.

The audit does not treat every missing string in raw HTML as proof that Ads is absent. It renders up to four relevant pages in Chromium, observes network requests, detects Consent Mode and paid-click handling, and attempts common cookie-consent actions. A direct Ads ID or conversion request is reported as `detected`. When GTM is present but no direct Ads evidence is visible, the status is `possible-via-gtm`, because the container can hold tags that are conditional, consent-gated, or not publicly inspectable. `not-observed` means no direct signal appeared during this audit, not that the business definitely has no Google Ads account.

`advertisingIntelligence.adsActivityStatus` remains `not-verified` unless a future ad-observation source is explicitly enabled. A conversion tag can exist without active spending, and an active campaign can use a different landing page. The Actor never converts tag detection into an unsupported claim that a campaign is currently running.

### Local Competitor Benchmark 🏁

When enabled, each lead is compared with deduplicated businesses collected for the same search term and location in that run. The benchmark reports cohort size, average rating, median review count, average PPC readiness, average website weakness, concrete gaps, advantages, and up to five comparison businesses. It does not claim to represent the entire market and returns `insufficient-data` when fewer than two businesses are available.

### Website Opportunity Scoring 🖥️

`websiteOpportunityScore` ranks prospects for web designers, developers, technical SEO specialists, and conversion agencies. It uses concrete public signals such as missing HTTPS, mobile viewport, title, meta description, H1, structured data, failed resources, browser JavaScript errors, high page weight, weak CTAs, missing image alt text, and an unavailable or outdated website. Set `focusService` to `web_design`, filter with `minimumWebsiteOpportunityScore`, and sort by `websiteOpportunityScore` to build a web-development sales list.

### Agency Outreach Brief 💬

Every result also includes an `agencyOpportunity` object and a richer `salesAuditReport`. The report contains observed strengths and gaps, source URLs, confidence, a recommended first offer, discovery questions, email copy, a call opener, and a verification disclaimer. The run-level HTML and PDF place up to 50 ranked leads into a printable report. Treat these outputs as research support, not permission for unsolicited outreach; users remain responsible for complying with applicable privacy and anti-spam rules.

### Example Output 📊

```json
{
  "leadScore": 72,
  "leadScoreReasons": [
    "Many reviews with improvable rating (3.9 from 248 reviews)",
    "Website does not use HTTPS",
    "No public email address found",
    "No Facebook, Instagram, or LinkedIn link found",
    "Website appears technically outdated"
  ],
  "ppcOpportunityScore": 84,
  "ppcReadinessScore": 42,
  "competitorGapScore": 50,
  "agencyOpportunityScore": 80,
  "agencyOpportunity": {
    "priorityTier": "hot",
    "primaryService": "PPC tracking and conversion setup",
    "outreachAngle": "PPC tracking and conversion setup: No Google Ads conversion tag was detected; The website has weak conversion calls to action."
  },
  "advertisingIntelligence": {
    "adsActivityStatus": "not-verified",
    "conversionTrackingStatus": "not-observed",
    "googleAdsTagDetected": false,
    "ppcReadinessScore": 42
  },
  "localBenchmark": {
    "status": "available",
    "cohortSize": 12,
    "summary": "Example Local Restaurant trails local peers on 2 observed signals."
  },
  "ppcReasons": [
    "Business category is strong for local PPC campaigns",
    "Existing demand with rating improvement opportunity (3.9 from 248 reviews)",
    "Website exists, so PPC traffic has a destination",
    "No Google Ads conversion tag found",
    "No Google Tag Manager found",
    "No Meta Pixel found",
    "No call tracking signal found",
    "Website has weak call-to-action signals"
  ],
  "businessName": "Example Local Restaurant",
  "category": "Restaurant",
  "address": "123 Main Street, Austin, TX",
  "phoneNumber": "+1 555 123 4567",
  "website": "http://example-local-restaurant.com/",
  "emailAddress": null,
  "facebookUrl": null,
  "instagramUrl": null,
  "linkedinUrl": null,
  "googleMapsUrl": "https://www.google.com/maps/place/example",
  "rating": 3.9,
  "reviewCount": 248,
  "coordinates": {
    "lat": 30.2672,
    "lng": -97.7431
  },
  "trackingSignals": {
    "googleTagManager": false,
    "googleAnalytics": true,
    "googleAdsConversion": false,
    "metaPixel": false,
    "linkedInInsight": false,
    "callTracking": false,
    "hasAnyTracking": true
  },
  "conversionSignals": {
    "hasForm": false,
    "hasPhoneLink": false,
    "hasBookingCta": false,
    "hasLeadFormCta": false,
    "weakCta": true
  }
}
```

### Run Locally 💻

```bash
npm install
npm test
npx --yes apify-cli run --input-file examples/input-smoke.json
```

Local and cloud Google Maps runs may show limited data depending on region, consent state, and anti-bot behavior. If a default datacenter proxy times out on Google Maps, run without proxy or use a residential proxy group.

### Run On Apify ☁️

```bash
npx --yes apify-cli login
npx --yes apify-cli push
```

Then open the Actor in Apify Console, run it with `examples/input.json`, and inspect:

- default dataset for sorted lead rows
- `OUTPUT.csv` in the default key-value store
- `OUTPUT.json` in the default key-value store
- `RUN_SUMMARY.json` in the default key-value store
- `SALES_AUDIT_REPORT.html` and `SALES_AUDIT_REPORT.pdf` in the default key-value store
- optional `AUDIT_SCREENSHOT_*.png` evidence records

### Monetization Suggestions 💵

The Actor uses pay-per-event pricing with a low basic-lead price and higher mutually exclusive enrichment tiers. This keeps basic Google Maps prospecting competitive while charging fairly for additional website requests and agency analysis. The Actor charges one result event only after all user-selected qualification and score filters pass.

### Store Positioning 🚀

**Title:** Google Maps Lead Finder for SEO & PPC Agencies

**Short description:** 📍 Find local businesses with weak websites, missing conversion tracking, and review gaps. Get ranked agency leads, public contacts, and evidence-based PPC or web-design angles.

**SEO tags:** Google Maps lead finder, SEO agency leads, PPC agency leads, local business scraper, PPC opportunity score, web design leads, reputation management leads, B2B prospecting.

Best target users:

- 🔎 SEO agencies
- 🎨 Web design agencies
- 📈 PPC agencies
- ⭐ Reputation management companies
- 📞 Local sales teams
- 🤝 B2B lead generation consultants

### Notes And Limitations

Google Maps DOM and anti-bot behavior can change. This Actor uses retries, Apify Proxy support, deduplication, and nullable fields to stay stable, but some fields such as review count or opening hours may be unavailable in limited Google Maps views.

Use the data responsibly and follow applicable laws, platform terms, and outreach regulations.

# Actor input Schema

## `searchTerms` (type: `array`):

Business types or services to find. Add multiple terms to build one deduplicated prospect list, for example dentists, roofers, and med spas.

## `location` (type: `string`):

One city, region, or country used for every search term, for example Austin, TX or London, UK. Leave empty only when every search term already contains a location.

## `maxResultsPerSearch` (type: `integer`):

Maximum Google Maps places to inspect for each search term before qualification filters are applied.

## `language` (type: `string`):

Language used for Google Maps results and browser localization.

## `minReviews` (type: `integer`):

Keep businesses with at least this many Google reviews. Use 0 to keep businesses with missing review counts.

## `maxReviews` (type: `integer`):

Keep businesses with no more than this many reviews. Use 1000000 to disable this filter.

## `minRating` (type: `number`):

Keep businesses at or above this rating. Use 0 to disable the minimum rating filter.

## `maxRating` (type: `number`):

Keep businesses at or below this rating. A value around 4.3 is useful for reputation prospects; use 5 to disable.

## `websiteFilter` (type: `string`):

Find all businesses, only businesses with a website, or website-less prospects for web design outreach.

## `categoryIncludes` (type: `array`):

Optional case-insensitive words that must appear in the Google Maps category. Leave empty to allow every category.

## `categoryExcludes` (type: `array`):

Optional case-insensitive category words to remove from the result set.

## `excludeIrrelevantResults` (type: `boolean`):

Remove businesses whose category and name do not match the search niche, including unrelated sponsored Maps results. Disable only for intentionally broad discovery searches.

## `enrichmentMode` (type: `string`):

Choose one transparent, all-in result tier. Businesses without a website are automatically charged as basic leads because no website enrichment can be performed.

## `maxWebsitePages` (type: `integer`):

Maximum home/contact/about pages fetched per business in Contacts, Website audit, or Full mode. Higher values can find more signals but increase run time.

## `websiteTimeoutSecs` (type: `integer`):

Maximum seconds to wait for each public website request.

## `includeAuditScreenshots` (type: `boolean`):

In Website audit or Full mode, save a viewport screenshot for the first businesses as key-value store records. Screenshots are point-in-time evidence and are not embedded in CSV exports.

## `maxEvidenceScreenshots` (type: `integer`):

Safety limit for screenshot records created during one run.

## `focusService` (type: `string`):

Adjust the combined opportunity score and suggested outreach service to your agency offer.

## `includeCompetitorBenchmark` (type: `boolean`):

Compare each business only with deduplicated businesses collected for the same search term and location in this run. No external Actor or paid API is used.

## `benchmarkCompetitorCount` (type: `integer`):

Number of the strongest collected peers included as concrete comparison examples.

## `generateSalesReport` (type: `boolean`):

Create SALES\_AUDIT\_REPORT.json, a print-ready HTML report, and a PDF report in the run key-value store. Included in the selected result tier.

## `minimumLeadScore` (type: `integer`):

Remove records below this general lead score. Use 0 to keep all qualified businesses.

## `minimumPpcOpportunityScore` (type: `integer`):

Remove records below this PPC and conversion opportunity score. Use 0 to keep all.

## `minimumWebsiteOpportunityScore` (type: `integer`):

Remove records below this web-design, technical SEO, performance, and conversion experience score. Use 0 to keep all.

## `minimumAgencyOpportunityScore` (type: `integer`):

Only export prospects meeting this service-weighted combined score. Use 0 to keep all.

## `minimumPriorityTier` (type: `string`):

Optionally export only warm or hot prospects after the audit and scoring are complete.

## `sortBy` (type: `string`):

Choose which score determines the first rows in the dataset and CSV export.

## `websiteConcurrency` (type: `integer`):

Number of business websites enriched in parallel. Lower this if target websites rate-limit requests.

## `maxTotalResults` (type: `integer`):

Safety limit across all search terms. This controls run time and prevents unexpectedly large runs.

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

Optional Apify Proxy settings for Google Maps. Residential proxies are recommended for larger runs or regions where direct access is blocked.

## Actor input object example

```json
{
  "searchTerms": [
    "dentists"
  ],
  "location": "Austin, TX",
  "maxResultsPerSearch": 25,
  "language": "en",
  "minReviews": 0,
  "maxReviews": 1000000,
  "minRating": 0,
  "maxRating": 5,
  "websiteFilter": "all",
  "categoryIncludes": [],
  "categoryExcludes": [],
  "excludeIrrelevantResults": true,
  "enrichmentMode": "basic",
  "maxWebsitePages": 3,
  "websiteTimeoutSecs": 15,
  "includeAuditScreenshots": false,
  "maxEvidenceScreenshots": 10,
  "focusService": "balanced",
  "includeCompetitorBenchmark": true,
  "benchmarkCompetitorCount": 3,
  "generateSalesReport": true,
  "minimumLeadScore": 0,
  "minimumPpcOpportunityScore": 0,
  "minimumWebsiteOpportunityScore": 0,
  "minimumAgencyOpportunityScore": 0,
  "minimumPriorityTier": "all",
  "sortBy": "agencyOpportunity",
  "websiteConcurrency": 3,
  "maxTotalResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `salesPipeline` (type: `string`):

Ranked prospects with priority, recommended service, outreach angle, and contacts.

## `contactList` (type: `string`):

Contact-focused view for CSV export and CRM integrations.

## `ppcAudit` (type: `string`):

Tracking and conversion signals flattened into filterable columns.

## `websiteOpportunities` (type: `string`):

Technical and web-design opportunity view.

## `competitorBenchmark` (type: `string`):

Prospect gaps compared with businesses from the same search and location.

## `salesAudit` (type: `string`):

Evidence, recommended offer, email copy, and call opener in a flat dataset view.

## `allData` (type: `string`):

Broad structured dataset view for advanced integrations.

## `csvExport` (type: `string`):

CSV export saved in the default key-value store.

## `jsonExport` (type: `string`):

JSON export saved in the default key-value store.

## `salesAuditPdf` (type: `string`):

Print-ready lead report generated when the sales report option is enabled.

## `salesAuditHtml` (type: `string`):

Browser-ready lead report generated when the sales report option is enabled.

## `salesAuditJson` (type: `string`):

Structured report objects for automation and CRM workflows.

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

Run-level summary with counts and configuration.

# 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 = {
    "searchTerms": [
        "dentists"
    ],
    "location": "Austin, TX"
};

// Run the Actor and wait for it to finish
const run = await client.actor("feeng/google-maps-agency-lead-finder").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 = {
    "searchTerms": ["dentists"],
    "location": "Austin, TX",
}

# Run the Actor and wait for it to finish
run = client.actor("feeng/google-maps-agency-lead-finder").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 '{
  "searchTerms": [
    "dentists"
  ],
  "location": "Austin, TX"
}' |
apify call feeng/google-maps-agency-lead-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=feeng/google-maps-agency-lead-finder",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Lead Finder for SEO & PPC Agencies",
        "description": "📍 Google Maps agency leads from $4 per 1,000. Qualify prospects and get structured sales-pipeline, CRM contact, PPC audit, and website-opportunity views with scores and evidence-based outreach angles.",
        "version": "0.1",
        "x-build-id": "NwgIVC4dmGK9Rlxi1"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/feeng~google-maps-agency-lead-finder/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-feeng-google-maps-agency-lead-finder",
                "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/feeng~google-maps-agency-lead-finder/runs": {
            "post": {
                "operationId": "runs-sync-feeng-google-maps-agency-lead-finder",
                "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/feeng~google-maps-agency-lead-finder/run-sync": {
            "post": {
                "operationId": "run-sync-feeng-google-maps-agency-lead-finder",
                "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": {
                    "searchTerms": {
                        "title": "🔍 Search term(s)",
                        "minItems": 1,
                        "maxItems": 10,
                        "type": "array",
                        "description": "Business types or services to find. Add multiple terms to build one deduplicated prospect list, for example dentists, roofers, and med spas.",
                        "items": {
                            "type": "string"
                        },
                        "default": [
                            "dentists"
                        ]
                    },
                    "location": {
                        "title": "📍 Location (use one location per run)",
                        "type": "string",
                        "description": "One city, region, or country used for every search term, for example Austin, TX or London, UK. Leave empty only when every search term already contains a location.",
                        "default": "Austin, TX"
                    },
                    "maxResultsPerSearch": {
                        "title": "💯 Number of places to inspect (per search term)",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum Google Maps places to inspect for each search term before qualification filters are applied.",
                        "default": 25
                    },
                    "language": {
                        "title": "🌍 Language",
                        "enum": [
                            "en",
                            "de",
                            "fr",
                            "es",
                            "it",
                            "nl",
                            "pt",
                            "pl",
                            "cs"
                        ],
                        "type": "string",
                        "description": "Language used for Google Maps results and browser localization.",
                        "default": "en"
                    },
                    "minReviews": {
                        "title": "⭐ Minimum review count",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Keep businesses with at least this many Google reviews. Use 0 to keep businesses with missing review counts.",
                        "default": 0
                    },
                    "maxReviews": {
                        "title": "Maximum review count",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Keep businesses with no more than this many reviews. Use 1000000 to disable this filter.",
                        "default": 1000000
                    },
                    "minRating": {
                        "title": "Minimum rating",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "number",
                        "description": "Keep businesses at or above this rating. Use 0 to disable the minimum rating filter.",
                        "default": 0
                    },
                    "maxRating": {
                        "title": "Maximum rating",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "number",
                        "description": "Keep businesses at or below this rating. A value around 4.3 is useful for reputation prospects; use 5 to disable.",
                        "default": 5
                    },
                    "websiteFilter": {
                        "title": "🌐 Website availability",
                        "enum": [
                            "all",
                            "withWebsite",
                            "withoutWebsite"
                        ],
                        "type": "string",
                        "description": "Find all businesses, only businesses with a website, or website-less prospects for web design outreach.",
                        "default": "all"
                    },
                    "categoryIncludes": {
                        "title": "Include categories containing",
                        "type": "array",
                        "description": "Optional case-insensitive words that must appear in the Google Maps category. Leave empty to allow every category.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "categoryExcludes": {
                        "title": "Exclude categories containing",
                        "type": "array",
                        "description": "Optional case-insensitive category words to remove from the result set.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "excludeIrrelevantResults": {
                        "title": "Remove obviously unrelated Maps results",
                        "type": "boolean",
                        "description": "Remove businesses whose category and name do not match the search niche, including unrelated sponsored Maps results. Disable only for intentionally broad discovery searches.",
                        "default": true
                    },
                    "enrichmentMode": {
                        "title": "💼 Lead enrichment level",
                        "enum": [
                            "basic",
                            "contacts",
                            "websiteAudit",
                            "full"
                        ],
                        "type": "string",
                        "description": "Choose one transparent, all-in result tier. Businesses without a website are automatically charged as basic leads because no website enrichment can be performed.",
                        "default": "basic"
                    },
                    "maxWebsitePages": {
                        "title": "Pages checked per website",
                        "minimum": 1,
                        "maximum": 8,
                        "type": "integer",
                        "description": "Maximum home/contact/about pages fetched per business in Contacts, Website audit, or Full mode. Higher values can find more signals but increase run time.",
                        "default": 3
                    },
                    "websiteTimeoutSecs": {
                        "title": "Website request timeout",
                        "minimum": 5,
                        "maximum": 60,
                        "type": "integer",
                        "description": "Maximum seconds to wait for each public website request.",
                        "default": 15
                    },
                    "includeAuditScreenshots": {
                        "title": "📸 Save website evidence screenshots",
                        "type": "boolean",
                        "description": "In Website audit or Full mode, save a viewport screenshot for the first businesses as key-value store records. Screenshots are point-in-time evidence and are not embedded in CSV exports.",
                        "default": false
                    },
                    "maxEvidenceScreenshots": {
                        "title": "Maximum evidence screenshots",
                        "minimum": 1,
                        "maximum": 25,
                        "type": "integer",
                        "description": "Safety limit for screenshot records created during one run.",
                        "default": 10
                    },
                    "focusService": {
                        "title": "🎯 Service you want to sell",
                        "enum": [
                            "balanced",
                            "ppc",
                            "seo",
                            "web_design",
                            "reputation"
                        ],
                        "type": "string",
                        "description": "Adjust the combined opportunity score and suggested outreach service to your agency offer.",
                        "default": "balanced"
                    },
                    "includeCompetitorBenchmark": {
                        "title": "🏁 Compare leads with local competitors",
                        "type": "boolean",
                        "description": "Compare each business only with deduplicated businesses collected for the same search term and location in this run. No external Actor or paid API is used.",
                        "default": true
                    },
                    "benchmarkCompetitorCount": {
                        "title": "Comparison businesses per lead",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Number of the strongest collected peers included as concrete comparison examples.",
                        "default": 3
                    },
                    "generateSalesReport": {
                        "title": "📄 Generate sales audit report",
                        "type": "boolean",
                        "description": "Create SALES_AUDIT_REPORT.json, a print-ready HTML report, and a PDF report in the run key-value store. Included in the selected result tier.",
                        "default": true
                    },
                    "minimumLeadScore": {
                        "title": "Minimum lead gap score",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Remove records below this general lead score. Use 0 to keep all qualified businesses.",
                        "default": 0
                    },
                    "minimumPpcOpportunityScore": {
                        "title": "Minimum PPC opportunity score",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Remove records below this PPC and conversion opportunity score. Use 0 to keep all.",
                        "default": 0
                    },
                    "minimumWebsiteOpportunityScore": {
                        "title": "Minimum website opportunity score",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Remove records below this web-design, technical SEO, performance, and conversion experience score. Use 0 to keep all.",
                        "default": 0
                    },
                    "minimumAgencyOpportunityScore": {
                        "title": "Minimum combined agency score",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Only export prospects meeting this service-weighted combined score. Use 0 to keep all.",
                        "default": 0
                    },
                    "minimumPriorityTier": {
                        "title": "Minimum priority tier",
                        "enum": [
                            "all",
                            "warm",
                            "hot"
                        ],
                        "type": "string",
                        "description": "Optionally export only warm or hot prospects after the audit and scoring are complete.",
                        "default": "all"
                    },
                    "sortBy": {
                        "title": "Sort final lead list by",
                        "enum": [
                            "agencyOpportunity",
                            "leadScore",
                            "ppcOpportunityScore",
                            "ppcReadinessScore",
                            "websiteOpportunityScore",
                            "competitorGapScore",
                            "reviewCount"
                        ],
                        "type": "string",
                        "description": "Choose which score determines the first rows in the dataset and CSV export.",
                        "default": "agencyOpportunity"
                    },
                    "websiteConcurrency": {
                        "title": "⚡ Concurrent website audits",
                        "minimum": 1,
                        "maximum": 8,
                        "type": "integer",
                        "description": "Number of business websites enriched in parallel. Lower this if target websites rate-limit requests.",
                        "default": 3
                    },
                    "maxTotalResults": {
                        "title": "🛑 Maximum places per run",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Safety limit across all search terms. This controls run time and prevents unexpectedly large runs.",
                        "default": 100
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional Apify Proxy settings for Google Maps. Residential proxies are recommended for larger runs or regions where direct access is blocked.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
