# Website Marketing Audit & Agency Prospect Finder (`danielmichalek/website-marketing-audit`) Actor

Audit any list of company websites for analytics, ad pixels, SEO basics, tech stack, social links and public contacts, then score them as agency prospects.

- **URL**: https://apify.com/danielmichalek/website-marketing-audit.md
- **Developed by:** [Daniel Michałek](https://apify.com/danielmichalek) (community)
- **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

## Website Marketing Audit & Agency Prospect Finder

Feed it a list of company websites and get back, for each one, a marketing audit an agency can act on: which analytics and advertising pixels are installed (or missing), whether tracking has a consent manager, how the homepage performs on SEO basics, which platform the site runs on, which social profiles are linked, and the public contact details from the homepage and the linked contact or imprint page. In prospect mode every site also receives a **prospect score** built from its marketing gaps, so the hottest leads for paid ads, analytics, SEO or conversion work are at the top of the list.

### What it does

- **Tracking stack**: GA4, Universal Analytics, GTM, Clarity, Hotjar; conversion pixels for Meta, Google Ads, TikTok, LinkedIn, Microsoft, Pinterest, Snap and X; chat and marketing tools (HubSpot, Intercom, Crisp, Tawk, Klaviyo, Mailchimp); consent manager detection.
- **SEO basics** with PASS / WARN / FAIL findings and a grade: HTTPS, title and meta description length, H1 count, mobile viewport, html lang, canonical, structured data, Open Graph, image alt coverage.
- **Tech stack** hints: WordPress, WooCommerce, Elementor, Shopify, Wix, Squarespace, Webflow, Next.js, Nuxt, React, HubSpot CMS, Magento, PrestaShop, IdoSell, Cloudflare, server headers.
- **Contacts and organization**: public e-mail addresses and phone numbers from the homepage and one linked contact / imprint / about page, plus name, telephone, e-mail and address from JSON-LD `Organization` / `LocalBusiness` markup when present.
- **Social profiles**: Facebook, Instagram, LinkedIn, TikTok, YouTube, X, Pinterest links found on the page.
- **Prospect score (0–100)** and tier (HOT ≥ 60, WARM ≥ 35, COLD): weighted gaps — no analytics 25, no ad pixel 20, weak SEO 15, trackers without consent 10, no call to action 10, no lead capture 10, no social 5, no HTTPS 5 — with `recommendedServices` filtered to the services you sell.
- **Report**: `REPORT` (Markdown) in the key-value store with prospects ranked by score, ready for a sales pipeline.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| domains | array of strings | required | Domains or URLs (max 2000). |
| prospectMode | boolean | true | Compute prospect score, tier, gaps and recommended services. |
| targetServices | array | all six | paid-ads, analytics, seo, conversion, tracking-compliance, social. |
| fetchContactPage | boolean | true | Follow one linked contact / imprint / about page for public contacts. |
| maxItems | integer | 200 | Hard cap on audited sites per run. |

### Output

One dataset item per site: `domain`, `finalUrl`, `httpStatus`, `title`, `language`, `organization` (from JSON-LD), `contacts` (emails, phones, contactPage, address), `social`, `tech`, `tracking` (analytics, adPixels, other, consentManager, hasAnalytics, hasAdPixel), `conversion` (ctas, forms, phone, email, chat, pricing, testimonials), `seo` (score, grade, findings) and `prospect` (score, tier, gaps, recommendedServices). Unreachable sites are returned with `ok: false` and `error`. The `prospects` view ranks sites by score. The key-value store contains `REPORT` and `OUTPUT`.

Example item (shortened):

```json
{
  "domain": "kowalski-bud.example",
  "tracking": { "hasAnalytics": false, "hasAdPixel": false, "consentManager": false },
  "seo": { "score": 45, "grade": "D" },
  "contacts": { "emails": ["biuro@kowalski-bud.example"], "phones": ["601 234 567"], "contactPage": "http://kowalski-bud.example/kontakt.html" },
  "prospect": { "score": 90, "tier": "HOT", "gaps": ["noAnalytics", "noAdPixel", "noCta", "weakSeo", "noSocial", "noHttps"], "recommendedServices": ["analytics", "paid-ads", "conversion", "seo", "social"] }
}
```

### Pricing and cost control

Pay per event: **Website audited** (`site-audited`) — one event per site that returned a response (unreachable sites are reported but not charged by the handler's charge-after-delivery rule when the dataset write fails). `maxItems` caps the number of sites per run; the contact page adds at most one extra request per site. 100 sites run in a few minutes at 256 MB.

### Limitations and fair use

- Homepage HTML as served; tags injected only by JavaScript after consent may be invisible, which is reported as a gap to verify.
- Contacts are limited to what the company publishes on its own website; no third-party enrichment, no personal data beyond public business contacts, no CAPTCHA solving or logins.
- Prospect scoring is a heuristic prioritization for agencies, not a verdict on the business.
- Respect local marketing laws (GDPR, telecommunications law in PL/DE) when contacting prospects.

### Example

Input: four websites. Output: four audited items — the content-heavy marketing sites score COLD with full tracking stacks, while a public institution site without analytics or pixels ranks as a HOT prospect for tracking and conversion work. See `examples/input.json` and `examples/output.json`.

### Use cases

- Agencies: qualify a list of local businesses (from a registry or a directory export) before cold outreach.
- Freelancers: pick the ten prospects with the biggest, most sellable gaps.
- Sales teams of SaaS tools: find sites without analytics, consent management or pixels.

# Actor input Schema

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

Domains or URLs of company websites to audit (max 2000 per run). One billable event per audited site.

## `prospectMode` (type: `boolean`):

Compute a prospect score (0-100) from marketing gaps: missing analytics, missing ad pixels, weak SEO, no CTA or lead capture, no consent manager, no social profiles.

## `targetServices` (type: `array`):

Only these services are listed under recommendedServices. Options: paid-ads, analytics, seo, conversion, tracking-compliance, social.

## `fetchContactPage` (type: `boolean`):

Follow one linked contact, imprint or about page per site to collect public e-mail addresses and phone numbers (one extra request).

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

Hard cap on audited sites (cost control).

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "hubspot.com"
  ],
  "prospectMode": true,
  "targetServices": [
    "paid-ads",
    "analytics",
    "seo",
    "conversion",
    "tracking-compliance",
    "social"
  ],
  "fetchContactPage": true,
  "maxItems": 200
}
```

# 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": [
        "apify.com",
        "hubspot.com"
    ],
    "maxItems": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("danielmichalek/website-marketing-audit").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": [
        "apify.com",
        "hubspot.com",
    ],
    "maxItems": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("danielmichalek/website-marketing-audit").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": [
    "apify.com",
    "hubspot.com"
  ],
  "maxItems": 200
}' |
apify call danielmichalek/website-marketing-audit --silent --output-dataset

```

## MCP server setup

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

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/uWoh3qV2FceV8Zrke/builds/emnTI4Z5qYbo8o8Bh/openapi.json
