← ジャーナルに戻る
· 19 分で読了

SEO Rank Tracking Without Paid Tools: How to Monitor Your Search Rankings for Free

Rank tracking is the most oversold part of SEO. Here's how to monitor your keyword rankings accurately using Google Search Console, free APIs, and a DIY Python tracker — without paying $99/month for Ahrefs or Semrush.

I spent three months obsessing over keyword rankings. Every morning, I’d open my rank tracker, type in a keyword, scroll past the ads, and count where my page appeared. Position 12. Position 9. Position 7. Then back to 11. Then 15. Then 6. I was tracking 40 keywords manually, and it was eating 30 minutes of my day.

The worst part? I was doing it wrong.

Manual rank checking is inherently unreliable. Google personalizes results based on location, search history, device, and dozens of other signals. The rank I saw at my desk in the morning wasn’t the same rank someone in another city saw, or even what I’d see in incognito mode. I was making decisions based on phantom data.

When I finally understood how rank tracking actually works — and how little of it you need paid tools for — I built a system that gives me better data than any $99/month tracker, using nothing but free tools and a Python script. This guide walks through everything I learned.

Why Most Rank Tracking Advice Is Wrong

Open any SEO blog and you’ll find the same advice: “Track your rankings daily. Use Ahrefs, Semrush, or SE Ranking. Watch for position changes and optimize accordingly.”

This advice has three problems:

Problem 1: Rankings are personalized. Google doesn’t serve one universal ranking. The same query returns different results for different users based on location, language, search history, Google account activity, and device. A rank tracker that checks from a single data center in one location is sampling one possible result set out of thousands. The “position 7” it reports might be position 3 for some users and position 15 for others.

Problem 2: Rankings fluctuate naturally. I’ve watched keywords bounce 5-10 positions day to day with no changes on my end. Google constantly tests different result orderings. If you react to every fluctuation, you’ll drive yourself crazy making changes that have no effect.

Problem 3: Position doesn’t predict traffic. I had a keyword where I ranked position 4 and got 3 clicks a month. Another keyword at position 11 brought 40 clicks. Why? Search volume, SERP features (featured snippets, People Also Ask, local packs), and click-through rate variations. A rank tracker tells you position. It doesn’t tell you what actually matters: traffic, engagement, and conversions.

This doesn’t mean rank tracking is useless. It means you need to track the right things, interpret the data correctly, and not overpay for tools that give you a false sense of precision.

What Actually Matters in Rank Tracking

Before building a tracking system, let me clarify what’s worth tracking:

Average position trends, not daily snapshots. A single day’s ranking is noise. A 7-day or 30-day average position smooths out fluctuations and shows the real trend. Is your average position improving over weeks? That’s signal. Did you drop 3 positions overnight? That’s noise.

Impressions and clicks, not just position. Google Search Console gives you impression and click data for every keyword your site ranks for. This is far more valuable than raw position because it accounts for search volume and SERP features. A position 15 result in a high-volume query with a featured snippet above it might get zero impressions. A position 5 result in a niche query might get consistent traffic.

Page-level performance, not keyword-level obsession. Instead of tracking 100 individual keywords, track how each page performs across all its keywords. A single blog post might rank for 200 different queries. Tracking each one individually is unsustainable. Tracking the page’s aggregate performance tells you whether the content is working.

Competitor movements, not just your own. When your rankings drop, the first question should be “Who took my spot?” not “What did I do wrong?” Sometimes you did nothing wrong — a competitor published better content or earned a strong backlink. Context matters.

Method 1: Google Search Console (The Only Rank Tracker You Need)

Google Search Console is the most accurate rank tracking tool available, and it’s free. The data comes directly from Google — not from a third-party scraper checking from a random data center.

Here’s the thing most guides miss: GSC doesn’t show you “your ranking for keyword X.” It shows you the aggregate performance of your site across all the keywords Google has seen your site appear for. This is actually better than rank tracking because it reflects real user behavior, not simulated queries.

Setting Up GSC for Rank Tracking

