Skip to content
Back to skills

local-competitive-landscape

ASecurity

Compare observed local business supply, categories, attributes, hours, and review-sample themes across defined areas using Crawlora's Google Maps dataset, live Google Maps, Apple Maps, and Yelp. Use for matched-area competitor landscapes and coverage comparisons, not lead generation, demand forecasts, sales estimates, or site-viability claims.

  • 0 votes
  • 0 copies
  • 0 views
  • Added October 12, 2026
ai-agentsgogitapi

Works with

  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned October 12, 2026

npx -y skills add Crawlora-org/crawlora-skills --skill local-competitive-landscape --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of local-competitive-landscape?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for local-competitive-landscape
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/crawlora-org-local-competitive-landscape/badge)](https://www.skillsdirectory.com/skills/crawlora-org-local-competitive-landscape)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: local-competitive-landscape
description: Compare observed local business supply, categories, attributes, hours, and review-sample themes across defined areas using Crawlora's Google Maps dataset, live Google Maps, Apple Maps, and Yelp. Use for matched-area competitor landscapes and coverage comparisons, not lead generation, demand forecasts, sales estimates, or site-viability claims.
---

# Local competitive landscape

Compare like-for-like observations of businesses across defined areas. Produce a
traceable market map without turning search-result coverage into a population,
demand, revenue, or site-selection estimate.

## Setup and API contract

Set `CRAWLORA_API_KEY` to your key from [crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).
Run the bundled `scripts/crawlora.sh` from this skill directory or by absolute
path. It sends `x-api-key` to `https://api.crawlora.net/api/v1`; keep the key in
the environment. Read [reference/endpoints.md](reference/endpoints.md) for exact
parameters and response behavior. Check the application `code` as well as HTTP
status. Stop on `401`/`403`, back off on `429`, and retry a transient `5xx` once.
A failed request is unavailable evidence, not an empty area. Keep Google Maps
calls at least one second apart.

## Define a comparable frame

1. Record each named area and its operational boundary: administrative name,
   radius with center coordinates, or explicit polygon supplied by the user.
   Record the business concept, inclusion rules, closure treatment, sources,
   filters, retrieval date, page/limit budget, and whether all available pages
   or only a bounded sample will be collected.
2. Use identical category, geography type, status filters, dates, pagination,
   and source mix across areas. Do not treat a Google radius in meters as
   equivalent to an Apple viewport `span` in latitude/longitude degrees. Keep a
   separate coverage row for every source and area when geometry differs.
3. Discover exact dataset category values with
   `/datasets/google-map-businesses/facets?facet=category`; pass returned values
   unchanged. A text query can return businesses whose primary category differs,
   so preserve every source's returned category and apply the stated inclusion
   rule locally.

```sh
scripts/crawlora.sh /datasets/google-map-businesses/facets \
  facet=category q=coffee permanently_closed=false
# Set CATEGORY to one exact `.data.items[].value` returned above.
scripts/crawlora.sh /datasets/google-map-businesses/search \
  category="$CATEGORY" lat=42.3736 lon=-71.1097 radius_m=2000 \
  permanently_closed=false sort=distance_asc page=1 page_size=100
scripts/crawlora.sh -X POST /google/map/search \
  '{"keyword":"coffee shop Cambridge Massachusetts","language":"en","country":"us"}'
```

## Collect and reconcile coverage

1. Use `/datasets/google-map-businesses/search` for a bounded indexed-corpus
   baseline. Capture `total`, page, page size, filters, and whether the result
   window was exhausted. Dataset totals describe Crawlora's indexed corpus, not
   the business population. A zero or short result cannot prove local absence.
   Preserve each record's dataset update/crawl timestamp separately from request
   retrieval time; matched request dates do not make stored records equally fresh.
   Use `/datasets/google-map-businesses/items/{place_id}` only when a stored row
   needs its full record.
2. Run the same live Google query wording for every area. Post-filter returned
   coordinates or addresses against the defined boundary. Search ranking and a
   bounded result list can omit relevant businesses, so retain both returned and
   in-area counts. Refresh selected ambiguous or representative rows with
   `/google/map/place/{place_id}`.
3. Run Apple searches with the same query, regional catalog, language, span, and
   limit. Record Apple's returned region and `relocated`; discard results outside
   the intended boundary. A relocated search is evidence about Apple's fallback,
   not about the target area. Apple has no pagination, so a full returned viewport
   is still a bounded result set.
4. Run Yelp with the same term and location convention, paging only to the stated
   bound. Refresh selected rows with `/yelp/business/{id}`. Provider search areas
   and ranking differ; compare source-specific observations before merging them.
5. Preserve businesses with unknown coordinates or status in an unknown bucket.
   `permanently_closed=false` excludes confirmed closures but can retain dataset
   rows with `null` status; it does not certify they are open. Radius searches
   omit locationless service-area businesses, so run a matched text/area check if
   those businesses are in scope and disclose the omission otherwise.

Deduplicate within each area and source by provider ID first. Across providers,
require consistent name, address, coordinates, phone, or domain evidence. Keep
chain branches separate unless the evidence identifies the same location. Retain
source-specific IDs and disagreements after a merge. Do not assume a dataset
`place_id` and live Google `place_id` are interchangeable when their formats or
provenance differ: use the raw dataset ID for the stored-item endpoint, then
resolve the business through live search using name and address before calling
live Google detail unless ID compatibility has been established. Assign a business
to every area whose boundary contains it, but do not sum overlapping-area counts
as a unique total.

## Compare the areas

Create three linked outputs:

- **Coverage ledger:** area, source, query/category, geometry, filters, page or
  limit range, retrieved count, in-area count, unknown-location count, relocated
  status, exhausted/bounded/failed status, and retrieval time.
- **Business matrix:** area membership, canonical branch, provider IDs, source
  names and categories, address/coordinates, status, hours/attributes when
  returned, rating, review count, source URLs, retrieval time, and match confidence.
- **Comparison:** deduplicated observed counts and category/attribute mix within
  each matched frame, with unknowns and source disagreements shown beside every
  conclusion.

Treat `rating: null` and `review_count: null` as unknown, distinct from numeric
zero. Compare ratings only within the same platform and state sample sizes; do
not blend Google, Apple, and Yelp rating scales or rank areas from cross-platform
averages. Use `/google/map/place/{place_id}/reviews` only for a small, disclosed
sample of visible review themes. Report theme counts within that sample, retain
source/date, and do not infer customer-population prevalence.

Missing hours or service attributes are unknown, never evidence that a service
is absent. Keep returned attributes source-specific and date them; do not infer
that an unlisted amenity, offering, or schedule is unavailable.

Call a finding a **proven service gap** only when the service definition is
explicit, complete eligible-business coverage establishes the candidate set, and
verified service attributes establish absence across that set. Bounded map and
directory listings ordinarily support only an **observed gap in the collected
sample** with **search omission risk**. State which one the evidence supports. Do
not turn business counts, ratings, or review themes into demand, revenue, market
share, sales potential, or site-viability claims.

Files in this skill

  • SKILL.md7.3 KB
  • reference/endpoints.md13.5 KB
  • scripts/crawlora.sh5.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.