Build log
If you sell local SEO, web design or lead-gen services, you probably look at a lot of small-business homepages. Checking them one at a time in a browser is slow, and the notes end up in different formats. This tutorial shows how to audit a whole list at once with the Local SEO Bulk Site Auditor, an Apify Actor.
Disclosure first: my agency, Manta Media, built and publishes this Actor. I'll stick to what it actually does, as described on its public page, and the sample output is from a real run, with business details removed.
What the Actor does
You give it a list of URLs. For each one it fetches that single page (plus robots.txt and one http:// redirect check) and returns one dataset item. It doesn't crawl the rest of the site.
For each URL you get:
- Availability: the final URL after redirects, HTTP status, response time and page size
- Security: whether the SSL certificate is valid, its expiry date, days left, and whether
http://redirects tohttps:// - On-page: the title and its length, the meta description and its length, and all H1 headings
- Local schema: whether LocalBusiness or Organization JSON-LD is present (including subtypes like Dentist or Plumber), plus the name, address and phone it contains
- NAP: phone numbers found on the page (normalised to E.164), a street address on the page, and whether the page phone matches the schema phone
- Contact: public email addresses on the page
- Mobile and indexing: viewport tag, canonical URL and robots meta (it flags
noindex) - Speed (optional): the Google PageSpeed Insights mobile score, using your own free API key
- Summary: a
localSeoScorefrom 0 to 100 and anissueslist written in plain English
Step 1: build your URL list
Start with homepages. One page per URL is the design, so if you also want a contact or location page checked, add it as a separate URL.
A few tips for a clean list:
- Remove duplicates and obvious directory listings (Yelp, BBB and similar). You want the business's own site.
- You can leave off
https://. The Actor adds it if it's missing. - Keep a separate sheet with the business name, city and trade for each URL. The Actor returns site facts, not your prospect notes, so you'll join the two later on the URL.
Step 2: open the Actor and set the input
Open the Local SEO Bulk Site Auditor on Apify. The input has four fields:
| Field | Type | Default | What it does |
|---|---|---|---|
urls |
array | (required) | The pages to audit. One dataset item per URL. |
includeSpeed |
boolean | false |
Adds the PageSpeed mobile score. Adds about 10 to 40 seconds per URL. |
pagespeedApiKey |
string | (empty) | Your free Google PageSpeed Insights API key. Without one, Google rate-limits quickly (HTTP 429). |
maxConcurrency |
integer | 3 |
How many sites to audit in parallel, from 1 to 10. |
A minimal input looks like this:
{
"urls": [
{ "url": "https://www.example-plumber.com" },
{ "url": "example-roofer.com" }
],
"includeSpeed": false,
"maxConcurrency": 3
}
My advice for a first run: leave includeSpeed off. You'll get every other check quickly, and you can run speed later on the shortlist that matters. If you do turn it on, get a free PageSpeed Insights key from Google Cloud Console first.
Step 3: run it and check the cost
Pricing is pay per event: $0.004 per URL audited, which the Actor page states as about $4 per 1,000 URLs. Platform usage is included, and there's no start fee. PageSpeed calls use your own Google key, so they don't add to the Apify bill.
Before a big run, try 10 to 20 URLs. It's cheap, and it shows you what the output looks like for your kind of businesses.
The Actor is polite by design. It respects robots.txt (disallowed pages are skipped and reported), uses 10-second connect and 20-second read timeouts, reads at most 3 MB of HTML per page and identifies itself with its own User-Agent.
Step 4: read the results
The dataset has three views:
- Overview: URL, local SEO score, HTTP status, title, phones, emails, issues and any error
- Technical SEO: SSL valid, SSL expiry, http→https, title length, meta description length, H1, viewport, canonical, robots meta, response time and PageSpeed mobile score
- NAP & schema: whether schema is present, whether it's LocalBusiness, its type, name, address and phone, plus phones on the page, the address on the page, whether the phone matches, and emails
You can export any view to CSV, Excel or JSON.
Sample output (real run, anonymized)
These are real results from my own test of the Actor on 11 Oct 2026, with business names, domains and phone numbers removed. Six small-business homepages: four in Idaho, US (trades) and two in Singapore (dental).
In the cloud run, the six scores were 100, 89, 89, 87, 77 and 77. All six had a valid SSL certificate and redirected http:// to https://. PageSpeed was off, because it needs your own key.
The local test run of the same six sites gave slightly different scores. That run couldn't complete the http:// redirect probe, so httpRedirectsToHttps came back null (unknown). The table below is from the local run, because that's where I have every field:
| Site | Score | Title length | Meta desc length | H1 count | Schema | Email on page | Main issues |
|---|---|---|---|---|---|---|---|
| Site A (Roofing, US) | 87 | 54 | 221 | 4 | Organization only | Yes | Long meta description; 4 H1s; schema not LocalBusiness |
| Site B (Plumbing, US) | 77 | 25 | 75 | 1 | None | Yes | No LocalBusiness schema; no street address on page |
| Site C (HVAC and plumbing, US) | 100 | 48 | 131 | 1 | LocalBusiness | Yes | None |
| Site D (Dental, SG) | 89 | 11 | 206 | 5 | LocalBusiness, no address or phone | Yes | Very short title; long meta description; 5 H1s; schema missing address/phone |
| Site E (HVAC, US) | 94 | 182 | 146 | 1 | LocalBusiness | No | Title cut off in Google; phone in schema doesn't match page |
| Site F (Dental, SG) | 74 | 38 | 0 | 8 | Organization only | No | No meta description; 8 H1s; schema not LocalBusiness; server took 13.2 s |
One item, anonymized (Site B):
{
"inputUrl": "https://www.site-b.example/",
"httpStatus": 200,
"sslValid": true,
"sslDaysLeft": 34,
"httpRedirectsToHttps": null,
"titleLength": 25,
"metaDescriptionLength": 75,
"h1": ["[business name]: Your Trusted Plumber"],
"schema": { "present": false, "localBusiness": false, "type": null,
"name": null, "address": null, "phone": null },
"phones": ["+1208XXXXXXX"],
"addressOnPage": null,
"napConsistent": null,
"emails": ["[redacted]@gmail.com"],
"hasViewport": true,
"responseTimeMs": 33,
"pageSizeKb": 477,
"pagespeedMobileScore": null,
"localSeoScore": 77,
"issues": [
"No LocalBusiness structured data (schema markup) - this helps Google show your business in local results.",
"No street address was found on the page; show your full address to rank in local searches."
]
}
Fields that couldn't be determined come back as null, as httpRedirectsToHttps does here.
Step 5: understand the score
The score is a weighted checklist that adds up to 100:
| Check | Weight |
|---|---|
| LocalBusiness schema | 15 |
| Phone on page | 12 |
| Title | 10 |
| SSL | 8 |
| Meta description | 8 |
| Address on page | 8 |
| Viewport | 8 |
| Indexable | 8 |
| Single H1 | 7 |
| Response time | 5 |
| http→https | 4 |
| Canonical | 4 |
| 3 |
When PageSpeed is on, it contributes 10% of the final score. An HTTP error caps the score at 20.
Treat the score as a way to sort a list, not a verdict on a business. A site can score well and still not get calls, and a low score on a site that's mainly rendered by JavaScript may partly reflect what the Actor can see (more on that below).
Step 6: turn issues into something useful
The issues field is the part you'll actually use. Each entry is one plain-English problem with a hint about the fix, written so you can pass it on. The README gives this example: "No LocalBusiness structured data (schema markup) - this helps Google show your business in local results."
Before you send any of it to a prospect, check it. Websites change. In my own outreach, a re-check of 30 audits before sending found that 10 cited a problem the business had already fixed. Re-run the Actor on your shortlist right before you send, and drop anything that no longer shows up.
Limits to know
- One page per URL. No crawl. Add extra pages as extra URLs.
- Raw HTML only. The Actor analyses the HTML as delivered. Content injected only by JavaScript may be missed.
- Phone regions. The default region comes from the domain ending (
.co.ukmeans GB,.commeans US, and so on). Numbers written with a+countryprefix are detected anywhere. - Robots.txt is respected. A disallowed page is skipped and reported, not audited.
A sensible first workflow
- Run 20 URLs with speed off.
- Export the Overview view to CSV.
- Sort by score, then read the issues for the lowest and highest few to get a feel for them.
- Re-run the shortlist with speed on, using your own API key.
- Re-check right before you contact anyone.
That's the whole tool. It won't find you clients on its own, and it makes no promises about rankings. It turns a long list of homepages into a sortable sheet of facts you can check, which is the slow part of qualifying local sites.