Why I Built My Own Rank Tracker (And What I Discovered)
Building a custom rank tracker using a SERP API and discovering what commercial tools hide about real search data.
Commercial rank trackers cost $50-500 per month and give you a dashboard you did not ask for. They track keywords on a schedule they choose, from locations they support, with data freshness they control. If you want something different -- custom metrics, raw SERP data, integration with your own tools -- you are out of luck.
Building your own rank tracker with a SERP API takes a few hours and costs a fraction of what commercial tools charge. More importantly, you get access to the raw search data, not just a position number.
Why Build Your Own
The main reasons to build a custom rank tracker:
- You want raw SERP features (People Also Ask, knowledge graph, featured snippets) not just rank position
- You need to track competitors' SERP features, not just their rank
- You want to integrate ranking data into your existing analytics pipeline
- You need custom alerting logic beyond simple position changes
- You want to control the check frequency and locations
The Basic Tracker
At its core, a rank tracker searches Google for a keyword and finds your domain in the results:
interface RankResult {
keyword: string;
position: number | null;
url: string | null;
title: string | null;
featuredSnippet: boolean;
peopleAlsoAsk: string[];
checkedAt: string;
}
async function checkRank(
keyword: string,
domain: string
): Promise<RankResult> {
const res = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.SCAVIO_API_KEY
},
body: JSON.stringify({
platform: "google",
query: keyword,
mode: "full",
gl: "us"
})
});
const data = await res.json();
const organic = data.organic ?? [];
const idx = organic.findIndex(
(r: any) => r.link?.includes(domain)
);
return {
keyword,
position: idx === -1 ? null : idx + 1,
url: idx === -1 ? null : organic[idx].link,
title: idx === -1 ? null : organic[idx].title,
featuredSnippet: data.featuredSnippet?.link?.includes(domain) ?? false,
peopleAlsoAsk: data.peopleAlsoAsk?.map((q: any) => q.question) ?? [],
checkedAt: new Date().toISOString()
};
}Tracking SERP Features
This is where a custom tracker shines. Commercial tools tell you your position is 4. Your tracker tells you that position 1 is a featured snippet from your competitor, positions 2-3 are Reddit threads, and position 4 is you -- but there is also a People Also Ask box pushing you below the fold.
Scavio's full mode returns all of this data:
- Featured snippets with source URL and content
- People Also Ask questions and their answers
- Knowledge graph panels
- Local pack results
- Image and video carousels
- News results and their timestamps
Batch Checking and Storage
Run your full keyword list on a schedule and store the results:
async function dailyRankCheck(
keywords: string[],
domain: string
) {
const results: RankResult[] = [];
for (const keyword of keywords) {
const result = await checkRank(keyword, domain);
results.push(result);
// Respect rate limits
await new Promise((r) => setTimeout(r, 1000));
}
// Store in your database
await db.insert("rank_checks", results);
// Check for significant changes
const alerts = await detectChanges(results);
if (alerts.length > 0) {
await sendAlerts(alerts);
}
}What You Discover
When you have access to raw SERP data, you notice things commercial trackers hide:
- Position 1 is meaningless if a featured snippet owns the click
- Your position can stay the same while the SERP layout changes dramatically
- People Also Ask boxes reveal content opportunities your competitors miss
- Local pack results cannibalize organic clicks for certain queries
A position number without context is just a vanity metric. The SERP layout tells you whether that position actually drives traffic.
Cost Math
Tracking 100 keywords daily with Scavio costs roughly $3 per month at standard pricing. A commercial rank tracker charges $50-100 per month for the same keyword volume but gives you less data. At 500 keywords, the savings are even more significant. And you own the data -- no vendor lock-in, no export limitations, no surprise price increases.