# Website Sales Opportunity Brief — Agency Audit Report (`elfajad/website-sales-opportunity-brief`) Actor

Turn business websites into evidence-backed agency briefs: prioritized fixes, source links, public contact observations, and a printable HTML report. Bounded multi-page checks; blocked sites stay unknown. No AI key needed.

- **URL**: https://apify.com/elfajad/website-sales-opportunity-brief.md
- **Developed by:** [El Fajad](https://apify.com/elfajad) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3,000.00 / 1,000 website opportunity briefs

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 Sales Opportunity Brief

Turn a business website into an evidence-backed brief your agency can review with a prospect or client. Get **prioritized fixes, exact source URLs, public contact observations and a printable HTML report**, plus structured JSON for your CRM or AI workflow.

Designed for web agencies, freelance developers and account managers preparing a scoped improvement proposal. No AI API key, browser setup or external paid data provider is required.

### What you receive

- One report per usable website, covering up to 10 pages and 20 internal link destinations.
- Findings grouped by issue across pages, with evidence and a specific next action.
- Service categories such as conversion path repair, HTTPS implementation, mobile layout review, content structure and accessibility remediation.
- Public `mailto:` and `tel:` observations, booking links and contact-form counts.
- A clean HTML report: open **reportUrl**, then print or save as PDF in your browser.
- Explicit coverage and unknowns. A blocked or unreachable site is never labeled a bad lead.

The Actor does **not** discover businesses by location. Supply your own website list or URLs from another Actor. It does not send outreach or submit contact forms.

### Quick start

```json
{
  "websites": ["https://example.com"],
  "maxPages": 6,
  "maxLinks": 12,
  "reportLabel": "Website opportunity brief"
}
```

1. Replace the example with public websites relevant to your work.
2. Set a maximum run charge in Apify and start the Actor.
3. Open **Opportunity briefs** in the output. Follow **Open report** for the client-readable version.
4. Use **Evidence and actions** for implementation work and **Coverage and unknowns** to see what was not established.

`example.com` is a technical demonstration, not a customer endorsement or a real sales lead.

### Checks and interpretation

| Check | Evidence | Interpretation |
|---|---|---|
| Missing internal destination | HTTP 404 or 410 on a checked internal link | Candidate for link repair; verify before outreach |
| HTTP page | Final URL uses HTTP | Candidate for HTTPS implementation |
| Missing title or description | No non-empty tag in fetched HTML | Search-presentation review, not a ranking prediction |
| Missing mobile viewport | No non-empty viewport declaration | Inspect in a real mobile browser before claiming a layout defect |
| Images without alt attributes | Count of `img` elements without `alt` | Static accessibility observation; empty decorative alt is accepted |
| Missing main heading | No non-empty H1 in fetched HTML | Content/template review |
| Noindex or none directive | HTML or response-header directive | Review item: this may be intentional |

No arbitrary “lead quality” or “lost revenue” score is assigned. A missing WhatsApp link, booking provider or contact method is not proof that the business wants to buy one.

### Inputs

| Field | Default | Limits |
|---|---|---|
| `websites` | Required | 1–10 public HTTP(S) URLs; exact duplicates are removed |
| `maxPages` | 6 | 1–10, including homepage; additional pages come from homepage links |
| `maxLinks` | 12 | 0–20 same-origin destinations; contact/service links are prioritized |
| `reportLabel` | Website opportunity brief | Up to 80 characters |

Queries are not followed during link discovery. Homepage redirects may change the audited origin; subsequent navigation stays on that origin. Inputs with credentials, nonstandard ports, private/reserved IP addresses or unsupported schemes are rejected.

### Outputs

The default dataset contains one usable report per website: `website`, `finalUrl`, `createdAt`, `status`, `pagesAudited`, `linksChecked`, `findingCount`, `priorityCounts`, `summary`, `findings`, `recommendedServices`, `contacts`, `observedFeatures`, `pages`, `linkChecks`, `unavailable`, `coverage`, `reportUrl` and `reportKey`.

Each finding includes `priority`, `service`, `recommendation` and an `evidence` array of source URLs and observations. `complete` describes completion of the bounded checks, not a guarantee of whole-site coverage or correctness. `partial` means useful evidence was obtained but some checks were unavailable.

Key-value records:

- `brief-<hash>.html`: printable report per usable website.
- `RUN-SUMMARY`: delivered count, prior results, budget stop and unavailable targets.
- `UNAVAILABLE`: websites without usable reports, including reasons. These are not paid dataset rows.

Apify storage retention applies. Download important reports before they expire.

### Pricing

Launch pricing is **$3 per delivered website brief**, using the `website-brief` pay-per-event event, plus **$0.00005 per Actor start** at the supported memory sizes. Platform usage is included; there is no separate dataset-item charge. The **Pricing tab is authoritative**.

A report covers the selected page/link caps. A partial report is billable when at least one page has usable static HTML and the report is saved. A usable report with no findings is still a completed report. Unavailable websites, robots refusals, bot challenges and invalid input do not trigger a report event. The code checks the remaining event budget before each website and stops at the cap. The minimum run spending limit is $3.01. This is a spending cap, not a minimum charge: an unavailable site triggers no report event, but the startup event still applies.

Report-event examples: 1 report = $3; 5 reports = $15; 10 reports = $30. No paid enrichment API is used.

### Limits

This MVP reads **static HTML**. It does not render JavaScript, measure Core Web Vitals, test mobile layout visually, execute a booking, validate a contact form or certify accessibility/legal compliance. Thin HTML shells and recognizable challenge pages are recorded as unavailable. Some partially rendered pages may still contain incomplete HTML; verify findings in a normal browser.

HTTP 401/403/429, server errors and network failures stay unknown. Only observed 404/410 internal destinations are reported as missing. The Actor respects robots.txt, keeps requests sequential, bounds each site to 80 requests / approximately 150 seconds, caps response bodies at 2 MiB, and rejects private network targets at every redirect. It does not bypass access controls.

All findings require human review before a proposal. Website weaknesses do not establish willingness to purchase, lost sales, or a specific project budget.

### API and AI agents

Run through Apify's API or the official client. After public publication, discover it through the Apify MCP server by its Actor name `elfajad/website-sales-opportunity-brief`. Input, output and dataset schemas are included so tools can inspect the result structure.

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('elfajad/website-sales-opportunity-brief').call({
  websites: ['https://example.com'], maxPages: 6, maxLinks: 12
}, { maxTotalChargeUsd: 3.01 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

### Development and support

Node.js 22+, Apify SDK (Apache-2.0), Cheerio (MIT), ipaddr.js (MIT), robots-parser (MIT). Dependencies are pinned in `package-lock.json`. No VPS is needed.

```sh
npm ci
npm test
npm run sample -- https://example.com
```

Use the Actor's Issues tab for reproducible problems. Include the run ID and the observed issue, without secrets or private data.

# Actor input Schema

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

1–10 public HTTP(S) website URLs. Exact duplicate URLs are audited once. Start with the example, then replace it with business sites relevant to your work.

## `maxPages` (type: `integer`):

Homepage plus same-origin pages linked from it; prioritizes contact, service and pricing pages. This is a coverage cap, not a whole-site crawl.

## `maxLinks` (type: `integer`):

Check up to this many internal destinations, prioritizing contact and service links. 404/410 are reported as missing; refusals and errors remain unknown.

## `reportLabel` (type: `string`):

Optional heading for the printable report.

## Actor input object example

```json
{
  "websites": [
    "https://example.com"
  ],
  "maxPages": 6,
  "maxLinks": 12,
  "reportLabel": "Website opportunity brief"
}
```

# Actor output Schema

## `briefs` (type: `string`):

One structured record per usable report, with evidence, actions, coverage and an HTML report URL.

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

Delivery counts, budget stop and unbillable unavailable targets.

## `unavailable` (type: `string`):

Sites that did not produce a usable report, with reasons. These do not trigger a report event.

# 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 = {
    "websites": [
        "https://example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("elfajad/website-sales-opportunity-brief").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 = { "websites": ["https://example.com"] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,elfajad/website-sales-opportunity-brief"
        }
    }
}
```

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/Qi51Q2wECiLARFQDE/builds/t7CKWfl6y4w19tp70/openapi.json
