Local Service Lead Qualifier avatar

Local Service Lead Qualifier

Pricing

from $20.00 / 1,000 qualified leads

Go to Apify Store
Local Service Lead Qualifier

Local Service Lead Qualifier

Rank local service businesses by outreach-readiness and return evidence-backed qualified leads.

Pricing

from $20.00 / 1,000 qualified leads

Rating

0.0

(0)

Developer

Rasputin Kaiser

Rasputin Kaiser

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

Qualified local service leads with evidence-backed reasons to contact.

This Actor helps local SEO agencies, web studios, reputation teams, and B2B sales teams prioritize outreach to local service businesses. It is not another raw Google Maps clone: it discovers or accepts candidates, scores them, enriches public websites when requested, and returns only the leads that look actionable.

Quick Start

  1. Pick a vertical (for example HVAC) and a city (Dallas, TX).
  2. Run in Live places mode with the default caps (25 places, 25 leads).
  3. Get back a short list of evidence-backed leads: contact paths, score reasons, and outreach copy you can send with light editing.

What it costs: billing is per event, so you pay for what the run actually finds. A real 25-place HVAC/Dallas run charged 24 candidate evaluations at $0.008 each and 5 qualified leads at $0.05 each — about $0.44 in events; typical single-city runs land around $0.30–0.80 all-in. A 100-place benchmark across three vertical/city mixes charged 98 candidate evaluations and, with the current credibility gate, those mixes yield 11 qualified leads — about $1.33 in events for the whole batch.

Real run output: 25 Dallas HVAC places in, 5 evidence-backed leads out

What you get — a lead discovered in that Dallas run, exactly as emitted:

{
"businessName": "Texla HVAC",
"vertical": "HVAC",
"location": "Dallas, TX",
"phone": "(972) 514-5618",
"categoryName": "HVAC contractor",
"rating": 5,
"reviewCount": 12,
"leadScore": 79,
"leadQuality": "strong",
"contactReadiness": "phoneReady",
"evidenceSummary": [
"Listed as HVAC contractor",
"Strong 5-star rating but only 12 reviews so far",
"Google Maps listing links to no website",
"Direct contact path available",
"Competitive local market"
],
"reasonToContact": "Texla HVAC looks worth contacting: strong 5-star rating but only 12 reviews so far; Google Maps listing links to no website; direct contact path available.",
"suggestedMessage": "Hi Texla HVAC, I was researching HVAC in Dallas, TX and yours stood out. I noticed you hold a strong 5-star rating but only 12 reviews so far, and your Google Maps listing doesn't link to a website. I help businesses like yours with Local SEO and conversion audit and think there may be a quick win here. Worth a short note with specifics?"
}

Evidence in, sendable outreach out: the suggested message is built only from observed evidence

Who It Is For

  • Local SEO and web-design agencies building weekly prospect lists.
  • Reputation-management teams looking for review/rating pain.
  • B2B sales teams selling to local service businesses.
  • SaaS vendors selling booking, CRM, review, phone, or field-service tools.

When Not To Use It

Do not use this Actor when you need a complete raw places export with every business in an area. Use it when you want a shorter list of businesses that already look worth contacting, with the evidence to back that up.

Input

