# Website Audit & Lead Scorer for Agencies (`mambo_melon/website-audit-lead-scorer`) Actor

Audit a list of business websites and rank them as sales leads: mobile-friendliness, SSL, load time, outdated footer year, online booking, live chat, analytics, contact details. Each site gets a lead score, a list of problems and a ready first line for outreach.

- **URL**: https://apify.com/mambo\_melon/website-audit-lead-scorer.md
- **Developed by:** [Joran Morgan](https://apify.com/mambo_melon) (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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Website Audit & Lead Scorer for Agencies

Paste a list of local business websites and get them back ranked as sales leads. Each site is checked for the things a web or marketing agency would pitch: no mobile layout, broken or missing HTTPS, slow loading, a footer that still says © 2016, no way to book online, no chat, no analytics, no contact form. You get a lead score from 0 to 100, the list of problems in plain English, and a first line you can use in a cold email or DM.

I built this for my own agency work. Google Maps gives you hundreds of dentists or plumbers in a city; the hard part is figuring out which of them actually need help with their site. Opening each one and clicking around takes a few minutes per business. This does that part for you and puts the worst sites at the top.

Sites that don't load at all are still returned (with the reason) but aren't charged. If a business lists a Facebook or Instagram page instead of a website, that's reported as a lead too, usually the best kind.

### What a result looks like

Real output from a run over dentists and plumbers in Austin, TX. The business name is changed:

```json
{
  "domain": "www.example-dental.com",
  "title": "Example Dental: Serving Austin since 2011",
  "leadScore": 73,
  "priority": "hot",
  "pitchHook": "Hi, I was looking at example-dental.com and noticed browsers mark your site as \"Not secure\", and the footer still says © 2011. I help local businesses fix exactly this. Happy to show you what it would look like.",
  "issueCount": 9,
  "issues": [
    { "code": "no_https", "points": 20, "message": "Site is not served over HTTPS" },
    { "code": "outdated_copyright", "points": 10, "message": "Footer copyright says 2011" },
    { "code": "no_online_booking", "points": 10, "message": "No online booking or scheduling found" },
    { "code": "no_analytics", "points": 10, "message": "No analytics or tag manager detected" },
    { "code": "outdated_software", "points": 5, "message": "jQuery 1.8.3 is outdated" },
    { "code": "site_builder", "points": 5, "message": "Built with Weebly (limited SEO and speed control)" }
  ],
  "mobileFriendly": true,
  "hasHttps": false,
  "sslValid": false,
  "loadTimeMs": 801,
  "copyrightYear": 2011,
  "hasOnlineBooking": false,
  "hasLiveChat": false,
  "hasAnalytics": false,
  "hasContactForm": false,
  "cms": "Weebly",
  "techNames": ["Weebly", "Hostgator", "Cloudflare", "jQuery", "PHP", "reCAPTCHA", "..."],
  "phones": ["5128212394"],
  "emails": [],
  "socialLinks": { "facebook": "https://facebook.com/example-dental" },
  "error": null
}
```

Every row has the same fields, `null` when something couldn't be determined, so CSV and Excel exports stay aligned. The **Leads** view in the dataset shows just the score, priority, pitch line and contacts; **All checks** shows every check as a column.

### What gets checked

| Check | Points if it fails |
|---|---|
| No website at all, only a social media page | 60 |
| Not on HTTPS, or the SSL certificate is broken/expired | 20 |
| No mobile viewport (page doesn't adapt to phones) | 20 |
| Homepage takes more than 5 s to load (3 s: 5 points) | 10 |
| Footer copyright is 2+ years old (last year: 3 points) | 10 |
| No online booking or scheduling (widgets like Calendly, or "book now" links) | 10 |
| No analytics or tag manager | 10 |
| No live chat widget | 5 |
| No contact form on the homepage or the contact page | 5 |
| Outdated WordPress, Joomla, Drupal, jQuery or PHP | 5 |
| Built on a site builder (Wix, Squarespace, Weebly...) | 5 |
| http:// doesn't redirect to https:// | 5 |
| Missing title, meta description or H1, no social links | 3 to 5 each |

The score is the sum, capped at 100. 50 and up is `hot`, 25 to 49 `warm`, below that `cold`. The pitch line uses the two heaviest problems that make sense to mention to a business owner.

### Input

| Field | What it does | Default |
|---|---|---|
| `urls` | Business websites, as domains or URLs. The `website` column of a Google Maps export works as-is. | required |
| `minLeadScore` | Only return sites scoring at least this much. Sites below it are skipped and not charged. | 0 |
| `maxItems` | Cap on websites per run | 1000 |
| `maxConcurrency` | Sites checked in parallel | 10 |
| `requestTimeoutSecs` | How long to wait for a slow site | 20 |

### A typical workflow

1. Get businesses for a niche and city, for example with a Google Maps scraper.
2. Feed the `website` column into this Actor, maybe with `minLeadScore: 40`.
3. Sort by `leadScore`, adjust the `pitchHook` to your voice, and reach out using the phone numbers and emails the audit found on each site.

It runs on a schedule and connects to Google Sheets, n8n, Make, Zapier or your CRM through the usual Apify integrations.

### FAQ

**How accurate is the load time?**
It's the time to download the homepage HTML from the Apify cloud, not a full browser render like PageSpeed Insights. If the first load is slow, the site is measured a second time and the better result is kept, so one hiccup doesn't mark a site as slow. Good enough to spot sites that are genuinely sluggish.

**Why does almost every site get "no live chat"?**
Because most small business sites don't have one. It's only 5 points, so it shifts the ranking a little without dominating it.

**Does it run a browser?**
No. It reads the HTML, headers, DNS and the TLS certificate, and detects tools from 7,600+ technology fingerprints. That keeps it fast and cheap. Widgets that only appear after JavaScript runs can occasionally be missed.

**Some sites return an error.**
The `error` field says why: a timeout, a domain that no longer resolves, or HTTP 403 from a site that blocks automated visits. Sites that block cloud servers get one more try through a residential connection first, which gets most of them through. Rows that still fail are free.

**Where do the emails and phones come from?**
Only from what the business publishes on its own homepage (mailto/tel links and visible text). Nothing is looked up elsewhere.

### Notes

Only public pages are read, no logins. Technology detection uses the open-source [webappanalyzer](https://github.com/enthec/webappanalyzer) rules (GPL-3.0).

Don't have a list yet? [Local Business Leads with Website Audit](https://apify.com/mambo_melon/local-leads-website-audit) finds the businesses on Google Maps for a niche and city and runs these same checks on them.

Need only the technology list for a big batch of domains, without the audit? [Tech Stack Detector](https://apify.com/mambo_melon/tech-stack-detector) is cheaper per site.

If a check gets a site wrong, open an issue with the URL and I'll look at it.

# Actor input Schema

## `urls` (type: `array`):

Websites of the businesses you want to audit, e.g. the 'website' column from a Google Maps export. Plain domains or full URLs. Duplicates are removed.

## `minLeadScore` (type: `integer`):

Skip well-maintained sites. 0 returns everything. Sites below the threshold are not returned and not charged.

## `maxItems` (type: `integer`):

Maximum number of websites to audit in this run.

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

How many websites to audit in parallel. Higher is faster but makes load-time measurements noisier.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for a slow website.

## Actor input object example

```json
{
  "urls": [
    "joesplumbingandheating.com",
    "smiledental.com"
  ],
  "minLeadScore": 0,
  "maxItems": 1000,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

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

No description

## `checks` (type: `string`):

No description

# 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 = {
    "urls": [
        "joesplumbingandheating.com",
        "smiledental.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mambo_melon/website-audit-lead-scorer").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 = { "urls": [
        "joesplumbingandheating.com",
        "smiledental.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("mambo_melon/website-audit-lead-scorer").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 '{
  "urls": [
    "joesplumbingandheating.com",
    "smiledental.com"
  ]
}' |
apify call mambo_melon/website-audit-lead-scorer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mambo_melon/website-audit-lead-scorer"
        }
    }
}
```

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/v9ajiZ1mnHdSIrw2s/builds/ZO5Vb1S3xa38i6NAU/openapi.json