If you haven’t already, verify your site in Google Search Console. I recommend domain verification (DNS TXT record) because it covers all subdomains and both http/https variants automatically. Property-level verification (HTML file or meta tag) only covers one specific protocol and subdomain.

Once verified, the Performance > Search results report is your rank tracking dashboard. Here’s how to use it:

1. Enable the “Average position” metric. By default, GSC shows clicks, impressions, and CTR. Click the “Average position” checkbox to add position data. Now you see the average ranking position for each query across the selected time period.

2. Filter by page to track specific content. Click “Add filter > Page” and enter a URL. Now you see all queries that page ranks for, with position data for each. This is page-level tracking — far more useful than keyword-level because it shows you the full picture of how a page performs.

3. Compare date ranges to see trends. Click the date selector and choose “Compare.” I use “Last 28 days vs. previous 28 days” as my default comparison. This shows you whether each query’s position improved or declined, with the exact delta. Green arrows mean improvement, red means decline.

4. Export to build a historical record. GSC only retains 16 months of data. If you want longer-term tracking, export your data monthly and store it. I keep a simple CSV per month with columns: query, page, clicks, impressions, CTR, position. After a year, I can chart trends that GSC’s UI can’t show.

The Queries Report: Your Keyword Intelligence Source

The Queries tab in the Performance report lists every search query that triggered your site in Google’s results. This is gold. Here’s how I mine it:

Sort by position (ascending) to find near-miss opportunities. Queries where you rank position 4-15 are your biggest opportunities. You’re on page one or the top of page two — a small content improvement or internal link boost could push you into the top 3. I maintain a running list of queries in the 4-15 range and review it monthly.

Sort by impressions (descending) to find visibility gaps. High impressions with low CTR means your page appears in results but users don’t click. This usually means a weak title tag or meta description, or a SERP feature (like a featured snippet or ads) pushing your result below the fold. I rewrite titles and descriptions for any query with 100+ impressions and less than 2% CTR.

Sort by clicks (descending) to find your money keywords. These are the queries that actually bring traffic. Double down on them — create related content, build internal links, and optimize the landing page for conversions.

Look for “new” queries. When you compare date ranges, GSC shows queries that appeared for the first time. These are early signals that Google is associating your site with new topics. If a new query is relevant to your content, consider creating dedicated content for it.

The Pages Report: Content-Level Tracking

Switch from Queries to Pages in the Performance report. This shows you how each page performs across all its keywords combined. This is where I spend most of my analysis time.

Identify declining pages. Sort by the position delta column (in compare mode). Pages with declining average position need attention — they may need content updates, fresh internal links, or technical fixes.

Identify growing pages. Pages with improving position are working. Analyze why: Did you recently update the content? Did you earn a new backlink? Did you add internal links? Replicate whatever worked.

Find underperforming pages with potential. Pages with high impressions but low clicks have visibility but poor engagement. This is usually a title/meta description problem, not a ranking problem. A headline rewrite can double your CTR without changing your position.

GSC Limitations (And How to Work Around Them)

GSC isn’t perfect. Here are the limitations I’ve learned to work around:

Data delay. GSC data is typically 2-3 days delayed. The most recent data you’ll see is from 2 days ago. For real-time tracking, you need manual SERP checks or API-based tools (covered later).

Sampling. GSC shows a maximum of 1,000 rows per query in the UI. If your site ranks for thousands of queries, the UI truncates. Use the GSC API to get complete data — the API returns up to 50,000 rows per request.

No exact position tracking. GSC shows average position over a time period, not the position at a specific moment. This is actually better for trend analysis but makes it hard to know “am I ranking position 3 or position 5 right now?”

Aggregate, not per-user. GSC data is aggregated across all users. You can’t see how you rank for a specific user in a specific location. For local rank tracking, you need other methods.

16-month data retention. As mentioned, export monthly if you need long-term history.

Method 2: The Incognito SERP Check (For Quick Spot Checks)

Sometimes you just want to know “does my page show up when I Google this?” The incognito method is the simplest approach:

  1. Open a new incognito/private window
  2. Search for your target keyword
  3. Count your position manually

This is crude but useful for quick checks. Here’s how to make it more accurate:

