Multi-Location Tracking
Track keyword rankings across different countries, states, and cities. Essential for
local SEO, international businesses, and location-based services.
Overview
Search results vary significantly by location. A keyword ranking #1 in New York might be
on page 3 in Los Angeles. The SerpWatch API lets you specify exact locations to get
accurate, location-specific SERP data.
Location Targeting Options
| Parameter | Description | Example |
|---|---|---|
location_name |
Human-readable location name | "New York, United States" |
location_code |
Google Ads location code (numeric) | 1023191 (New York City) |
Location Codes
We recommend using location_code for precise targeting. Location codes
correspond to Google Ads geo targets and provide the most accurate results.
See Locations & Languages for a list of common codes.
Use Cases
- Local SEO – Track rankings in specific cities for local businesses
- Multi-Location Businesses – Monitor performance across franchise locations
- International SEO – Compare rankings across different countries
- Competitor Analysis – See how competitors rank in different markets
- Location-Based Services – Optimize for “near me” and local intent queries
Basic Multi-Location Query
Track the same keyword across multiple locations by submitting separate requests
for each location. Use the batch endpoint to submit all locations efficiently.
# Track "pizza delivery" in multiple US cities
curl -X POST "https://engine.v2.serpwatch.io/api/v2/serp/crawl/google/batch" \
-H "Authorization: Bearer $SERPWATCH_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"keyword": "pizza delivery",
"location_name": "New York, United States",
"device": "mobile",
"depth": 20
},
{
"keyword": "pizza delivery",
"location_name": "Los Angeles, United States",
"device": "mobile",
"depth": 20
},
{
"keyword": "pizza delivery",
"location_name": "Chicago, United States",
"device": "mobile",
"depth": 20
}
]'
import requests
import os
API_KEY = os.environ.get("SERPWATCH_API_KEY")
BASE_URL = "https://engine.v2.serpwatch.io"
# Define target locations
locations = [
{"name": "New York, United States", "code": 1023191},
{"name": "Los Angeles, United States", "code": 1013962},
{"name": "Chicago, United States", "code": 1016367},
{"name": "Houston, United States", "code": 1026339},
{"name": "Phoenix, United States", "code": 1013659},
]
keyword = "pizza delivery"
# Build batch request
batch = []
for loc in locations:
batch.append({
"keyword": keyword,
"location_name": loc["name"],
"location_code": loc["code"],
"device": "mobile",
"depth": 20,
"language_code": "en"
})
# Submit batch
response = requests.post(
f"{BASE_URL}/api/v2/serp/crawl/google/batch",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json=batch
)
tasks = response.json()
print(f"Submitted {len(tasks)} location queries")
# Store task IDs for retrieval
task_map = {task["id"]: task["location_name"] for task in tasks}
const API_KEY = process.env.SERPWATCH_API_KEY;
const BASE_URL = "https://engine.v2.serpwatch.io";
// Define target locations
const locations = [
{ name: "New York, United States", code: 1023191 },
{ name: "Los Angeles, United States", code: 1013962 },
{ name: "Chicago, United States", code: 1016367 },
{ name: "Houston, United States", code: 1026339 },
{ name: "Phoenix, United States", code: 1013659 },
];
const keyword = "pizza delivery";
// Build batch request
const batch = locations.map(loc => ({
keyword,
location_name: loc.name,
location_code: loc.code,
device: "mobile",
depth: 20,
language_code: "en"
}));
// Submit batch
const response = await fetch(
`${BASE_URL}/api/v2/serp/crawl/google/batch`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify(batch)
}
);
const tasks = await response.json();
console.log(`Submitted ${tasks.length} location queries`);
// Store task IDs for retrieval
const taskMap = new Map(tasks.map(t => [t.id, t.location_name]));
Common Location Codes
Here are frequently used location codes for the United States. For a complete list,
see Locations & Languages.
US Major Cities
| City | Location Code | Location Name |
|---|---|---|
| New York City | 1023191 |
New York, New York, United States |
| Los Angeles | 1013962 |
Los Angeles, California, United States |
| Chicago | 1016367 |
Chicago, Illinois, United States |
| Houston | 1026339 |
Houston, Texas, United States |
| Miami | 1015116 |
Miami, Florida, United States |
| Seattle | 1027744 |
Seattle, Washington, United States |
| Boston | 1018127 |
Boston, Massachusetts, United States |
| San Francisco | 1014221 |
San Francisco, California, United States |
Countries
| Country | Location Code | Language Code |
|---|---|---|
| United States | 2840 |
en |
| United Kingdom | 2826 |
en |
| Canada | 2124 |
en or fr |
| Australia | 2036 |
en |
| Germany | 2276 |
de |
| France | 2250 |
fr |
| Spain | 2724 |
es |
| Brazil | 2076 |
pt |
Complete Multi-Location Workflow
Here’s a complete example that tracks keywords across multiple locations
and generates a comparison report.
#!/usr/bin/env python3
"""
Multi-Location Rank Tracker
Compares keyword rankings across different geographic locations
"""
import os
import time
import requests
from collections import defaultdict
API_KEY = os.environ.get("SERPWATCH_API_KEY")
BASE_URL = "https://engine.v2.serpwatch.io"
# Configuration
TARGET_DOMAIN = "yourdomain.com"
KEYWORDS = ["pizza delivery", "best pizza near me", "pizza restaurant"]
LOCATIONS = [
{"name": "New York, United States", "code": 1023191},
{"name": "Los Angeles, United States", "code": 1013962},
{"name": "Chicago, United States", "code": 1016367},
]
def submit_batch(keywords, locations):
"""Submit batch request for all keyword/location combinations."""
batch = []
for keyword in keywords:
for location in locations:
batch.append({
"keyword": keyword,
"location_name": location["name"],
"location_code": location["code"],
"device": "mobile",
"depth": 20,
"language_code": "en"
})
response = requests.post(
f"{BASE_URL}/api/v2/serp/crawl/google/batch",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json=batch
)
response.raise_for_status()
return response.json()
def wait_for_results(tasks, timeout=300):
"""Wait for all tasks to complete."""
results = {}
pending = {t["id"] for t in tasks}
start = time.time()
while pending and (time.time() - start) < timeout: for task_id in list(pending): response = requests.get( f"{BASE_URL}/api/v2/serp/crawl/{task_id}", headers={"Authorization": f"Bearer {API_KEY}"} ) data = response.json() if data["status"] in ["success", "completed", "error"]: results[task_id] = data pending.remove(task_id) if pending: print(f" Waiting... {len(pending)} tasks remaining") time.sleep(5) return results def find_rank(result, domain): """Find domain position in organic results.""" for item in result.get("result", {}).get("organic", []): item_domain = item.get("domain", "").lower() if domain.lower() in item_domain: return item["position"] return None def generate_report(tasks, results, domain): """Generate location comparison report.""" # Organize by keyword -> location -> rank
report = defaultdict(dict)
for task in tasks:
task_id = task["id"]
keyword = task["keyword"]
location = task["location_name"]
result = results.get(task_id, {})
if result.get("status") in ["success", "completed"]:
rank = find_rank(result, domain)
report[keyword][location] = rank
else:
report[keyword][location] = "Error"
return report
def print_report(report, locations):
"""Print formatted comparison report."""
# Header
loc_names = [loc["name"].split(",")[0] for loc in locations]
print("\n" + "=" * 80)
print("MULTI-LOCATION RANKING REPORT")
print("=" * 80)
print(f"\nDomain: {TARGET_DOMAIN}\n")
# Column headers
header = f"{'Keyword':<30}" for name in loc_names: header += f"{name:>12}"
print(header)
print("-" * 80)
# Data rows
for keyword, ranks in report.items():
row = f"{keyword[:28]:<30}" for loc in locations: rank = ranks.get(loc["name"]) if rank is None: display = "Not found" elif rank == "Error": display = "Error" else: display = f"#{rank}" row += f"{display:>12}"
print(row)
print("-" * 80)
def main():
total_queries = len(KEYWORDS) * len(LOCATIONS)
print(f"Tracking {len(KEYWORDS)} keywords across {len(LOCATIONS)} locations")
print(f"Total queries: {total_queries}")
print("-" * 50)
# Submit batch
print("\nSubmitting batch request...")
tasks = submit_batch(KEYWORDS, LOCATIONS)
print(f"Submitted {len(tasks)} tasks")
# Wait for results
print("\nWaiting for results...")
results = wait_for_results(tasks)
print(f"Received {len(results)} results")
# Generate report
report = generate_report(tasks, results, TARGET_DOMAIN)
print_report(report, LOCATIONS)
if __name__ == "__main__":
main()
Best Practices
Optimize Query Efficiency
- Use batch endpoints – Submit all location queries in a single batch request
- Prioritize locations – Focus on your highest-value markets first
- Set appropriate depth – Use lower depth (10-20) for local tracking where top positions matter most
- Use location codes – More precise than location names and faster to process
Local SEO Considerations
- Mobile-first – Use
device: "mobile"for local searches as most are mobile - Check local pack – Look for your business in the
local_packresults, not just organic - Monitor variations – Track both “pizza delivery” and “pizza delivery near me”
- Track competitors – Include competitor domains in your analysis
Local Pack Results
For local businesses, the local pack (map results) often matters more than organic rankings.
The SERP response includes a local_pack array with map listings. Check both
organic and local pack positions for complete local SEO tracking.
International SEO Tips
- Match language codes – Use the appropriate
language_codefor each country - Account for ccTLDs – Track your country-specific domains (example.de, example.fr)
- Consider hreflang – Different URLs may rank in different countries
- Time zone awareness – Schedule checks at appropriate local times
Credit Usage
Each location query consumes credits separately. Tracking 10 keywords across 5 locations
uses 50 credits. Plan your location coverage based on your credit budget and business priorities.
Related Topics
Rank Tracking
Learn the fundamentals of keyword rank tracking.
Batch Processing
Efficiently process large volumes of multi-location queries.