Overview
This workflow exports local business data from Google across multiple category and city combinations. It queries Google local results for each combination, extracts business names, ratings, review counts, and addresses, and compiles everything into a structured dataset. The output feeds market research, franchise scouting, and lead generation pipelines.
Trigger
Manual or scheduled (weekly)
Schedule
Weekly or on-demand
Workflow Steps
Load categories and cities
Read the matrix of business categories and target cities from configuration.
Query local results for each combination
For each category-city pair, call the Scavio API to get Google local pack results.
Extract business data
Parse local pack results to get name, address, rating, review count, and phone number.
Deduplicate across queries
Remove duplicate businesses that appear in multiple category searches for the same city.
Export to structured format
Write the deduplicated dataset to JSON and optionally CSV for spreadsheet import.
Generate summary statistics
Calculate average ratings, total businesses per city, and coverage metrics.
Python Implementation
import requests
import json
import time
import csv
from pathlib import Path
from datetime import datetime
API_KEY = "your_scavio_api_key"
CATEGORIES = ["coffee shops", "coworking spaces", "gyms", "restaurants"]
CITIES = ["Austin TX", "Denver CO", "Portland OR", "Nashville TN", "Raleigh NC"]
def fetch_local(category: str, city: str) -> list[dict]:
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": f"{category} in {city}"},
timeout=15,
)
res.raise_for_status()
data = res.json()
businesses = []
for biz in data.get("local_pack", []):
businesses.append({
"name": biz.get("name", ""),
"address": biz.get("address", ""),
"rating": biz.get("rating"),
"reviews": biz.get("reviews", 0),
"phone": biz.get("phone", ""),
"category": category,
"city": city,
})
return businesses
def run():
all_businesses = []
seen = set()
total_queries = len(CATEGORIES) * len(CITIES)
completed = 0
for category in CATEGORIES:
for city in CITIES:
businesses = fetch_local(category, city)
for biz in businesses:
key = f"{biz['name']}_{biz['address']}"
if key not in seen:
seen.add(key)
all_businesses.append(biz)
completed += 1
if completed % 5 == 0:
print(f"Progress: {completed}/{total_queries} queries")
time.sleep(1)
date = datetime.utcnow().strftime("%Y-%m-%d")
# Export JSON
json_path = Path(f"local_businesses_{date}.json")
json_path.write_text(json.dumps(all_businesses, indent=2))
# Export CSV
csv_path = Path(f"local_businesses_{date}.csv")
if all_businesses:
with csv_path.open("w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=all_businesses[0].keys())
writer.writeheader()
writer.writerows(all_businesses)
# Summary
print(f"Export complete: {len(all_businesses)} unique businesses")
print(f" Categories: {len(CATEGORIES)} | Cities: {len(CITIES)}")
print(f" Avg rating: {sum(b['rating'] for b in all_businesses if b['rating']) / max(1, sum(1 for b in all_businesses if b['rating'])):.1f}")
if __name__ == "__main__":
run()JavaScript Implementation
const API_KEY = "your_scavio_api_key";
const CATEGORIES = ["coffee shops", "coworking spaces", "gyms", "restaurants"];
const CITIES = ["Austin TX", "Denver CO", "Portland OR", "Nashville TN", "Raleigh NC"];
async function fetchLocal(category, city) {
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: `${category} in ${city}` }),
});
if (!res.ok) throw new Error(`scavio ${res.status}`);
const data = await res.json();
return (data.local_pack ?? []).map((biz) => ({
name: biz.name ?? "",
address: biz.address ?? "",
rating: biz.rating ?? null,
reviews: biz.reviews ?? 0,
phone: biz.phone ?? "",
category,
city,
}));
}
async function run() {
const fs = await import("fs/promises");
const allBusinesses = [];
const seen = new Set();
let completed = 0;
const total = CATEGORIES.length * CITIES.length;
for (const category of CATEGORIES) {
for (const city of CITIES) {
const businesses = await fetchLocal(category, city);
for (const biz of businesses) {
const key = `${biz.name}_${biz.address}`;
if (!seen.has(key)) {
seen.add(key);
allBusinesses.push(biz);
}
}
completed++;
if (completed % 5 === 0) {
console.log(`Progress: ${completed}/${total} queries`);
await new Promise((r) => setTimeout(r, 1000));
}
}
}
const date = new Date().toISOString().slice(0, 10);
await fs.writeFile(`local_businesses_${date}.json`, JSON.stringify(allBusinesses, null, 2));
// CSV export
if (allBusinesses.length) {
const header = Object.keys(allBusinesses[0]).join(",");
const rows = allBusinesses.map((b) => Object.values(b).map((v) => `"${String(v ?? "").replace(/"/g, '""')}"`).join(","));
await fs.writeFile(`local_businesses_${date}.csv`, [header, ...rows].join("\n"));
}
const rated = allBusinesses.filter((b) => b.rating);
const avgRating = rated.length ? rated.reduce((s, b) => s + b.rating, 0) / rated.length : 0;
console.log(`Export: ${allBusinesses.length} unique businesses | Avg rating: ${avgRating.toFixed(1)}`);
}
run();Platforms Used
Web search with knowledge graph, PAA, and AI overviews