Add &pws=0 to the URL to disable personalization. After searching, add &pws=0 to the end of the Google search URL. This tells Google to depersonalize results. It’s not perfect — Google removed the full effect of this parameter years ago — but it helps.

Use &num=100 to see more results per page. Add &num=100 to see 100 results instead of 10. This lets you find your page even if it’s on page 5 without clicking through pages.

Change location in search tools. Click “Search tools > Any country” and set a specific country to see localized results. For city-level results, append &near=cityname to the URL.

Combine both parameters. A URL like https://www.google.com/search?q=your+keyword&pws=0&num=100 gives you a depersonalized view of the top 100 results. I bookmark template URLs for my top 20 keywords and check them weekly.

The limitation is obvious: this is manual, time-consuming, and still not perfectly depersonalized. But for a quick sanity check — “is my page even in the top 100?” — it works.

Method 3: Free SERP APIs for Automated Rank Checking

If you want automated rank tracking without paying for Ahrefs or Semrush, free SERP APIs are the way to go. Here are the ones I use:

Serper.dev (2,500 Free Searches/Month)

Serper.dev provides Google SERP results via API. The free tier gives you 2,500 searches per month — enough to track 80 keywords daily (80 × 31 days = 2,480).

Here’s a simple Python script I use to check rankings:

import requests, json

SERPER_API_KEY = "your_api_key"
keyword = "free seo audit"
target_domain = "zens.ink"

response = requests.post(
    "https://google.serper.dev/search",
    headers={"X-API-KEY": SERPER_API_KEY, "Content-Type": "application/json"},
    json={"q": keyword, "num": 100}
)

results = response.json().get("organic", [])
position = None
for i, result in enumerate(results, 1):
    if target_domain in result.get("link", ""):
        position = i
        url = result["link"]
        title = result["title"]
        break

if position:
    print(f"Position {position}: {title}")
    print(f"URL: {url}")
else:
    print(f"{target_domain} not found in top 100 for '{keyword}'")

This returns the exact position, title, and URL of your ranking page. Run it for multiple keywords and you have a basic rank tracker.

Brave Search API (2,000 Free Queries/Month)

Brave Search API is another free option. The free tier gives you 2,000 queries per month. It’s not a Google SERP clone — it has its own index — but it’s useful as a second data point.

import requests

BRAVE_API_KEY = "your_api_key"
keyword = "free seo audit"
target_domain = "zens.ink"

response = requests.get(
    "https://api.search.brave.com/res/v1/web/search",
    headers={"X-Subscription-Token": BRAVE_API_KEY, "Accept": "application/json"},
    params={"q": keyword, "count": 20}
)

results = response.json().get("web", {}).get("results", [])
for i, result in enumerate(results, 1):
    if target_domain in result.get("url", ""):
        print(f"Brave position {i}: {result['title']}")
        break

Google Custom Search API (100 Free Searches/Day)

Google’s Custom Search JSON API gives you 100 free searches per day (3,000/month). You need to create a Custom Search Engine in the Google Cloud Console. By default, CSE searches the entire web (if you don’t restrict it to specific sites), giving you Google search results via API.

import requests

API_KEY = "your_google_api_key"
CSE_ID = "your_custom_search_engine_id"
keyword = "free seo audit"
target_domain = "zens.ink"

response = requests.get(
    "https://www.googleapis.com/customsearch/v1",
    params={"key": API_KEY, "cx": CSE_ID, "q": keyword, "num": 10}
)

for i, item in enumerate(response.json().get("items", []), 1):
    if target_domain in item.get("link", ""):
        print(f"Position {i}: {item['title']}")
        print(f"URL: {item['link']}")
        break

The limitation is 10 results per request, and CSE results don’t perfectly match regular Google search results (Google applies different ranking signals to CSE). But it’s another free data point.

Comparing the Three APIs

I run all three for my top 20 keywords weekly:

  • Serper.dev gives the closest approximation to real Google SERPs because it scrapes Google directly.
  • Brave Search provides a different perspective — if your page ranks on both Google and Brave, that’s a stronger signal than ranking on one.
  • Google CSE uses Google’s index but with slightly different ranking. Good for cross-referencing.

