# Local AI Visibility Tracker: ChatGPT, Perplexity & Maps (`zaiq/local-ai-visibility`) Actor

Track ChatGPT, Perplexity, Gemini, Claude and readable Google AI recommendations for your business and city. Get Maps matches, competitors, citations, review gaps, an HTML report and history. $0.10 per analysed answer plus model usage.

- **URL**: https://apify.com/zaiq/local-ai-visibility.md
- **Developed by:** [Zaiq](https://apify.com/zaiq) (community)
- **Categories:** AI, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $100.00 / 1,000 local ai answers

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

## Local AI Visibility Tracker: ChatGPT, Perplexity, Gemini, Claude & Maps

**Does AI recommend your business for your service in your city?** Get one row per answer: a plain verdict, recommended businesses in order, Google Maps identities, your position, competitors and cited sources. Open the included HTML report for share of voice, review gaps and changes since the last comparable run.

**$0.10 per analysed answer**, the same price on every Apify plan. Maps lookups and the report are included. Model usage for the answer and a separate entity-extraction step is billed to your account through Apify’s OpenRouter gateway. Failed, refused and unreadable answers have no answer-event charge.

**Smallest useful input:** a business name, city and one service. The prefill asks one question on Perplexity. Replace the example business name with yours. Add ChatGPT, Gemini, Claude or readable Google AI search answers when you want a broader comparison.

### What you get

| Field | What it holds |
|---|---|
| Verdict first | Recommended #2 or Not recommended, with the engine, question, recommended businesses, Maps ratings and review counts, and source names. |
| Recommendations | Every extracted recommended business in answer order, its exact supporting quote and a Maps match with confidence and reason. |
| Maps listings | Place ID, rating, review count, category, address, website and Maps URL when identity can be established in the requested city. Ambiguous or unmatched names remain visible. |
| Your business | Named anywhere, positively recommended, recommendation position, and whether that recommendation was verified to your exact Maps listing. |
| Competitors | Your supplied competitor names or the first local Maps results for each service/place query. These do not seed the AI answers. |
| Citations | Source URLs and domains grouped as review sites, directories, communities, business websites, known local news or unclassified sources. |
| SUMMARY and REPORT.html | Share of voice, recommendation rates by engine, question-by-question winners, source frequency, Maps rating/review gaps, prompt plan and coverage notes. |
| CHANGES and named history | Changes against the previous complete run with the same questions, settings and model versions. Failed or incomplete runs do not replace that baseline. |

### What people use it for

- **Local SEO reporting:** Show which businesses appear for local customer questions and where the target is absent.
- **Multi-location monitoring:** Schedule a run for each business location and use named stores to retain comparable results.
- **Competitor research:** Compare the businesses AI recommends with Maps ratings and review counts, with explicit identity confidence. Confidence scores are matching heuristics, not calibrated probabilities.
- **Citation research:** Identify directories, community discussions and local pages cited in the sampled answers, then inspect them for factual information gaps.

### How to use it

1. Enter the business name and city, or a precise Google Maps place URL. Replace the example business in the prefill.
2. Enter a service. Start with the Best service intent and one engine; expand only after checking the first report.
3. Open Local recommendations and REPORT.html. Inspect unresolved matches and free notes alongside the rates.
4. Copy generated questions from SUMMARY into Prompts to edit them. Add a named history store and schedule sequential runs to track changes.

### Input

| Field | Example | Notes |
|---|---|---|
| Business name and city | Example Dental; Example City | Or supply a precise Google Maps place URL. City evidence is required for a verified listing. |
| Services | \["dentist"] | Up to 10 service phrases. |
| Places | \["Downtown", "West End"] | Neighbourhoods within the city; empty uses the city. |
| Intents | best, emergency, problem, budget, open-now | Choose relevant intents. The problem intent needs Problems, such as a leaking pipe. |
| Competitors | \["Example Dental Two"] | Optional. Empty discovers the first local Maps results for the service and place. |
| Business aliases | \["Example Dental Clinic"] | Exact alternate names, not generic service words. |
| Engines | One or more engines from the form | ChatGPT/OpenAI API, Perplexity, Gemini, Claude, Google AI Overview or Google AI Mode when readable. |
| Country and language | US; en | Approximate search context and answer language. Not GPS coordinates. |
| Prompts | \["best dentist in Example City"] | Replaces generated templates. Up to 100. Extra prompts are appended. |
| Maximum answers | 1 for a first check | Up to 100 question × engine combinations, in prompt order then engine order. |
| Named history store | example-local-visibility | A store name using letters, digits and hyphens. Use sequential schedules. |
| Model IDs | Optional | Default: newest supported family release from the gateway catalog. Pin IDs for stable comparisons. |

### Output

Each result is one row in the run's dataset (download it as JSON, CSV, Excel, XML or HTML, or read it through the API). An example row (values shortened):

```json
{
  "verdict": "Recommended #1 · Engine 1 · best plumber in Example City · recommended: Example Plumbing 1 (4.7★, 1,720 reviews), Example Plumbing 2 (4.7★, 2,929 reviews), Example Plumbing 3 (4.8★, 2,609 reviews), Example Plumbing 4 (4.5★, 624 reviews), Example Plumbing 5 (4.9★, 1,232 reviews), Example Plumbing 6 (4.8★, 18,078 reviews) · cites Directory A, Community B",
  "engine": "engine-1",
  "prompt": "best plumber in Example City",
  "targetRecommended": true,
  "targetRank": 1,
  "targetVerifiedRecommended": true,
  "recommendations": [
    {
      "name": "Example Plumbing 1",
      "rank": 1,
      "mapsMatch": {
        "status": "matched",
        "confidence": 0.995,
        "reason": "Exact name and matching city; street address appears in the answer",
        "listing": {
          "placeId": "example-place-1",
          "rating": 4.7,
          "reviewsCount": 1720,
          "category": "Plumber",
          "address": "1 Example Street, Example City"
        }
      }
    },
    {
      "name": "Example Plumbing 2",
      "rank": 2,
      "mapsMatch": {
        "status": "matched",
        "confidence": 0.995,
        "reason": "Exact name and matching city; street address appears in the answer",
        "listing": {
          "placeId": "example-place-2",
          "rating": 4.7,
          "reviewsCount": 2929,
          "category": "Plumber",
          "address": "2 Example Street, Example City"
        }
      }
    }
  ],
  "citedDomains": [
    "directory.example",
    "community.example"
  ],
  "status": "ok",
  "dataMode": "fake-ai-live-maps"
}
```

This example comes from an executed free test on 26 October 2026 using simulated AI answers and live, signed-out Maps lookups. Business names, engine labels, cities, identifiers, addresses and cited site addresses were replaced; numeric Maps observations and match results are retained. It is not a measurement of actual AI recommendations. SUMMARY records the prompt plan, coverage, models, traffic and charges for each run.

### Pricing

- **$0.10 per analysed AI answer**, the same price on every Apify plan. One question on four engines can deliver four chargeable answers.
- Maps identity checks, automatic competitor discovery, SUMMARY, the HTML report and history are included in the answer price.
- The answering model and Gemini Flash entity-extraction step use Apify’s OpenRouter gateway. Their usage is billed separately to your account at the gateway’s applicable rates. No developer AI key or buyer-supplied AI key is required.
- Refused, empty, truncated, invalidly extracted or unavailable answers have no answer-event charge. An informative answer with no recommendation, or an answer citing no sources, can still be a successful analysed answer.
- Model usage may still be billed when a model call completes but the answer cannot be analysed. Unresolved individual Maps names are shown honestly alongside the delivered analysis.
- Apify’s **$0.00005 Actor start charge counts towards Maximum cost per run**.

What typical jobs cost at the list price:

| Job | Cost |
|---|---|
| One question, one successful engine | $0.10 + $0.00005 start + model usage |
| Five questions, four successful engines | $2.00 + $0.00005 start + model usage |
| One hundred analysed answers | $10.00 + $0.00005 start + model usage |
| No readable or analysable answers | $0 in answer events; the start charge and any completed model usage can still apply |

Maximum cost per run limits this Actor’s answer events and start charge. The next answer is checked before work begins. Separately billed gateway model usage is not included in that answer-event budget. Free notes explain work skipped at the limit. A restarted run skips already delivered result IDs without another answer event or model call for those rows.

### Tips

- Use the same questions, language, country and model IDs each week. The report refuses to calculate visibility deltas when those change.
- Use explicit prompts in your desired language. Generated intent templates are English; the answering model is asked to respond in the selected language.
- Read source pages before taking action. Frequency of citation is an observation, not evidence that a directory caused a recommendation or that your business is missing from it.
- Use a precise Maps URL for businesses with common names or several local branches. Address evidence in the answer can distinguish branches.
- Run each business separately. One report covers one target business and its city, with optional neighbourhoods.

### Use it through the API

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("zaiq/local-ai-visibility").call(run_input={"businessName": "Example Dental", "city": "Example City", "services": ["dentist"], "maxAnswers": 1})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row)
```

**JavaScript**

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('zaiq/local-ai-visibility').call({"businessName": "Example Dental", "city": "Example City", "services": ["dentist"], "maxAnswers": 1});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**HTTP (one call, results back)**

```bash
curl -X POST 'https://api.apify.com/v2/acts/zaiq~local-ai-visibility/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{"businessName": "Example Dental", "city": "Example City", "services": ["dentist"], "maxAnswers": 1}'
```

### Integrations and schedules

- **Schedules:** run it every hour, day or week from the Apify Console (Schedules) and keep a history of results.
- **Make, Zapier, n8n, Google Sheets, Slack, Airtable:** connect it through Apify's integrations, or send each finished run to a **webhook**.
- **Datasets:** results stay in the run's dataset; export them or read them by API whenever you need them.

### Use it with AI agents (MCP)

Add Apify's MCP server (`https://mcp.apify.com`) to Claude, ChatGPT, Cursor, VS Code or any MCP client. The agent can find this Actor and run it for you: ask it for "check which local businesses AI recommends for this service in this city, compare my business with those results, and show the cited sources". AI agents can also pay for runs directly through Apify's agentic payments.

