ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build an SEO Ranking Alert Pipeline
Tutorial

How to Build an SEO Ranking Alert Pipeline

Build a pipeline that checks keyword rankings daily and sends alerts when positions drop below a threshold. Python script with CSV history and email alerts.

Get Free API KeyAPI Docs

Ranking drops can go unnoticed for days if you only check manually. By the time you spot a decline from position 3 to position 15, you have already lost significant traffic. This tutorial builds an automated SEO alert pipeline that checks your keyword rankings daily via the Scavio API, compares current positions against previous baselines stored in CSV, and fires an alert when any keyword drops below a configured threshold or falls more than a set number of positions. The pipeline costs about $0.005 per keyword per day, so monitoring 100 keywords runs under $0.50 daily.

Prerequisites

  • Python 3.8+ installed
  • requests library installed
  • A Scavio API key from scavio.dev
  • Your domain and a list of target keywords

Walkthrough

Step 1: Configure keywords and alert thresholds

Define keywords to track, your target domain, a position threshold to alert on, and a drop threshold to catch sudden declines.

Python
import os, csv, requests
from datetime import date

API_KEY = os.environ['SCAVIO_API_KEY']
ENDPOINT = 'https://api.scavio.dev/api/v1/search'
HEADERS = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}

TARGET_DOMAIN = 'mysite.com'
POSITION_THRESHOLD = 10
DROP_THRESHOLD = 5
KEYWORDS = [
    'web scraping api',
    'serp api python',
    'amazon price api',
    'tiktok data api',
]

Step 2: Fetch current rank and load previous baseline

Query the Scavio Google endpoint for each keyword and find your domain's position. Load the last recorded position from a CSV history file for comparison.

Python
def get_rank(keyword):
    resp = requests.post(ENDPOINT, headers=HEADERS,
        json={'query': keyword, 'country_code': 'us'})
    for r in resp.json().get('organic_results', []):
        if TARGET_DOMAIN in r.get('link', ''):
            return r['position']
    return None

def load_baselines(csv_path='rankings_history.csv'):
    baselines = {}
    try:
        with open(csv_path) as f:
            rows = list(csv.reader(f))
            for row in reversed(rows):
                if len(row) >= 3 and row[1] not in baselines and row[2]:
                    baselines[row[1]] = int(row[2])
    except FileNotFoundError:
        pass
    return baselines

Step 3: Check for drops and generate alerts

Compare current positions to baselines. Alert if the position exceeds the threshold or if the drop since last check exceeds the drop threshold.

Python
def run_alert_pipeline():
    baselines = load_baselines()
    alerts = []
    today = date.today().isoformat()
    with open('rankings_history.csv', 'a', newline='') as f:
        writer = csv.writer(f)
        for kw in KEYWORDS:
            rank = get_rank(kw)
            writer.writerow([today, kw, rank or ''])
            prev = baselines.get(kw)
            if rank is None:
                alerts.append(f'[GONE] {kw}: not found in top results')
            elif rank > POSITION_THRESHOLD:
                alerts.append(f'[LOW] {kw}: position {rank} (threshold {POSITION_THRESHOLD})')
            elif prev and rank - prev >= DROP_THRESHOLD:
                alerts.append(f'[DROP] {kw}: {prev} -> {rank} (dropped {rank - prev} positions)')
            else:
                print(f'[OK] {kw}: position {rank}')
    if alerts:
        print('\n--- ALERTS ---')
        for a in alerts:
            print(a)
    return alerts

run_alert_pipeline()

Python Example

Python
import os, csv, requests
from datetime import date

API_KEY = os.environ['SCAVIO_API_KEY']
ENDPOINT = 'https://api.scavio.dev/api/v1/search'
HEADERS = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
DOMAIN = 'mysite.com'
KEYWORDS = ['web scraping api', 'serp api python', 'amazon price api']

def get_rank(kw):
    resp = requests.post(ENDPOINT, headers=HEADERS,
        json={'query': kw, 'country_code': 'us'}).json()
    for r in resp.get('organic_results', []):
        if DOMAIN in r.get('link', ''): return r['position']
    return None

def load_prev():
    prev = {}
    try:
        with open('rankings.csv') as f:
            for row in reversed(list(csv.reader(f))):
                if row[1] not in prev and row[2]: prev[row[1]] = int(row[2])
    except FileNotFoundError: pass
    return prev

def run():
    prev = load_prev()
    today = date.today().isoformat()
    with open('rankings.csv', 'a', newline='') as f:
        w = csv.writer(f)
        for kw in KEYWORDS:
            rank = get_rank(kw)
            w.writerow([today, kw, rank or ''])
            p = prev.get(kw)
            if rank and p and rank - p >= 5:
                print(f'[DROP] {kw}: {p} -> {rank}')
            elif rank and rank > 10:
                print(f'[LOW] {kw}: position {rank}')
            elif rank:
                print(f'[OK] {kw}: #{rank}')
            else:
                print(f'[GONE] {kw}')

if __name__ == '__main__': run()

JavaScript Example

JavaScript
const fs = require('fs');
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };
const DOMAIN = 'mysite.com';
const KEYWORDS = ['web scraping api', 'serp api python'];

async function getRank(kw) {
  const data = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST', headers: H, body: JSON.stringify({ query: kw, country_code: 'us' })
  }).then(r => r.json());
  const match = (data.organic_results || []).find(r => r.link.includes(DOMAIN));
  return match ? match.position : null;
}

async function run() {
  const today = new Date().toISOString().slice(0, 10);
  for (const kw of KEYWORDS) {
    const rank = await getRank(kw);
    fs.appendFileSync('rankings.csv', `${today},${kw},${rank || ''}\n`);
    if (!rank) console.log(`[GONE] ${kw}`);
    else if (rank > 10) console.log(`[LOW] ${kw}: position ${rank}`);
    else console.log(`[OK] ${kw}: #${rank}`);
  }
}

run().catch(console.error);

Expected Output

JSON
[OK] web scraping api: #3
[OK] serp api python: #5
[DROP] amazon price api: 4 -> 11

--- ALERTS ---
[DROP] amazon price api: 4 -> 11 (dropped 7 positions)

Related Tutorials

  • How to Track SEO Rankings Daily with the Scavio API
  • How to Fetch Google Search Results in Python
  • How to Build an SEO Audit Tool with SERP and Competitor Analysis

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+ installed. requests library installed. A Scavio API key from scavio.dev. Your domain and a list of target keywords. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Related Resources

Best Of

Best SEO Rank Tracking APIs in 2026

Read more
Best Of

Best API-Based Rank Trackers for SEO in 2026

Read more
Workflow

Daily Local Rank Tracking Pipeline

Read more
Solution

Run SEO Rank Checks Overnight in Batch Mode

Read more
Use Case

n8n SEO Monitoring Pipeline

Read more
Solution

Build Reliable Local Rank Tracking with Scavio API

Read more

Start Building

Build a pipeline that checks keyword rankings daily and sends alerts when positions drop below a threshold. Python script with CSV history and email alerts.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy