# Businesses Without Website & Bad Website Leads (`aiden_boudreau/website-redesign-leads`) Actor

Find local businesses that need a new website. Searches Google Maps, then audits each site for dead or parked domains, expired plans, no HTTPS, poor mobile support, outdated tech and slow pages. Returns a 0-100 score, a ready-to-paste pitch and contacts.

- **URL**: https://apify.com/aiden\_boudreau/website-redesign-leads.md
- **Developed by:** [Aiden Boudreau](https://apify.com/aiden_boudreau) (community)
- **Categories:** Lead generation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 website auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Businesses Without Website & Bad Website Leads

**Find businesses without a website, plus the ones with a bad website, and get a ready-to-send pitch for each.** Built for web designers, freelancers, agencies and local SEO consultants.

![Local businesses ranked by how badly they need a new website: real audit results](https://api.apify.com/v2/key-value-stores/VsOADrgiznRqRejDw/records/hero.png)

Give it a business type and a city ("dentist", "Boise, ID"). It finds the businesses on Google Maps, keeps the **businesses without a website**, then **audits every website** of the rest and returns a ranked lead list:

- **No website at all**: only a Google Maps listing.
- **Dead, parked or expired**: domain doesn't resolve, server errors, "domain for sale" pages, an expired Squarespace or Wix plan, a dead Google `business.site` page.
- **Not a real website**: only a Facebook, Instagram or Yelp page, or a free builder subdomain.
- **Outdated or broken**: no HTTPS ("Not secure"), not mobile-friendly, a © 2015 footer, Flash or HTML frames, discontinued site builders (FrontPage, iWeb, Muse), old WordPress or jQuery, 10 MB homepages, uncompressed images, slow servers.

Each business gets a **0–100 opportunity score**, a **one-line pitch** written in plain English ("Not mobile-friendly; footer says © 2016; homepage is 9.4 MB."), and the **emails, phones and social links** found on its site.

### How to use it

Pick one or more sources:

| Source | Input | When to use it |
|---|---|---|
| Google Maps search | `searchTerms` + `location` | Start from zero: "plumber" + "Tulsa, OK" |
| Earlier Google Maps run | `mapsDatasetId` | You already ran Google Maps Scraper; audit those places without paying to scrape Maps again |
| Your own list | `websites` | Audit any list of URLs (from a CRM, a directory, a spreadsheet) |

Then filter:

- **`minScore`**: only return (and pay for) leads at or above a score. 45+ is "outdated", 85+ is dead, parked, expired or no real website.
- **`includeNoWebsite`**: keep or drop businesses with no website.

### What you get

One row per business (Leads view shown first, full audit in the Audit details view):

```json
{
  "businessName": "Golden Lantern Wok",
  "category": "Chinese restaurant",
  "city": "Springfield",
  "phone": "(555) 010-0101",
  "rating": 4.1,
  "reviewsCount": 210,
  "website": "http://www.example-wok.com/",
  "verdict": "OUTDATED",
  "opportunityScore": 85,
  "pitch": "No HTTPS (\"Not secure\" in the browser); not mobile-friendly; footer says © 2012.",
  "issues": [
    "The site loads over plain HTTP, so Chrome labels it \"Not secure\".",
    "There is no mobile viewport tag, so phones show a shrunken desktop page.",
    "The footer copyright reads 2012, a sign the site has not been touched in years.",
    "The site advertises WordPress 5.4; version 6.0 shipped in 2022, so it is probably missing years of security updates.",
    "The site loads jQuery 1.4.2, a JavaScript library from 2012 or earlier.",
    "There is no meta description, so Google writes its own snippet for the business.",
    "No tel: link on the homepage, so mobile visitors cannot tap to call."
  ],
  "emails": [],
  "socialLinks": {"facebook": "http://facebook.com/pages/...", "x": "http://twitter.com/..."},
  "platform": "WordPress",
  "https": false,
  "mobileFriendly": false,
  "copyrightYear": 2012,
  "pageWeightKb": 2014,
  "serverResponseMs": 1149
}
```

(A real audit result, with the business name and contact details replaced.)

#### Verdicts

| Verdict | Score | Meaning |
|---|---|---|
| `NO_WEBSITE` | 100 | On Google Maps with no website |
| `DEAD` | 90–95 | Doesn't resolve, doesn't load, server error, or dead `business.site` page |
| `PARKED` / `EXPIRED` / `PLACEHOLDER` | 85–90 | Parked or for-sale domain, expired builder subscription, "coming soon" or default server page |
| `SOCIAL_ONLY` | 85 | The "website" is a Facebook, Instagram, Yelp or link-in-bio page |
| `OUTDATED` | 45+ | Several serious problems; a redesign pitch |
| `NEEDS_WORK` | 25–44 | Fixable problems; a maintenance, speed or SEO pitch |
| `OK` | under 25 | A decent site; usually not a lead |

### Pricing

Pay per result, with no subscription and no rental:

- **$10 per 1,000 websites audited** ($0.01 each)
- **$3 per 1,000 no-website leads** ($0.003 each)
- **Free:** chain-store location pages (skipped), sites that block automated checks (skipped), and anything below your `minScore`.

Google Maps discovery runs Apify's [Google Maps Scraper](https://apify.com/compass/crawler-google-places) in your account at its own price (about $4 per 1,000 places). Use `maxMapsCostUsd` to cap it.

**Example:** 100 roofers in Denver works out to about $0.40 of Google Maps plus at most $1 of audits.

### Tips

- Run one trade per city for a focused list; schedule it monthly to catch sites that break or expire.
- Use `minScore: 45` when you only want strong redesign leads, or `85` for "no working website" leads.
- Already have Google Maps data? Pass its dataset ID instead of searching again.
- Lead with **one** concrete problem from the `pitch`, not a list. Owners respond to "your site shows 'Not secure' in Chrome" far more than to a score.

### How the audit works

Each website gets a small number of ordinary page requests: the homepage, optionally the contact page, and a size check of the homepage's images, scripts and styles. It is fast (about 200 websites a minute) and cheap. It does not run a full browser, so:

- Sites that build their whole page with JavaScript are audited on what the server sends (head tags, HTTPS, speed, platform), and aren't marked "blank".
- Sites behind bot challenges (e.g. Cloudflare "Just a moment...") can't be checked. They're skipped and never charged.
- Scores are heuristics. Open the site before you pitch.

### Use responsibly

The data is what each business publishes on its own website and Google Maps listing. When you contact businesses, follow the rules that apply to you (for example CAN-SPAM in the US: a real postal address, an honest subject line, and an opt-out in every email; GDPR and PECR in the EU and UK). Don't send bulk unsolicited email.

### FAQ

#### How do I find businesses without a website?

Enter a business type (e.g. "roofer") and a city, and leave `includeNoWebsite` on. Every Google Maps business with no website comes back as a `NO_WEBSITE` lead with its phone number, address and rating. Set `minScore: 85` to get only no-website, dead, parked and expired leads.

#### How much do 100 leads cost, all in?

**At most about $1.40 per 100 businesses**: roughly $0.40 of Google Maps Scraper usage per 100 places, plus $0.01 per audited website (up to $1.00) or $0.003 per no-website lead. A typical mix costs $0.80 to $1.20 per 100. Chains, sites that block checks and anything below `minScore` are free. Set `maxMapsCostUsd` to cap the Google Maps part.

#### What counts as a bad website?

Dead or parked domains, expired Squarespace/Wix plans, no HTTPS, not mobile-friendly, outdated copyright years, discontinued site builders, old WordPress or jQuery, very heavy pages and missing basics like a meta description. See the Verdicts table.

#### Does it work outside the US?

Yes. Any location Google Maps knows, e.g. "Leeds, UK" or "Toronto, Canada". Audit text is English.

#### Can I audit businesses I already have?

Yes: pass `websites` (a list of URLs) or `mapsDatasetId` (an earlier Google Maps Scraper dataset).

#### Can an AI agent use it?

Yes, through the Apify MCP server. Every input has a plain-English description, and the output schema lists all fields.

### Integrations

Run it from the Apify API, schedule it, send results to Google Sheets, Zapier, Make or n8n, or call it from AI agents through the Apify MCP server.

### Changelog

- **0.2**: new title and README for "businesses without website" searches; clearer input descriptions. No pricing or behavior changes.
- **0.1**: first release. Google Maps search, dataset and URL-list sources; dead, parked, expired, social-only, mobile, HTTPS, legacy tech, freshness, weight and SEO-basics checks; contact extraction.

# Actor input Schema

## `searchTerms` (type: `array`):

Business types to look up on Google Maps, one per entry, e.g. "dentist", "plumber", "hair salon". Each term is searched in the location below. Leave empty to only audit your own websites or an existing Google Maps dataset.

## `location` (type: `string`):

City and state or country where to search, e.g. "Boise, ID" or "Leeds, UK". Required when searchTerms is used.

## `maxPlacesPerSearch` (type: `integer`):

How many Google Maps businesses to collect for each search term (1-2000). Cost scales with this number: about $4 per 1,000 for Google Maps plus up to $0.01 per audited site. Use 20 for a quick test.

## `maxMapsCostUsd` (type: `integer`):

Optional cap on what the Google Maps Scraper step may charge. Google Maps discovery runs Apify's Google Maps Scraper (compass/crawler-google-places) in your account at its own price, roughly $4 per 1,000 places.

## `websites` (type: `array`):

Full URLs of business websites to audit directly, e.g. "https://example.com". Use instead of, or in addition to, a Google Maps search.

## `mapsDatasetId` (type: `string`):

A dataset from an earlier Google Maps Scraper run (pick it, or paste its ID). Every place in it is audited, so you don't pay to scrape Google Maps twice.

## `includeNoWebsite` (type: `boolean`):

If true (default), also return Google Maps businesses that have no website at all, the hottest leads for a web designer. Set false to only get businesses whose existing website is bad.

## `minScore` (type: `integer`):

Only return (and pay for) businesses scoring at least this much. 0 returns everything; 25+ is "needs work"; 45+ is "outdated"; 85+ is dead, parked, expired or no real website.

## `includeChains` (type: `boolean`):

Chain locations (e.g. a store-locator page on a national brand's site) are poor web design leads and are skipped free of charge unless you turn this on.

## `includeUnauditable` (type: `boolean`):

Some sites block automated checks (e.g. Cloudflare challenges). They are never charged; turn this on to see them anyway.

## `findContactPage` (type: `boolean`):

If the homepage has no email address, also check the site's contact page.

## `measurePageWeight` (type: `boolean`):

Checks the size of images, scripts and styles on the homepage to flag slow, heavy pages.

## `maxConcurrency` (type: `integer`):

How many websites to audit at once.

## Actor input object example

```json
{
  "searchTerms": [
    "plumber"
  ],
  "location": "Boise, ID",
  "maxPlacesPerSearch": 20,
  "includeNoWebsite": true,
  "minScore": 0,
  "includeChains": false,
  "includeUnauditable": false,
  "findContactPage": true,
  "measurePageWeight": true,
  "maxConcurrency": 20
}
```

# Actor output Schema

## `leads` (type: `string`):

One row per business: opportunity score, verdict, pitch line, website, phone, emails and Google Maps details.

## `audit` (type: `string`):

Full audit per website: every issue found, platform, HTTPS, mobile-friendliness, copyright year, page weight and server speed.

## `summary` (type: `string`):

Counts of each verdict for the run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "plumber"
    ],
    "location": "Boise, ID",
    "maxPlacesPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("aiden_boudreau/website-redesign-leads").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchTerms": ["plumber"],
    "location": "Boise, ID",
    "maxPlacesPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("aiden_boudreau/website-redesign-leads").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "plumber"
  ],
  "location": "Boise, ID",
  "maxPlacesPerSearch": 20
}' |
apify call aiden_boudreau/website-redesign-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aiden_boudreau/website-redesign-leads"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/FTjJpRgqkicIlTUj0/builds/CjMKassHciloDrH3p/openapi.json
