Local SEO Performance steigern: Der technische How‑to‑Guide (GMB, Schema, Mobile, Citations)

1) Performance-Baseline setzen: Local-SEO-KPIs, Tracking & Quick Wins
Messpunkte, die wirklich Performance abbilden
- Local Pack Sichtbarkeit (Top 3/Top 10 pro Keyword & Standort)
- Google My Business (Profilaufrufe, Anrufe, Routenanfragen, Website-Klicks)
- Organic Local Landing Pages (Impressions/Clicks/CTR, Conversions)
- NAP Consistency Score (Übereinstimmung über Verzeichnisse hinweg)
- Mobile KPIs (LCP/INP/CLS, TTFB, Interaktionsrate mobil)
Tooling (SEO Audit Tools) für belastbare Entscheidungen
- Google Search Console (Queries, Seiten, Geräte)
- Google Business Profile Insights (GMB Performance)
- PageSpeed Insights / Lighthouse (Core Web Vitals & Mobile)
- Ahrefs/Semrush/Sistrix (Local Keywords, SERP Features)
- Georank-Tracker (standortbasierte SERPs)
FeatureDetailsLocal Pack TrackingStandort- & Device-spezifisch messen; sonst sind Verbesserungen nicht valide.GMB KPI-SetCalls, Direction Requests, Website Clicks – als „Local Intent“ Proxy.NAP AuditName/Address/Phone Abgleich gegen Website & Listings; Inkonsistenzen priorisieren.Mobile Core Web VitalsLCP/INP/CLS auf echten Mobilgeräten; TTFB & Bildoptimierung korrelieren stark mit Local Conversions.Schema CoverageOrganization/LocalBusiness, FAQ, Breadcrumb, ggf. Service/Review – Fehlerfrei & konsistent.
Interessiert an diesem Thema?
Kontaktieren Sie uns für eine kostenlose Beratung →2) Google My Business (Google Business Profile) für Local Pack Performance optimieren
Kategorie- & Service-Fit (Ranking-Hebel #1 für Relevanz)
- Primärkategorie: so nah wie möglich an der Kernleistung.
- Zusatzkategorien: nur, wenn du diese Leistung wirklich anbietest.
- Services/Produkte: sauber strukturieren, mit lokalen Begriffen (ohne Keyword-Stuffing).
Performance-Setup: Inhalte, die Conversions treiben
- Fotos: echte Standortfotos; regelmäßig aktualisieren (Signal für Aktivität).
- Beiträge: 1–2/Woche (Aktionen, Events, Cases). Tracke UTM.
- Q&A: häufige Fragen pro Standort vorab beantworten.
- Bewertungen: Review-Request Prozess + Antwort-Templates; Themencluster aus Reviews später für Content nutzen.
GMB Technical: Tracking via UTM
Nutze UTM-Parameter für Website-Links im Profil, um GMB-Traffic/Conversions sauber zu messen.
3) NAP Consistency & Local Citations: Vertrauen skalieren
Warum NAP Consistency direkt Performance beeinflusst
- Inkonsequente Daten schwächen Entity-Confidence (wer/wo ist das Unternehmen?).
- Gerade bei mehreren Standorten entstehen Ranking-Schwankungen im Local Pack.
Citation-Strategie (Qualität vor Quantität)
- Starte mit den Top-Aggregatoren/Verzeichnissen in deiner Region/Branche.
- Ergänze branchenspezifische Verzeichnisse (B2B/B2C).
- Pflege Daten in einem „Source of Truth“ (z. B. YAML) und synce daraus.
Pro-Tipp: Baue „Local Citations“ nicht blind. Priorisiere Plattformen, die selbst ranken (und Traffic senden) oder die von Google häufig als Referenz genutzt werden.
YAML als Source of Truth für NAP & Standorte
**YAML: Standortdaten für NAP Consistency (als Single Source of Truth)**
brand:
name: "Beispiel GmbH"
website: "https://www.beispiel.de"
supportEmail: "hello@beispiel.de"
locations:
- id: "berlin-mitte"
name: "Beispiel GmbH Berlin-Mitte"
address:
street: "Musterstraße 12"
zip: "10115"
city: "Berlin"
country: "DE"
phone: "+49 30 1234567"
gmb:
placeId: "ChIJN1t_tDeuEmsRUsoyG83frY4"
url: "https://g.page/r/PLACEID"
openingHours:
- day: "Monday"
opens: "09:00"
closes: "18:00"
- day: "Tuesday"
opens: "09:00"
closes: "18:00"
categories:
primary: "SEO-Dienstleistungen"
additional:
- "Online-Marketing"
- "Marketingberatung"
- id: "hamburg"
name: "Beispiel GmbH Hamburg"
address:
street: "Beispielweg 8"
zip: "20095"
city: "Hamburg"
country: "DE"
phone: "+49 40 7654321"
gmb:
placeId: "ChIJZ2jHc-0HsUcR9c6z7d8pKqE"
url: "https://g.page/r/PLACEID"
openingHours:
- day: "Monday"
opens: "09:00"
closes: "17:00"
- day: "Friday"
opens: "09:00"
closes: "15:00"
4) Onpage Local: Standortseiten, interne Verlinkung & Conversion-UX
Standortseiten, die ranken (und nicht kannibalisieren)
- Eine Seite pro Standort + eindeutige Leistung/Einzugsgebiet.
- Unique Content: Anfahrt, Parken, Team, lokale Cases, lokale FAQs, lokale Bilder.
- Einheitliches NAP im Footer/Standortblock (genau wie in GMB & Citations).
Interne Verlinkung (Performance-Hebel)
- Von der Hauptleistung („SEO“) zu Standorten („SEO Berlin“, „SEO Hamburg“) verlinken.
- Breadcrumbs + Standort-Hub (Übersichtsseite) einsetzen.
Wenn du das operativ auslagern willst: Eine erfahrene SEO Agentur kann den lokalen Seiten-Cluster, die Verzeichnisstrategie und das Tracking als durchgehendes System aufsetzen.
5) Schema Markup Optimization: Local Entities sauber modellieren
Was Schema Markup bei Local SEO wirklich bringt
- Hilft Suchmaschinen, dein Unternehmen als Entity (Name, Adresse, Telefon, Öffnungszeiten) korrekt zu verstehen.
- Reduziert Widersprüche zwischen Website, Google My Business und Local Citations.
- Verbessert maschinelles Verständnis für Standortseiten (LocalBusiness, PostalAddress, Geo, OpeningHours).
Schema Best Practices (um Performance zu sichern)
- Nutze LocalBusiness oder spezifischere Typen (z. B. ProfessionalService).
- sameAs auf Social/Directory-Profile; url auf kanonische Standortseite.
- hasMap und geo (wenn sauber) ergänzen.
- Für mehrere Standorte: pro Standortseite ein eigenes JSON-LD, nicht alles in eine Seite pressen.
JSON Config für Schema Markup (mit \n Zeilenumbrüchen)
**JSON Config: LocalBusiness Schema (als Template, enthält "\n" für Zeilenumbrüche)**
{
"schemaTemplate": "{\n \"@context\": \"https://schema.org\",\n \"@type\": \"ProfessionalService\",\n \"name\": \"Beispiel GmbH Berlin-Mitte\",\n \"url\": \"https://www.beispiel.de/standorte/berlin-mitte\",\n \"telephone\": \"+49 30 1234567\",\n \"image\": [\n \"https://www.beispiel.de/assets/standorte/berlin-mitte.jpg\"\n ],\n \"address\": {\n \"@type\": \"PostalAddress\",\n \"streetAddress\": \"Musterstraße 12\",\n \"postalCode\": \"10115\",\n \"addressLocality\": \"Berlin\",\n \"addressCountry\": \"DE\"\n },\n \"geo\": {\n \"@type\": \"GeoCoordinates\",\n \"latitude\": 52.5321,\n \"longitude\": 13.3849\n },\n \"openingHoursSpecification\": [\n {\n \"@type\": \"OpeningHoursSpecification\",\n \"dayOfWeek\": [\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\"],\n \"opens\": \"09:00\",\n \"closes\": \"18:00\"\n },\n {\n \"@type\": \"OpeningHoursSpecification\",\n \"dayOfWeek\": [\"Friday\"],\n \"opens\": \"09:00\",\n \"closes\": \"15:00\"\n }\n ],\n \"sameAs\": [\n \"https://www.linkedin.com/company/beispiel\",\n \"https://www.facebook.com/beispiel\"\n ]\n}"
}
TypeScript: Template befüllen & pro Standort ausrollen
**TypeScript: Schema aus YAML/DB befüllen und als JSON-LD ausgeben**
type Location = {
name: string;
url: string;
phone: string;
address: {
street: string;
zip: string;
city: string;
country: string;
};
geo?: {
latitude: number;
longitude: number;
};
};
function buildLocalBusinessSchema(location: Location) {
return {
"@context": "https://schema.org",
"@type": "ProfessionalService",
name: location.name,
url: location.url,
telephone: location.phone,
address: {
"@type": "PostalAddress",
streetAddress: location.address.street,
postalCode: location.address.zip,
addressLocality: location.address.city,
addressCountry: location.address.country
},
...(location.geo
? {
geo: {
"@type": "GeoCoordinates",
latitude: location.geo.latitude,
longitude: location.geo.longitude
}
}
: {})
};
}
export function renderJsonLd(schemaObject: Record<string, unknown>) {
return `<script type="application/ld+json">${JSON.stringify(schemaObject)}</script>`;
}
const berlin: Location = {
name: "Beispiel GmbH Berlin-Mitte",
url: "https://www.beispiel.de/standorte/berlin-mitte",
phone: "+49 30 1234567",
address: {
street: "Musterstraße 12",
zip: "10115",
city: "Berlin",
country: "DE"
},
geo: { latitude: 52.5321, longitude: 13.3849 }
};
const jsonLd = buildLocalBusinessSchema(berlin);
const tag = renderJsonLd(jsonLd);
console.log(tag);
6) Mobile Optimization Techniques: Ladezeit, UX & „Near me“-Conversions
Warum Mobile Optimierung Local SEO Performance dominiert
- Local Intent ist häufig mobil („in der Nähe“, „jetzt geöffnet“, Navigation).
- Schlechte Mobile UX reduziert Interaktion (Anruf, Route, Formular) und kann indirekt Rankings/CTR verschlechtern.
Konkrete Mobile Optimization Techniques (priorisiert)
- Bildpipeline: WebP/AVIF, responsive srcset, Lazy-Loading für Below-the-fold.
- Rendering: kritisches CSS inline, Rest defer; JS reduzieren (3rd-party Skripte auditieren).
- Core Web Vitals: LCP (Hero-Bild/Font), INP (Event Handler, JS Main Thread), CLS (reservierte Plätze für Medien).
- Mobile Conversion-UX: Sticky Call-to-Action (Anrufen), klickbare Telefonnummern, „Route“ prominent, kurze Formulare.
- Server/Cache: CDN, HTTP caching headers, Brotli, Early Hints (optional).
7) Automatisierter Local SEO Check: Python Script für SEO Analysis
Was das Skript prüft (praxisnah für Performance)
- Erreichbarkeit & Statuscodes
- Title/H1 Basics
- NAP-Footprint (Telefon/Adresse als einfache Heuristik)
- Vorhandensein von JSON-LD (application/ld+json)
- Simple Mobile/Performance-Proxy: Antwortzeit (TTFB grob über Request-Latenz)
**Python Script for SEO Analysis: Crawl + Onpage Checks für lokale Landingpages**
import re
import time
import json
from dataclasses import dataclass
from typing import List, Dict, Optional
import requests
from bs4 import BeautifulSoup
@dataclass
class PageResult:
url: str
status_code: int
response_ms: int
title: str
h1: str
has_json_ld: bool
phone_found: Optional[str]
address_hint_found: bool
PHONE_REGEX = re.compile(r"(\+?\d[\d\s\-\(\)]{8,}\d)")
ADDRESS_HINTS = ["straße", "str.", "weg", "platz", "allee", "postaladdress", "plz"]
def fetch(url: str, timeout: int = 15) -> requests.Response:
headers = {
"User-Agent": "LocalSEO-AuditBot/1.0 (+https://example.com/bot)"
}
start = time.perf_counter()
resp = requests.get(url, headers=headers, timeout=timeout, allow_redirects=True)
elapsed_ms = int((time.perf_counter() - start) * 1000)
resp.elapsed_ms = elapsed_ms # type: ignore[attr-defined]
return resp
def parse_html(html: str) -> BeautifulSoup:
return BeautifulSoup(html, "html.parser")
def extract_title(soup: BeautifulSoup) -> str:
tag = soup.find("title")
return tag.get_text(strip=True) if tag else ""
def extract_h1(soup: BeautifulSoup) -> str:
tag = soup.find("h1")
return tag.get_text(strip=True) if tag else ""
def has_json_ld(soup: BeautifulSoup) -> bool:
scripts = soup.find_all("script", attrs={"type": "application/ld+json"})
return len(scripts) > 0
def find_phone(text: str) -> Optional[str]:
match = PHONE_REGEX.search(text)
if not match:
return None
return match.group(1).strip()
def find_address_hint(text: str) -> bool:
lower = text.lower()
return any(hint in lower for hint in ADDRESS_HINTS)
def audit_page(url: str) -> PageResult:
resp = fetch(url)
status = resp.status_code
ms = getattr(resp, "elapsed_ms", -1)
title = ""
h1 = ""
json_ld_present = False
phone = None
address_hint = False
if "text/html" in resp.headers.get("Content-Type", "") and resp.text:
soup = parse_html(resp.text)
title = extract_title(soup)
h1 = extract_h1(soup)
json_ld_present = has_json_ld(soup)
text = soup.get_text(" ", strip=True)
phone = find_phone(text)
address_hint = find_address_hint(text)
return PageResult(
url=url,
status_code=status,
response_ms=ms,
title=title,
h1=h1,
has_json_ld=json_ld_present,
phone_found=phone,
address_hint_found=address_hint,
)
def audit(urls: List[str]) -> List[PageResult]:
results = []
for url in urls:
try:
results.append(audit_page(url))
except requests.RequestException as exc:
results.append(
PageResult(
url=url,
status_code=0,
response_ms=-1,
title="",
h1="",
has_json_ld=False,
phone_found=None,
address_hint_found=False,
)
)
print(f"Error fetching {url}: {exc}")
return results
def to_report(results: List[PageResult]) -> Dict[str, object]:
issues = []
for r in results:
if r.status_code >= 400 or r.status_code == 0:
issues.append({"url": r.url, "issue": f"HTTP {r.status_code}"})
if not r.title:
issues.append({"url": r.url, "issue": "Missing <title>"})
if not r.h1:
issues.append({"url": r.url, "issue": "Missing <h1>"})
if not r.has_json_ld:
issues.append({"url": r.url, "issue": "Missing JSON-LD (Schema Markup)"})
if not r.phone_found:
issues.append({"url": r.url, "issue": "Phone not found (NAP footprint)"})
if not r.address_hint_found:
issues.append({"url": r.url, "issue": "Address hint not found (NAP footprint)"})
if r.response_ms != -1 and r.response_ms > 1200:
issues.append({"url": r.url, "issue": f"Slow response ({r.response_ms}ms)"})
return {
"summary": {
"pages": len(results),
"issues": len(issues)
},
"results": [r.__dict__ for r in results],
"issues": issues
}
if __name__ == "__main__":
urls_to_check = [
"https://www.beispiel.de/standorte/berlin-mitte",
"https://www.beispiel.de/standorte/hamburg"
]
results = audit(urls_to_check)
report = to_report(results)
print(json.dumps(report, indent=2, ensure_ascii=False))
8) Workflow: Von Audit → Fix → Rollout (skalierbar für mehrere Standorte)
flowchart TD A[SEO Audit Tools: GSC, GBP Insights, Lighthouse, Rank Tracker] --> B[Priorisierung nach Impact: Local Pack + Conversions] B --> C[NAP Consistency: Website ↔ Google My Business ↔ Local Citations] C --> D[Schema Markup Optimization: LocalBusiness je Standort] D --> E[Mobile Optimization Techniques: CWV + CTA UX] E --> F[Content & Reviews: lokale Proofs, FAQs, Q&A] F --> G[Monitoring: Rankings, GBP KPIs, Leads] G --> B