Total monthly cost: $0. Total queries available: ~7,500. That’s more than enough for weekly tracking of 100+ keywords.

Method 4: Building a DIY Rank Tracker in Python

Running individual scripts for each keyword is tedious. Here’s how I built a complete rank tracker that runs weekly, stores results in a CSV, and generates a trend report.

#!/usr/bin/env python3
"""
DIY Rank Tracker — Zero cost, fully automated.
Tracks keyword positions using Serper.dev free API.
Stores results in CSV for historical trend analysis.
"""

import requests, csv, json, os
from datetime import datetime, timedelta

SERPER_API_KEY = os.environ.get("SERPER_API_KEY", "")
TARGET_DOMAIN = "zens.ink"
DATA_FILE = "rank_history.csv"

KEYWORDS = [
    "free seo audit",
    "keyword research without ahrefs",
    "geo optimization",
    "technical seo audit free",
    "keyword clustering free",
    "search intent analysis",
    "on-page seo checklist",
    "backlink analysis free",
    "content gap analysis free",
    "core web vitals check",
    "fix indexing issues",
    "serp analysis without tools",
    "rank tracking without paid tools",
    "seo without ahrefs",
    "free seo tools for developers",
]

def check_rank(keyword, domain):
    """Check ranking position for a keyword using Serper.dev."""
    try:
        response = requests.post(
            "https://google.serper.dev/search",
            headers={
                "X-API-KEY": SERPER_API_KEY,
                "Content-Type": "application/json"
            },
            json={"q": keyword, "num": 100},
            timeout=15
        )
        results = response.json().get("organic", [])
        for i, result in enumerate(results, 1):
            if domain in result.get("link", ""):
                return {
                    "position": i,
                    "url": result["link"],
                    "title": result["title"]
                }
        return {"position": None, "url": None, "title": None}
    except Exception as e:
        print(f"  Error checking '{keyword}': {e}")
        return {"position": None, "url": None, "title": None}

def save_results(results, filename):
    """Append results to CSV file."""
    file_exists = os.path.isfile(filename)
    with open(filename, "a", newline="") as f:
        writer = csv.writer(f)
        if not file_exists:
            writer.writerow(["date", "keyword", "position", "url", "title"])
        for r in results:
            writer.writerow([
                r["date"], r["keyword"],
                r["position"] if r["position"] else "100+",
                r["url"] or "", r["title"] or ""
            ])

def generate_report(filename, days=30):
    """Generate a trend report comparing current vs. past positions."""
    if not os.path.isfile(filename):
        print("No history file found.")
        return

    rows = []
    with open(filename, "r") as f:
        reader = csv.DictReader(f)
        for row in reader:
            rows.append(row)

    today = datetime.now().date()
    past = today - timedelta(days=days)

    print(f"\n{'='*60}")
    print(f"Rank Trend Report — Last {days} days")
    print(f"{'='*60}")
    print(f"{'Keyword':<35} {'Current':<10} {'Previous':<10} {'Change':<10}")
    print(f"{'-'*35} {'-'*10} {'-'*10} {'-'*10}")

    for keyword in KEYWORDS:
        keyword_rows = [r for r in rows if r["keyword"] == keyword]
        if not keyword_rows:
            continue

        # Get most recent position
        recent = [r for r in keyword_rows if datetime.strptime(r["date"], "%Y-%m-%d").date() >= past]
        if recent:
            current = recent[-1]["position"]
        else:
            current = keyword_rows[-1]["position"]

        # Get position from ~30 days ago
        older = [r for r in keyword_rows if datetime.strptime(r["date"], "%Y-%m-%d").date() < past]
        previous = older[-1]["position"] if older else "N/A"

        # Calculate change
        if current != "N/A" and previous != "N/A":
            try:
                delta = int(previous) - int(current)
                change = f"+{delta}" if delta > 0 else str(delta) if delta < 0 else "—"
                if delta > 0:
                    change = f"↑{delta}"
                elif delta < 0:
                    change = f"↓{abs(delta)}"
            except ValueError:
                change = "—"
        else:
            change = "—"

        print(f"{keyword:<35} {current:<10} {previous:<10} {change:<10}")

