Resumen
Este flujo de trabajo monitorea producto prices diario a traves de Amazon y Walmart, compara contra almacenado baselines, y fires alertas cuando prices cambio mas alla de un configurable umbral. It handles ambos caidas de precio (deal alertas) y price increases (inteligencia competitiva), con separate notificacion canales for cada direction.
Desencadenador
Cron programar (diario at 8 AM UTC)
Programación
Ejecuta diario at 8 AM UTC
Pasos del flujo de trabajo
Cargar producto watchlist
Leer el lista of productos to monitorear con their objetivo plataformas y alerta umbrales.
Obtener actual prices
Consulta Scavio for cada producto on Amazon y Walmart to obtener actual listing prices.
Comparar contra linea base
Cargar yesterday's prices y compute absolute y porcentaje cambios.
Categorizar alertas
Separate cambios de precio en drops (deals) y increases (competitive alertas) basado on direction.
Enviar notificaciones
Route deal alertas y competitive alertas to their respective canales.
Actualizar linea base
Almacenar today's prices as el nuevo linea base for tomorrow's comparacion.
Implementacion en Python
import requests
import json
from pathlib import Path
from datetime import datetime
API_KEY = "your_scavio_api_key"
DEAL_WEBHOOK = "https://hooks.slack.com/services/YOUR/DEALS/WEBHOOK"
COMPETITIVE_WEBHOOK = "https://hooks.slack.com/services/YOUR/COMPETITIVE/WEBHOOK"
THRESHOLD_PCT = 5.0
def fetch_price(query: str, platform: str) -> float | None:
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": platform, "query": query},
timeout=15,
)
res.raise_for_status()
for item in res.json().get("organic", []):
if item.get("price"):
return item["price"]
return None
def run():
watchlist = json.loads(Path("price_watchlist.json").read_text())
baseline_path = Path("price_baseline.json")
baseline = json.loads(baseline_path.read_text()) if baseline_path.exists() else {}
deals = []
increases = []
for item in watchlist:
for platform in item.get("platforms", ["amazon", "walmart"]):
key = f"{item['slug']}_{platform}"
current = fetch_price(item["query"], platform)
previous = baseline.get(key)
if current and previous:
pct_change = ((current - previous) / previous) * 100
if pct_change <= -THRESHOLD_PCT:
deals.append({
"product": item["query"],
"platform": platform,
"was": previous,
"now": current,
"drop_pct": round(abs(pct_change), 1),
})
elif pct_change >= THRESHOLD_PCT:
increases.append({
"product": item["query"],
"platform": platform,
"was": previous,
"now": current,
"increase_pct": round(pct_change, 1),
})
if current:
baseline[key] = current
baseline_path.write_text(json.dumps(baseline, indent=2))
if deals:
msg = f"Price Drop Alert ({len(deals)} products):\n"
for d in deals:
msg += f" {d['product']} on {d['platform']}: {d['was']} -> {d['now']} (-{d['drop_pct']}%)\n"
requests.post(DEAL_WEBHOOK, json={"text": msg}, timeout=10)
if increases:
msg = f"Price Increase Alert ({len(increases)} products):\n"
for i in increases:
msg += f" {i['product']} on {i['platform']}: {i['was']} -> {i['now']} (+{i['increase_pct']}%)\n"
requests.post(COMPETITIVE_WEBHOOK, json={"text": msg}, timeout=10)
print(f"Checked {len(watchlist)} products: {len(deals)} drops, {len(increases)} increases")
if __name__ == "__main__":
run()Implementacion en JavaScript
const API_KEY = "your_scavio_api_key";
const DEAL_WEBHOOK = "https://hooks.slack.com/services/YOUR/DEALS/WEBHOOK";
const COMPETITIVE_WEBHOOK = "https://hooks.slack.com/services/YOUR/COMPETITIVE/WEBHOOK";
const THRESHOLD_PCT = 5.0;
async function fetchPrice(query, platform) {
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, query }),
});
if (!res.ok) throw new Error(`scavio ${res.status}`);
for (const item of (await res.json()).organic ?? []) {
if (item.price) return item.price;
}
return null;
}
async function run() {
const fs = await import("fs/promises");
const watchlist = JSON.parse(await fs.readFile("price_watchlist.json", "utf8"));
let baseline = {};
try { baseline = JSON.parse(await fs.readFile("price_baseline.json", "utf8")); } catch {}
const deals = [];
const increases = [];
for (const item of watchlist) {
for (const platform of item.platforms ?? ["amazon", "walmart"]) {
const key = `${item.slug}_${platform}`;
const current = await fetchPrice(item.query, platform);
const previous = baseline[key];
if (current && previous) {
const pctChange = ((current - previous) / previous) * 100;
if (pctChange <= -THRESHOLD_PCT) {
deals.push({ product: item.query, platform, was: previous, now: current, dropPct: Math.round(Math.abs(pctChange) * 10) / 10 });
} else if (pctChange >= THRESHOLD_PCT) {
increases.push({ product: item.query, platform, was: previous, now: current, increasePct: Math.round(pctChange * 10) / 10 });
}
}
if (current) baseline[key] = current;
}
}
await fs.writeFile("price_baseline.json", JSON.stringify(baseline, null, 2));
if (deals.length) {
const msg = `Price Drop Alert (${deals.length} products):\n` + deals.map((d) => ` ${d.product} on ${d.platform}: $${d.was} -> $${d.now} (-${d.dropPct}%)`).join("\n");
await fetch(DEAL_WEBHOOK, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ text: msg }) });
}
if (increases.length) {
const msg = `Price Increase Alert (${increases.length} products):\n` + increases.map((i) => ` ${i.product} on ${i.platform}: $${i.was} -> $${i.now} (+${i.increasePct}%)`).join("\n");
await fetch(COMPETITIVE_WEBHOOK, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ text: msg }) });
}
console.log(`Checked ${watchlist.length} products: ${deals.length} drops, ${increases.length} increases`);
}
run();Plataformas utilizadas
Amazon
Búsqueda de productos con precios, calificaciones y reseñas
Walmart
Búsqueda de productos con precios y datos de cumplimiento