# Google Maps Website Lead Scorer (`market_radar_tools/google-maps-website-lead-scorer`) Actor

Post-process Google Maps Scraper datasets and local business lists. Extract visible emails, phones and social links, score each lead, and output CRM/n8n-ready records with offers, sales angles and next actions.

- **URL**: https://apify.com/market\_radar\_tools/google-maps-website-lead-scorer.md
- **Developed by:** [Mathieu](https://apify.com/market_radar_tools) (community)
- **Categories:** Automation, Lead generation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.25 / 1,000 website lead records

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

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

## Google Maps Website Lead Scorer

**Turn Google Maps business datasets into enriched, prioritized lead records.**

More than an email finder. Extract visible contacts from business websites, then layer on commercial signals, priority scores, and CRM-ready notes. No AI. No API keys. No email sending.

> **Not a Google Maps scraper.** This Actor analyzes websites you already have, from a Google Maps Scraper run, a CSV export, or a direct URL list. It does not touch Google Maps itself.

---

### Quick start

Pick the scenario that matches your input and run the Actor. All three produce the same output format.

#### Scenario 1: I have a list of websites

Paste URLs directly. No scraper needed.

```json
{
  "urls": [
    "https://northside-plumbing.com",
    "https://brightdental.co.uk",
    "https://greenleaf-restaurant.com"
  ],
  "categoryHint": "plumber",
  "languageHint": "en"
}
````

**Key fields to check:** `public_emails_csv`, `public_phones_csv`, `lead_priority_score`, `workflow_action`

***

#### Scenario 2: I have business objects from a local business dataset

Pass objects that include a website field and optionally a name, category, or city. Field names are auto-detected. Items without a website URL produce a `skipped` record with `workflow_action: find_website` - never silently dropped.

```json
{
  "items": [
    {
      "business_name": "Northside Plumbing",
      "website": "https://northside-plumbing.com",
      "category": "plumber",
      "city": "Chicago"
    },
    {
      "title": "Bright Dental Studio",
      "url": "https://brightdental.co.uk"
    }
  ],
  "categoryHint": "plumber",
  "languageHint": "en"
}
```

**Key fields to check:** `workflow_action`, `lead_segment`, `sales_priority_label`, `recommended_offer`, `crm_note`

***

#### Scenario 3: I have an Apify dataset from Google Maps Scraper

Pass the dataset ID from any Google Maps Scraper run. Field names are auto-detected.

```json
{
  "datasetId": "YOUR_DATASET_ID_HERE",
  "maxItems": 200,
  "categoryHint": "restaurant",
  "languageHint": "en"
}
```

> **Running locally?** Set `APIFY_TOKEN` before running `python run_local.py`. On the Apify platform it is set automatically.
>
> **Custom field names?** If your dataset uses a non-standard field for the website URL (e.g. `homepage` instead of `website`), set `datasetWebsiteField: "homepage"`. Same for business name with `datasetNameField`.

**Key fields to check:** `workflow_action`, `lead_segment`, `outreach_ready`, `manual_review_recommended`

**After the run, start with `workflow_action`:** `send_to_crm` for ready leads, `manual_review` for uncertain records, `find_website` for missing websites, `enrich_later` for low-priority leads. Use `sales_priority_label` (`hot`/`warm`/`cold`/`invalid`) for colour-coding in Google Sheets.

See [EXAMPLE\_RUN\_LOCAL\_BUSINESS.md](docs/EXAMPLE_RUN_LOCAL_BUSINESS.md) for a full end-to-end walkthrough with a 100-plumber dataset.

***

### Contents

- [What this Actor does](#what-this-actor-does) · [What it does NOT do](#what-this-actor-does-not-do)
- [How this Actor is different](#how-this-actor-is-different) · [Recommended workflow](#recommended-workflow)
- [Who is this for](#who-is-this-for) · [Which fields should I use?](#which-fields-should-i-use)
- [Input](#input) · [Output](#output) · [Field reference](#field-reference)
- [Scoring model](#scoring-model) · [n8n / Make / Sheets](#use-with-n8n--make--google-sheets)
- [Best use cases](#best-use-cases) · [Limitations](#limitations) · [FAQ](#faq)
- [What happens when a site cannot be analyzed?](#what-happens-when-a-website-cannot-be-analyzed)
- [Local development](#local-development)
- **Full docs:** [OUTPUT\_SCHEMA](docs/OUTPUT_SCHEMA.md) · [SCORING\_MODEL](docs/SCORING_MODEL.md) · [FIRST\_RUN\_CHECKLIST](docs/FIRST_RUN_CHECKLIST.md) · [EXAMPLE\_RUN](docs/EXAMPLE_RUN_LOCAL_BUSINESS.md) · [NO\_CODE\_WORKFLOWS](docs/NO_CODE_WORKFLOWS.md)

***

### What this Actor does

You already have a list of local businesses, from a Google Maps Scraper run, a CSV export, or a direct URL list. This Actor fetches each business website (static HTML only), analyzes it for commercial signals, and returns a scored, enriched dataset ready for your CRM or no-code workflow.

This Actor extracts visible emails, phone numbers and social links from business websites, then scores and prioritizes each lead. Your team sees who to call first and what to say.

For each business you get:

**Contact extraction:**

- **Visible emails:** extracted from public HTML, deduplicated, CSV-ready
- **Phone numbers:** FR and international formats, CSV-ready
- **Social profile links:** Facebook, Instagram, LinkedIn, YouTube and more, CSV-ready
- **Primary contact method:** `phone`, `email`, `phone_and_email`, `contact_form`, or `none`
- **Website status:** reachable, unreachable, error, redirected
- **CMS detected:** WordPress, Wix, Squarespace, Shopify, and more

**Lead prioritization:**

- **Lead priority score (0-100):** who to contact first
- **Website quality score (0-100):** how complete and trustworthy the site is
- **Conversion leaks:** what is missing (no booking, no form, no phone, no HTTPS...)
- **Recommended offer:** the best service to pitch this business
- **Sales angle:** a ready-to-use conversation opener
- **CRM note:** pre-written, paste directly into HubSpot or Pipedrive
- **Next action:** what your SDR should do with this lead
- **CSV-compatible fields:** all array fields available as comma-separated strings

Every input item produces exactly one output record, including unreachable or broken sites.

***

### What this Actor does NOT do

- **Does not scrape Google Maps:** bring your own list from any scraper or CSV
- **Does not use AI or require any API key:** fully deterministic, no LLM calls
- **Does not send emails or contact businesses:** analysis only
- **Does not deep-crawl websites:** homepage analysis by default; one-hop contact page optional
- **Does not render JavaScript:** static HTML only (see [Limitations](#limitations))
- **Does not provide a full SEO audit:** commercial conversion signals only
- **Does not guarantee sales:** it surfaces opportunities, your team closes them

***

### How this Actor is different

The Apify Store has Google Maps scrapers, email finders, website checkers, and SEO audit tools. This Actor is different from all of those. It is a **commercial post-processor** designed to run after a Google Maps Scraper and before your CRM or outreach workflow.

| Alternative | What it gives you | What this Actor adds |
|---|---|---|
| **Google Maps Scraper** | Business names, addresses, reviews, phones from Maps | Fetches each website, extracts contacts, detects gaps, and scores the commercial opportunity |
| **Email finder** | Email addresses from websites | Phones and social links too, plus `lead_priority_score`, `recommended_offer`, `sales_angle`, `crm_note`, `next_action` |
| **Website checker** | Site up/down, response time | Commercial readiness score, conversion leaks, CRM-ready next action for each site |
| **SEO audit tool** | Detailed technical SEO report (backlinks, keywords, Core Web Vitals) | Fast commercial qualification: who to contact first and what to pitch |
| **CRM enrichment tool** | Company data from third-party databases | Actual analysis of each business website, based on real HTML (not cached records) |

**Designed for outreach preparation, not automated outreach.** Use it after a Google Maps Scraper run. Extract visible contacts, then prioritize who to contact first. Built for agencies, automation freelancers, local SEO teams and growth teams. The output works with Google Sheets, n8n, Make, Airtable, HubSpot or Pipedrive. It does not guarantee sales. It helps you qualify leads faster.

**In practice:** an email finder returns a flat list of addresses. This Actor returns those contacts plus a commercial score, evidence for each signal, a pitch paragraph, and a paste-ready CRM note for every business in your list.

**What makes it different in practice:**

- **`evidence` field:** Every output record includes an evidence trace: which keyword triggered `booking_found`, which path detected the CMS, which button text triggered `cta_found`. You can verify every score claim without visiting the site manually.
- **`outreach_ready` flag:** Boolean shortcut. `true` when the site is reachable, has a visible contact method, and scores >= 60. Filter your n8n/Make workflow with one field check.
- **`manual_review_recommended` flag:** `true` for JS-heavy sites, 403 errors, or sites with no contact info. Automatically routes uncertain leads to a review queue instead of your SDR's inbox.
- **`categoryHint`:** Tell the Actor what type of business you are scoring. Restaurant, dentist, and plumber keywords are detected separately and appended to the sales angle. Scores stay objective; context becomes specific.
- **CRM-ready output:** `crm_note` is paste-ready. `next_action` is task-ready. CSV variants for every array field. No post-processing formulas needed.

***

### Recommended workflow

```
[Google Maps Scraper]             apify/google-maps-scraper (any variant)
          ↓
    output dataset
          ↓
[Google Maps Website Lead Scorer]     ← you are here
          ↓
[Google Sheets / Airtable / n8n / Make / HubSpot / Pipedrive / CSV]
```

**Step 1.** Run any Google Maps Scraper on Apify Store. Save the output dataset.\
**Step 2.** Pass the dataset ID (or a JSON export) to this Actor via the `datasetId` or `items` input.\
**Step 3.** Get back a scored, enriched, CRM-ready dataset in seconds.

***

### Who is this for

#### Web agencies

Find local businesses with outdated sites to pitch a redesign, landing page, booking system, or contact form. The lead priority score and recommended offer tell you exactly who to call and what to propose.

**Example:** You scrape 500 plumbers in Chicago. This Actor identifies the 87 with a reachable site but no booking flow, the top targets for a booking system pitch.

#### Automation freelancers

You sell n8n, Make, or Zapier setups for lead capture, appointment booking, or CRM integration. This Actor identifies businesses with no form, no booking, or no CRM-ready contact point.

**Example:** You scrape 200 dentists in Austin. This Actor surfaces the ones with no contact form and no booking. Your pitch: "I can add a patient booking form to your site in a day."

#### Local SEO agencies

Prioritize prospects with weak meta descriptions, no HTTPS, or incomplete contact pages. The conversion leaks field gives you a ranked list of what is missing for each business.

**Example:** You scrape 300 restaurants in Manchester. This Actor flags 40 with no meta description, no social links, and no CTA, your entry point for an SEO audit proposal.

#### Sales and growth teams

Enrich a list of business targets with a priority score and pre-written CRM notes before handing off to SDRs. The output drops directly into HubSpot or Pipedrive via CSV or Apify integration.

***

### Two ways to use this Actor

#### Way 1: Contact enrichment from business websites

You have a list of local businesses and you want their contact details in a clean, deduplicated CSV.

Run this Actor and export the output dataset as CSV. Use these fields:

| Field | What you get |
|---|---|
| `business_name` | Business name |
| `source_website` | Input URL |
| `website_status` | Whether the site is reachable |
| `public_emails_csv` | All visible emails, comma-separated |
| `public_phones_csv` | All visible phones, comma-separated |
| `social_links_csv` | Social profile URLs, comma-separated |
| `primary_contact_method` | `phone`, `email`, `phone_and_email`, `contact_form`, or `none` |
| `cms_detected` | WordPress, Wix, Shopify, etc. |
| `analysis_status` | `completed`, `partial`, `failed`, `skipped` |
| `data_quality_score` | 0-100 confidence score for this record |

This mode is useful when you just need a contact list from a batch of websites: no scoring, no pitching, just extraction.

#### Way 2: Sales prioritization and CRM-ready recommendations

You want to know not just who to contact, but who to contact **first** and what to say.

Add these fields to your workflow:

| Field | What you get |
|---|---|
| `lead_priority_score` | 0-100 opportunity score |
| `priority_level` | `very_high`, `high`, `medium`, `low` |
| `outreach_ready` | Boolean: safe to route to outreach immediately |
| `manual_review_recommended` | Boolean: route to review queue |
| `conversion_leaks` | What is missing on the site |
| `recommended_offer` | What to pitch this business |
| `sales_angle` | Ready-to-use pitch opening |
| `crm_note` | Pre-written CRM note |
| `next_action` | What your SDR should do next |
| `evidence` | Per-signal audit trail |

Both ways use the same Actor run and the same output dataset. You choose which fields to use.

#### Business-ready routing fields

Every record also includes four pre-computed routing fields that let you connect the output to your CRM or no-code workflow without building your own logic:

| Field | Values | Use for |
|---|---|---|
| `sales_priority_label` | `hot`, `warm`, `cold`, `invalid` | Colour-code rows; filter `hot` in Google Sheets or CRM |
| `lead_segment` | `ready_to_contact`, `review_first`, `low_priority`, `unreachable`, `missing_website` | Human-readable routing bucket for Switch nodes |
| `workflow_action` | `send_to_crm`, `manual_review`, `enrich_later`, `skip`, `find_website` | Single-field routing: replaces the `outreach_ready` + `manual_review_recommended` boolean chain |
| `crm_status` | `new_qualified`, `needs_review`, `not_ready`, `invalid_or_unreachable` | CRM import status label; use as pipeline stage or tag |

**Example:** in n8n, a single Switch node on `workflow_action` replaces two chained IF nodes and handles all five lead states.

***

### Which fields should I use?

| Goal | Fields to use |
|---|---|
| Extract contacts only | `public_emails_csv`, `public_phones_csv`, `social_links_csv`, `primary_contact_method` |
| Find the best leads | `lead_priority_score`, `priority_level`, `outreach_ready` |
| Avoid bad data | `data_quality_score`, `analysis_status`, `manual_review_recommended` |
| Understand why a lead is interesting | `conversion_leaks`, `evidence`, `score_reasons` |
| Prepare a CRM import | `crm_note`, `next_action`, `recommended_offer`, `crm_status` |
| Route leads in one node (n8n/Make) | `workflow_action`: 5 values, no boolean chain needed |
| Colour-code leads by priority | `sales_priority_label`: `hot`, `warm`, `cold`, `invalid` |
| Route or debug errors | `failure_category`, `failure_reason` |

***

### When to use this instead of a simple email finder

| If you want... | Use this Actor |
|---|---|
| Emails from a batch of local business websites | ✓ Extracts visible emails into `public_emails_csv` |
| Phone numbers as well as emails | ✓ Extracts visible phones into `public_phones_csv` |
| Social links alongside contact details | ✓ Detects Facebook, Instagram, LinkedIn, YouTube and more |
| A single CSV column per contact type | ✓ Every array field has a parallel `_csv` variant |
| To know which leads to call first | ✓ `lead_priority_score` and `priority_level` |
| To know what to pitch each lead | ✓ `recommended_offer`, `sales_angle`, `crm_note` |
| To avoid contacting leads with no real opportunity | ✓ `outreach_ready` and `manual_review_recommended` flags |
| To use the output in n8n / Make / Google Sheets | ✓ Flat JSON, CSV fields, no post-processing needed |

A simple email finder gives you a list. This Actor gives you a **prioritized, pitch-ready list**: emails, phones, social links, scores, notes, and next actions, all in one dataset.

***

### Input

At least one of `urls`, `items`, or `datasetId` is required.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `urls` | `string[]` | `[]` | Direct list of website URLs to analyze |
| `items` | `object[]` | `[]` | Business objects: auto-detects website and name fields |
| `datasetId` | `string` | `null` | Apify dataset ID from a Google Maps Scraper run |
| `datasetWebsiteField` | `string` | auto | Override field name for website URL in dataset |
| `datasetNameField` | `string` | auto | Override field name for business name in dataset |
| `maxItems` | `integer` | `100` | Maximum items to process |
| `concurrency` | `integer` | `10` | Concurrent HTTP requests |
| `timeoutPerItemSeconds` | `integer` | `20` | Per-site request timeout in seconds |
| `totalTimeoutSeconds` | `integer` | `300` | Approximate total run timeout |
| `languageHint` | `string` | `"en"` | Keyword language: `en` or `fr` |
| `countryHint` | `string` | `null` | ISO country code, e.g. `"FR"` for France |
| `categoryHint` | `string` | `"generic"` | Business category: `generic`, `restaurant`, `plumber`, `contractor`, `dentist`, `clinic`, `salon`, `agency` |
| `includeContactExtraction` | `boolean` | `true` | Extract visible emails and phone numbers |
| `includeSocialLinks` | `boolean` | `true` | Extract social media profile links |
| `includeContactPageCheck` | `boolean` | `false` | Follow one contact page link per site |
| `minLeadPriorityScore` | `integer` | `0` | Score threshold: items below are flagged, not dropped |

#### Input example: URL list

```json
{
  "urls": [
    "https://northside-plumbing.com",
    "https://brightdental.co.uk",
    "https://greenleaf-restaurant.com"
  ],
  "languageHint": "en",
  "maxItems": 100,
  "minLeadPriorityScore": 40
}
```

#### Input example: Google Maps dataset items

```json
{
  "items": [
    {
      "title": "Northside Plumbing",
      "website": "https://northside-plumbing.com",
      "phone": "+1 555 234 5678",
      "address": "Chicago, IL 60601"
    },
    {
      "businessName": "Bright Dental Studio",
      "businessWebsite": "https://brightdental.co.uk",
      "phoneNumber": "+44 207 123 4567"
    }
  ],
  "languageHint": "en",
  "includeContactPageCheck": true,
  "minLeadPriorityScore": 30
}
```

Field names are auto-detected. Supported variants: `website`, `url`, `website_url`, `businessWebsite`, `homepage`, `site`, `domain` for URLs; `name`, `title`, `business_name`, `businessName`, `company` for names.

#### Input example: dataset ID

```json
{
  "datasetId": "aBcDeFgHiJkL1234",
  "maxItems": 500,
  "concurrency": 15,
  "languageHint": "en"
}
```

Pass the dataset ID from any Google Maps Scraper run. The Actor reads items directly from the dataset without downloading the full export.

***

### Output

Every input item produces exactly one output record, including unreachable sites, failed URLs, and items with no website URL. No records are silently dropped.

#### Output example: key fields

```json
{
  "business_name": "Northside Plumbing",
  "source_website": "https://northside-plumbing.com",
  "analysis_status": "completed",
  "data_quality_score": 80,
  "lead_priority_score": 82,
  "priority_level": "very_high",
  "sales_priority_label": "hot",
  "lead_segment": "ready_to_contact",
  "workflow_action": "send_to_crm",
  "outreach_ready": true,
  "manual_review_recommended": false,
  "public_emails_csv": "",
  "public_phones_csv": "+1 555 234 5678",
  "recommended_offer": "booking_system",
  "crm_note": "Northside Plumbing: Site reachable, phone visible. No booking or contact form. Recommended: pitch booking_system.",
  "next_action": "Contact this week. Very high conversion potential."
}
```

For the complete record structure, including `evidence`, `score_breakdown`, `score_reasons`, all boolean signals, and failure fields, see [`docs/OUTPUT_SCHEMA.md`](docs/OUTPUT_SCHEMA.md). Full example records (reachable, unreachable, partial, and missing-website) are in `examples/output_sample.json`.

***

### Field reference

See [`docs/OUTPUT_SCHEMA.md`](docs/OUTPUT_SCHEMA.md) for the complete field reference with all 55+ fields.

Key fields for immediate use:

| Field | Use for |
|---|---|
| `public_emails_csv`, `public_phones_csv` | Contact extraction: paste directly into spreadsheets |
| `social_links_csv` | Social profile links: Facebook, Instagram, LinkedIn and more |
| `lead_priority_score` (0-100) | Sort leads by commercial opportunity |
| `workflow_action` | Single-field routing: `send_to_crm`, `manual_review`, `enrich_later`, `skip`, `find_website` |
| `outreach_ready` | Boolean gate: `true` when safe to route to automated outreach |
| `manual_review_recommended` | Boolean gate: `true` when a human should verify before outreach |
| `crm_note` | Paste directly into HubSpot, Pipedrive, or any CRM notes field |
| `next_action` | Use as CRM task title |
| `evidence` | Per-signal audit trail: verify every score claim without visiting the site |
| `analysis_status` | `completed`, `partial`, `failed`, `skipped` |
| `failure_reason` | Machine-readable failure code for workflow branching |

***

### Scoring model

**Lead priority score (0-100):** Commercial opportunity score. A site that is reachable and contactable but has no booking system or contact form scores high because there is something clear to sell. Measured across contactability (30 pts), commercial gaps (50 pts), and vitality (20 pts). Levels: 0-30 = low, 31-60 = medium, 61-80 = high, 81-100 = very\_high.

**Website quality score (0-100):** How complete and visitor-friendly the site is: HTTPS, title, meta description, visible contacts, contact form, CTA, social links. Bands: poor / weak / average / good.

**Conversion leaks:** Missing commercial elements on the site: `missing_booking`, `missing_contact_form`, `missing_email`, `missing_https`, `no_social_links`, etc. Each leak maps to a `recommended_offer` for your pitch (`booking_system`, `contact_form_setup`, `ssl_setup`, `local_seo`, `website_rebuild`, etc.).

For the full per-signal point table and recommended offer mapping, see [`docs/SCORING_MODEL.md`](docs/SCORING_MODEL.md).

***

### Use with n8n / Make / Google Sheets

#### Field mapping for CRM and automation

| This Actor field | Map to |
|---|---|
| `priority_level` | CRM segment or filter condition |
| `outreach_ready` | Gate for immediate outreach routing |
| `manual_review_recommended` | Flag for manual review queue |
| `recommended_offer` | Sales segment or deal type |
| `crm_note` | CRM notes field (HubSpot, Pipedrive, Salesforce) |
| `next_action` | CRM task title or action item |
| `sales_angle` | Outreach email body or first message template |
| `public_emails_csv` | Contact email column: no parsing needed |
| `public_phones_csv` | Contact phone column: no parsing needed |
| `top_conversion_leak` | Primary pitch anchor |
| `category_specific_signals` | Industry context for personalization |
| `evidence` | Audit trail for manual review |

#### n8n workflow

1. Use the **Apify** node to trigger this Actor with your URL list or `datasetId`.
2. Add an **IF** node: `outreach_ready == true` → route to CRM / outreach sequence.
3. Add a second **IF** node: `manual_review_recommended == true` → route to Slack notification or review spreadsheet.
4. Map `crm_note` to HubSpot "Notes" or Pipedrive "Description".
5. Map `next_action` to a task title.
6. Map `recommended_offer` to deal type or pipeline stage.
7. Map `public_phones_csv` and `public_emails_csv` as contact fields. No formula needed.

#### Make (Integromat) workflow

1. Use the **Apify** module to run the Actor and watch the output dataset.
2. Add a **Router** module:
   - Branch 1: `outreach_ready == true` → add to CRM immediately
   - Branch 2: `manual_review_recommended == true` → send to Slack review channel
   - Branch 3: everything else → nurture list or archive
3. Map `recommended_offer` to a deal property to pre-segment your pipeline.
4. Use `priority_level` as the CRM score or lead rating field.

#### Google Sheets / Excel

Export the Apify dataset as CSV. All array fields have parallel `_csv` string variants:

| Array field | CSV variant |
|---|---|
| `public_emails` | `public_emails_csv` |
| `public_phones` | `public_phones_csv` |
| `social_links` | `social_links_csv` |
| `conversion_leaks` | `conversion_leaks_csv` |
| `score_reasons` | `score_reasons_csv` |

These import cleanly into spreadsheet columns without formula parsing.

***

### Best use cases

#### Web agency prospecting

Scrape 500 local businesses in your city with Google Maps Scraper. Run this Actor with `categoryHint="plumber"` (or whatever vertical you serve). Filter by `outreach_ready=true` and `priority_level in (high, very_high)`. You get a ranked list with pitch text already written.

#### Automation freelancer lead qualification

You build n8n / Make flows for local businesses. Scrape dentists, lawyers, or restaurants in your region. Filter for `top_conversion_leak in (missing_booking, missing_contact_form)`. These businesses have an obvious automation opportunity you can pitch immediately.

#### Local SEO opportunity detection

Run on a list of businesses in a niche. Filter for `conversion_leaks containing missing_meta_description, missing_https, no_social_links`. These are your SEO audit prospects. The `evidence.title` and `evidence.meta_description` fields give you talking points for the initial call.

#### Sales team list prioritization

Your BDR team has 1000 inbound leads but no time to research them all. Run this Actor on the website list. Route `outreach_ready=true` records to the top of the calling queue. Route `manual_review_recommended=true` records to a research list for junior staff. Route `priority_level=low` to the archive.

#### Freelance web developer client hunting

Look for businesses with `cms_detected=wordpress` and `conversion_leaks containing weak_cta, missing_contact_form`. These are WordPress sites with a clear UX gap, your target market for a conversion-focused redesign pitch.

***

### Limitations

**JavaScript-rendered sites**\
This Actor uses static HTML analysis only. Sites built entirely with JavaScript frameworks (React, Vue, Next.js) may return an empty or near-empty HTML shell from the server. When minimal content is detected, a `js_heavy_or_low_html_detected` warning is added and the `js_heavy_or_low_html` conversion leak is included. Some signals (emails, phones, forms) may be missing for these sites.

**Homepage analysis only**\
By default, only the homepage is analyzed. Enable `includeContactPageCheck` to make one additional request to a detected contact page per site. This doubles HTTP request count for sites where a contact link is found.

**Phone number formats**\
Phone extraction is optimized for French (FR) and English (EN/US) formats. Numbers in other formats may not be detected.

**Bot-protected sites**\
Sites behind Cloudflare or similar bot protection may return an error page (e.g. "Just a moment...") instead of real content. These sites receive partial scores based on the error page HTML.

**No JavaScript execution**\
Dynamic content loaded after page render (chat widgets, pop-up contact forms, lazy-loaded CTAs) is not detected.

**No authentication**\
Sites behind login pages or cookie consent walls that hide content cannot be analyzed.

**CMS detection**\
8 platforms are covered: WordPress, Wix, Squarespace, Shopify, Joomla, Drupal, Webflow, Jimdo. Sites on other platforms or custom stacks are reported as `cms=unknown`.

**Security: outbound request restrictions**\
The Actor blocks outbound requests to private IP ranges (10.x, 172.16.x, 192.168.x), localhost, link-local addresses (169.254.x.x including the cloud metadata endpoint 169.254.169.254), and non-HTTP schemes (file://, ftp://). URLs matching these are returned with `website_status=unreachable`. This is a deliberate SSRF protection; it cannot be disabled.

**No sales guarantee**\
A high `lead_priority_score` indicates a detectable conversion gap on the website. It does not guarantee that the business owner will buy, respond, or convert. The scores are signal-based heuristics. Human judgment and qualification are required before any outreach.

***

### User tutorial

A step-by-step guide to using this Actor, from pasting your first URL to filtering results in n8n, is available in [`docs/USER_TUTORIAL.md`](docs/USER_TUTORIAL.md). A French version is in [`docs/USER_TUTORIAL_FR.md`](docs/USER_TUTORIAL_FR.md).

After your first run, follow the [First Run Checklist](docs/FIRST_RUN_CHECKLIST.md) to interpret `completed`, `partial`, and `failed` records and calibrate the scoring for your market.

***

### FAQ

**Does it scrape Google Maps?**\
No. This Actor does not touch Google Maps. It only analyzes websites you provide via `urls`, `items`, or `datasetId`. Use a Google Maps Scraper to collect your list first.

**Can I use it after running a Google Maps Scraper?**\
Yes, that is the primary use case. Pass the scraper's output dataset ID via `datasetId`, or export as JSON and pass via `items`. Field names from popular Google Maps scrapers are auto-detected.

**Does it find emails and phone numbers?**\
Yes, if they are visible in the static HTML. Emails and phones hidden in JavaScript, images, or behind login walls cannot be extracted. Enable `includeContactPageCheck` to check the contact page as well.

**Why are `public_phones` and `public_emails` empty?**\
The most common causes: (1) the site renders content with JavaScript (static HTML analysis misses React/Vue/Next.js-embedded contacts); (2) contact details are in images or PDFs; (3) the business has no visible contact info. Enable `includeContactPageCheck: true` and check `manual_review_recommended`.

**Why is `analysis_status` partial?**\
The site was fetched but signals are incomplete, typically because the site is JavaScript-heavy (`js_heavy_or_low_html`) or is behind bot protection (`cloudflare_or_bot_protection`). Partial records have valid scores but may be missing emails, phones, and social links.

**What does `manual_review_recommended: true` mean?**\
The record cannot be safely routed to automated outreach. Main triggers: `analysis_status: partial`, an HTTP error response, or no visible contact info. Route these to a review queue in n8n or Make. The lead may still be good.

**Does it use AI or require any API key?**\
No. All analysis is keyword-based and deterministic. No API key of any kind is required. No LLM calls.

**Does it send outreach messages?**\
No. This Actor only reads and scores websites. It does not send emails, make calls, or contact businesses.

***

### What happens when a website cannot be analyzed?

Every input item produces exactly one output record. The `analysis_status` field explains what happened:

| `analysis_status` | Meaning |
|---|---|
| `completed` | Full analysis (all signals extracted) |
| `partial` | Site fetched but signals incomplete (JS-heavy, bot-blocked, low HTML) |
| `failed` | Site unreachable: DNS error, timeout, or HTTP error with no usable HTML |
| `skipped` | No URL provided, or URL blocked by security policy |

Use `workflow_action` to route each outcome: `send_to_crm`, `manual_review`, `enrich_later`, `skip`, or `find_website`. The `failure_reason` field is machine-readable for fine-grained branching in n8n or Make.

For the full `failure_category` and `failure_reason` code reference, interpretation guide, and calibration tips, see [`docs/FIRST_RUN_CHECKLIST.md`](docs/FIRST_RUN_CHECKLIST.md).

***

### Local development

```bash
## Install dependencies
pip install -r requirements.txt -r requirements-dev.txt

## Run tests
pytest

## Run locally on a URL list (no Apify account needed)
python3 run_local.py examples/input_urls.json
python3 run_local.py examples/input_items.json

## Run on a custom input inline
python3 run_local.py - '{"urls": ["https://example.com"], "languageHint": "en"}'

## Use datasetId locally - requires APIFY_TOKEN
export APIFY_TOKEN=your_token_here
python3 run_local.py - '{"datasetId": "your_dataset_id"}'
```

When using `datasetId` locally, the `APIFY_TOKEN` environment variable must be set. On the Apify platform, it is set automatically.

See [docs/DEVELOPMENT\_WORKFLOW.md](docs/DEVELOPMENT_WORKFLOW.md) for the full development guide.

# Actor input Schema

## `urls` (type: `array`):

Paste website URLs directly, one per line. Leave empty if using Business items or Apify Dataset ID. Use one input method: URLs, items, or datasetId.

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

Paste business objects as JSON — accepts Google Maps Scraper output directly. Field names are auto-detected (website, url, businessWebsite, name, title…). Items with a business name but no website produce a skipped record with workflow\_action=find\_website. Leave empty if using Website URLs or Apify Dataset ID.

## `datasetId` (type: `string`):

Dataset ID from a previous Apify run — typically the output of a Google Maps Scraper. Find it in the run's Output tab or Dataset page. Leave empty if using Website URLs or Business items.

## `datasetWebsiteField` (type: `string`):

Optional. Leave empty for auto-detection. Use only if your dataset stores the website URL in a non-standard field, e.g. 'homepage' or 'link'.

## `datasetNameField` (type: `string`):

Optional. Leave empty for auto-detection. Use only if your dataset stores the business name in a non-standard field, e.g. 'company' or 'firm\_name'.

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

Maximum number of items to process per run. Items without a website also count — they produce a skipped record. Useful for testing on a subset before running on your full list.

## `timeoutPerItemSeconds` (type: `integer`):

How long to wait for a single website to respond before marking it as unreachable. Increase for slow or international sites. Default 20s covers most business websites.

## `totalTimeoutSeconds` (type: `integer`):

Approximate maximum duration for the entire run. Increase for large batches (500+ items). The Actor stops accepting new items once this limit is reached.

## `concurrency` (type: `integer`):

Number of websites fetched in parallel. Keep moderate (10–15) to avoid overloading shared hosting servers. Increase to 20–30 for faster runs on stable infrastructure.

## `countryHint` (type: `string`):

Optional ISO country code, e.g. FR, US, GB. Used for context and future keyword tuning. Does not restrict which sites are analyzed.

## `languageHint` (type: `string`):

Language for keyword detection: 'en' for English, 'fr' for French. Affects booking, CTA, and contact signal keywords. Both languages are always active — this setting prioritizes one for ambiguous detections.

## `categoryHint` (type: `string`):

Optional context for category-specific signals and sales angles. Use 'plumber' for plumbers, 'restaurant' for restaurants, etc. Use 'generic' for mixed or unknown industries.

## `includeContactExtraction` (type: `boolean`):

When enabled, scans the page HTML for visible email addresses and phone numbers. Disable only if you need scoring signals without contact data.

## `includeSocialLinks` (type: `boolean`):

When enabled, detects links to Facebook, Instagram, LinkedIn, YouTube, TikTok, and other social platforms. Results appear in 'social\_links' and 'social\_links\_csv'.

## `includeContactPageCheck` (type: `boolean`):

If enabled, the Actor follows one detected contact page per website. This can improve contact extraction (emails and phones not shown on the homepage) but may add one extra request per site, increasing run time by 20–40%.

## `minLeadPriorityScore` (type: `integer`):

Records below this score are not removed — they are flagged with passed\_min\_lead\_priority\_filter=false. Filter this field in your CRM or spreadsheet downstream. Set to 0 to include all records.

## Actor input object example

```json
{
  "urls": [
    "https://example-plumber.com",
    "https://example-dentist.com"
  ],
  "items": [
    {
      "name": "Example Plumbing",
      "website": "https://example.com",
      "phone": "+33 1 23 45 67 89"
    }
  ],
  "maxItems": 100,
  "timeoutPerItemSeconds": 20,
  "totalTimeoutSeconds": 300,
  "concurrency": 10,
  "languageHint": "en",
  "categoryHint": "generic",
  "includeContactExtraction": true,
  "includeSocialLinks": true,
  "includeContactPageCheck": false,
  "minLeadPriorityScore": 0
}
```

# 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 = {
    "urls": [
        "https://example-plumber.com",
        "https://example-dentist.com"
    ],
    "items": [
        {
            "name": "Example Plumbing",
            "website": "https://example.com",
            "phone": "+33 1 23 45 67 89"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("market_radar_tools/google-maps-website-lead-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 = {
    "urls": [
        "https://example-plumber.com",
        "https://example-dentist.com",
    ],
    "items": [{
            "name": "Example Plumbing",
            "website": "https://example.com",
            "phone": "+33 1 23 45 67 89",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("market_radar_tools/google-maps-website-lead-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 '{
  "urls": [
    "https://example-plumber.com",
    "https://example-dentist.com"
  ],
  "items": [
    {
      "name": "Example Plumbing",
      "website": "https://example.com",
      "phone": "+33 1 23 45 67 89"
    }
  ]
}' |
apify call market_radar_tools/google-maps-website-lead-scorer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=market_radar_tools/google-maps-website-lead-scorer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Website Lead Scorer",
        "description": "Post-process Google Maps Scraper datasets and local business lists. Extract visible emails, phones and social links, score each lead, and output CRM/n8n-ready records with offers, sales angles and next actions.",
        "version": "0.1",
        "x-build-id": "6o9B9P94aq5DrSPQr"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/market_radar_tools~google-maps-website-lead-scorer/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-market_radar_tools-google-maps-website-lead-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/market_radar_tools~google-maps-website-lead-scorer/runs": {
            "post": {
                "operationId": "runs-sync-market_radar_tools-google-maps-website-lead-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/market_radar_tools~google-maps-website-lead-scorer/run-sync": {
            "post": {
                "operationId": "run-sync-market_radar_tools-google-maps-website-lead-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",
                "properties": {
                    "urls": {
                        "title": "Website URLs",
                        "type": "array",
                        "description": "Paste website URLs directly, one per line. Leave empty if using Business items or Apify Dataset ID. Use one input method: URLs, items, or datasetId.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "items": {
                        "title": "Business items (JSON)",
                        "type": "array",
                        "description": "Paste business objects as JSON — accepts Google Maps Scraper output directly. Field names are auto-detected (website, url, businessWebsite, name, title…). Items with a business name but no website produce a skipped record with workflow_action=find_website. Leave empty if using Website URLs or Apify Dataset ID."
                    },
                    "datasetId": {
                        "title": "Apify Dataset ID",
                        "type": "string",
                        "description": "Dataset ID from a previous Apify run — typically the output of a Google Maps Scraper. Find it in the run's Output tab or Dataset page. Leave empty if using Website URLs or Business items."
                    },
                    "datasetWebsiteField": {
                        "title": "Dataset website field name",
                        "type": "string",
                        "description": "Optional. Leave empty for auto-detection. Use only if your dataset stores the website URL in a non-standard field, e.g. 'homepage' or 'link'."
                    },
                    "datasetNameField": {
                        "title": "Dataset business name field",
                        "type": "string",
                        "description": "Optional. Leave empty for auto-detection. Use only if your dataset stores the business name in a non-standard field, e.g. 'company' or 'firm_name'."
                    },
                    "maxItems": {
                        "title": "Max items to process",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum number of items to process per run. Items without a website also count — they produce a skipped record. Useful for testing on a subset before running on your full list.",
                        "default": 100
                    },
                    "timeoutPerItemSeconds": {
                        "title": "Timeout per website (seconds)",
                        "minimum": 5,
                        "maximum": 120,
                        "type": "integer",
                        "description": "How long to wait for a single website to respond before marking it as unreachable. Increase for slow or international sites. Default 20s covers most business websites.",
                        "default": 20
                    },
                    "totalTimeoutSeconds": {
                        "title": "Total run timeout (seconds)",
                        "minimum": 30,
                        "maximum": 3600,
                        "type": "integer",
                        "description": "Approximate maximum duration for the entire run. Increase for large batches (500+ items). The Actor stops accepting new items once this limit is reached.",
                        "default": 300
                    },
                    "concurrency": {
                        "title": "Concurrent requests",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Number of websites fetched in parallel. Keep moderate (10–15) to avoid overloading shared hosting servers. Increase to 20–30 for faster runs on stable infrastructure.",
                        "default": 10
                    },
                    "countryHint": {
                        "title": "Country hint",
                        "type": "string",
                        "description": "Optional ISO country code, e.g. FR, US, GB. Used for context and future keyword tuning. Does not restrict which sites are analyzed."
                    },
                    "languageHint": {
                        "title": "Language hint",
                        "enum": [
                            "en",
                            "fr"
                        ],
                        "type": "string",
                        "description": "Language for keyword detection: 'en' for English, 'fr' for French. Affects booking, CTA, and contact signal keywords. Both languages are always active — this setting prioritizes one for ambiguous detections.",
                        "default": "en"
                    },
                    "categoryHint": {
                        "title": "Business category",
                        "enum": [
                            "generic",
                            "restaurant",
                            "plumber",
                            "contractor",
                            "dentist",
                            "clinic",
                            "salon",
                            "agency"
                        ],
                        "type": "string",
                        "description": "Optional context for category-specific signals and sales angles. Use 'plumber' for plumbers, 'restaurant' for restaurants, etc. Use 'generic' for mixed or unknown industries.",
                        "default": "generic"
                    },
                    "includeContactExtraction": {
                        "title": "Extract emails and phone numbers",
                        "type": "boolean",
                        "description": "When enabled, scans the page HTML for visible email addresses and phone numbers. Disable only if you need scoring signals without contact data.",
                        "default": true
                    },
                    "includeSocialLinks": {
                        "title": "Extract social media links",
                        "type": "boolean",
                        "description": "When enabled, detects links to Facebook, Instagram, LinkedIn, YouTube, TikTok, and other social platforms. Results appear in 'social_links' and 'social_links_csv'.",
                        "default": true
                    },
                    "includeContactPageCheck": {
                        "title": "Follow contact page link",
                        "type": "boolean",
                        "description": "If enabled, the Actor follows one detected contact page per website. This can improve contact extraction (emails and phones not shown on the homepage) but may add one extra request per site, increasing run time by 20–40%.",
                        "default": false
                    },
                    "minLeadPriorityScore": {
                        "title": "Minimum lead priority score",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Records below this score are not removed — they are flagged with passed_min_lead_priority_filter=false. Filter this field in your CRM or spreadsheet downstream. Set to 0 to include all records.",
                        "default": 0
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