if __name__ == "__main__":
    today = datetime.now().strftime("%Y-%m-%d")
    print(f"Checking rankings for {TARGET_DOMAIN} on {today}...")
    print(f"Keywords: {len(KEYWORDS)}\n")

    results = []
    for keyword in KEYWORDS:
        rank = check_rank(keyword, TARGET_DOMAIN)
        pos_str = str(rank["position"]) if rank["position"] else "100+"
        print(f"  {keyword:<40} → Position {pos_str}")
        rank["date"] = today
        rank["keyword"] = keyword
        results.append(rank)

    save_results(results, DATA_FILE)
    print(f"\nResults saved to {DATA_FILE}")

    if os.path.isfile(DATA_FILE):
        generate_report(DATA_FILE, days=28)

This script does three things:

  1. Checks current rankings for all tracked keywords via Serper.dev
  2. Stores results in a CSV file for historical tracking
  3. Generates a trend report comparing current vs. previous positions

I run this every Sunday via cron. The output looks like:

Checking rankings for zens.ink on 2026-08-05...
Keywords: 15

  free seo audit                            → Position 8
  keyword research without ahrefs           → Position 12
  geo optimization                          → Position 100+
  ...

Results saved to rank_history.csv

============================================================
Rank Trend Report — Last 28 days
============================================================
Keyword                              Current    Previous   Change
----------------------------------- ---------- ---------- ----------
free seo audit                       8          11         ↑3
keyword research without ahrefs     12          15         ↑3
geo optimization                     100+       100+       —

Setting Up Automated Cron

On any Linux server or even a GitHub Action, you can automate this:

# Add to crontab — runs every Sunday at 9 AM
0 9 * * 0 cd /path/to/tracker && SERPER_API_KEY=your_key python3 rank_tracker.py >> tracker.log 2>&1

Or use GitHub Actions for a server-free setup:

name: Weekly Rank Tracking
on:
  schedule:
    - cron: '0 9 * * 0'
jobs:
  track:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install requests
      - run: python3 rank_tracker.py
        env:
          SERPER_API_KEY: ${{ secrets.SERPER_API_KEY }}
      - uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "Weekly rank tracking update"

The GitHub Action runs weekly, checks rankings, commits the updated CSV to your repo, and costs nothing.

Method 5: Bing Webmaster Tools (The Underrated Alternative)

Everyone focuses on Google rankings, but Bing powers a significant chunk of search traffic — especially through Windows search, Edge browser, and AI search experiences like ChatGPT’s web browsing.

Bing Webmaster Tools is free and provides ranking data similar to GSC but for Bing’s search engine. The Search Performance report shows queries, impressions, clicks, and average position.

Why this matters: Bing’s index feeds multiple AI search experiences. If your site ranks well on Bing, it’s more likely to appear in AI-generated answers. Tracking Bing rankings alongside Google gives you a more complete picture of your search visibility.

The interface is less polished than GSC, but the data is valuable:

Keyword research tool. Bing’s keyword research tool shows search volume trends for keywords. I use it as a free alternative to Ahrefs’ keyword explorer for initial volume estimates.

SEO Reports. Bing automatically scans your site and generates an SEO report with specific issues to fix. It’s like a mini technical audit for free.

Site Explorer. Shows how Bingbot sees your site, which pages are indexed, and any crawl issues.

I check Bing Webmaster Tools monthly. It takes 10 minutes and often reveals opportunities I miss in GSC — keywords that drive more Bing traffic than Google traffic, or pages that Bing indexes faster than Google.

How to Interpret Rank Data Without Losing Your Mind

Having data is one thing. Interpreting it correctly is another. Here are the principles I follow:

Rule 1: Never React to a Single Data Point

A position change of 3 spots in one day means nothing. Google constantly reshuffles results. I wait at least 7 days before concluding that a ranking change is real, and 30 days before taking action.

Exception: If a page drops from position 3 to position 50+ overnight, investigate immediately. That’s not normal fluctuation — it usually signals a technical issue (broken page, robots.txt block, accidental noindex, server error) or a manual penalty.

