Resumen
Este flujo de trabajo pulls fresh SERP datos semanal for todos tracked palabras clave y feeds it en your personalizado panel de control. It rastrea posiciones organicas, caracteristica SERP presence, competidor movements, y AI Overview cambios. El salida actualiza your panel de control base de datos o genera un JSON informe for visualization herramientas.
Desencadenador
Cron programar (cada Monday at 6:00 AM UTC)
Programación
Ejecuta cada Monday at 6:00 AM UTC
Pasos del flujo de trabajo
Cargar lista de palabras clave de config
Leer el tracked palabras clave y dominio objetivo de configuracion file o base de datos.
Consulta SERP for cada palabra clave
Call Scavio for cada palabra clave con AI Overview enabled y num establecer to 20 for deeper position seguimiento.
Extraer position y caracteristica datos
Analizar cada respuesta for dominio objetivo position, caracteristica SERP presence, y top competidor dominios.
Comparar contra anterior semana
Cargar last week's datos y compute position cambios, nuevo/lost caracteristicas, y competidor movements.
Actualizar panel de control base de datos
Escribir actual semana datos to panel de control storage y generar cambio alertas for significativo movements.
Implementacion en Python
import requests
import json
from pathlib import Path
from datetime import datetime
API_KEY = "your_scavio_api_key"
DOMAIN = "yourdomain.com"
KEYWORDS = ["best search API", "SERP API pricing", "web scraping alternative", "search data for AI agents"]
def query_serp(keyword: str) -> dict:
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": keyword, "num": 20, "ai_overview": True},
timeout=15,
)
res.raise_for_status()
data = res.json()
position = None
for item in data.get("organic", []):
if DOMAIN in item.get("link", ""):
position = item.get("position")
break
return {
"keyword": keyword,
"position": position,
"has_ai_overview": bool(data.get("ai_overview")),
"has_featured_snippet": bool(data.get("featured_snippet")),
"top_3_domains": [r.get("link", "").split("/")[2] if "/" in r.get("link", "") else "" for r in data.get("organic", [])[:3]],
}
def run():
date = datetime.utcnow().strftime("%Y-%m-%d")
history_path = Path("dashboard_history.json")
history = json.loads(history_path.read_text()) if history_path.exists() else {}
current = {}
alerts = []
for kw in KEYWORDS:
result = query_serp(kw)
current[kw] = result
prev = history.get(kw, {})
if prev.get("position") and result["position"]:
change = result["position"] - prev["position"]
if abs(change) >= 3:
alerts.append({"keyword": kw, "previous": prev["position"], "current": result["position"], "change": change})
history_path.write_text(json.dumps(current, indent=2))
report = {
"date": date,
"keywords_tracked": len(KEYWORDS),
"keywords_ranking": sum(1 for r in current.values() if r["position"]),
"alerts": alerts,
"data": current,
}
Path(f"dashboard_{date}.json").write_text(json.dumps(report, indent=2))
print(f"Dashboard refresh: {report['keywords_ranking']}/{report['keywords_tracked']} ranking")
for alert in alerts:
direction = "dropped" if alert["change"] > 0 else "improved"
print(f" ALERT: {alert['keyword']} {direction} by {abs(alert['change'])} (#{alert['previous']} -> #{alert['current']})")
if __name__ == "__main__":
run()Implementacion en JavaScript
const API_KEY = "your_scavio_api_key";
const DOMAIN = "yourdomain.com";
const KEYWORDS = ["best search API", "SERP API pricing", "web scraping alternative"];
async function querySerp(keyword) {
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: keyword, num: 20, ai_overview: true }),
});
if (!res.ok) throw new Error(`scavio ${res.status}`);
const data = await res.json();
let position = null;
for (const item of data.organic ?? []) {
if (item.link?.includes(DOMAIN)) { position = item.position; break; }
}
return { keyword, position, hasAiOverview: !!data.ai_overview, hasFeaturedSnippet: !!data.featured_snippet };
}
async function run() {
const fs = await import("fs/promises");
let history = {};
try { history = JSON.parse(await fs.readFile("dashboard_history.json", "utf8")); } catch {}
const current = {};
const alerts = [];
for (const kw of KEYWORDS) {
const result = await querySerp(kw);
current[kw] = result;
const prev = history[kw] ?? {};
if (prev.position && result.position) {
const change = result.position - prev.position;
if (Math.abs(change) >= 3) alerts.push({ keyword: kw, previous: prev.position, current: result.position, change });
}
}
await fs.writeFile("dashboard_history.json", JSON.stringify(current, null, 2));
const ranking = Object.values(current).filter((r) => r.position).length;
console.log(`Dashboard: ${ranking}/${KEYWORDS.length} ranking, ${alerts.length} alerts`);
for (const a of alerts) console.log(` ${a.keyword}: #${a.previous} -> #${a.current}`);
}
run();Plataformas utilizadas
Búsqueda web con grafo de conocimiento, PAA y resúmenes de IA