### Limits

- This samples web-enabled API models, not signed-in consumer chat sessions. Consumer products can use different models, search behaviour, personalisation and locations.
- Google AI Overview requires an answer included in the SERP page. Google AI Mode often loads its answer asynchronously through a route the SERP proxy does not support; those attempts return free notes. No browser challenge is solved and no alternative paid data supplier is used.
- Maps reads public, signed-out results. Blocked, empty or incomplete calls try the next available cloud route: direct, datacenter, then fresh residential sessions. The final unreadable result is reported. No account is used.
- Up to 100 answer attempts, 25 extracted businesses per answer, three extra name searches per answer and 150 Maps requests per run. Each answer has a 180-second deadline. Candidate results are cached within the run. Unresolved names are retained with their reasons.
- Entity extraction uses AI, with quotes checked against the original answer and order derived from the text. Read the evidence for ambiguous recommendations, spelling differences and branches.
- Open-now, emergency availability and price claims are not verified booking availability or price quotes. Missing Maps city evidence prevents a verified match.
- Share of voice is each business’s appearances divided by all recommended-business appearances. Recommendation rate is the fraction of analysed answers recommending it. Free notes do not enter that denominator.
- History comparisons need a complete run with the same questions, models and settings. Overlapping runs can overwrite a named store’s latest pointer. An interruption during an undelivered model call may repeat separately billed model work after restart.