Rule 2: Track Positions in Buckets

Instead of obsessing over exact positions, group keywords into buckets:

  • Top 3: Money positions. These get the most clicks. Maintain and defend.
  • Positions 4-10: Page one. Strong visibility. Push to improve.
  • Positions 11-20: Page two. Close to breakthrough. Focus optimization here for quick wins.
  • Positions 21-50: Indexed but buried. Needs significant content or link improvement.
  • 50+ or unranked: Not competitive yet. Consider whether the keyword is worth pursuing.

Moving from bucket to bucket (e.g., 11-20 to 4-10) is more meaningful than moving from position 13 to 11.

Rule 3: Correlate Position Changes With Actions

When your position improves, identify what you did:

  • Published new content on the topic
  • Updated existing content
  • Added internal links
  • Earned a new backlink
  • Fixed a technical issue
  • Nothing (natural fluctuation)

Keep a simple log of SEO actions with dates. When rankings change, check what happened 1-2 weeks before. Over time, you’ll learn which actions actually move the needle for your site.

I keep this in a simple text file:

2026-07-15: Published GSC guide (2,800 words)
2026-07-18: Updated internal links from 5 posts to GSC guide
2026-07-20: Earned backlink from dev.to article
2026-07-25: Updated keyword clustering article (added FAQ schema)
2026-08-01: Fixed broken internal links (12 found and fixed)

Rule 4: Watch the SERP, Not Just Your Position

Your position can stay the same while your traffic changes dramatically. Why? SERP features.

If Google adds a featured snippet above your position 3 result, your CTR might drop by 30%. If Google removes a featured snippet, your traffic might jump without any position change.

Check the SERP for your important keywords periodically:

  • Is there a featured snippet? (Can you steal it?)
  • Are there People Also Ask boxes? (Can you answer those questions in your content?)
  • Are there image/video results pushing organic results down?
  • How many ads are above the organic results?

Use Serper.dev or manual checks to see the full SERP layout, not just your position.

Building a Sustainable Weekly Workflow

Here’s my exact rank tracking workflow. It takes about 45 minutes per week:

Monday (10 minutes):

  • Open GSC, compare last 7 days vs. previous 7 days
  • Note any queries with significant position changes
  • Check the “Pages” report for declining content

Wednesday (15 minutes):

  • Run the Python rank tracker script for all tracked keywords
  • Review the trend report
  • Add any new keywords discovered in GSC to the tracker

Friday (10 minutes):

  • Manual SERP check for top 5 priority keywords using incognito
  • Note SERP feature changes (new featured snippets, PAA boxes, etc.)
  • Check if competitors have moved significantly

Monthly (30 minutes):

  • Run the full trend report (28-day comparison)
  • Export GSC data for historical archive
  • Check Bing Webmaster Tools
  • Review and update the keyword tracking list (add new targets, remove dead ones)
  • Update the SEO actions log with the month’s activities

Total weekly time: ~35 minutes. Monthly: ~2.5 hours. Total cost: $0.

Common Pitfalls to Avoid

Pitfall 1: Tracking too many keywords. I started with 200 keywords. Half of them were variations of the same intent. I was spending hours analyzing noise. Cut to 30-50 keywords that represent your most important pages and topics. Quality over quantity.

Pitfall 2: Checking rankings daily. Daily checking leads to emotional reactions. Rankings fluctuate. Check weekly, analyze monthly, act quarterly. Your mental health will improve.

Pitfall 3: Ignoring long-tail keywords. Rank trackers often miss long-tail queries because you’re not explicitly tracking them. But long-tail keywords often have higher conversion rates. Use GSC’s queries report to discover long-tail keywords you’re already ranking for, and optimize for them.

Pitfall 4: Confusing ranking with revenue. Position 1 for a keyword nobody searches for is worthless. Position 15 for a keyword with high commercial intent and decent volume might bring qualified traffic. Always connect rank tracking to business outcomes — traffic, leads, revenue — not just position numbers.

