The Problem
Local SEO rankings vary by location -- a business ranks #1 within a mile but #15 three miles away. Manual rank checking is time-consuming and cannot capture geographic variation. Agencies need automated grid-based rank tracking for client reporting.
The Scavio Solution
Daily cron queries Google for target keywords with location parameters across a grid of coordinates. Record the business position for each grid point. Generate heatmap data showing ranking strength across the service area.
Before
Before automation, an agency manually checked Google Maps rankings for 5 client keywords from 3 locations. Total: 15 manual checks per day, taking 30 minutes. Coverage was sparse and missed ranking variations across neighborhoods.
After
After automation, 25 grid points x 5 keywords = 125 daily queries per client at $0.625/day ($18.75/month). Heatmap shows exact ranking for every grid point. Agency discovered a client ranked #2 in the city center but #12 in the west suburbs, leading to a targeted local content strategy that improved suburban ranking by 6 positions in 8 weeks.
Who It Is For
Local SEO agencies and multi-location businesses who need automated, location-aware Google Maps rank tracking for competitive analysis and client reporting.
Key Benefits
- 25-point grid covers the entire service area automatically
- Daily snapshots track ranking trends by neighborhood
- Competitor position tracking for the same queries
- Heatmap visualization for client reporting
- 125 queries/day per client at $0.625
Python Example
import requests, os, json
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def track_local_rank(keyword: str, business_name: str, lat: float, lon: float) -> dict:
r = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': keyword,
'location': f'{lat},{lon}'}, timeout=10).json()
# Find business position in local results
local = r.get('local_results', [])
position = None
for i, result in enumerate(local):
if business_name.lower() in result.get('title', '').lower():
position = i + 1
break
return {'keyword': keyword, 'lat': lat, 'lon': lon,
'position': position, 'total_local': len(local)}
# Grid of 5 points across service area
grid = [(40.7128, -74.0060), (40.7200, -74.0000),
(40.7050, -74.0100), (40.7180, -73.9900), (40.7100, -74.0200)]
for lat, lon in grid:
result = track_local_rank('plumber near me', 'Joes Plumbing', lat, lon)
pos = result['position'] or 'not found'
print(f'({lat},{lon}): position {pos}')JavaScript Example
const H = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
async function trackLocalRank(keyword, businessName, lat, lon) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({ platform: 'google', query: keyword, location: `${lat},${lon}` })
}).then(r => r.json());
const local = r.local_results || [];
const pos = local.findIndex(l => (l.title || '').toLowerCase().includes(businessName.toLowerCase()));
return { keyword, lat, lon, position: pos >= 0 ? pos + 1 : null };
}
const grid = [[40.7128, -74.0060], [40.7200, -74.0000]];
for (const [lat, lon] of grid) {
const r = await trackLocalRank('plumber near me', 'Joes Plumbing', lat, lon);
console.log(`(${lat},${lon}): position ${r.position || 'not found'}`);
}Platforms Used
Web search with knowledge graph, PAA, and AI overviews