### FAQ

**Does it ask AI about my business by name?**

The generated customer questions ask about the service and location. The target and competitor lists are not added to the answering prompt. A separate extraction step identifies businesses in the returned answer. Your own explicit prompts are sent as written.

**Is a mention the same as a recommendation?**

No. Neutral mentions and advice against a business are separated from positive recommendations. Name-based recommendations and exact Maps identity verification are reported separately.

**Can I use only a Maps link?**

Yes, if it opens one unambiguous listing with a city. Otherwise the run gives a free note asking for a precise name and city. Services or explicit prompts are still needed.

**What happens when two businesses have the same name?**

The city, listing identity and any street-address evidence are checked. Multiple equally good branches remain ambiguous instead of being assigned the first Maps result.

**What does the source report recommend?**

It shows the sources cited in the sampled answers and suggests factual checks: listing accuracy, authentic reviews, relevant discussions and useful service/location information. It does not claim guaranteed ranking improvements.

**Can I compare weekly runs?**

Set a named history store and run the same configuration sequentially. A new model version or changed question set starts a non-comparable snapshot rather than showing a misleading delta.

**Does every engine use web search?**

Search behaviour depends on the model and provider. The Actor requests web-enabled answers; Gemini can return an answer without citations. That is recorded as zero-cite.

**What if the gateway is unavailable?**

The affected answers are free notes. Account eligibility for the gateway is controlled by Apify. The Actor does not fall back to a developer’s AI key.

### Related Actors from Zaiq