Pitfall 5: Trusting third-party search volume estimates. Tools like Ahrefs and Semrush estimate search volume using clickstream data, which is notoriously inaccurate for long-tail keywords. GSC’s impression data is more reliable because it’s actual data from Google. Use GSC impressions as your primary volume signal.

Pitfall 6: Forgetting about SERP features. A position 1 result below 4 ads and a featured snippet might get fewer clicks than a position 5 result on a clean SERP. Always consider the full SERP layout when evaluating ranking opportunities.

What About Competitor Rank Tracking?

Tracking competitors’ rankings is valuable but harder to do for free. Here’s my approach:

Use Serper.dev to check competitor positions. Run the same rank tracker script but for competitor domains instead of yours. I track 3 competitors across 10 shared keywords each. That’s 30 API calls per week — well within the free tier.

COMPETITORS = ["competitor1.com", "competitor2.com", "competitor3.com"]
SHARED_KEYWORDS = [
    "free seo audit",
    "keyword research tool",
    # ... shared keywords
]

for domain in COMPETITORS:
    for keyword in SHARED_KEYWORDS:
        rank = check_rank(keyword, domain)
        print(f"{domain}{keyword}: Position {rank['position'] or '100+'}")

Use the “People also ask” and “Related searches” sections. When checking SERPs manually, scroll to the bottom and look at “Related searches.” These show what Google considers related topics — often revealing keywords your competitors are targeting that you haven’t considered.

Monitor their content publishing. Subscribe to competitor blogs or RSS feeds. When they publish new content, check if it’s ranking within a few weeks. This tells you how competitive their domain authority is and how fast Google indexes their content.

The Real Value of Rank Tracking

After a year of tracking rankings with free tools, here’s what I’ve learned:

Rank tracking is a diagnostic tool, not an optimization strategy. Knowing your position doesn’t improve it. What improves rankings is:

  1. Creating genuinely useful content that answers search intent better than competing pages
  2. Building topical authority through comprehensive content clusters
  3. Earning natural backlinks through quality content and outreach
  4. Fixing technical issues that prevent Google from properly crawling and indexing your site
  5. Improving user experience — page speed, mobile usability, clear navigation

Rank tracking tells you whether these efforts are working. It’s a compass, not a destination. Use it to identify what’s working and double down, and to catch problems early. But don’t confuse the measurement with the work.

Tool Summary

Here’s every tool mentioned in this guide and what it costs:

  • Google Search Console — Free. The foundation. Provides actual ranking data, impressions, clicks, and CTR directly from Google.
  • Bing Webmaster Tools — Free. Bing’s equivalent of GSC plus a keyword research tool and automated SEO reports.
  • Serper.dev — Free tier: 2,500 searches/month. Best for automated SERP checking via API.
  • Brave Search API — Free tier: 2,000 queries/month. Alternative SERP data source.
  • Google Custom Search API — Free tier: 100 searches/day (3,000/month). Uses Google’s index.
  • Python + requests library — Free. For building your own rank tracker.
  • GitHub Actions — Free. For automating weekly rank tracking runs.
  • Your browser (incognito mode) — Free. For manual SERP spot checks.

Total cost: $0. Total tools: 8. The key insight is that GSC provides 80% of the data you need — actual position, impressions, clicks, and CTR from Google itself. The API-based tools fill the gap when you need to check current positions in real time or track competitors.

The Bottom Line

You don’t need a $99/month rank tracker. You need Google Search Console, a free SERP API, and a Python script that runs weekly. That combination gives you:

  • Accurate aggregate ranking data from Google’s own records
  • Real-time position checks for specific keywords
  • Historical trend analysis stored in a CSV you control
  • Competitor tracking across shared keywords
  • SERP feature monitoring for priority keywords

The SEO industry has convinced us that rank tracking requires expensive tools. It doesn’t. What it requires is discipline — checking regularly, interpreting correctly, and acting on insights rather than reacting to noise.

Build the tracker. Run it weekly. Focus on trends, not snapshots. Connect rankings to traffic and revenue. That’s the entire job. Everything else is noise sold to you at $99/month.

Want to run this analysis on your own site?

ZensInk Pro automates this pipeline. One command, from seed keywords to content plan.

Get Pro →