# AEO Visibility Audit (`swholmes/aeo-visibility-audit`) Actor

AEO Visibility.   $0.06/check.  Real Google AI Overview, exact sources AI cites, ranked action plan. MCP-ready.

- **URL**: https://apify.com/swholmes/aeo-visibility-audit.md
- **Developed by:** [Scott Holmes](https://apify.com/swholmes) (community)
- **Categories:** SEO tools, AI, MCP servers
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $60.00 / 1,000 llm visibility checks

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## AEO Visibility Audit — does AI actually recommend your business?

**Find out whether ChatGPT, Perplexity, and Google's AI recommend your business — or your competitors — then get the exact sources you need to fix it.**

Drop in one URL. This Actor figures out your brand and what you do, generates real buyer-intent questions for your city, asks them across the major AI answer engines, and returns a single structured JSON: your visibility score, who's getting recommended instead of you, the **real Google AI Overview**, the exact pages AI cites, and a prioritized action plan. Built for SEO/GEO agencies, local businesses, and anyone selling AEO services.

***

### Why this one is different

Most "AI visibility" Actors send a prompt to a model and count mentions. This one adds the three things those tools leave out:

1. **The REAL Google AI Overview.** We pull the actual AI Overview from the live Google SERP (DataForSEO `load_async_ai_overview`) plus the local pack. Almost every competitor *fakes* this by querying the Gemini model and calling it "Google AI" — and several say so in their own docs. If the buyer's customers see a Google AI Overview, you should measure the real thing.
2. **Real AI search volume (opt-in).** Enable `includeAiSearchVolume` and each tracked prompt is enriched with DataForSEO AI Keyword Data — actual LLM prompt demand, not a made-up estimate. Straight talk on coverage: this is genuinely useful for national and brand-level prompts, but hyperlocal city-level phrasing mostly has no measured demand yet — in one 12-keyword Toronto sample, only one returned a volume. We return `null` rather than inventing a number, and it's **off by default** so you don't pay for empty fields on a local audit.
3. **Brand → citation attribution.** Not just "Competitor X was mentioned" and "these domains were cited" as two separate lists — we connect them: *"Competitor X was named, and that mention was attributed to clutch.co and semrush.com."* That's the causal map that tells you exactly which placement to go earn.

Plus: **location-specific prompts** (down to the city), a **ranked action plan** that names the competitor brands behind each source, and a **shared cache** that auto-refreshes on the 1st and 15th of each month so repeat lookups of the same URL are near-free.

***

### Us vs. the other guys

| | **AEO Visibility Audit (this Actor)** | LLM Visibility Tracker (khadinakbar) | LLM Visibility Monitor (constructive\_calm) |
|---|---|---|---|
| Engines | ChatGPT, Perplexity, Google/Gemini | ChatGPT, Claude, Perplexity, Gemini | + Claude, Grok |
| **Real Google AI Overview (live SERP)** | ✅ Yes — actual AI Overview + local pack | ❌ Gemini model as proxy | ❌ Gemini model as proxy |
| **Real AI search volume per prompt** | ✅ Opt-in (DataForSEO AI Keyword Data) | ❌ | ❌ |
| **Never billed for a check that didn't search** | ✅ | ❌ | ❌ |
| **Brand → source attribution** | ✅ Yes — which sources produced each competitor mention | ❌ (cited domains only) | ❌ (share-of-voice only) |
| Auto-generated local buyer-intent prompts | ✅ City-level | ⚠️ Generic | ✅ Category-level |
| Ranked action plan (names competitor brands) | ✅ | ❌ | ⚠️ Gaps list |
| Shared cache + scheduled refresh | ✅ 1st & 15th, repeat ≈ free | ❌ | ❌ |
| Output | One clean structured JSON | Per-result rows | Dataset + report files |
| **Pricing (12-prompt audit)** | **$0.72 Quick · $2.65 Standard** | ~$4.32 | ~$6.90 (Quick preset $3.76) |
| Per-check price (metered) | **$0.06** | $0.09 | $0.15 + $1.50 fixed fees |

**Reading the price right:** competitors quote a *per-check* rate (e.g. "$150 / 1,000" = **$0.15 for one prompt to one engine**). A real audit is dozens of checks, so their full audits land at **$3.76–$13.51** (their own published presets). We're the cheapest per check *and* bundle the real AI Overview and brand→source attribution they don't.

***

### Two ways to pay

**Mode 1 — Preset (one URL = one predictable price).** Every preset is just a fixed number of billable checks, so the price is exact, not an estimate:

| Preset | What runs | Price |
|---|---|---|
| **Quick** *(default)* | 4 prompts × 3 engines, fast models, no AI Overview | **$0.72** |
| **Standard** | 12 prompts × 3 engines + real AI Overview + attribution | **$2.65** |
| **Deep** | 20 prompts × 3 engines, premium models + AI Overview | **$4.09** |

**Mode 2 — Metered (pay per check).** Set `preset: "custom"` and only pay for what you ask for — ideal for power users and big or tiny audits:

| Event | Price |
|---|---|
| Audit started | $0.00005 |
| LLM visibility check (1 prompt × 1 engine) | $0.06 |
| Real Google AI Overview module (per run) | $0.49 |
| Brand → source attribution | Included free |

**You are never charged for a check that didn't search the web.** If an engine answers from training data instead of running a live search, that check returns no citations — so we don't bill it. The count surfaces as `summary.checks_without_web_search`.

Cache hits incur only the start charge — no LLM cost for a repeat lookup inside the refresh window.

***

### Input

| Field | Description |
|---|---|
| `url` *(required)* | Homepage to audit. Brand + industry are auto-detected. |
| `preset` | `quick` (default), `standard`, `deep`, or `custom` (metered). |
| `city`, `province`, `country` | Localizes the generated prompts and the AI Overview SERP. |
| `engines` | Any of `chat_gpt`, `perplexity`, `gemini`. |
| `maxPrompts` | Prompts per engine (custom mode; presets set this). |
| `includeAiOverview` / `serpMaxKeywords` | Real Google AI Overview module (custom mode). |
| `includeAiSearchVolume` | Real LLM prompt-demand lookup (default **off** — see note below). |
| `fastModels` | Custom mode: use cheaper mini models. |
| `cache` / `forceRefresh` | Shared cache with 1st/15th auto-refresh. |
| `dataforseoLogin` / `dataforseoPassword` | Your DataForSEO credentials (owner-configured as Actor secrets for bundled runs). |

### Output (single structured JSON)

```json
{
  "business": { "url": "...", "brand": "Flying Pigs Marketing", "descriptor": "marketing agency", "city": "Barrie" },
  "summary": { "prompts_run": 12, "engine_runs": 36, "mentioned": 3, "visibility_pct": 8,
               "ai_overview_appeared": 6, "ai_overview_you_cited": 0,
               "checks_without_web_search": 1, "dataforseo_cost_usd": 1.55 },
  "coverage": { "preset": "standard", "model_tier": "standard",
                "engines_checked": ["chatgpt", "perplexity", "google_ai"], "engines_not_checked": [],
                "ai_overview": "checked (6 keywords)",
                "ai_search_volume": "not run — includeAiSearchVolume was false",
                "citation_graph": "full", "upgrade": null },
  "by_engine": [ { "engine": "chatgpt", "model": "gpt-4o", "visibility_pct": 8 } ],
  "you_vs_them": { "yours": 2, "others": 71, "yours_pct": 3 },
  "google_ai_overview": { "source": "Google SERP ai_overview (real)", "appeared": 6, "you_cited": 0, "results": [ ] },
  "prompts": [ { "text": "best marketing agency in Barrie", "ai_search_volume": 210, "visibility_pct": 0,
                 "engines": [ { "engine": "chatgpt", "mentioned": false, "citations": ["clutch.co"],
                                "named_brands": [ { "brand": "Tactycs", "sources": ["tactycs.io"] } ] } ] } ],
  "top_sources": [ { "domain": "clutch.co", "times_cited": 9 } ],
  "competitor_attribution": [ { "brand": "Tactycs", "times_named": 5,
                               "attributed_sources": [ { "domain": "clutch.co", "count": 4 } ] } ],
  "action_plan": [ { "priority": 5, "title": "Earn placement / get cited on clutch.co",
                     "type": "directory", "competitors_present": ["Tactycs", "Thrive"] } ]
}
```

### Methodology & honesty

LLM rows come from the engine **APIs** with live web search — a repeatable, labeled proxy that differs from a logged-in consumer app and is non-deterministic between runs. The `google_ai_overview` block is the **real** Google AI Overview scraped from the SERP. Every result is labeled by engine and model so you always know what produced it. This is a directional visibility audit for benchmarking and prioritization — not a traffic-analytics measurement.

***

*Built by Scott Holmes — Pinnacle Tech Projects, Barrie, ON.*

# Actor input Schema

## `url` (type: `string`):

Homepage to audit

## `preset` (type: `string`):

Pick a fixed-price bundle, or 'custom' to bill per check (metered mode) using the fields below.

## `city` (type: `string`):

City the business serves. Used to localize the generated buyer-intent prompts and the AI Overview SERP.

## `province` (type: `string`):

Province or state (abbreviation is fine, e.g. ON). Used to localize prompts and SERP results.

## `country` (type: `string`):

Country used for the AI search-volume lookup and SERP location.

## `brand` (type: `string`):

Blank = auto-detect from og:site\_name

## `industry` (type: `string`):

Optional: force the business category used to build prompts (e.g. 'AI receptionist service', 'roofing company'). Blank = auto-detect.

## `engines` (type: `array`):

Which AI answer engines to query: ChatGPT, Perplexity, and/or Google (Gemini).

## `maxPrompts` (type: `integer`):

Maximum number of prompts per engine (custom mode; presets set this automatically).

## `includeAiOverview` (type: `boolean`):

Runs DataForSEO SERP with load\_async\_ai\_overview for the true AI Overview + local pack

## `serpMaxKeywords` (type: `integer`):

How many top buyer-intent keywords to check for the real Google AI Overview.

## `serpLocation` (type: `string`):

e.g. "Barrie,Ontario,Canada". Overrides city/province/country if set.

## `cache` (type: `boolean`):

Reuse a stored result for the same URL; auto-refreshes after the 1st and 15th of each month

## `forceRefresh` (type: `boolean`):

Ignore the cache and run a fresh audit even if a cached result exists.

## `dataforseoLogin` (type: `string`):

Optional bring-your-own-key: your DataForSEO account email. Leave blank to use the Actor's bundled credentials.

## `dataforseoPassword` (type: `string`):

Optional bring-your-own-key: your DataForSEO account password (or API password).

## `includeAiSearchVolume` (type: `boolean`):

Look up real LLM prompt-demand volume (DataForSEO AI Keyword Data) for each tracked prompt. Most useful for national or brand-level audits — hyperlocal city-level prompts usually return no data (measured: 1 of 12 Toronto keywords had any volume).

## `fastModels` (type: `boolean`):

Custom mode only: use gpt-4o-mini etc. ~3x cheaper, but cites noticeably fewer third-party sources — fast models tend to cite businesses' own sites rather than the directories and review sites your action plan targets. Fine for a mention yes/no; use standard models for the full citation graph. Presets set this automatically.

## Actor input object example

```json
{
  "url": "https://example.com",
  "preset": "quick",
  "city": "Toronto",
  "province": "ON",
  "country": "Canada",
  "engines": [
    "chat_gpt",
    "perplexity",
    "gemini"
  ],
  "maxPrompts": 12,
  "includeAiOverview": true,
  "serpMaxKeywords": 6,
  "cache": true,
  "forceRefresh": false,
  "includeAiSearchVolume": false,
  "fastModels": false
}
```

# Actor output Schema

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

The full AI-visibility audit: visibility score, per-engine breakdown, you-vs-competitors, real Google AI Overview, brand detection, competitor-to-source attribution, and the ranked action plan.

## `report` (type: `string`):

The same audit object stored as the OUTPUT record in the default key-value store.

# 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 = {
    "url": "https://example.com",
    "city": "Toronto",
    "province": "ON"
};

// Run the Actor and wait for it to finish
const run = await client.actor("swholmes/aeo-visibility-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 = {
    "url": "https://example.com",
    "city": "Toronto",
    "province": "ON",
}

# Run the Actor and wait for it to finish
run = client.actor("swholmes/aeo-visibility-audit").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "url": "https://example.com",
  "city": "Toronto",
  "province": "ON"
}' |
apify call swholmes/aeo-visibility-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=swholmes/aeo-visibility-audit",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dJgLpuZsgn18y6nRb/builds/75dPjzDLc7UicW0cD/openapi.json
