# Local SEO Analytics API (`listingsapi/local-seo-analytics-api`) Actor

Pull Google, Facebook and Bing performance for every business location, plus live listing coverage across 80 plus directories, duplicate listings and voice assistant presence.

- **URL**: https://apify.com/listingsapi/local-seo-analytics-api.md
- **Developed by:** [Local Business Listings Submission API](https://apify.com/listingsapi) (community)
- **Categories:**
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## Local SEO Analytics API

Pull Google, Facebook and Bing performance data for every business location you manage, plus live listing coverage, duplicate suppression status and voice assistant presence.

This Actor wraps the analytics and listing endpoints of the [Listings API](https://www.listingsapi.com). It answers the two questions a local SEO report has to answer: where are we listed, and what did those listings actually do.

### What this Actor does

**Performance**

- Google performance for a location: views, searches, direction requests, calls, website clicks
- Facebook performance for a location
- Bing performance for a location

**Listing coverage**

- Live listings for a location, so you can see which of the 80 plus directories are publishing your data
- Duplicate listings for a location, or every duplicate across the account in one run
- Voice assistant listings, covering the assistants your data reaches
- Mark a listing as a duplicate, or clear that flag

**Reference data**

- Sites included in your plan
- Subcategories and supported countries and states

Run one operation per location and the dataset becomes a per location report you can pivot in a sheet or load into a warehouse.

### Who this is for

- Agencies producing monthly local SEO reports across a client portfolio
- Multi location brands tracking map pack visibility store by store
- Anyone auditing citation coverage and cleaning up duplicate listings
- Teams feeding local performance into an internal dashboard instead of screenshotting a vendor UI

### What you need

A Listings API account and an API key. Create one at [listingsapi.com](https://www.listingsapi.com/pricing).

| Access level | Covers |
| --- | --- |
| Read | Every analytics, listing and reference operation |
| Write | `markAsDuplicate`, `markAsNotDuplicate` |

Publisher analytics need the matching profile connected and matched to the location. Google performance requires a connected Google account, Facebook performance a connected Facebook account. Use the [Create Google Listing API](https://apify.com/listingsapi/create-google-listing-api) Actor to link them and to check that nothing has dropped its connection.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `apiKey` | string | Yes | Your Listings API key. Stored as a secret. |
| `operation` | string | Yes | Which endpoint to call. See the operations table. |
| `pathParams` | object | No | Values for placeholders in the path, for example `{ "locationId": "123" }`. |
| `query` | object | No | Query string values such as `limit`, `after`, `startDate` or `endDate`. |
| `body` | object | No | JSON payload for the duplicate marking operations. |
| `paginate` | boolean | No | Keep requesting pages while `pageInfo.hasNextPage` is true. Default `false`. |
| `maxItems` | integer | No | Stop after this many dataset items. `0` means no limit. |

### Operations

| Operation | Method and path | Returns |
| --- | --- | --- |
| `allLocations` | `GET /locations` | Your locations, used to look up location IDs |
| `searchLocations` | `GET /locations/search` | Locations matching a search term |
| `locationsByIds` | `GET /locations-by-ids` | A specific set of locations |
| `locationsByStoreCodes` | `GET /locations-by-store-codes` | Locations matched on your own store codes |
| `googleAnalyticsOfLocation` | `GET /locations/{locationId}/google-analytics` | Google performance for a location |
| `facebookAnalyticsOfLocation` | `GET /locations/{locationId}/facebook-analytics` | Facebook performance for a location |
| `bingAnalyticsOfLocation` | `GET /locations/{locationId}/bing-analytics` | Bing performance for a location |
| `premiumListingsOfLocation` | `GET /locations/{locationId}/listings/premium` | Live listings and their status per site |
| `duplicateListingsOfLocation` | `GET /locations/{locationId}/listings/duplicates` | Duplicates found for one location |
| `allDuplicateListings` | `GET /locations/listings/duplicates` | Every duplicate across the account |
| `voiceAssistantsOfLocation` | `GET /locations/{locationId}/voice-assistants` | Voice assistant listings for a location |
| `markAsDuplicate` | `POST /locations/listings/mark-as-duplicate` | Flags a listing for suppression |
| `markAsNotDuplicate` | `POST /locations/listings/mark-as-not-duplicate` | Clears the duplicate flag |
| `planSites` | `GET /plan-sites` | Directories included in your plan |
| `subCategories` | `GET /sub-categories` | Category IDs used when creating locations |
| `countries` | `GET /countries` | Supported countries and states |

Field level detail is at [docs.listingsapi.com/docs/analytics](https://docs.listingsapi.com/docs/analytics) and [docs.listingsapi.com/docs/listings](https://docs.listingsapi.com/docs/listings).

### Examples

Google performance for one location over a date range:

```json
{
  "apiKey": "<your key>",
  "operation": "googleAnalyticsOfLocation",
  "pathParams": { "locationId": "123" },
  "query": { "startDate": "2026-08-01", "endDate": "2026-08-31" }
}
```

Check where a location is live across the citation network:

```json
{
  "apiKey": "<your key>",
  "operation": "premiumListingsOfLocation",
  "pathParams": { "locationId": "123" }
}
```

Audit every duplicate in the account in one run:

```json
{
  "apiKey": "<your key>",
  "operation": "allDuplicateListings",
  "query": { "limit": 50 },
  "paginate": true
}
```

Suppress a duplicate you have confirmed:

```json
{
  "apiKey": "<your key>",
  "operation": "markAsDuplicate",
  "body": {
    "input": {
      "locationId": "123",
      "listingId": "yelp-4471"
    }
  }
}
```

Confirm which directories your plan covers before you promise a client a number:

```json
{
  "apiKey": "<your key>",
  "operation": "planSites"
}
```

### Output

Each item becomes one dataset row. A Google performance row looks roughly like this:

```json
{
  "locationId": "123",
  "site": "GOOGLE",
  "periodStart": "2026-08-01",
  "periodEnd": "2026-08-31",
  "searchViews": 4821,
  "mapViews": 3117,
  "directionRequests": 288,
  "phoneCalls": 141,
  "websiteClicks": 402
}
```

A listing coverage row carries the site, the live URL, the publish status and the last sync time, which is what you need to compute a coverage percentage per location.

Exact fields follow the API response. Download the dataset as JSON, CSV, Excel or XML, or read it from the Apify API. The run also writes a `SUMMARY` record to the key value store.

### Running it on a schedule

Set a monthly schedule on the first of the month with `googleAnalyticsOfLocation` and a fixed date range to build a rolling performance history in one dataset. Run `allDuplicateListings` weekly and send the output to a webhook so new duplicates get triaged instead of accumulating.

For a portfolio, run one task per location using the same Actor with different `pathParams`, or chain runs from your own script using the Apify API.

### Rate limits and pagination

Requests go out one at a time. The Actor reads `pageInfo.hasNextPage` before fetching the next page, waits out a 429 using `retry_after_seconds`, and retries server errors with a backoff. Plan limits are 10 requests per minute on Launch and 50 on Growth. See [rate limits](https://docs.listingsapi.com/docs/rate-limits).

### Errors

A non success response stops the run and logs the status, the URL and the response body including the `correlation_id`. Codes are listed at [docs.listingsapi.com/docs/error-codes](https://docs.listingsapi.com/docs/error-codes).

If a publisher analytics call returns empty, the usual cause is that the profile is not connected rather than that traffic was zero. Run `connectedAccounts` in the [Create Google Listing API](https://apify.com/listingsapi/create-google-listing-api) Actor to confirm before you report a zero to a client.

### Cost

You pay Apify for platform usage of the run. Analytics and listing data are billed by your Listings API plan, which starts at 99 dollars a month with a 14 day trial.

### Related Actors

- [Create Google Listing API](https://apify.com/listingsapi/create-google-listing-api) for linking Google and Facebook profiles to your locations, which publisher analytics depend on
- [Local Business Listings Submission API](https://apify.com/listingsapi/local-business-listings-submission-api) for creating and syncing locations
- [Create Bulk GBP Listings API](https://apify.com/listingsapi/create-bulk-gbp-listings-api) for creating Google listings across hundreds of locations in one run
- [Local Business Reviews API](https://apify.com/listingsapi/local-business-reviews-api) for reading and replying to reviews
- [Local Business Posts API](https://apify.com/listingsapi/local-business-posts-api) for publishing to Google, Facebook, Instagram and X

### Links

- Documentation: [docs.listingsapi.com](https://docs.listingsapi.com/docs)
- Analytics endpoints: [docs.listingsapi.com/docs/analytics](https://docs.listingsapi.com/docs/analytics)
- Listing endpoints: [docs.listingsapi.com/docs/listings](https://docs.listingsapi.com/docs/listings)
- SDKs: [docs.listingsapi.com/sdks](https://docs.listingsapi.com/sdks)
- MCP server: [listingsapi.com/mcp](https://www.listingsapi.com/mcp)
- Support: support@listingsapi.com

# Actor input Schema

## `apiKey` (type: `string`):

Your Listings API key. Create one at https://listingsapi.com. Read access is enough for every analytics and listing report.

## `operation` (type: `string`):

Which analytics or listing health endpoint to call.

## `pathParams` (type: `object`):

Values for placeholders in the endpoint path, for example { "locationId": "123" }.

## `query` (type: `object`):

Query string values such as limit, after, startDate or endDate.

## `body` (type: `object`):

JSON payload for the duplicate marking operations.

## `paginate` (type: `boolean`):

Keep requesting pages while pageInfo.hasNextPage is true.

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

Stop after this many dataset items. Set 0 for no limit.

## Actor input object example

```json
{
  "operation": "googleAnalyticsOfLocation",
  "pathParams": {},
  "query": {},
  "body": {},
  "paginate": false,
  "maxItems": 0
}
```

# Actor output Schema

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

Every analytics record, listing, duplicate or location returned by the operation you ran.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("listingsapi/local-seo-analytics-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("listingsapi/local-seo-analytics-api").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 '{}' |
apify call listingsapi/local-seo-analytics-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,listingsapi/local-seo-analytics-api"
        }
    }
}

```

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/QNJ8qqyblXSUP7zhE/builds/vi2sPliaM1bx92kg4/openapi.json
