A weekly SERP report does not need to start as a dashboard.
For many teams, a CSV file is enough for the first version.
The goal is simple: take daily SERP snapshots, compare them over a week, and summarize the changes that someone should review.
This post shows a lightweight pattern for building that report from normalized SERP data. The collection layer can be a SERP API such as Talor Data SERP API, while the report logic stays in your own code.
The input shape
Assume you already save one normalized SERP snapshot per keyword per day.
A simplified record can look like this:
{
"keyword": "serp api for seo monitoring",
"checked_at": "2026-07-06T09:00:00Z",
"results": [
{
"position": 1,
"title": "Example result title",
"url": "https://example.com/page",
"domain": "example.com"
}
]
}
The exact fields depend on your provider and normalization layer. Do not build the report directly against a provider-specific response if you can avoid it. Normalize first, report second.
What the weekly report should answer
For a first version, avoid too many metrics.
I would start with five questions:
- Which domains appeared most often this week?
- Which tracked URLs moved up or down?
- Which new URLs entered the top results?
- Which URLs disappeared from the tracked range?
- Which titles changed for important pages?
Those questions are easier to review than a raw dump of every daily result.
Minimal Python example
This example assumes you have a folder of JSON snapshots.
import csv
import json
from pathlib import Path
from urllib.parse import urlparse
SNAPSHOT_DIR = Path("serp_snapshots")
REPORT_PATH = Path("weekly_serp_report.csv")
def domain_from_url(url: str) -> str:
return urlparse(url).netloc.replace("www.", "")
def load_snapshots() -> list[dict]:
snapshots = []
for path in SNAPSHOT_DIR.glob("*.json"):
with path.open("r", encoding="utf-8") as file:
snapshots.append(json.load(file))
return snapshots
def flatten_results(snapshots: list[dict]) -> list[dict]:
rows = []
for snapshot in snapshots:
keyword = snapshot["keyword"]
checked_at = snapshot["checked_at"]
for result in snapshot.get("results", []):
url = result.get("url")
if not url:
continue
rows.append(
{
"keyword": keyword,
"checked_at": checked_at,
"position": result.get("position"),
"title": result.get("title"),
"url": url,
"domain": result.get("domain") or domain_from_url(url),
}
)
return rows
def write_csv(rows: list[dict]) -> None:
fieldnames = ["keyword", "checked_at", "position", "domain", "title", "url"]
with REPORT_PATH.open("w", newline="", encoding="utf-8") as file:
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
if __name__ == "__main__":
snapshots = load_snapshots()
rows = flatten_results(snapshots)
write_csv(rows)
print(f"Wrote {len(rows)} rows to {REPORT_PATH}")
This is not a finished analytics system. It is a clean export that lets you inspect the week before deciding what to automate next.
Add a small summary layer
A raw CSV is useful, but a weekly review needs a summary.
You can start with domain frequency:
from collections import Counter
def summarize_domains(rows: list[dict]) -> list[tuple[str, int]]:
counts = Counter(row["domain"] for row in rows if row.get("domain"))
return counts.most_common(20)
Then write a second CSV:
def write_domain_summary(domain_counts: list[tuple[str, int]]) -> None:
with Path("weekly_domain_summary.csv").open("w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(["domain", "appearances"])
writer.writerows(domain_counts)
Now the team has two useful files:
- one detailed result export
- one quick domain-level summary
Keep the first report boring
The first weekly report should not try to explain everything.
It should help someone ask better questions:
- Why did this competitor domain appear so often?
- Which keywords changed the most?
- Are the same directories or review pages showing up repeatedly?
- Did the search results become more commercial, educational, or comparison-driven?
A SERP API like Talor Data can provide the structured search result data. The report layer should translate that data into a review habit your team can maintain.
What I would add later
After the CSV version is useful, then consider adding:
- position change calculations
- new and removed URL detection
- SERP feature summaries
- keyword priority grouping
- Slack or email delivery
- a dashboard only if people keep asking for one
That order matters. A report that people read is better than a dashboard nobody reviews.
Final note
If you build weekly SERP reports, what do you summarize first: domains, URLs, ranking movement, SERP features, or content formats?
Top comments (0)