Core fields:

  • discoveryMode: demo, providedCandidates, or livePlaces.
  • vertical: business type. Cross-vertical noise filtering covers HVAC, roofers, plumbers, dentists, lawyers, med spas, landscapers, pest control, electricians, garage door, cleaning, painters, locksmiths, movers, auto repair, and veterinarians; other verticals still score but without that filter (the run logs a warning and sets RUN_SUMMARY.verticalFilterActive: false so the difference is visible).
  • locations: one or more cities, counties, metros, or states.
  • maxPlacesPerLocation: hard cap to control spend.
  • qualificationThreshold: minimum score required for dataset output.
  • maxQualifiedLeads: stop after this many qualified leads have been emitted.
  • minimumEvidenceSignals: minimum number of score reasons required for output.
  • minimumReviewCount: skip candidates with fewer than this many public reviews before any scoring or billing (default 0; set 3+ for a firmer evidence floor on volume outreach).
  • requireContactPath: skip candidates without a phone, email, website, or Maps URL.
  • excludeChains: off by default. Skip national chain/franchise listings (known brand names, #1042-style unit markers, or the same name repeated 3+ times in one location) before any billing; counted in RUN_SUMMARY.filteredChains.
  • suppressBusinessIdentifiers: optional repeat-run suppression list. Add an exact website domain, business phone, public email, or business name from your CRM to skip businesses you already contacted or already manage before enrichment and billing. The run receipt keeps only the number supplied and the number skipped.
  • offerType: the pitch or service the buyer wants to sell.
  • includeWebsiteCrawl: fetch candidate homepage/contact/about/careers pages and infer website signals. Defaults to on for provided-candidate and live-place runs.
  • includeContactExtraction: extract public emails and social profile links from crawled pages. Defaults to on for provided-candidate and live-place runs.
  • includeUpstreamContactEnrichment: off by default. Enables the Google Maps Scraper's paid scrapeContacts add-on during live discovery, which pulls business emails and social profiles from each place's website far more reliably than a static crawl. Adds a small upstream cost per place (see the discovery Actor's pricing tab).
  • maxWebsitePages: page cap per candidate.
  • websiteTimeoutSecs: per-page request timeout.

Advanced fields:

  • placesActorId: Apify Store Actor used for live discovery. Defaults to the Google Maps Scraper (compass/crawler-google-places), which manages its own proxying internally. An alternative Actor must accept searchStringsArray/locationQuery-style input and return items shaped like the Google Maps Scraper's; the common aliases name, rating, reviewCount, and category are also accepted. Only the default Actor has been tested end to end.
  • parallelLocationDiscovery: off by default. Starts the next location's discovery while the current one is being evaluated (one location of lookahead), cutting wall-clock time on multi-city runs. The trade-off: a run that stops early at a lead or charge limit has already paid for the prefetched location's discovery.
  • proxyConfiguration: proxy used for this Actor's own website/contact enrichment fetches. Defaults to Apify Proxy. Does not apply to the discovery Actor call, which handles proxying itself.

Discovery modes

  • Demo candidates — three fixed sample businesses, useful for verifying the pipeline without spend.
  • Provided candidates — score business rows you already have (from your own list or an upstream discovery Actor).
  • Live places — orchestrates the Google Maps Scraper (or another Actor you point placesActorId at) per vertical/location, normalizes results, deduplicates by website domain, phone, and address, then scores and enriches them. This is the mode to use for a self-contained, no-upstream-data-needed run.

Output

Each dataset item includes business identity, source category evidence, contact fields, a Google Maps link, enrichment status, candidate source, score, quality tier, confidence score, score reasons, suggested offer, outreach copy, next best action, and source URLs. The default key-value store also includes RUN_SUMMARY, a compact run receipt with evaluated, rejected, enriched, emitted, charged, and deduplicated counts plus proof-boundary notes. It also reports verticalFilterActive (whether the requested vertical gets cross-vertical noise filtering), filteredBelowReviewMinimum (candidates skipped by minimumReviewCount before billing), filteredSuppressed (repeat-run CRM exclusions skipped before billing), and contactReadinessCounts (how many emitted leads are emailReady, phoneReady, or manual-lookup).

Billing-safety guarantees: candidates are deduplicated across all requested locations, so a business serving two nearby cities is charged and emitted at most once per run. If the platform migrates or restarts a run, it resumes from a checkpoint instead of re-charging already-billed candidates (RUN_SUMMARY.resumedFromCheckpoint is set to true), and re-reads each location's already-paid discovery results instead of calling the discovery Actor again. If a lead is ever charged but fails to write to the dataset, it is recorded under the CHARGE_DISCREPANCIES key-value store record so it can be recovered or refunded, and counted in RUN_SUMMARY.pushFailures.

Outreach copy (reasonToContact, suggestedSubject, suggestedMessage) is built only from concrete, buyer-usable evidence — specific ratings, review counts, and website gaps — never from internal scoring labels, so it can be sent with light editing instead of a rewrite.

{
"businessName": "Metro Comfort Air",
"vertical": "HVAC",
"location": "Dallas, TX",
"phone": "+1 214 555 0101",
"website": "https://metro-comfort-air.invalid",
"mapsUrl": "https://www.google.com/maps/place/Metro+Comfort+Air",
"categoryName": "HVAC contractor",
"categories": [
"HVAC contractor",
"Air conditioning contractor"
],
"rating": 4.2,
"reviewCount": 184,
"websiteSignals": [
"Public email found",
"Social profile found"
],
"enrichmentStatus": "enriched",
"candidateSource": "livePlaces",
"leadScore": 95,
"leadQuality": "hot",
"confidenceScore": 90,
"contactReadiness": "emailReady",
"evidenceSummary": [
"Listed as HVAC contractor",
"4.2-star rating across 184 reviews leaves reputation upside",
"Website has no obvious booking or contact call to action",
"Direct contact path available"
],
"scoreReasons": [
"High-value local service category",
"Review volume exists but rating leaves reputation upside",
"Website has no obvious booking or contact CTA"
],
"reasonToContact": "Metro Comfort Air looks worth contacting: 4.2-star rating across 184 reviews leaves reputation upside; website has no obvious booking or contact call to action.",
"suggestedOffer": "Local SEO and conversion audit",
"suggestedSubject": "Quick Local SEO and conversion audit idea for Metro Comfort Air",
"suggestedMessage": "Hi Metro Comfort Air, I was researching HVAC in Dallas, TX and yours stood out. I noticed your 4.2-star rating across 184 reviews has real room to climb, and your website doesn't give visitors an obvious way to book or request a quote. I help businesses like yours with Local SEO and conversion audit and think there may be a quick win here. Worth a short note with specifics?",
"nextBestAction": "Send a short personalized email and follow up by phone within two business days.",
"sourceUrls": [
"https://maps.example.invalid/metro-comfort-air",
"https://metro-comfort-air.invalid/contact"
]
}

Scoring

The scoring model is deterministic and transparent:

  • High-value local service category.
  • Reputation gap from rating and review volume.
  • Missing website or weak conversion CTA.
  • Stale service or offer copy.
  • Direct contact path.
  • Hiring, growth, or multi-location signal.
  • Competitive local density (computed from how many candidates were returned per location in Live places mode).
  • Source evidence present.

Only candidates at or above qualificationThreshold with at least minimumEvidenceSignals score reasons are emitted. Candidates are deduplicated by website domain, normalized phone, and normalized address before scoring. Credibility gate: the missing-website signal only counts when the listing has at least one public review, and rating-based signals require at least three reviews. Listings with no website, no reviews, and no rating — the shape of Google Maps lead-gen spam networks — do not reach the qualification threshold and are never charged as leads. Live discovery also filters obvious vertical mismatches before scoring or candidate billing, using source category/name evidence. For example, a roofing/siding listing returned by a broad HVAC Maps query is counted in RUN_SUMMARY.filteredOutOfVertical instead of being charged or emitted. Use maxQualifiedLeads to cap the final list size and spend. With requireContactPath enabled, candidates without any public route to contact or verify them are skipped before scoring.

Pricing Direction

Monetization is pay-per-event. The primary event is qualifiedLead, priced at $50 per 1,000 qualified leads ($0.05 each). The Actor calls Actor.charge({ eventName: 'qualifiedLead' }) before writing each emitted lead and stops cleanly when the user's max-charge limit prevents another paid lead.

For live discovery, configure a secondary candidateEvaluated event before publishing. The pilot economics currently support about $8 per 1,000 evaluated live candidates ($0.008 each) to cover upstream Google Maps discovery and wrapper runtime before qualified leads are known.

The Store setup also includes Apify's synthetic apify-actor-start and apify-default-dataset-item events at minimal prices. Platform usage costs are included, not passed through separately to users.

Accuracy And Limits

  • Live place discovery depends on a third-party Store Actor (the Google Maps Scraper by default); its coverage, freshness, and cost are separate from this Actor's own proof.
  • Website enrichment uses static HTML fetches, not a full browser; script-rendered contact details will be missed.
  • Some websites block crawlers or hide contact details behind scripts.
  • Contact extraction filters common asset filenames and placeholder domains, but buyers should still spot-check email deliverability before outreach.
  • Live place category data can be noisy, so category/name relevance checks are conservative guardrails rather than a guarantee that every retained business perfectly matches the buyer's target vertical.
  • Scores explain likely outreach fit; they do not prove buyer intent or conversion.
  • Live discovery runs pay upstream Store Actor costs before this Actor can decide which candidates qualify, so use maxPlacesPerLocation for bounded tests and review RUN_SUMMARY before scaling a new vertical/location mix.

Support & Issues

Report problems through this Actor's Issues tab in Apify Console (or the Issues section of the Store listing). Include the run ID so the RUN_SUMMARY receipt and charge records can be checked against what you were billed. Issues are typically answered within one business day; anything that looks like a charged-but-undelivered lead is treated as a refund-priority bug — the Actor records those under CHARGE_DISCREPANCIES precisely so they can be verified and made right.

Compliance Note

Use public or authorized business data, respect target-site terms, and contact businesses responsibly. This Actor is designed to prioritize legitimate B2B outreach, not to bypass privacy controls or spam recipients.

Local Development

Install dependencies:

$npm install

Run the demo:

$apify run --purge

Run with provided candidates and website enrichment:

$npm run run:provided

Run with live place discovery (requires APIFY_TOKEN and a funded account, since it calls a paid Store Actor):

$apify run --purge --input-file examples/live-places-input.json

Validate release files and syntax:

$npm run check

Validate sample output:

$npm run validate:sample

Validate local run output:

$npm run validate:local

Proof Boundaries

  • Local apify run proves Actor wiring and Console schema validity for the demo and provided-candidates modes.
  • Harness validation proves output schema and lead-evidence minimums.
  • Provided-candidate runs prove static website/contact enrichment against the supplied URLs.
  • Live place discovery has been run end to end, both locally and as a real cloud apify actors call, against the actual Google Maps Scraper: discovery, dedupe, website enrichment, scoring, and dataset output all verified with real data.
  • Pay-per-event pricing is configured in Console with qualifiedLead as the primary event. The code now checks eventChargeLimitReached and stops once the buyer's max-charge limit prevents another paid lead.
  • Store publication, source freshness, manual spot-checks, and revenue remain separate proof layers that require an actual Store listing.