- [ai-answer-tracker](https://apify.com/zaiq/ai-answer-tracker): brand visibility across AI answers
- [google-maps-rank-grid](https://apify.com/zaiq/google-maps-rank-grid): Maps rankings across geographic points
- [google-maps-leads-scraper](https://apify.com/zaiq/google-maps-leads-scraper): public Maps business listing data

### Support

Questions, a site that changed, or a field you need? Open an issue on this Actor's **Issues** tab: we answer there, usually within a day.

***

Also found as: local AI visibility tracker, local GEO, AI recommendations for local businesses, local SEO AI tracker, AI share of voice by city, Maps and AI visibility, local business citation tracking.

# Actor input Schema

## `businessName` (type: `string`):

The local business to monitor. Give its name and city, or use its Google Maps URL. Names are matched conservatively.

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

City with region where useful, such as Austin, Texas. Required with a business name. A precise Maps link can supply the city.

## `googleMapsUrl` (type: `string`):

Optional precise place link. A single listing supplies the name and city when they are not entered.

## `services` (type: `array`):

What the business sells. Each service combines with the selected places and intent templates. Up to 10.

## `places` (type: `array`):

Optional neighbourhoods within the city, up to 10. The city is appended to keep neighbourhood names unambiguous. Empty uses the city.

## `intents` (type: `array`):

Templates for generated questions. Emergency and open-now intents should be used only for relevant services. Use Prompts to edit the wording.

## `problems` (type: `array`):

Problems for the problem intent, such as a leaking pipe. Required when that intent is selected. Up to 10.

## `competitors` (type: `array`):

Optional businesses to track alongside yours. When empty, use the top local Maps results for each service and place. Recommendations are extracted independently of this list.

## `businessAliases` (type: `array`):

Exact alternate names used for your business. Do not use generic service words. Up to 10.

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

API models with web search; these are not signed-in consumer app sessions. Google AI requires readable SERP-page answers; AI Mode may be unavailable and then produces free notes.

## `language` (type: `string`):

Language code for answers and Google pages, such as en, de or pt-BR. Generated templates are English; use explicit prompts for native-language phrasing.

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

Two-letter country code for approximate model search location, Maps and Google pages. It does not set GPS coordinates.

## `prompts` (type: `array`):

Optional exact customer questions. When present, these replace the services × places × intent templates. Generated questions are listed in SUMMARY for editing. Up to 100.

## `extraPrompts` (type: `array`):

Additional customer questions, appended to generated or explicit prompts. Up to 20.

## `historyStore` (type: `string`):

Optional key-value store name, using letters, digits and hyphens. Schedule runs sequentially with the same questions and models for comparable changes. Incomplete runs keep the previous complete baseline.

## `competitorsPerSearch` (type: `integer`):

Number of local Maps results to include as tracked competitors for each service/place query.

## `maxAnswers` (type: `integer`):

Maximum question × engine combinations to attempt, in prompt order then engine order. Failures are free. Model usage is billed separately.

## `maxAnswerTokens` (type: `integer`):

Answering-model output limit. The gateway supports up to 2048. Truncated or refused answers produce free notes.

## `openaiModel` (type: `string`):

Leave empty to select the newest model in the supported family from the gateway catalog. Set the same model for stable scheduled comparisons.

## `perplexityModel` (type: `string`):

Leave empty to select the newest model in the supported family from the gateway catalog. Set the same model for stable scheduled comparisons.

## `geminiModel` (type: `string`):

Leave empty to select the newest model in the supported family from the gateway catalog. Set the same model for stable scheduled comparisons.

## `claudeModel` (type: `string`):

Leave empty to select the newest model in the supported family from the gateway catalog. Set the same model for stable scheduled comparisons.

## Actor input object example

```json
{
  "businessName": "Example Dental",
  "city": "Austin, Texas",
  "services": [
    "dentist"
  ],
  "places": [],
  "intents": [
    "best"
  ],
  "problems": [],
  "competitors": [],
  "businessAliases": [],
  "engines": [
    "perplexity"
  ],
  "language": "en",
  "country": "US",
  "prompts": [],
  "extraPrompts": [],
  "competitorsPerSearch": 5,
  "maxAnswers": 1,
  "maxAnswerTokens": 1600
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset: the results.

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

What each input returned, and notes.

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

A one-page view of the results to open in a browser.

# 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 = {
    "businessName": "Example Dental",
    "city": "Austin, Texas",
    "services": [
        "dentist"
    ],
    "intents": [
        "best"
    ],
    "engines": [
        "perplexity"
    ],
    "language": "en",
    "country": "US",
    "maxAnswers": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("zaiq/local-ai-visibility").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 = {
    "businessName": "Example Dental",
    "city": "Austin, Texas",
    "services": ["dentist"],
    "intents": ["best"],
    "engines": ["perplexity"],
    "language": "en",
    "country": "US",
    "maxAnswers": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("zaiq/local-ai-visibility").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 '{
  "businessName": "Example Dental",
  "city": "Austin, Texas",
  "services": [
    "dentist"
  ],
  "intents": [
    "best"
  ],
  "engines": [
    "perplexity"
  ],
  "language": "en",
  "country": "US",
  "maxAnswers": 1
}' |
apify call zaiq/local-ai-visibility --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zaiq/local-ai-visibility"
        }
    }
}
```

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/wMG42oi6SOfPacBWI/builds/VNGdtMffegFq5Z3yd/openapi.json
