Restaurant menu benchmarking
Build a matched menu comparison for specified branches, dishes, and order modes.
The output is a benchmark with evidence and unmatched items, not an order.
Setup and API contract
Set CRAWLORA_API_KEY to your key from crawlora.net.
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 for the
selected endpoints, required parameters, limits, and response behavior.
Check the application code as well as HTTP status; successful payloads are
inside data. Stop on 401/403, back off on 429, and retry a transient
5xx once. A failed or partial fetch is not an empty market or catalog.
Bound requests to the user's scope and credit budget. For repeated collection,
save the query, source IDs, pagination progress, and retrieval timestamps with
the results so interrupted work can resume; do not create monitors implicitly.
Collect comparable menus
- Define the city or coordinates, restaurant branches, meal/daypart, currency,
collection window, and order mode. Compare the same branch across channels
before attributing a difference to a platform. A chain name alone is not a
branch match: verify address and location using store metadata.
- Discover DoorDash stores with
/doordash/search and Uber Eats stores with
/ubereats/search. DoorDash search is a pickup catalog; do not label its
prices as delivery quotes. Its store and menu calls both need the same
latitude and longitude. Uber Eats IDs are storeUuid values from search;
they are not DoorDash numeric IDs. Keep platform IDs separate.
- Use
/chipotle/restaurants to resolve a nearby restaurant_number, then
/chipotle/restaurant/menu for its priced menu. Preserve its dine-in and
delivery price pair, including customization charges. /chipotle/menu is
national taxonomy and customization context only: omitted prices are unknown,
never zero. include_unavailable=true can distinguish menu presence from
current availability on the restaurant endpoint.
- For national menu breadth, discover McDonald's categories for one
country
and pass that same country and returned category slug to /mcdonalds/menu.
This surface has no prices. Compare its item coverage, not invented prices.
National catalogs and branch menus describe different scopes.
scripts/crawlora.sh /chipotle/restaurants \
latitude=37.7749 longitude=-122.4194 page_size=3
# Take restaurant_number from discovery before fetching /chipotle/restaurant/menu.
scripts/crawlora.sh /mcdonalds/categories country=us
scripts/crawlora.sh /doordash/search \
query=Chipotle latitude=37.7749 longitude=-122.4194
Match and calculate
- Retain original names and descriptions. Match dish, protein/filling, size,
item count, included sides/drink, and required modifiers. Mark exact matches,
comparable alternatives, and unmatched items separately; do not force a combo
meal and a standalone entree into one price comparison.
- Preserve displayed currency and price units. Inspect actual payload fields
before converting minor units; an integer alone does not prove cents. A missing
price is null. A free modifier is not evidence that the base dish is free.
- For exact matches, report absolute difference and
(comparison - baseline) / baseline * 100, only with a positive priced baseline. Use per-item or per-size
prices only when quantities and units are known and comparable.
- Separate regular, promotional, membership, and starting prices. Menu prices
exclude any fees, taxes, tips, and minimum-order effects not explicitly returned.
Do not call their sum a final checkout total. Preserve availability flags.
- Count unique menu items separately from modifiers and bundles. Deduplicate items
repeated in several menu sections without collapsing genuinely different sizes.
Deliverable
Return a table with branch/address, source and collection time, order mode,
original item, matched item, portion/bundle contents, currency, price, availability,
match confidence, and price difference. Include a coverage summary with fetched
branches/sections and missing sources. Summarize price positioning and menu gaps
as hypotheses; popularity, margins, sales volume, and customer demand are not
established by menu presence. Link original URLs when returned and retain IDs and
API request paths when no public item URL is supplied.
1---2name: restaurant-menu-benchmarking3description: Compare restaurant menu breadth, matched dishes, bundles, and location-specific prices with the Crawlora API. Use for restaurant competitor benchmarks or comparisons of direct, pickup, and delivery menus in a defined market.4---56# Restaurant menu benchmarking78Build a matched menu comparison for specified branches, dishes, and order modes.9The output is a benchmark with evidence and unmatched items, not an order.1011## Setup and API contract1213Set `CRAWLORA_API_KEY` to your key from [crawlora.net](https://crawlora.net).14Run the bundled `scripts/crawlora.sh` from this skill directory or by absolute15path. It sends `x-api-key` to `https://api.crawlora.net/api/v1`; keep the key in16the environment. Read [reference/endpoints.md](reference/endpoints.md) for the17selected endpoints, required parameters, limits, and response behavior.18Check the application `code` as well as HTTP status; successful payloads are19inside `data`. Stop on `401`/`403`, back off on `429`, and retry a transient20`5xx` once. A failed or partial fetch is not an empty market or catalog.21Bound requests to the user's scope and credit budget. For repeated collection,22save the query, source IDs, pagination progress, and retrieval timestamps with23the results so interrupted work can resume; do not create monitors implicitly.2425## Collect comparable menus26271. Define the city or coordinates, restaurant branches, meal/daypart, currency,28 collection window, and order mode. Compare the same branch across channels29 before attributing a difference to a platform. A chain name alone is not a30 branch match: verify address and location using store metadata.312. Discover DoorDash stores with `/doordash/search` and Uber Eats stores with32 `/ubereats/search`. DoorDash search is a pickup catalog; do not label its33 prices as delivery quotes. Its store and menu calls both need the same34 `latitude` and `longitude`. Uber Eats IDs are `storeUuid` values from search;35 they are not DoorDash numeric IDs. Keep platform IDs separate.363. Use `/chipotle/restaurants` to resolve a nearby `restaurant_number`, then37 `/chipotle/restaurant/menu` for its priced menu. Preserve its dine-in and38 delivery price pair, including customization charges. `/chipotle/menu` is39 national taxonomy and customization context only: omitted prices are unknown,40 never zero. `include_unavailable=true` can distinguish menu presence from41 current availability on the restaurant endpoint.424. For national menu breadth, discover McDonald's categories for one `country`43 and pass that same country and returned category slug to `/mcdonalds/menu`.44 This surface has no prices. Compare its item coverage, not invented prices.45 National catalogs and branch menus describe different scopes.4647```sh48scripts/crawlora.sh /chipotle/restaurants \49 latitude=37.7749 longitude=-122.4194 page_size=350# Take restaurant_number from discovery before fetching /chipotle/restaurant/menu.51scripts/crawlora.sh /mcdonalds/categories country=us52scripts/crawlora.sh /doordash/search \53 query=Chipotle latitude=37.7749 longitude=-122.419454```5556## Match and calculate5758- Retain original names and descriptions. Match dish, protein/filling, size,59 item count, included sides/drink, and required modifiers. Mark exact matches,60 comparable alternatives, and unmatched items separately; do not force a combo61 meal and a standalone entree into one price comparison.62- Preserve displayed currency and price units. Inspect actual payload fields63 before converting minor units; an integer alone does not prove cents. A missing64 price is null. A free modifier is not evidence that the base dish is free.65- For exact matches, report absolute difference and `(comparison - baseline) /66 baseline * 100`, only with a positive priced baseline. Use per-item or per-size67 prices only when quantities and units are known and comparable.68- Separate regular, promotional, membership, and starting prices. Menu prices69 exclude any fees, taxes, tips, and minimum-order effects not explicitly returned.70 Do not call their sum a final checkout total. Preserve availability flags.71- Count unique menu items separately from modifiers and bundles. Deduplicate items72 repeated in several menu sections without collapsing genuinely different sizes.7374## Deliverable7576Return a table with branch/address, source and collection time, order mode,77original item, matched item, portion/bundle contents, currency, price, availability,78match confidence, and price difference. Include a coverage summary with fetched79branches/sections and missing sources. Summarize price positioning and menu gaps80as hypotheses; popularity, margins, sales volume, and customer demand are not81established by menu presence. Link original URLs when returned and retain IDs and82API request paths when no public item URL is supplied.