If you've ever built a lead-gen pipeline for a local SEO or web design agency, you know the pattern: scrape a bunch of businesses off Google Maps, then manually eyeball which ones are worth calling. Missing website? Good lead. Unclaimed Google Business Profile? Also good. Both? Great lead. But sorting hundreds or thousands of rows by hand on multiple criteria doesn't scale. I built Google Maps Lead Priority Scorer, an Apify Actor that takes the JSON output you already have from a Google Maps scraper and turns it into a single sortable priorityScore (0-100) per business, plus a plain-English list of reasons. It does no scraping and makes no LLM or external API calls — it's pure post-processing of data you already paid to collect. The problem with single-signal lead lists Most "find leads with no website" tools give you exactly one signal. But a business that has no website and an unclaimed GBP listing and fewer reviews than its neighbors is a categorically hotter lead than one that's just missing a website. If you're running four separate scrapers/filters and merging spreadsheets by hand, you're doing manual work a scoring function should do for you. This Actor combines four signals into one number: Signal Max points No independent website (a bare social-media link doesn't count) 35 Unclaimed Google Business Profile 25 Other missing profile fields (phone, description, hours, photos, categories) 25 Review count below the median for similar nearby businesses 15 Scores map to tiers: Hot (≥70), Warm (40-69), Cold (<40). Businesses marked permanently closed on Google Maps are dropped automatically before scoring, so you never waste an outreach call on a place that no longer exists. How it works: no scraping, no LLM This is the detail that matters most for a technical audience: this Actor is not a Maps scraper. It expects you to already have place objects (from something like Google Maps Scraper) and does pure computation on top of them — string checks for real vs. social-media-only URLs, null checks across profile fields, and a percentile calculation against other places in the same input batch. No headless browser, no OpenAI call, nothing that can time out or hallucinate. That's also why it's cheap: pay-per-event pricing is $0.005 per run start plus $0.0015 per scored lead returned. Scoring 1,000 already-scraped places costs about $1.51 on top of whatever the scraper itself charged. Usage: Apify Console or the API Option 1 — Apify Console Run a Google Maps scraper for your target city/category and grab its dataset output (as JSON). Open Google Maps Lead Priority Scorer in Apify Console, paste that array into the Google Maps places input field. Optionally set Minimum priority tier to Warm or Hot so you're only ever billed for the leads worth calling. Click Start. Results come back sorted highest-priority first, downloadable as JSON/CSV/Excel. Option 2 — apify call from the CLI apify call reverenced_garnet/apify-gmaps-lead-priority \ --input '{ "places": [ { "title": "Lemari Coffee", "placeId": "ChIJv79rmEfzGGARhXlSEd8ceiQ" } ], "minTier": "Warm" }' Option 3 — Apify API / SDK (chaining two Actors) The realistic production setup is: scrape → score → dataset, all in one script. Here's a minimal Node example using the Apify client that chains a Maps scraper run into this Actor: import { ApifyClient } from 'apify-client'; const client = new ApifyClient({ token: process.env.APIFY_TOKEN }); // 1. Run a Google Maps scraper for a city/category const scrapeRun = await client.actor('compass/crawler-google-places').call({ searchStringsArray: ['coffee shop in Austin, TX'], maxCrawledPlacesPerSearch: 200, }); const { items: places } = await client .dataset(scrapeRun.defaultDatasetId) .listItems(); // 2. Score those places for lead priority const scoreRun = await client.actor('reverenced_garnet/apify-gmaps-lead-priority').call({ places, minTier: 'Warm', webhookUrl: 'https://your-n8n-instance.example.com/webhook/new-leads', }); const { items: leads } = await client .dataset(scoreRun.defaultDatasetId) .listItems(); console.log(`Got ${leads.length} Warm+ leads, top one:`, leads[0]); The same works in Python with the apify-client package (ApifyClient(token=...), .actor(...).call(run_input=...), .dataset(...).list_items()). Input schema Field Type Description places array Place objects from a Google Maps scraper's dataset output minTier string Hot, Warm, or Cold (default) — minimum tier to include in the output slackWebhookUrl string (optional) Slack Incoming Webhook URL — posts a run summary discordWebhookUrl string (optional) Discord Channel Webhook URL — posts a run summary webhookUrl string (optional) Any URL — receives a structured JSON summary (e.g. for n8n/Make) notifyOnlyNewOrUpdated boolean Default true — only include NEW/UPDATED leads in notifications Output fields { "title": "Lemari Coffee", "placeId": "ChIJv79rmEfzGGARhXlSEd8ceiQ", "priorityScore": 60, "tier": "Warm", "changeStatus": "NEW", "reasons": [ "No independent website (social-media link or none at all)", "No business description" ], "hasRealWebsite": false, "isUnclaimed": false, "completenessScore": 70, "reviewPercentileInGroup": 25.0 } Field Type Description title string Business name placeId string Google Maps place ID priorityScore number 0-100 combined lead-priority score tier string Hot, Warm, or Cold changeStatus string NEW, UPDATED, or UNCHANGED vs. the previous run on this Actor reasons array Plain-English reasons contributing to the score hasRealWebsite boolean False if no site, or only a social-media link isUnclaimed boolean True if the Google Business Profile is unclaimed completenessScore number 0-100 GBP profile completeness reviewPercentileInGroup number Review-count percentile vs. same city+category peers One useful, unusual feature for anyone running this on a schedule: changeStatus. Run the Actor again later on the same area and every lead gets tagged NEW, UPDATED, or UNCHANGED compared to the previous run, so your sales team only re-reviews what actually moved instead of re-triaging the whole list every week. Use case: building an outbound list for a local SEO agency A typical workflow for an agency doing outbound prospecting for, say, dentists in a metro area: Run Google Maps Scraper for "dentist in Denver, CO", get back a few hundred place objects. Feed that array into this Actor with minTier: "Hot" — you now only pay for and receive the businesses with the strongest combination of no website, unclaimed profile, and thin review count. Set slackWebhookUrl so the agency's sales channel gets pinged with a summary whenever a run finds new or updated leads. Schedule the whole pipeline (scraper → scorer) weekly with Apify's built-in Scheduler. Because of changeStatus, week-over-week runs only surface leads that changed, so the team isn't re-triaging the same 300 businesses every Monday. Export the dataset as CSV and import into whatever CRM or cold-email tool the agency uses. The same pattern works for directory sites deciding which unclaimed listings to email about claiming their profile, or freelancers building a target list for a single vertical + city combo before a cold-call sprint. A word on scope and legality This Actor deliberately does one thing: turn place data you already have into a priority score. It doesn't scrape anything, doesn't call any external API, and doesn't infer anything with an LLM — which is also why it's fast and cheap. It's also worth being explicit that the presence of a phone number or address on a public Google Business Profile doesn't by itself mean you have consent to cold-call or cold-email that business. If you're using this for outreach, you're responsible for complying with applicable law (GDPR, CAN-SPAM, TCPA, etc. depending on where your leads are). Try it The Actor is live on the Apify Store: Google Maps Lead Priority Scorer. If you're already running a Google Maps scraper as part of a lead-gen pipeline, this is a five-minute addition that replaces a manual sorting/filtering step with a single number your sales team can trust.