This tutorial walks you through conducting a comprehensive local SEO audit for businesses with multiple locations.
Prerequisites
- Google Business Profile access for all locations
- Google Search Console access
- Basic Python knowledge
- Access to citation management tool
Step 1: Audit Google Business Profiles
import csv
def audit_gbp_profiles(locations_file):
with open(locations_file, "r") as f:
locations = csv.DictReader(f)
audit_results = []
for loc in locations:
checks = {
"name_consistent": bool(loc.get("gbp_name")),
"category_set": bool(loc.get("primary_category")),
"photos_count": int(loc.get("photo_count", 0)),
"reviews_responded": float(loc.get("review_response_rate", 0)),
"posts_last_30_days": int(loc.get("recent_posts", 0)),
"hours_updated": bool(loc.get("hours_current")),
"description_filled": bool(loc.get("description")),
}
completeness = sum(1 for v in checks.values() if v) / len(checks) * 100
audit_results.append({
"location": loc["name"],
"city": loc["city"],
"completeness": f"{completeness:.0f}%",
"checks": checks
})
return sorted(audit_results, key=lambda x: float(x["completeness"].rstrip("%")))
Step 2: NAP Consistency Check
from difflib import SequenceMatcher
def check_nap_consistency(listings):
issues = []
canonical = listings[0]
for i, listing in enumerate(listings[1:], 1):
name_sim = SequenceMatcher(None, canonical["name"].lower(), listing["name"].lower()).ratio()
address_sim = SequenceMatcher(None, canonical["address"].lower(), listing["address"].lower()).ratio()
phone_match = canonical["phone"].replace("-", "") == listing["phone"].replace("-", "")
if name_sim < 0.9:
issues.append(f"Listing {i}: Name mismatch ({name_sim:.0%})")
if address_sim < 0.9:
issues.append(f"Listing {i}: Address mismatch ({address_sim:.0%})")
if not phone_match:
issues.append(f"Listing {i}: Phone mismatch")
return issues
Step 3: Local Keyword Ranking Check
def check_local_rankings(keywords, locations):
results = []
for location in locations:
for keyword in keywords:
ranking = get_local_rank(keyword, location["city"])
results.append({
"keyword": keyword,
"location": location["city"],
"ranking": ranking,
"in_local_pack": ranking <= 3,
"in_top_10": ranking <= 10
})
return results
Step 4: Competitor Local SEO Analysis
def analyze_local_competitors(your_business, competitors, city):
analysis = {
"your_business": analyze_gbp_completeness(your_business),
"competitors": [],
"opportunities": []
}
for comp in competitors:
comp_data = analyze_gbp_completeness(comp)
analysis["competitors"].append(comp_data)
if comp_data["review_count"] > analysis["your_business"]["review_count"]:
analysis["opportunities"].append(
f"Get more reviews (competitor has {comp_data[