Mobile app visibility extends beyond the App Store and Google Play internal search. Google surfaces Google Play app listings directly in web search results, making Google SERP rankings an important signal for app discoverability. Tracking where your app appears for target keywords in Google search — including app-specific rich results — helps you measure the impact of ASO efforts and monitor competitor apps. This tutorial builds an app ranking tracker using the Scavio Google SERP API.
Prerequisites
- Python 3.8 or higher
- requests library installed
- A Scavio API key
- Your app's Google Play URL or package name
Walkthrough
Step 1: Define app tracking targets
Set up the app package names and keywords to track. Google Play URLs contain the package name in the id parameter.
APPS = {
"My Fitness App": "com.example.fitnessapp",
"Competitor App": "com.competitor.fitnessapp",
}
KEYWORDS = ["workout tracker app", "fitness planner android", "calorie counter app"]Step 2: Search and find app positions
Search each keyword and scan organic results for Google Play URLs containing each app's package name.
def get_app_rank(keyword: str, package: str) -> int | None:
data = search_google(keyword)
for r in data.get("organic_results", []):
link = r.get("link", "")
if "play.google.com" in link and package in link:
return r["position"]
return NoneStep 3: Track multiple apps across keywords
Build a ranking matrix showing each app's position for each keyword.
def track_apps() -> dict:
matrix = {}
for kw in KEYWORDS:
matrix[kw] = {}
for app_name, package in APPS.items():
rank = get_app_rank(kw, package)
matrix[kw][app_name] = rank
return matrixStep 4: Print the ranking matrix
Display the results as a table with keywords as rows and apps as columns.
matrix = track_apps()
for kw, ranks in matrix.items():
print(f"\n{kw}:")
for app, rank in ranks.items():
print(f" {app}: {'#' + str(rank) if rank else 'not found'}")Python Example
import os
import requests
API_KEY = os.environ.get("SCAVIO_API_KEY", "your_scavio_api_key")
ENDPOINT = "https://api.scavio.dev/api/v1/search"
APPS = {"MyApp": "com.example.myapp", "CompApp": "com.competitor.app"}
KEYWORDS = ["workout tracker app", "fitness planner android"]
def search_google(q: str) -> dict:
r = requests.post(ENDPOINT, headers={"x-api-key": API_KEY},
json={"query": q, "country_code": "us"})
r.raise_for_status()
return r.json()
def get_rank(kw: str, pkg: str) -> int | None:
data = search_google(kw)
for r in data.get("organic_results", []):
if "play.google.com" in r.get("link", "") and pkg in r.get("link", ""):
return r["position"]
return None
if __name__ == "__main__":
for kw in KEYWORDS:
print(f"\n{kw}:")
for name, pkg in APPS.items():
rank = get_rank(kw, pkg)
print(f" {name}: {'#' + str(rank) if rank else 'not found'}")JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY || "your_scavio_api_key";
const ENDPOINT = "https://api.scavio.dev/api/v1/search";
const APPS = { MyApp: "com.example.myapp", CompApp: "com.competitor.app" };
const KEYWORDS = ["workout tracker app", "fitness planner android"];
async function searchGoogle(q) {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ query: q, country_code: "us" })
});
return res.json();
}
async function getRank(kw, pkg) {
const data = await searchGoogle(kw);
const match = (data.organic_results || []).find(r => r.link.includes("play.google.com") && r.link.includes(pkg));
return match ? match.position : null;
}
async function main() {
for (const kw of KEYWORDS) {
console.log(`\n${kw}:`);
for (const [name, pkg] of Object.entries(APPS)) {
const rank = await getRank(kw, pkg);
console.log(` ${name}: ${rank ? "#" + rank : "not found"}`);
}
}
}
main().catch(console.error);Expected Output
workout tracker app:
MyApp: #4
CompApp: #2
fitness planner android:
MyApp: not found
CompApp: #6