A rank tracker reports a position. What it rarely shows is how much that position depends on where the query ran and on what device. This post describes a setup for measuring that with the Google engine. It covers the method only; the measurements belong in their own post, with their own dates.
Pick what varies
Three parameters place a search:
locationtakes a canonical location name, for examplelocation=London. The Locations API lists the accepted values, and when several match, the most popular one is used.uuleis the Google-encoded form of the same thing, for when you need an exact place rather than a name.latitudeandlongitudeplace the search by coordinates in decimal degrees;glis inferred from them.
The three are mutually exclusive. device is the other axis: desktop (the default), mobile or tablet. Keep gl and hl fixed within a run so that only one thing changes between two searches.
Collect
A run is the same query, once per combination. Save each response under a name that says what it was:
for location in London Manchester Edinburgh; do
for device in desktop mobile; do
curl -s "https://www.searchapi.io/api/v1/search?engine=google&q=coffee+shops&location=$location&gl=gb&hl=en&device=$device&api_key=YOUR_API_KEY" \
> "coffee-$location-$device.json"
done
done
Two fields in search_metadata matter for later: id, which re-opens the search, and html_url, the page as it was parsed. When a number looks odd weeks later, the HTML is the evidence.
Compare
Organic results are an ordered list of links, so the simplest comparison is set overlap plus the movement of the links both pages share:
import json
def links(path):
with open(path) as f:
return [result["link"] for result in json.load(f).get("organic_results", [])]
a = links("coffee-London-desktop.json")
b = links("coffee-London-mobile.json")
overlap = len(set(a) & set(b)) / len(set(a) | set(b))
print(f"overlap: {overlap:.2f}")
for link in a:
if link in b and a.index(link) != b.index(link):
print(f"{link}: {a.index(link) + 1} -> {b.index(link) + 1}")
An overlap of 1.0 means the two pages list the same links; the loop then shows which of them moved and by how much. Run it across locations with the device fixed, then across devices with the location fixed, and the two numbers separate the two effects.
What to record
For every search, keep the query, location, device, the timestamp, the search id, the ordered links, and which top-level keys were present. That last one captures the features: a local pack appearing on mobile but not on desktop is a bigger change than any single position shift, and it shows up as local_results in one file and not the other.
Repeat the run on a few different days. Google changes results over time on its own, and without a baseline of day-to-day movement, a difference between two locations can not be told apart from a difference between two afternoons.