LSD

Geogrid Rank Scan

Map Google Maps rankings across a geographic grid centered on a location. Returns a rank matrix showing where a business ranks from each grid point, plus ARP, ATRP and SoLV scores. 5x5 by default; 3x3, 7x7 and 9x9 on request, at 2 credits a point.

When to use this

You want to see where your business ranks on Google Maps from different parts of your city — not just from one location, but from a grid of 9 to 81 points around your area. It's like checking your ranking from every neighborhood at once. Shows you exactly which parts of town you dominate and where you're invisible.

POST/v1/geogrid/scan
Cost: 2 credits per grid point: 50 credits for the default 5x5. 18 (3x3), 98 (7x7) or 162 (9x9) when you set grid_size
Rate Limit: Varies by plan
Response: Asynchronous. The submit returns a job_id in about a second. The scan usually takes 25-40 seconds whatever its size, occasionally longer. Collect it from poll_url.

Parameters

ParameterTypeRequiredDescription
businessstringNoBusiness name to track, matched against listing titles. Required unless place_id is given.
place_idstringNoGoogle place_id for the business. Matches exactly one listing, so it is the reliable choice; when given, business is not used for matching.
locationstringNoCenter point — city/state or lat,lng (e.g. "Brooklyn, NY"). Required unless center is given.
centerobjectNoExact center as {"lat": 40.6892, "lng": -73.9857}. Overrides location. Use the business's own coordinates when tracking it over time, so the grid never moves.
keywordstringYesSearch keyword (e.g. "pizza")
grid_sizestringNo"3x3", "5x5", "7x7" or "9x9". Default: "5x5". Larger grids cost more: 2 credits per point.
radius_milesnumberNoDistance from the center to the edge of the grid, in miles. Default: 3
zoomstring | integerNo"auto" (14) or a Maps zoom from 3 to 21. Default: "auto". Fix it only to match an existing series.
include_listingsbooleanNoAlso return the top 20 organic listings at every point, for competitor analysis. Same price; a 9x9 response runs to about half a megabyte. Default: false
callback_urlstringNoPublic https URL to POST the finished scan to, instead of polling.

Example Request

curl -X POST https://api.localseodata.com/v1/geogrid/scan \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "business": "Joe'\''s Pizza",
    "location": "Brooklyn, NY",
    "keyword": "pizza",
    "grid_size": "5x5",
    "radius_miles": 3
  }'

Example Response

JSON
// The submit. Credits are charged here.
{
  "status": "success",
  "credits_used": 50,
  "data": {
    "job_id": "geo_V1StGXR8Z5",
    "status": "pending",
    "estimated_seconds": 25,
    "poll_url": "/v1/geogrid/status/geo_V1StGXR8Z5"
  }
}

// GET the poll_url until status is "complete" or "failed". Polling is free.
{
  "status": "success",
  "credits_used": 0,
  "data": {
    "job_id": "geo_V1StGXR8Z5",
    "status": "complete",
    "grid_size": "5x5",
    "radius_miles": 3,
    "center": { "lat": 40.6892, "lng": -73.9857 },
    "keyword": "pizza",
    "business_name": "Joe's Pizza",
    "zoom": 14,
    "zoom_mode": "auto",
    "average_rank": 3.2,
    "atrp": 6.1,
    "solv": 48,
    "found_in": 21,
    "failed_points": 0,
    "total_points": 25,
    "credits_refunded": 0,
    "grid": [
      [4, 2, 1, 3, 5],
      [3, 1, 1, 2, 4]
    ],
    "grid_points": [
      { "row": 0, "col": 0, "lat": 40.710, "lng": -74.006, "rank": 4, "status": "ok" },
      { "row": 0, "col": 1, "lat": 40.710, "lng": -73.996, "rank": 2, "status": "ok" }
    ],
    "cached": false,
    "completed_at": "2026-09-20T21:34:25.447Z"
  }
}

Response Fields

FieldTypeDescription
job_idstringThe scan's id. The submit returns it; the poll URL carries it
statusstring"pending" or "running" while the scan is going, then "complete" or "failed"
poll_urlstringSubmit only. GET this path to collect the scan. Polling is free and does not expire
estimated_secondsintegerSubmit only. Usual time to finish
progressintegerWhile running: 0, then total once complete
average_rankfloatARP: average rank across the points where the business was found (lower is better)
atrpfloatATRP: average rank across every point that answered, counting not found as 21
solvfloatSoLV: percentage of answered points where the business ranks in the top 3
found_inintegerHow many grid points found the business in the top 20
failed_pointsintegerPoints that could not be checked. They are left out of the scores and refunded
credits_refundedintegerCredits returned for failed points: 2 each
total_pointsintegerPoints in the grid: 9, 25, 49 or 81
gridarray[][]Rank at each point as a plain 2D number matrix, row by row. 0 means not found, or a failed point
grid_pointsarrayThe same points as objects carrying row, col, lat, lng, rank and status ("ok" or "error"). With include_listings, each also carries results: the top 20 organic listings (place_id, cid, title, category, rating, reviews_count, address, lat, lng)
grid_sizestringGrid dimensions ("3x3", "5x5", "7x7", "9x9")
centerobjectCenter point lat/lng of the grid
business_namestringThe business's name as Google Maps lists it, or null if it was not found
zoomintegerThe Maps zoom each point searched at
cachedbooleanWhether the scan was served from a previous run. A cached scan carries no job_id
errorstringOn status "failed" only: why the scan died. A failed scan is refunded

Notes

  • This endpoint submits and returns immediately. It hands back a job_id and a poll_url, not a grid — GET the poll_url until status is "complete". Polling is free and does not expire.
  • Credits are charged at submit. A scan that fails is refunded in full, and so is any single point that could not be checked. Polling costs nothing, so the poll response reads credits_used: 0.
  • An identical submit inside the replay window returns the scan already running rather than starting a second one, and comes back with deduplicated: true at 0 credits.
  • The default grid is 5x5 = 25 points (50 credits). Set grid_size for a different grid; every size costs 2 credits a point: 3x3 = 9 points (18 credits), 7x7 = 49 points (98 credits), 9x9 = 81 points (162 credits).
  • Ranks count organic Google Maps listings only. Sponsored listings are skipped, so a business is never ranked on its own ad.
  • Rankings hold across the whole grid, outer points included: a business is not lost at the edges of a wide grid.
  • Rank of 0 means the business was not in the top 20 at that grid point.
  • Combine with Claude via MCP for narrative interpretation of grid results.
  • Store results over time to track geographic ranking trends.