# Google Maps Booking & Ordering Detector (`web-signal-lab/google-maps-booking-signal-enricher`) Actor

Enrich Google Maps business datasets with online booking and ordering signals. Detect booking providers, Google booking links, and classify each business as confirmed, probable, none detected, explicit no-booking, or unknown.

- **URL**: https://apify.com/web-signal-lab/google-maps-booking-signal-enricher.md
- **Developed by:** [Sebastian Philipp](https://apify.com/web-signal-lab) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 processed businesses

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Maps Booking & Ordering Detector

Enrich business datasets with structured online booking, reservation, ordering, and provider signals.

Use this Actor to identify businesses that:

- have confirmed online booking,
- show probable booking signals,
- have no supported booking signal detected,
- explicitly state that online booking is unavailable,
- or could not be classified reliably.

It works especially well as a downstream enrichment step for Google Maps business datasets.

### What this Actor does

Provide either:

- an Apify dataset containing business records with website URLs, or
- a direct list of website URLs.

The Actor inspects each website and returns structured booking and ordering signals.

It can combine evidence from:

- the business website,
- known booking-provider links,
- Google Maps booking URLs when present in the source dataset,
- explicit booking or no-booking language on the website.

The Actor does **not** scrape Google Maps itself. It enriches an existing dataset, such as output from a Google Maps scraper.

### Example use cases

#### Find businesses without detectable online booking

Use `booking_status = none_detected` to identify businesses whose website was successfully inspected but where no supported online-booking signal was found.

Useful for:

- booking software vendors,
- lead generation,
- sales prospecting,
- market research,
- local business analysis.

#### Segment businesses by booking status

Filter businesses by:

- `confirmed`
- `probable`
- `explicit_no_online_booking`
- `none_detected`
- `unknown`

#### Identify booking providers

Where supported evidence exists, the Actor can identify providers such as Doctolib and other known booking, reservation, or ordering platforms.

### Booking classification

#### `confirmed`

A strong booking signal was found.

Examples:

- a provider-backed booking link on the website,
- a booking URL supplied by Google Maps in the source dataset.

#### `probable`

The website shows a meaningful online-booking signal, but the Actor cannot confirm it strongly enough to label it `confirmed`.

Examples:

- "Book appointment online" without a recognized provider,
- a booking-provider-hosted business profile whose booking interface is dynamically rendered.

#### `explicit_no_online_booking`

The website explicitly states that online booking is currently unavailable.

#### `none_detected`

The website was successfully inspected, but no supported online-booking signal was detected.

**This does not prove that online booking does not exist.**

A JavaScript widget, unsupported provider, or booking flow on an uninspected page may still be present.

#### `unknown`

The Actor could not reliably determine the result.

Examples:

- the website could not be fetched,
- available sources directly conflict.

### Important output fields

Typical output includes:

- `booking_status`
- `booking_source`
- `booking_provider`
- `google_booking_available`
- `google_booking_url`
- `website_booking_available`
- `website_booking_status`
- `explicit_no_online_booking`
- `signal_conflict`
- `unknown_reason`
- `has_online_booking`
- `has_online_ordering`
- `ordering_provider`
- `commerce_provider`
- `provider_references`
- `confidence`
- `evidence_type`
- `evidence_url`
- `evidence_text`
- `inspected_urls`

Evidence fields make the classification auditable instead of returning only a yes/no result.

### Input

#### Apify dataset

Select a source dataset containing business records with website URLs.

Common website fields are detected automatically, including:

- `website`
- `url`
- `websiteUrl`
- `webUrl`

The Actor only requests read access to the dataset explicitly selected by the user.

#### Direct website URLs

You can also submit website URLs directly without using another dataset.

### How detection works

For each website, the Actor:

1. fetches the website using lightweight HTTP requests,
2. looks for booking, reservation, ordering, and commerce evidence,
3. identifies supported provider links,
4. optionally follows a small number of likely internal booking-related pages,
5. combines website evidence with Google Maps booking information when available,
6. returns a conservative classification with supporting evidence.

No LLM or external classification API is used.

### Limitations

This Actor intentionally favors conservative results over aggressive classification.

It does not:

- render full JavaScript applications,
- use a headless browser,
- bypass anti-bot protection,
- crawl an entire website,
- claim that `none_detected` means online booking definitely does not exist.

Some JavaScript-only widgets or unsupported booking providers may therefore be missed.

For lead-generation workflows, consider `none_detected` a **candidate signal**, not proof of absence.

### Evidence-first output

Whenever possible, results include the exact URL and text that caused the classification:

- `evidence_type`
- `evidence_url`
- `evidence_text`

This makes it possible to review or independently verify the Actor's decision.

### Privacy and permissions

The Actor operates only on:

- URLs supplied directly by the user, and
- datasets explicitly selected by the user.

Dataset access uses read-only permissions.

The Actor does not request access to unrelated account data.

# Actor input Schema

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

Select an Apify dataset whose rows contain business website URLs. The Actor requests read-only access to this dataset.

## `websites` (type: `array`):

Optional direct list of business website URLs to inspect. Replace or remove the example URL when using your own dataset.

## `websiteFields` (type: `array`):

Candidate field names searched in each source dataset row, in order. The first usable website URL is processed.

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

Maximum number of source items to process in one run.

## `timeoutMs` (type: `integer`):

Maximum HTTP request time per page in milliseconds.

## `followCandidateLinks` (type: `boolean`):

If no confirmed booking or ordering signal is found on the first page, inspect up to 3 likely internal booking or ordering pages.

## Actor input object example

```json
{
  "websites": [
    "https://example.com/"
  ],
  "websiteFields": [
    "website",
    "websiteUrl",
    "webUrl",
    "url"
  ],
  "maxItems": 100,
  "timeoutMs": 10000,
  "followCandidateLinks": true
}
```

# Actor output Schema

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

No description

# 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 = {
    "websites": [
        "https://example.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("web-signal-lab/google-maps-booking-signal-enricher").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 = { "websites": ["https://example.com/"] }

# Run the Actor and wait for it to finish
run = client.actor("web-signal-lab/google-maps-booking-signal-enricher").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "websites": [
    "https://example.com/"
  ]
}' |
apify call web-signal-lab/google-maps-booking-signal-enricher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,web-signal-lab/google-maps-booking-signal-enricher"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/4gthgCCjnoQTqqXBP/builds/ZF2FA4ag4aDDVWC04/openapi.json
