Google Maps Lead Enricher: Website Audit + AI Facts avatar

Google Maps Lead Enricher: Website Audit + AI Facts

Pricing

from $10.00 / 1,000 ai-enriched businesses

Go to Apify Store
Google Maps Lead Enricher: Website Audit + AI Facts

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

Sniper Search

Maintained by Community

Actor 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_gaps code such as no_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 sellLook forInput 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 agenciesno_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 writersai.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).

TradeOnline bookingChatAd pixels seenCopyrightPitch gapsEmergency / financing / hiring
PlumbernoneTidioGoogle Ads (others ?)2023no_booking_seen, copyright_2023_or_olderyes / unknown / unknown
HVACown form or pagePodiumnonenot foundno_ad_tags_seenunknown / yes / unknown
Roofernone?Google Ads (others ?)2026no_booking_seenyes / yes / unknown
Electriciannonenonenone2018no_booking_seen, no_chat_seen, no_ad_tags_seen, no_https, copyright_2023_or_olderunknown / unknown / unknown
Hair salonSchedulicitynonenone2026no_chat_seen, no_ad_tags_seenunknown / unknown / yes
Auto repairown form or pagenoneGoogle Ads2026no_chat_seenunknown / yes / unknown

Three ways to give it businesses

Use any one, or all three in one run. All of them produce the same rows.

  1. Search. searchTerms (for example ["plumber", "hvac contractor"]), location (for example Seattle, WA, USA) and maxBusinessesPerSearch (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.
  2. 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, with mapsDatasetId set to {{resource.defaultDatasetId}}) so every run is enriched as it finishes. Left empty, mapsDatasetId falls back to the dataset of the run that triggered the integration. The rows work as they are.
  3. Your own list. businesses: items with a name or a website, and optionally city, state, phone, address and placeId. 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-5 or claude-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 is title, and meta.source is dataset. 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 as acmeplumbing.example), else the first entry of websites that is not a Google Maps link. The name is title, the category is the first of categories after Page, and the link to the page (pageUrl) goes to input_extra.source_url. meta.source is facebook. 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 of externalUrls. The name is fullName, the category is businessCategoryName, and the profile link (url) goes to input_extra.source_url. meta.source is instagram. When fullName reads like a person's name ("Jane Smith"), it is not used: the business is named by its username. 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 under input_extra (for example emails from Google Maps Scraper's contacts option). A Facebook or Instagram row also gets input_extra.source_url, the link to its page or profile.
  • signals: https, mobile_ready, copyright_year, site_builder, booking_platform and booking_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, with evidence quotes and a confidence.
  • status and charged_event:
statusMeaningCharged
enrichedWebsite scanned and AI facts addedbusiness-enriched $0.01
scannedWebsite 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_unavailableWebsite scanned, but the AI facts could not be added (the AI call failed, or no key works); error says whybusiness-scanned $0.002
no_websiteNo usable websitefree
unreadableThe site could not be read: bot check, a page built only in JavaScript, a dead domainfree
not_own_siteThe website is a directory, a social network, a marketplace page, or another businessfree
skipped_free_planPast the 100 businesses a free-plan run processesfree
errorAn item that is not a business, or an unexpected failurefree

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.

EventPriceWhen
Scanned business (business-scanned)$0.002The site was read and the website signals came back
AI-enriched business (business-enriched)$0.01The 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 unknown there.
  • 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 unreadable and 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 evidence quotes 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.