DEV Community

Elowen
Elowen

Posted on

Build a Location-Aware SERP Check for Local SEO Experiments

A keyword does not always have one SERP.

The result page for the same query can change by city, region, country, language, or device context. If your script only checks the default location, you may be reviewing a search page your target users never see.

This post shows a small pattern for building a location-aware SERP check.

The SERP collection layer can be a provider such as TalorData SERP API. The important part in your application is making location an explicit input instead of a hidden default.

Why location should be explicit

Location affects many search workflows:

  • local SEO monitoring
  • regional competitor research
  • market-specific content planning
  • location-sensitive product categories
  • queries with map, service, or retail intent
  • multi-country SERP comparison

Even if you are not doing local SEO, location can still change which domains, page types, and snippets appear.

A location-aware check helps you avoid treating one SERP as the universal result.

A simple input shape

Start with a query config:

{
  "keyword": "serp api for seo monitoring",
  "location": "New York, United States",
  "language": "en",
  "device": "desktop"
}
Enter fullscreen mode Exit fullscreen mode

The exact supported location fields depend on your SERP API provider. Keep your internal shape stable, then map it to the provider parameters in one place.

Minimal Python example

This example is intentionally generic. Replace endpoint, auth, parameters, and response fields with the real API documentation for your provider.

import json
import os
from datetime import datetime, timezone
from pathlib import Path

import requests


SERP_API_ENDPOINT = os.environ["SERP_API_ENDPOINT"]
SERP_API_KEY = os.environ["SERP_API_KEY"]
OUTPUT_DIR = Path("location_serp_snapshots")


QUERY_CONFIGS = [
    {
        "keyword": "serp api for seo monitoring",
        "location": "New York, United States",
        "language": "en",
        "device": "desktop",
    },
    {
        "keyword": "serp api for seo monitoring",
        "location": "Austin, United States",
        "language": "en",
        "device": "desktop",
    },
]


def fetch_serp(config: dict) -> dict:
    response = requests.get(
        SERP_API_ENDPOINT,
        headers={"Authorization": f"Bearer {SERP_API_KEY}"},
        params={
            "q": config["keyword"],
            "location": config["location"],
            "language": config["language"],
            "device": config["device"],
        },
        timeout=30,
    )
    response.raise_for_status()
    return response.json()
Enter fullscreen mode Exit fullscreen mode

Normalize the result

Keep location in every saved snapshot:

def normalize_snapshot(config: dict, raw: dict) -> dict:
    results = []

    # Adjust this path to match your SERP API response schema.
    for index, item in enumerate(raw.get("organic_results", [])[:10], start=1):
        results.append(
            {
                "position": item.get("position", index),
                "title": item.get("title"),
                "url": item.get("link") or item.get("url"),
                "snippet": item.get("snippet"),
            }
        )

    return {
        "keyword": config["keyword"],
        "location": config["location"],
        "language": config["language"],
        "device": config["device"],
        "checked_at": datetime.now(timezone.utc).isoformat(),
        "results": results,
    }
Enter fullscreen mode Exit fullscreen mode

Save one file per keyword and location

def safe_name(value: str) -> str:
    return (
        value.lower()
        .replace(" ", "_")
        .replace(",", "")
        .replace("/", "_")
    )


def save_snapshot(snapshot: dict) -> Path:
    OUTPUT_DIR.mkdir(exist_ok=True)

    filename = "__".join(
        [
            safe_name(snapshot["keyword"]),
            safe_name(snapshot["location"]),
            snapshot["checked_at"][:10],
        ]
    )

    path = OUTPUT_DIR / f"{filename}.json"
    with path.open("w", encoding="utf-8") as file:
        json.dump(snapshot, file, indent=2, ensure_ascii=False)

    return path


if __name__ == "__main__":
    for config in QUERY_CONFIGS:
        raw = fetch_serp(config)
        snapshot = normalize_snapshot(config, raw)
        path = save_snapshot(snapshot)
        print(f"Saved {config['keyword']} for {config['location']} to {path}")
Enter fullscreen mode Exit fullscreen mode

Compare locations carefully

Once you have snapshots for multiple locations, compare them with context.

Useful questions:

  • Which domains appear in every location?
  • Which domains are location-specific?
  • Which SERP features appear only in some markets?
  • Does the query show local intent in one city but informational intent in another?
  • Are competitors different across regions?

Do not assume every difference is meaningful. Use repeated checks before making a decision.

Where the SERP API fits

The SERP API provides structured search result data for each configured location.

Your code should make location visible in the config, file name, storage model, and report output.

For workflows that need repeatable location-aware search result collection, TalorData can provide the collection layer while your application owns the experiment design and comparison rules.

Final note

If you run local or regional SEO checks, do you compare cities, countries, languages, devices, or all of them separately?

Top comments (0)