Local SEO Map Rank Tracker with API
Track Google Local Pack rankings across queries and locations programmatically. Alert on ranking drops before they compound.
Local SEO map rank tracking requires checking your Google Business Profile position across multiple search queries and locations. Manual checking does not scale past 10 locations. An API-based tracker checks hundreds of queries programmatically and alerts you when rankings drop.
Why Map Rankings Matter
Google's Local Pack (the map with 3 business listings) appears for 46% of all Google searches. If your business drops from position 1 to position 4 in the local pack, you disappear from the visible results. Unlike organic rankings that change gradually, local pack rankings can shift overnight due to review velocity, NAP inconsistencies, or competitor actions.
Building a Map Rank Tracker
Search for your target keywords, parse the local pack results, and find your business position. Run this daily across all your target queries and locations.
import requests, os
from datetime import datetime
H = {"x-api-key": os.environ["SCAVIO_API_KEY"]}
def check_local_rank(business_name, query, location=None):
"""Check business position in Google Local Pack."""
search_query = f"{query} {location}" if location else query
r = requests.post("https://api.scavio.dev/api/v1/search",
headers=H,
json={"platform": "google", "query": search_query},
timeout=10
).json()
local_pack = r.get("localPack", [])
for i, result in enumerate(local_pack):
if business_name.lower() in result.get("title", "").lower():
return {
"query": search_query,
"position": i + 1,
"total_results": len(local_pack),
"found": True,
"rating": result.get("rating"),
"reviews": result.get("reviews"),
}
return {
"query": search_query,
"position": None,
"found": False,
}
rank = check_local_rank("Blue Bottle Coffee", "coffee shop", "San Francisco")
if rank["found"]:
print(f"Position {rank['position']} for '{rank['query']}'")
else:
print(f"Not in Local Pack for '{rank['query']}")Multi-Location Tracking
Track rankings across multiple cities or neighborhoods. Each location query returns different local pack results. A business ranking #1 in downtown may not appear at all in suburban searches.
def track_all_locations(business, keywords, locations):
"""Track map rankings across all keyword-location combos."""
results = []
for keyword in keywords:
for location in locations:
rank = check_local_rank(business, keyword, location)
rank["keyword"] = keyword
rank["location"] = location
rank["date"] = datetime.now().strftime("%Y-%m-%d")
results.append(rank)
return results
keywords = ["coffee shop", "best coffee", "coffee near me"]
locations = ["San Francisco", "Oakland", "Berkeley"]
rankings = track_all_locations("Blue Bottle Coffee", keywords, locations)
found = [r for r in rankings if r["found"]]
print(f"Found in {len(found)}/{len(rankings)} queries")
for r in found:
print(f" {r['keyword']} + {r['location']}: position {r['position']}")Alert on Ranking Drops
def detect_ranking_changes(current, previous):
"""Compare current rankings to previous day."""
alerts = []
prev_map = {
(r["keyword"], r["location"]): r["position"]
for r in previous if r["found"]
}
for r in current:
key = (r["keyword"], r["location"])
prev_pos = prev_map.get(key)
if r["found"] and prev_pos:
if r["position"] > prev_pos:
alerts.append({
"type": "drop",
"keyword": r["keyword"],
"location": r["location"],
"from": prev_pos,
"to": r["position"],
})
elif not r["found"] and prev_pos:
alerts.append({
"type": "lost",
"keyword": r["keyword"],
"location": r["location"],
"previous_position": prev_pos,
})
return alertsCost at Scale
100 keywords across 10 locations = 1,000 daily queries. At $0.005/credit: $5/day or $150/month. Commercial local rank trackers (BrightLocal, Whitespark) charge $30-100/month for similar coverage but with less customization. The API approach lets you build exactly the tracker you need and integrate it into your existing monitoring stack.
Competitor Tracking
Run the same queries for competitors. If a competitor appears in a local pack where you do not, that is a gap to investigate. Track competitor review counts and ratings alongside your own to understand what drives ranking changes.