# Local SEO SMB Lead Gap Scorer (`rotvuvo/local-seo-smb-lead-gap-scorer`) Actor

Turn imported Google Maps or Google Places business rows into deterministic local SEO and SMB outreach gap scores.

- **URL**: https://apify.com/rotvuvo/local-seo-smb-lead-gap-scorer.md
- **Developed by:** [Wit Nomad](https://apify.com/rotvuvo) (community)
- **Categories:** Marketing, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.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/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 SMB Lead Gap Scorer

Turn imported Google Maps, Google Places, CSV, spreadsheet, dataset, or manual local-business rows into deterministic local SEO and SMB outreach gap scores.

This is an ingest-first Actor for agencies and operators that already have business rows from existing Google Maps/Places scrapers or manual research. It does not collect data itself. It normalizes the rows, dedupes likely duplicate businesses, classifies website presence from supplied URLs, and outputs a CRM-ready priority table.

### What it does

- Normalizes business name, category, address, city, phone, website, rating, review count, source URL, and Google Maps URL aliases.
- Dedupes by supplied place ID/CID/FID, canonical Google Maps URL, or normalized business identity.
- Classifies website status as `missing`, `weak_web_presence`, or `present` without fetching the website.
- Scores local SEO / web design / marketing outreach gaps from supplied fields only.
- Produces gap reasons, evidence snippets, a helpful outreach angle, a recommended offer, CRM fields, confidence, and warnings.

### Input

The MVP supports `items` mode only. Use rows from existing Google Maps/Places scrapers, Google Places exports, CSV/spreadsheet/manual research, or Apify datasets that you paste/import.

Common row fields:

- `businessName`, `business`, `name`, `title`, `company`, `companyName`, `placeName`
- `category`, `categoryName`, `primaryCategory`, `categories`, `types`
- `address`, `fullAddress`, `streetAddress`, `location`
- `city`, `suburb`, `locality`, `town`, `region`
- `phone`, `phoneNumber`, `contactPhone`, `internationalPhoneNumber`
- `website`, `websiteUrl`, `site`, `domain`
- `rating`, `stars`, `googleRating`
- `reviewCount`, `reviews`, `reviewsCount`, `userRatingsTotal`
- `googleMapsUrl`, `mapsUrl`, `googleBusinessProfileUrl`, `placeUrl`, `sourceUrl`, `sourceLink`, `url`
- `placeId`, `place_id`, `cid`, `fid`

If an email or social field is already present, the Actor can pass it through in `crmFields`. It does not discover new emails or social profiles.

### Output

Each dataset item includes:

- normalized business identity and contact fields;
- `websiteStatus`, `leadScore`, and `priority`;
- `gapReasons` such as `website_missing`, `weak_web_presence`, `low_review_count`, or `phone_missing`;
- input-grounded `evidenceSnippets`;
- `outreachAngle` and `recommendedOffer` written to stay helpful and evidence-led, not spammy or shaming;
- `crmFields` for downstream sales workflows;
- `confidence` and `warnings` for data quality review.

### Example use cases

- Prioritize local businesses that appear to need a starter website or clearer owned web presence.
- Sort Google Maps scraper output into CRM-ready agency outreach lists.
- Identify rows where review operations, GBP cleanup, or contact-data cleanup may be a helpful offer.
- Deprioritize stronger profiles with real websites, phone numbers, categories, addresses, high ratings, and meaningful review counts.

### Limits and safety notes

- This Actor does not scrape Google Maps.
- This Actor does not scrape Google Places.
- This Actor does not scrape websites, fetch URLs, crawl pages, or verify if a supplied site is live.
- This Actor does not discover emails.
- This Actor does not discover social profiles.
- This Actor does not scrape reviews or infer review recency.
- This Actor does not use AI/LLMs.
- This Actor does not guarantee buyer intent.
- This Actor does not guarantee lead validity.
- This Actor does not guarantee GBP truth.
- This Actor does not guarantee legal compliance.
- This Actor does not guarantee SEO ranking impact.
- This Actor does not guarantee outreach deliverability.
- Outreach should be helpful/evidence-led and not spammy or shaming. Validate the business context before contacting anyone.

### Local development

```bash
npm install
npm test
apify validate-schema
````

To run locally without Apify storage, save input as `input.json` and run:

```bash
node src/main.js --input input.json --output output.json
```

# Actor input Schema

## `mode` (type: `string`):

Input mode. This version supports pasted/imported Google Maps, Google Places, CSV/spreadsheet, or manual SMB business rows only.

## `items` (type: `array`):

Rows from existing Google Maps/Google Places scrapers, CSV/spreadsheet exports, datasets, or manual research. Common fields: businessName/name/title, category/categoryName, address/fullAddress, city/locality, phone/phoneNumber, website/websiteUrl, rating/googleRating, reviewCount/userRatingsTotal, googleMapsUrl/mapsUrl, placeId/cid.

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

Maximum input business rows to process.

## `scrapedAt` (type: `string`):

Optional ISO timestamp for deterministic output metadata. This Actor does not scrape; when omitted or invalid, the runtime uses this fixed default reference timestamp.

## Actor input object example

```json
{
  "mode": "items",
  "items": [
    {
      "businessName": "Bright Smile Dental",
      "category": "Dentist",
      "address": "123 Main St",
      "city": "Austin",
      "phone": "+1 512 555 0100",
      "rating": 4.7,
      "reviewCount": 34,
      "googleMapsUrl": "https://www.google.com/maps/place/Bright+Smile+Dental"
    },
    {
      "title": "Oak Street Bakery",
      "categoryName": "Bakery",
      "city": "Portland",
      "contactPhone": "+1 503 555 0111",
      "websiteUrl": "https://oakstreetbakery.business.site",
      "rating": 4.6,
      "reviews": 18,
      "mapsUrl": "https://www.google.com/maps/place/Oak+Street+Bakery"
    },
    {
      "name": "Cedar Family Dentistry",
      "primaryCategory": "Dentist",
      "streetAddress": "9 Cedar Ave",
      "locality": "Raleigh",
      "phoneNumber": "+1 919 555 0123",
      "website": "https://cedarfamilydentistry.com",
      "googleRating": "4.8",
      "userRatingsTotal": "184",
      "placeId": "sample-place-cedar-raleigh"
    }
  ],
  "maxItems": 500,
  "scrapedAt": "2026-07-08T00:00:00.000Z"
}
```

# 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 = {
    "mode": "items",
    "items": [
        {
            "businessName": "Bright Smile Dental",
            "category": "Dentist",
            "address": "123 Main St",
            "city": "Austin",
            "phone": "+1 512 555 0100",
            "rating": 4.7,
            "reviewCount": 34,
            "googleMapsUrl": "https://www.google.com/maps/place/Bright+Smile+Dental"
        },
        {
            "title": "Oak Street Bakery",
            "categoryName": "Bakery",
            "city": "Portland",
            "contactPhone": "+1 503 555 0111",
            "websiteUrl": "https://oakstreetbakery.business.site",
            "rating": 4.6,
            "reviews": 18,
            "mapsUrl": "https://www.google.com/maps/place/Oak+Street+Bakery"
        },
        {
            "name": "Cedar Family Dentistry",
            "primaryCategory": "Dentist",
            "streetAddress": "9 Cedar Ave",
            "locality": "Raleigh",
            "phoneNumber": "+1 919 555 0123",
            "website": "https://cedarfamilydentistry.com",
            "googleRating": "4.8",
            "userRatingsTotal": "184",
            "placeId": "sample-place-cedar-raleigh"
        }
    ],
    "scrapedAt": "2026-07-08T00:00:00.000Z"
};

// Run the Actor and wait for it to finish
const run = await client.actor("rotvuvo/local-seo-smb-lead-gap-scorer").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 = {
    "mode": "items",
    "items": [
        {
            "businessName": "Bright Smile Dental",
            "category": "Dentist",
            "address": "123 Main St",
            "city": "Austin",
            "phone": "+1 512 555 0100",
            "rating": 4.7,
            "reviewCount": 34,
            "googleMapsUrl": "https://www.google.com/maps/place/Bright+Smile+Dental",
        },
        {
            "title": "Oak Street Bakery",
            "categoryName": "Bakery",
            "city": "Portland",
            "contactPhone": "+1 503 555 0111",
            "websiteUrl": "https://oakstreetbakery.business.site",
            "rating": 4.6,
            "reviews": 18,
            "mapsUrl": "https://www.google.com/maps/place/Oak+Street+Bakery",
        },
        {
            "name": "Cedar Family Dentistry",
            "primaryCategory": "Dentist",
            "streetAddress": "9 Cedar Ave",
            "locality": "Raleigh",
            "phoneNumber": "+1 919 555 0123",
            "website": "https://cedarfamilydentistry.com",
            "googleRating": "4.8",
            "userRatingsTotal": "184",
            "placeId": "sample-place-cedar-raleigh",
        },
    ],
    "scrapedAt": "2026-07-08T00:00:00.000Z",
}

# Run the Actor and wait for it to finish
run = client.actor("rotvuvo/local-seo-smb-lead-gap-scorer").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 '{
  "mode": "items",
  "items": [
    {
      "businessName": "Bright Smile Dental",
      "category": "Dentist",
      "address": "123 Main St",
      "city": "Austin",
      "phone": "+1 512 555 0100",
      "rating": 4.7,
      "reviewCount": 34,
      "googleMapsUrl": "https://www.google.com/maps/place/Bright+Smile+Dental"
    },
    {
      "title": "Oak Street Bakery",
      "categoryName": "Bakery",
      "city": "Portland",
      "contactPhone": "+1 503 555 0111",
      "websiteUrl": "https://oakstreetbakery.business.site",
      "rating": 4.6,
      "reviews": 18,
      "mapsUrl": "https://www.google.com/maps/place/Oak+Street+Bakery"
    },
    {
      "name": "Cedar Family Dentistry",
      "primaryCategory": "Dentist",
      "streetAddress": "9 Cedar Ave",
      "locality": "Raleigh",
      "phoneNumber": "+1 919 555 0123",
      "website": "https://cedarfamilydentistry.com",
      "googleRating": "4.8",
      "userRatingsTotal": "184",
      "placeId": "sample-place-cedar-raleigh"
    }
  ],
  "scrapedAt": "2026-07-08T00:00:00.000Z"
}' |
apify call rotvuvo/local-seo-smb-lead-gap-scorer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=rotvuvo/local-seo-smb-lead-gap-scorer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Local SEO SMB Lead Gap Scorer",
        "description": "Turn imported Google Maps or Google Places business rows into deterministic local SEO and SMB outreach gap scores.",
        "version": "0.1",
        "x-build-id": "MwbndwpYy7v2HOQxP"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/rotvuvo~local-seo-smb-lead-gap-scorer/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-rotvuvo-local-seo-smb-lead-gap-scorer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/rotvuvo~local-seo-smb-lead-gap-scorer/runs": {
            "post": {
                "operationId": "runs-sync-rotvuvo-local-seo-smb-lead-gap-scorer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/rotvuvo~local-seo-smb-lead-gap-scorer/run-sync": {
            "post": {
                "operationId": "run-sync-rotvuvo-local-seo-smb-lead-gap-scorer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "items"
                ],
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "items"
                        ],
                        "type": "string",
                        "description": "Input mode. This version supports pasted/imported Google Maps, Google Places, CSV/spreadsheet, or manual SMB business rows only.",
                        "default": "items"
                    },
                    "items": {
                        "title": "Business rows",
                        "minItems": 1,
                        "type": "array",
                        "description": "Rows from existing Google Maps/Google Places scrapers, CSV/spreadsheet exports, datasets, or manual research. Common fields: businessName/name/title, category/categoryName, address/fullAddress, city/locality, phone/phoneNumber, website/websiteUrl, rating/googleRating, reviewCount/userRatingsTotal, googleMapsUrl/mapsUrl, placeId/cid.",
                        "items": {
                            "type": "object"
                        }
                    },
                    "maxItems": {
                        "title": "Maximum rows",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum input business rows to process.",
                        "default": 500
                    },
                    "scrapedAt": {
                        "title": "Reference timestamp",
                        "type": "string",
                        "description": "Optional ISO timestamp for deterministic output metadata. This Actor does not scrape; when omitted or invalid, the runtime uses this fixed default reference timestamp.",
                        "default": "2026-07-08T00:00:00.000Z"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
