# Website Redesign Signals: Outdated Website Checker (`shanmukhkiransagar/website-redesign-signals`) Actor

Outdated website checker for web design agencies: audit a site list, get a 0-100 score with reasons and a factual outreach hook to qualify redesign prospects.

- **URL**: https://apify.com/shanmukhkiransagar/website-redesign-signals.md
- **Developed by:** [Shanmukh kiran Sagar](https://apify.com/shanmukhkiransagar) (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 $15.00 / 1,000 site analyzeds

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

## Website Redesign Signals: Outdated Website Checker for Web Design Leads

**Paste a list of business websites. Get back which ones look outdated, why, and one factual sentence you can open an outreach email with.**

Website Redesign Signals is an **outdated website checker** and quick **website audit** tool for web design agencies, SEO agencies and freelancers. You bring a list of prospect websites; it checks each homepage over plain HTTP (no browser), gives it a 0–100 outdated score with a reason for every point, and writes one neutral, checkable outreach line per site. Use it to turn a raw list into ranked **redesign prospects** instead of opening 200 tabs.

> Example hook from a real run: *"The site has no mobile viewport tag and it still loads jQuery 1.10.2."*

### What does this outdated website checker do?

For every website in your list it:

1. Loads the homepage (`https://` first, then `http://`), plus the contact page by default.
2. Checks the signals that make a site look old or hard to use: no mobile viewport, no working HTTPS, a stale © year, old jQuery/Bootstrap, legacy markup (Flash, frames, table layouts), broken homepage links, very large images, missing title/meta description/Open Graph tags, no enquiry or booking form, no tap-to-call link.
3. Adds up an **outdated score (0–100)** and lists each finding in `reasons[]` with its points and a plain-English explanation.
4. Writes an `outreachHook`: one factual sentence built from the two strongest findings, plus `primaryIssueType` and `primaryGapTag` so you can segment campaigns.

Results land in an Apify dataset you can export to CSV, Excel or JSON, or pull through the API.

### Who is it for?

#### Web design agencies and freelancers

- **Qualify a prospect list** before a cold-email campaign: sort by `outdatedScore` and start with the 40+ sites.
- **Personalise the first line** with a verifiable observation (`outreachHook`) instead of a generic compliment.
- **Segment campaigns** by the main issue (`primaryIssueType`: no mobile viewport, plain HTTP, broken links, dated footer, heavy images, no enquiry form…).

#### SEO agencies

- **Quick technical website audit** across many homepages at once: missing title or meta description, missing Open Graph tags, broken internal links, HTTPS problems, mixed content, heavy images.
- **Spot quick-win prospects** whose sites have basic on-page gaps you can fix.
- It is a fast first-pass check, not a full SEO crawler (see Limitations).

#### Lead qualification and sales teams

- **Score web design leads** you already have (from your CRM, a licensed data source or your own research) so reps spend time on sites that clearly need work.
- **Audit your own client portfolio** for quick wins (old jQuery, missing meta descriptions, broken homepage links).
- **Re-check on a schedule** to see when a prospect's site changes.

### What the website audit checks (per site)

| Signal | How |
|---|---|
| Final URL, HTTPS works, certificate errors | Loads `https://` first, falls back to `http://`; reports certificate/TLS errors |
| `http://` forwards to `https://` | One extra request to the plain-http address |
| Mixed content | `http://` scripts/styles/images on an `https` page |
| Mobile viewport tag | `<meta name="viewport" content="width=device-width…">` |
| Copyright year in the footer | `© 2019`, `Copyright 2015–2019` etc. Script-generated years are recognised and not penalised |
| CMS / site builder + version | WordPress, Wix, Squarespace, Shopify, Webflow, Joomla, Drupal, GoDaddy, Weebly, Jimdo, Duda, BaseKit, Framer, Next.js, FrontPage, Dreamweaver templates… (version only when it is public in the markup) |
| jQuery and Bootstrap versions | From public script/style URLs and library banners |
| Legacy markup | Flash, frames, `<font>`/`<center>`, table layouts, HTML4 doctype, old-IE comments |
| HTML size and referenced resources | Size of the homepage HTML and the number of scripts/styles/images it references |
| Largest images | Top 3 by file size (HEAD `Content-Length`) |
| Title, meta description, Open Graph tags | Missing / empty |
| Broken internal links on the homepage | Up to 25 links checked (HEAD, GET fallback) |
| Contact / quote / booking form | Forms on the homepage and the linked contact page; Contact Form 7, WPForms, Gravity, HubSpot, JotForm, Typeform…; booking widgets such as Calendly, Acuity, Setmore, Fresha, OpenTable, ResDiary |
| Tap-to-call | Whether a `tel:` link exists (true/false only) |
| Placeholder text | "Lorem ipsum", "Just another WordPress site"… |

### How the outdated score works (0–100)

Each finding adds points, e.g. no mobile viewport +25, HTTPS certificate error +22, plain-http only +20, © year 5+ years old +15, Flash +15, broken homepage links up to +14, jQuery 1.x +10, Bootstrap 3 +8, old WordPress/Joomla/Drupal +8, 1 MB+ image +7, no enquiry form +6 … capped at 100. Every point comes with a `reasons[]` entry (code, points, plain-English detail), so you can see exactly why.

Rough guide from testing: **40+** = strong redesign prospect · **15–39** = fix-level issues worth a short email · **under 15** = modern site, skip.

### Outreach hooks for redesign prospects

One neutral, factual sentence built from the two strongest findings, e.g.

- "The footer still says © 2019 and the phone number isn't tap-to-call."
- "The "Kitchens" link opens a 404 page and the homepage has no meta description."
- "The secure (https) version of the site shows a browser warning."

It never uses scare words ("hacked", "insecure", "dangerous"), and each record also has `primaryIssueType` (e.g. `NOVIEWPORT`, `HTTP`, `BROKEN`, `DATED`, `HEAVY`, `NOFORM`, `NOTAPCALL`) and `primaryGapTag` (e.g. `site-no-viewport`) so you can segment your campaigns. **Check every hook yourself before you send it.** Sites change, and a quick look takes 20 seconds.

### How to check if websites are outdated (step by step)

1. Click **Try for free** / **Start** and paste your websites into **Domains or URLs** (bare domains or full URLs, one per line).
2. Keep the defaults, or set **Max pages per site** to 1 for homepage only.
3. Optionally set a **maximum cost per run** in the run options.
4. Run it, then sort the dataset by `outdatedScore` and export to CSV or Excel.

### Input example

```json
{
  "domains": ["example.co.uk", "https://www.another-example.com/"],
  "maxPagesPerSite": 2,
  "maxConcurrency": 5,
  "checkBrokenLinks": true,
  "checkImages": true
}
```

- `maxPagesPerSite`: 1 = homepage only; 2 (default) = + contact page; 3 = + one services/about/quote page.
- `minScore`: rows under this score get `belowMinScore: true`, so they're easy to filter out.

### Output example (one dataset item per site, abridged)

```json
{
  "domain": "www.example.co.uk",
  "finalUrl": "https://www.example.co.uk/",
  "status": "ok",
  "httpsOk": true,
  "httpRedirectsToHttps": true,
  "hasViewportMeta": false,
  "copyrightYear": null,
  "cms": "Adobe Dreamweaver template",
  "jqueryVersion": "1.10.2",
  "bootstrapVersion": null,
  "titleMissing": false,
  "metaDescriptionMissing": true,
  "ogTagsMissing": ["og:title", "og:description", "og:image"],
  "largestImages": [{ "url": "https://www.example.co.uk/images/home.jpg", "kb": 476 }],
  "brokenInternalLinks": [],
  "hasContactOrBookingForm": true,
  "hasTapToCall": false,
  "outdatedScore": 52,
  "reasons": [
    { "code": "no_viewport", "points": 25, "detail": "No <meta name=\"viewport\" content=\"width=device-width\"> tag", "issueType": "NOVIEWPORT", "gapTag": "site-no-viewport" },
    { "code": "old_jquery", "points": 10, "detail": "jQuery 1.10.2 (1.x line, no longer supported)", "issueType": "DATED", "gapTag": "site-old-jquery" }
  ],
  "outreachHook": "The site has no mobile viewport tag and it still loads jQuery 1.10.2.",
  "primaryIssueType": "NOVIEWPORT",
  "primaryGapTag": "site-no-viewport"
}
```

Other `status` values: `http_error` (the homepage returned 4xx/5xx; still analysed), `tls_error_only` (only the certificate error could be observed), `fetch_failed`, `skipped_robots_txt`, `invalid_input`.

### Pricing (pay per event)

| Event | Price | When it's charged |
|---|---|---|
| `site-analyzed` | **$0.015 per site** ($15 per 1,000 sites) | Once per website that was actually fetched and analysed (including sites whose homepage returned an error page or only a certificate warning, since those are still analysed) |

Not charged: invalid inputs, robots.txt skips, duplicate domains and sites that couldn't be reached. Set a maximum total charge per run in the run options; the actor stops when it's reached. Platform usage (compute) is included in the event price under Apify's pay-per-event model.

### Responsible use

- **You bring the list.** This actor doesn't discover businesses or scrape directories, maps or social networks.
- **No personal data.** It doesn't collect or output email addresses, phone numbers or people's names. Contact signals are true/false only (e.g. "a tap-to-call link exists"). Link text that looks like an email or phone number is dropped.
- **Polite by design.** It checks robots.txt before every request (user-agent token `RedesignSignalsBot`), identifies itself with a clear User-Agent, uses timeouts, never logs in, never submits forms, and only fetches the homepage plus at most 2 more pages per site. Link and image checks are lightweight `HEAD` requests with low per-site concurrency.
- **Not a security scanner.** It only reads what any visitor's browser sees. It doesn't probe paths, ports or logins.
- If you use the hooks in cold email, follow the law where your recipient is (e.g. PECR in the UK, CAN-SPAM in the US, CASL in Canada).

### Limitations

- It reads HTML over HTTP and doesn't run JavaScript, so content rendered only by scripts isn't seen. A form injected by a script may be missed, so `hasContactOrBookingForm: false` can be wrong on JavaScript-heavy sites. Check those by eye.
- It doesn't measure full page weight, load time or Core Web Vitals. Image sizes come from HEAD requests for homepage images only.
- A CMS version is reported only when the site exposes it publicly. Many don't, and that's fine.
- A missing © year isn't penalised. Only an old year is.
- Sites behind bot protection (e.g. Cloudflare challenge pages) may return `http_error` 403/503.
- The scores are heuristics for prioritising, not a quality verdict. The weights are ours and haven't been calibrated against campaign reply rates.
- Tested on 10 real UK small-business homepages before launch (the main issue matched a manual audit on 7 of 10). Treat hooks as drafts and check each one.

### FAQ

**Can it find web design leads for me?** No, on purpose. It qualifies a list you already have. Use your CRM, a licensed data source or your own research to build the list.

**How do I find outdated websites in my list?** Paste the list, run the actor, and sort by `outdatedScore`. Sites scoring 40+ usually show several clear problems (for example no mobile viewport plus an old © year or old jQuery).

**Is this a full website audit or SEO audit?** It's a fast homepage-level check of the most visible problems. It doesn't crawl whole sites, run JavaScript, or measure Core Web Vitals.

**Does it run Lighthouse / PageSpeed?** No. It reports HTML size and the largest homepage images instead, which is faster and cheaper per site.

**Does it collect emails or phone numbers?** No. It outputs no personal data; contact signals are true/false only.

**Can I run it on a schedule?** Yes. Save a task with your list and schedule it to spot sites that changed.

**Can I use it through the API or with Make, Zapier or n8n?** Yes, like any Apify actor: call it through the Apify API or Apify's integrations and read the dataset.

**How much does it cost?** $0.015 per analysed site ($15 per 1,000 sites). See Pricing above for what is and isn't charged.

# Actor input Schema

## `domains` (type: `array`):

Websites to audit, one per line. Bare domains (example.co.uk) or full URLs. Use your own lead list; this actor does not discover businesses.

## `startUrls` (type: `array`):

Same as Domains, in Apify request-list format (url entries only).

## `maxPagesPerSite` (type: `integer`):

1 = homepage only. 2 (default) = homepage + contact page (to look for an enquiry form). 3 = also one services/about/quote page.

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

Sites processed in parallel. Each site also uses up to 3-4 small parallel HEAD requests for link/image checks.

## `checkBrokenLinks` (type: `boolean`):

HEAD-checks the homepage's internal links (robots.txt respected) and reports any that return errors.

## `maxLinkChecks` (type: `integer`):

Upper limit on internal links checked per site (HEAD requests). 0 turns link checking off.

## `checkImages` (type: `boolean`):

HEAD-requests homepage images to find the largest files.

## `maxImageChecks` (type: `integer`):

Upper limit on homepage images measured per site (HEAD requests).

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

How long to wait for each page before giving up.

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

Sites scoring below this still appear in the dataset but get belowMinScore=true, so you can filter them out.

## `proxyConfiguration` (type: `object`):

Optional. Not needed for most small-business sites.

## Actor input object example

```json
{
  "domains": [
    "example.com"
  ],
  "maxPagesPerSite": 2,
  "maxConcurrency": 5,
  "checkBrokenLinks": true,
  "maxLinkChecks": 25,
  "checkImages": true,
  "maxImageChecks": 20,
  "requestTimeoutSecs": 15,
  "minScore": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "domains": [
        "example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("shanmukhkiransagar/website-redesign-signals").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 = { "domains": ["example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("shanmukhkiransagar/website-redesign-signals").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 '{
  "domains": [
    "example.com"
  ]
}' |
apify call shanmukhkiransagar/website-redesign-signals --silent --output-dataset

```

## MCP server setup

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

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/UPbmEIEzDMOOhu5oL/builds/WgOiokxrfsAFb7dhW/openapi.json
