Workflow

Weekly SEO Rank Report

Generate automated weekly SEO ranking reports with Scavio. Track keyword positions on Google and detect ranking changes over time.

Overview

This workflow runs every Monday morning, queries Google for a list of target keywords, records the position of your domain in the organic results, and compiles a report showing position changes compared to the previous week. The output is a structured JSON or CSV file that can feed dashboards, email digests, or Slack notifications.

Trigger

Cron schedule (every Monday at 7 AM UTC)

Schedule

Runs every Monday at 7 AM UTC

Workflow Steps

1

Load keyword list

Read the target keywords and associated domains from a configuration file or database.

2

Query Google for each keyword

Call the Scavio API with platform google for each keyword, requesting enough results to cover the first two pages.

3

Find domain positions

Scan the organic results for each keyword and record the position where the target domain appears. Mark as not-found if absent from results.

4

Compare with previous week

Load last week's positions from storage and compute the delta for each keyword.

5

Generate report

Build a structured report with keyword, current position, previous position, and change. Export as JSON and optionally CSV.

Python Implementation

Python
import requests
import json
from pathlib import Path
from datetime import datetime

API_KEY = "your_scavio_api_key"
DOMAIN = "yourdomain.com"

def get_position(query: str) -> int | None:
    res = requests.post(
        "https://api.scavio.dev/api/v1/search",
        headers={"x-api-key": API_KEY},
        json={"platform": "google", "query": query, "num": 20},
        timeout=15,
    )
    res.raise_for_status()
    for item in res.json().get("organic", []):
        if DOMAIN in item.get("link", ""):
            return item["position"]
    return None

def run():
    keywords = json.loads(Path("keywords.json").read_text())
    history_path = Path("rank_history.json")
    previous = json.loads(history_path.read_text()) if history_path.exists() else {}
    report = []

    for kw in keywords:
        pos = get_position(kw)
        prev = previous.get(kw)
        delta = (prev - pos) if (pos and prev) else None
        report.append({
            "keyword": kw,
            "position": pos,
            "previous": prev,
            "change": delta,
        })
        if pos:
            previous[kw] = pos

    history_path.write_text(json.dumps(previous, indent=2))

    date_str = datetime.utcnow().strftime("%Y-%m-%d")
    Path(f"seo_report_{date_str}.json").write_text(json.dumps(report, indent=2))
    print(f"Report generated: {len(report)} keywords tracked")

if __name__ == "__main__":
    run()

JavaScript Implementation

JavaScript
const API_KEY = "your_scavio_api_key";
const DOMAIN = "yourdomain.com";

async function getPosition(query) {
  const res = await fetch("https://api.scavio.dev/api/v1/search", {
    method: "POST",
    headers: {
      "x-api-key": API_KEY,
      "content-type": "application/json",
    },
    body: JSON.stringify({ platform: "google", query, num: 20 }),
  });
  if (!res.ok) throw new Error(`scavio ${res.status}`);
  const data = await res.json();
  const match = data.organic?.find((r) => r.link?.includes(DOMAIN));
  return match ? match.position : null;
}

async function run() {
  const fs = await import("fs/promises");
  const keywords = JSON.parse(await fs.readFile("keywords.json", "utf8"));
  let previous = {};
  try {
    previous = JSON.parse(await fs.readFile("rank_history.json", "utf8"));
  } catch {}

  const report = [];

  for (const kw of keywords) {
    const pos = await getPosition(kw);
    const prev = previous[kw] ?? null;
    const change = pos && prev ? prev - pos : null;
    report.push({ keyword: kw, position: pos, previous: prev, change });
    if (pos) previous[kw] = pos;
  }

  await fs.writeFile("rank_history.json", JSON.stringify(previous, null, 2));

  const date = new Date().toISOString().slice(0, 10);
  await fs.writeFile(
    `seo_report_${date}.json`,
    JSON.stringify(report, null, 2)
  );
  console.log(`Report generated: ${report.length} keywords tracked`);
}

run();

Platforms Used

Google

Web search with knowledge graph, PAA, and AI overviews

Frequently Asked Questions

This workflow runs every Monday morning, queries Google for a list of target keywords, records the position of your domain in the organic results, and compiles a report showing position changes compared to the previous week. The output is a structured JSON or CSV file that can feed dashboards, email digests, or Slack notifications.

This workflow uses a cron schedule (every monday at 7 am utc). Runs every Monday at 7 AM UTC.

This workflow uses the following Scavio platforms: google. Each platform is called via the same unified API endpoint.

Yes. Scavio's free tier includes 500 credits per month with no credit card required. That is enough to test and validate this workflow before scaling it.

Weekly SEO Rank Report

Generate automated weekly SEO ranking reports with Scavio. Track keyword positions on Google and detect ranking changes over time.