Google Maps Lead Enricher: Website Audit + AI Facts
Pricing
from $10.00 / 1,000 ai-enriched businesses
Google Maps Lead Enricher: Website Audit + AI Facts
signals (booking_platform, chat_widget, ad_tags), pitch_gaps, ai (services, price_points, financing, emergency_24_7, hiring) with quotes for each business on a Google Maps list. $0.002 per site scanned, $0.01 with AI facts; the free plan gets AI facts for up to 3 businesses per run without a key.
Pricing
from $10.00 / 1,000 ai-enriched businesses
Rating
0.0
(0)
Developer
Sniper Search
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
signals (booking_platform, chat_widget, ad_tags), pitch_gaps, ai (services, price_points, financing, emergency_24_7, hiring) with quotes for each business on a Google Maps list. $0.002 per site scanned, $0.01 with AI facts; the free plan gets AI facts for up to 3 businesses per run without a key. Those are the first 3 businesses of a run that reach the AI step (a failed AI call uses up a slot); the AI runs on the Actor's key and each one is charged $0.01 like any other AI-enriched business. The rest are scanned only ($0.002 each); add your own Anthropic key for AI facts on all of them.
Give it businesses (a Google Maps search, the dataset of a Google Maps Scraper run, or your own list) and it reads each business's own website. You get one row per business with two kinds of answers:
- Website signals, found by rules on the pages, no AI: does the site take online bookings and with which tool (Housecall Pro, ServiceTitan, Jobber, Vagaro, Calendly and about 20 more), is there a chat widget (Podium, Tidio, Intercom, ...), does it run Meta, Google Ads, TikTok or Microsoft ads pixels, is it on HTTPS with a certificate a browser accepts, is it mobile-ready, which copyright year is in the footer, what is it built with. Each gap comes back as a ready-made
pitch_gapscode such asno_booking_seen. - AI facts, read by Claude from the site's own text, each with a verbatim quote and the page it came from: what the business does, services and service area, prices it states, financing and named providers, free estimates, emergency or 24/7 service, licensed or insured, years in business, guarantees, languages, and whether it is hiring.
Businesses with no website, or with a site that cannot be read, come back as free rows. The Actor collects facts about businesses, not about people (see Privacy).
Who uses it
Filter the rows on the gap you sell, and turn the AI on only for the prospects that have it. aiOnlyForGaps makes the Actor spend the $0.01 AI step only on businesses whose scan shows one of the gaps you list; the others cost $0.002.
| You sell | Look for | Input to save money |
|---|---|---|
| Websites and redesigns (web designers) | copyright_2023_or_older, no_https, not_mobile_ready, signals.site_builder, and the no_website rows: businesses on Google Maps without a site, free | "aiFacts": false for the scan alone, or "aiOnlyForGaps": ["copyright_2023_or_older", "no_https", "not_mobile_ready"] |
| Booking and field-service software (Housecall Pro, Jobber, Vagaro, Calendly resellers) | no_booking_seen for prospects, and signals.booking_platform to see which tool the competition already uses | "aiOnlyForGaps": ["no_booking_seen"] |
| Chat and review widgets (Podium, Tidio, Birdeye resellers) | no_chat_seen; signals.chat_widget names the vendor a business already has. It is unknown, never none, when Google Tag Manager is on the page, because the tag can load a widget later | "aiOnlyForGaps": ["no_chat_seen"] |
| Ad agencies | no_ad_tags_seen: no Meta, Google Ads, TikTok or Microsoft Ads pixel seen. ai.financing, ai.free_estimates and ai.price_points show the offer you can advertise | "aiOnlyForGaps": ["no_ad_tags_seen"] |
| Cold email and outreach writers | ai.services, ai.service_area and ai.evidence: a quote from the business's own site to open an email with. Emails from Google Maps Scraper's contacts option pass through in input_extra | "aiFacts": true on the businesses you will write to |
Example output
One business (a made-up plumber; meta is shortened):
{"name": "Acme Plumbing","website": "https://acmeplumbing.example/","place_id": "ChIJ-acme","category": "Plumber","city": "Seattle","state": "Washington","phone": "(206) 555-0100","rating": 4.8,"reviews_count": 412,"status": "enriched","charged_event": "business-enriched","pitch_gaps": ["no_chat_seen", "copyright_2023_or_older"],"signals": {"https": true,"mobile_ready": true,"copyright_year": 2022,"site_builder": "WordPress","gtm_present": false,"chat_widget": "none","booking_platform": "Housecall Pro","booking_url": "https://book.housecallpro.com/book/acme-plumbing","ad_tags": { "meta_pixel": "yes", "google_ads": "no", "ga4": "unknown", "tiktok": "no", "microsoft_ads": "no" },"contact_form": true,"social_links": ["https://www.facebook.com/acmeplumbing"]},"ai": {"summary": "Acme Plumbing is a Seattle plumber for water heaters, drains and sewer lines.","services": ["Water heater repair", "Drain cleaning", "Sewer line replacement"],"service_area": "Seattle, Bellevue and Renton","emergency_24_7": "yes","free_estimates": "yes","financing": "yes","financing_providers": ["Synchrony"],"price_points": ["$89 diagnostic fee"],"online_booking": "yes","booking_url": "https://book.housecallpro.com/book/acme-plumbing","licensed_insured": "yes","founded_year": 1995,"guarantees": ["One-year workmanship warranty"],"languages": ["Spanish"],"hiring": "yes","careers_url": "https://acmeplumbing.example/careers","evidence": [{ "field": "emergency_24_7", "quote": "24/7 emergency plumbing, nights and weekends", "url": "https://acmeplumbing.example/" },{ "field": "financing", "quote": "Financing available through Synchrony", "url": "https://acmeplumbing.example/financing" }],"confidence": "high"},"error": null,"input_extra": null,"meta": { "index": 0, "source": "list", "final_url": "https://acmeplumbing.example/", "pages_read": ["https://acmeplumbing.example/", "https://acmeplumbing.example/financing"] }}
Every AI fact is unknown, null or empty when the site does not say. Nothing is guessed. In the Apify Console the dataset has two table views: Overview (status, gaps and website signals) and AI facts (services, prices, financing, quotes).
Six real results
From the October 2026 test sites, one business per trade in Seattle, names left out. The website columns were read with the current version, the last column is what the AI read in the October test. ? means unknown (Google Tag Manager on the page).
| Trade | Online booking | Chat | Ad pixels seen | Copyright | Pitch gaps | Emergency / financing / hiring |
|---|---|---|---|---|---|---|
| Plumber | none | Tidio | Google Ads (others ?) | 2023 | no_booking_seen, copyright_2023_or_older | yes / unknown / unknown |
| HVAC | own form or page | Podium | none | not found | no_ad_tags_seen | unknown / yes / unknown |
| Roofer | none | ? | Google Ads (others ?) | 2026 | no_booking_seen | yes / yes / unknown |
| Electrician | none | none | none | 2018 | no_booking_seen, no_chat_seen, no_ad_tags_seen, no_https, copyright_2023_or_older | unknown / unknown / unknown |
| Hair salon | Schedulicity | none | none | 2026 | no_chat_seen, no_ad_tags_seen | unknown / unknown / yes |
| Auto repair | own form or page | none | Google Ads | 2026 | no_chat_seen | unknown / yes / unknown |
Three ways to give it businesses
Use any one, or all three in one run. All of them produce the same rows.
- Search.
searchTerms(for example["plumber", "hvac contractor"]),location(for exampleSeattle, WA, USA) andmaxBusinessesPerSearch(default 50, up to 500). The Actor runs Google Maps Scraper in your own Apify account and reads the websites of the places it finds. Closed places are left out. Google Maps Scraper bills you for the search, and your maximum cost per run does not cover it, see Pricing. - After Google Maps Scraper (or Facebook Pages Scraper, or Instagram Profile Scraper). Pick its dataset in
mapsDatasetId, or add this Actor as an integration of that Actor (its Integrations tab, Add integration, then this Actor, withmapsDatasetIdset to{{resource.defaultDatasetId}}) so every run is enriched as it finishes. Left empty,mapsDatasetIdfalls back to the dataset of the run that triggered the integration. The rows work as they are. - Your own list.
businesses: items with anameor awebsite, and optionallycity,state,phone,addressandplaceId. Rows exported from Google Maps Scraper or another tool work as they are.
{"searchTerms": ["plumber", "hvac contractor"],"location": "Seattle, WA, USA","maxBusinessesPerSearch": 25,"aiOnlyForGaps": ["no_booking_seen"]}
{"businesses": [{ "name": "Acme Plumbing", "website": "https://acmeplumbing.example/", "city": "Seattle", "state": "WA" }]}
The same place twice (same Google place ID) is one business, and so is the same website listed for several businesses: it is read once, every business gets the result, and you pay once.
Input
searchTerms,location,maxBusinessesPerSearch: the Google Maps search (see above).mapsDatasetId: the dataset of a Google Maps Scraper, Facebook Pages Scraper or Instagram Profile Scraper run. Each row is read on its own, so one dataset can mix them (see Chain it after another actor, below).businesses: your own list.maxBusinesses(default 500, up to 5000): a hard cap for the whole run. Businesses past it get no row.aiFacts(default on): add the AI facts. Off: website signals only, $0.002 per site.aiOnlyForGaps: run the AI only on businesses that show one of these gaps:no_booking_seen,no_chat_seen,no_ad_tags_seen,no_https,not_mobile_ready,copyright_2023_or_older,no_contact_form_seen.anthropicApiKey: your own Anthropic API key, billed to you by Anthropic. Leave it empty on paid plans: the Actor's own key gives AI facts to the first 1,000 businesses of a run and scans the rest. On the free Apify plan the Actor's own key gives AI facts to the first 3 businesses of a run and scans the rest, so add your own key for AI facts on all of them. Your key is also needed for Sonnet or Opus and for more than 5 pages per site. It is stored as a secret and is never logged or written to the output.model:claude-haiku-5-5(default),claude-sonnet-5-5orclaude-opus-5-5. Sonnet and Opus run only with your own key; without one the Actor uses Haiku.maxPagesPerSite(default 5): pages read per site, homepage included. At most 5 without your own key, 8 with it. The Actor reads the homepage and the subpages most likely to hold the answers: contact, services, booking, pricing, financing, careers, about.concurrency(default 3),proxyConfiguration.
Chain it after another actor
mapsDatasetId takes the dataset of a run of any of three Actors, and one dataset can hold rows of all three. The Actor tells them apart row by row, from the columns each row has, reads the business's website from the column named below, and returns a row that has none as no_website, free. The other columns of a row stay in input_extra, except the ones listed under Privacy.
Connected as an integration of one of these Actors (its Integrations tab, Add integration), the Actor reads the dataset of the run that triggered it automatically, so the Actor input can stay empty. If a run reports that it cannot read that dataset, set mapsDatasetId to {{resource.defaultDatasetId}}.
- Google Maps Scraper: the website is
website, the name istitle, andmeta.sourceisdataset. Rows work as they always did. A row{"title": "Acme Plumbing", "placeId": "ChIJ-acme", "website": "https://acmeplumbing.example/"}comes out as{"name": "Acme Plumbing", "website": "https://acmeplumbing.example/", "meta": {"source": "dataset"}}. - Facebook Pages Scraper: the website is
website(Facebook writes a bare domain such asacmeplumbing.example), else the first entry ofwebsitesthat is not a Google Maps link. The name istitle, the category is the first ofcategoriesafterPage, and the link to the page (pageUrl) goes toinput_extra.source_url.meta.sourceisfacebook. A row{"title": "Acme Plumbing", "pageUrl": "https://www.facebook.com/acmeplumbing", "categories": ["Page", "Plumber"], "website": "acmeplumbing.example"}comes out as{"name": "Acme Plumbing", "website": "acmeplumbing.example", "category": "Plumber", "input_extra": {"source_url": "https://www.facebook.com/acmeplumbing"}, "meta": {"source": "facebook"}}. - Instagram Profile Scraper: the website is
externalUrl, the link in the bio, else the first usable link ofexternalUrls. The name isfullName, the category isbusinessCategoryName, and the profile link (url) goes toinput_extra.source_url.meta.sourceisinstagram. WhenfullNamereads like a person's name ("Jane Smith"), it is not used: the business is named by itsusername. A row{"username": "acmeplumbing", "url": "https://www.instagram.com/acmeplumbing", "fullName": "Acme Plumbing", "externalUrl": "https://acmeplumbing.example/", "businessCategoryName": "Plumber"}comes out as{"name": "Acme Plumbing", "website": "https://acmeplumbing.example/", "category": "Plumber", "input_extra": {"source_url": "https://www.instagram.com/acmeplumbing"}, "meta": {"source": "instagram"}}.
maps_url is filled for Google Maps rows only. A link that cannot be a business's own site (Google Maps, a directory, a social network, Linktree and other link-in-bio pages, WhatsApp) is passed over when another column has a better one; when it is the only one, the row comes back as not_own_site, free. A Facebook row that carries a personal profile is a person, not a page: its title is not used as the name. The posts, related accounts and personal profiles these Actors write are not passed on (see Privacy). Rows pasted into businesses are read as plain items: use mapsDatasetId for the datasets of these Actors.
Output
One row per business in the default dataset.
- From Google Maps or your input:
name,website,place_id,maps_url,category,address,city,state,phone,rating,reviews_count. Any other column you gave comes back unchanged underinput_extra(for exampleemailsfrom Google Maps Scraper's contacts option). A Facebook or Instagram row also getsinput_extra.source_url, the link to its page or profile. signals:https,mobile_ready,copyright_year,site_builder,booking_platformandbooking_url,chat_widget,ad_tags(meta_pixel,google_ads,ga4,tiktok,microsoft_ads),gtm_present,contact_form,social_links(the business's own pages only).pitch_gaps: the gap codes above that apply to the site.ai: the AI facts, withevidencequotes and aconfidence.statusandcharged_event:
status | Meaning | Charged |
|---|---|---|
enriched | Website scanned and AI facts added | business-enriched $0.01 |
scanned | Website scanned, no AI facts (meta.ai_skipped says why: AI off, free plan after the first 3 businesses of a run, no matching gap, spending limit, the 1,000-business AI limit of the Actor's key, ...) | business-scanned $0.002 |
ai_unavailable | Website scanned, but the AI facts could not be added (the AI call failed, or no key works); error says why | business-scanned $0.002 |
no_website | No usable website | free |
unreadable | The site could not be read: bot check, a page built only in JavaScript, a dead domain | free |
not_own_site | The website is a directory, a social network, a marketplace page, or another business | free |
skipped_free_plan | Past the 100 businesses a free-plan run processes | free |
error | An item that is not a business, or an unexpected failure | free |
How to read the signals. "Seen" means seen in the pages the Actor read. A tag manager can load chat widgets and ad pixels later, so when Google Tag Manager is on the page they come back as unknown, never as absent. GA4 is also unknown on WordPress and on hosted site builders (Squarespace, Wix, GoDaddy, Duda, Weebly, Shopify, Webflow), where it is added in a way a plain page request cannot see. contact_form is null, not false, on Squarespace, Wix, GoDaddy, Duda and Weebly sites where no form was seen, because those builders often draw their forms with JavaScript. https is true when the final address is HTTPS and a browser would accept its certificate. It is false for plain HTTP and for an expired, self-signed or wrong-host certificate, which browsers show as "Not secure" (meta.certificate_error names the problem), and null when the certificate check could not settle (a timeout, an incomplete certificate chain). A pitch gap is only reported on a clear "no". copyright_year is empty when the footer is written by JavaScript.
Pricing
Pay per event, no start fee.
| Event | Price | When |
|---|---|---|
Scanned business (business-scanned) | $0.002 | The site was read and the website signals came back |
AI-enriched business (business-enriched) | $0.01 | The site was read and AI facts were added. Charged instead of the scan, never on top of it |
Free: businesses with no website, sites that cannot be read, sites that are not the business's own, businesses skipped on the free plan, errors, and every business that shares a website with one already processed in the same run. If the AI step fails for a business you still get the scan and pay the scan price (ai_unavailable). Your own Anthropic key costs the same.
For 100 businesses: about $0.20 for scans only, about $1.00 with AI facts, and less with aiOnlyForGaps. Set a maximum cost per run in the run options: the Actor stops cleanly at the limit and never charges past it for its own events, and the businesses after it have no row.
The Google Maps search is billed by Google Maps Scraper, on top of this Actor's price, to your account: up to $0.004 per place on the free plan (less on paid plans). The Actor sets none of its paid add-ons or filters, so a search of 100 places costs at most about $0.40. Using an existing dataset or your own list costs nothing extra.
Your maximum cost per run does not cover the Google Maps search, only this Actor's own events. To keep the two in step, the search asks for no more places than your maximum cost can pay for: at $0.01 each when every business gets AI facts, at $0.002 each when AI facts are off or limited by aiOnlyForGaps, and on a free-plan trial 3 at $0.01 and the rest at $0.002. Businesses without a website or with an unreadable site are free, so a run usually has money left over; set maxBusinessesPerSearch if you want a fixed number.
For comparison, Google Maps Scraper's own AI add-on costs $0.025 per place on the free plan, and Apify's AI Web Scraper costs $0.03 per page. This Actor reads up to five pages of a site by default and returns structured facts with quotes for $0.01.
How accurate is it?
Tested in October 2026 on 56 trade and salon businesses in Seattle (plumbers, HVAC, roofers, electricians, hair salons, auto repair shops). The test read up to 5 pages per site, the Actor's default.
- AI facts: 98.8% of the key-field answers were right (339 of 343, blind re-check against the pages). By field: own website 100%, services 100%, emergency or 24/7 100%, free estimates 98%, financing 100%, online booking 96%, licensed or insured 100%, hiring 98%.
- Website signals matched what a real browser shows on 18 of 20 sites. The 2 misses were GA4 reported as absent on sites where a site builder or plugin adds it; GA4 is now reported as
unknownthere. - Readable: 50 or 51 of the 56 sites (about 9 in 10) could be read without a browser. The others were bot checks, pages built only in JavaScript, or a dead domain; they come back as
unreadableand are free.
Quotes come from the visible text of the business's own pages, so you can check any fact.
Free plan
On the free Apify plan a run processes up to 100 businesses (within your spending limit) and returns the rest as free skipped_free_plan rows. Without your own Anthropic key, the free Apify plan gets AI facts for 3 businesses per run: the first 3 businesses get them on the Actor's key (Haiku, at most 5 pages per site) and are charged business-enriched, $0.01 each, like any other AI-enriched business. The rest are scanned only (charged business-scanned, $0.002 each; meta.ai_skipped is free_plan). With your own key in anthropicApiKey, every business of the run gets AI facts. Paid plans have no cap on businesses and need no key for AI facts, with one limit: on the Actor's own key a run gives AI facts to at most 1,000 businesses, and the rest are scanned only (meta.ai_skipped is run_ai_cap). Add anthropicApiKey to get AI facts for every business of a larger run.
Privacy
The Actor returns facts about businesses. It does not collect the names of owners, staff or reviewers, personal emails or personal phone numbers, and it asks the AI to leave them out of every field. Reviews, lead enrichment (named contacts), image authors, owner posts, an Instagram profile's latest posts and related accounts, a Facebook page's posts and personal profile, LinkedIn profile links and any column of your input whose name contains owner, staff, reviewer or personal are dropped, not passed on. Social links are the business's own pages only. Every other column of your input rows comes back unchanged under input_extra, so if a column of your own holds a person's name or email, leave it out of the input when you do not want it in the output. The one exception is an Instagram profile's fullName: it becomes the business name only when it reads like a business, and is never passed on. A name like "Jane Smith" is replaced by the username. If you need business emails, turn on the contacts option of Google Maps Scraper: its emails column passes through under input_extra as it is.
Good to know
- It reads public pages of the business's own site, a handful per site.
- Sites that need a full browser (built entirely in JavaScript, or behind a bot check) are
unreadable. - The AI facts are only as good as the site: the
evidencequotes show where each key fact came from. - Directory, social network and marketplace links (Yelp, Facebook, HomeAdvisor, Vagaro profiles, ...) are never read as the business's own site.
Looking for dental, veterinary, chiropractic, therapy or other clinics, with insurance and new-patient facts? See Dental & Clinic Enricher.