Hreflang-Konsistenz und Rückverweise prüfen
Hreflang-Cluster funktionieren nur zuverlässig, wenn jede beteiligte Seite denselben vollständigen Satz an Alternativen einschließlich Selbstverweis angibt.
Im Browser ausführen – kostenlos
Diese Prüfung vergleicht Zuordnungen mehrerer Seiten und erkennt unvollständige Cluster, ohne URLs abzurufen. Sie bildet die erwartete Seitengruppe aus allen Quell- und Ziel-URLs, prüft jede Quelle und nennt genau die Links, die pro Seite fehlen. Das deterministische Ergebnis eignet sich für Veröffentlichungen, Migrationen und wiederholbare SEO-Kontrollen.
Warum vollständige Rückverweise wichtig sind
Eine Hreflang-Auszeichnung ist keine einseitige Empfehlung von einer Seite zur anderen. Sie beschreibt die Zugehörigkeit zu einer Gruppe sprachlich oder regional gleichwertiger Seiten. Jedes Mitglied muss denselben Satz von Zielen veröffentlichen und sich selbst einschließen. Nennt eine englische Seite französische und deutsche Alternativen, die französische Seite aber nur die englische, bleibt das Cluster trotz mehrerer scheinbar korrekter Tags unvollständig. Suchmaschinen können unbestätigte Beziehungen ignorieren, die falsche Sprachversion anbieten oder das gewünschte Regionalsignal schwächen. Mit wachsender Gruppe wird die manuelle Prüfung unzuverlässig, da die Zahl der Beziehungen schnell steigt. Vier Seiten müssen jeweils vier Ziele angeben, also sechzehn Quell-Ziel-Beziehungen. Diese Prüfung ersetzt den Sichtvergleich durch einen exakten Mengentest. Konsistenz wird nur gemeldet, wenn jede dargestellte Seite alle Seiten des Clusters angibt. Auslassungen und fehlende Selbstverweise bleiben dadurch nicht hinter einer bloßen Gesamtzahl verborgen.
Zuordnungen vorbereiten und auswerten
Übermitteln Sie für jede beobachtete Hreflang-Deklaration einen Datensatz. page_url bezeichnet die Seite mit dem Tag, language enthält dessen Wert und target_url das Ziel. Nehmen Sie alle vorgesehenen Clusterseiten auf. Die Prüfung leitet die erwartete Gruppe aus der Vereinigung von Quell- und Ziel-URLs ab. Wird eine Seite von ihren Geschwistern genannt, liefert aber keine eigenen Deklarationen, gehört sie weiterhin zur erwarteten Menge und wird mit sämtlichen fehlenden Zielen gemeldet. URLs werden nach dem Entfernen äußerer Leerzeichen als exakte Zeichenfolgen verglichen. Ihre Erfassung sollte deshalb die von den Seiten ausgegebene kanonische absolute Form verwenden. Die Ausgabe enthält eine Zusammenfassung je Seite und eine Konfliktliste. Bei unvollständigen Seiten nennt missing_urls genau die zu ergänzenden Ziele. consistent ist nur bei leerer Konfliktliste wahr. Doppelte Deklarationen erzeugen keine scheinbare Vollständigkeit, weil Ziele als Menge verglichen werden.
Einsatz bei Releases, Migrationen und Audits
Am wertvollsten ist die Prüfung, bevor Crawler eine mehrsprachige Veröffentlichung erreichen. Exportieren Sie die erzeugten Hreflang-Deklarationen der gerenderten Seiten, wandeln Sie sie in Zuordnungen um und stoppen Sie das Release, wenn consistent falsch ist. So erkennen Sie Template-Zweige ohne aktuelle Seite, regionale Einführungen, die nur den neuen Markt aktualisieren, und Migrationen, bei denen eine Sprachversion noch alte URLs ausgibt. Die Prüfung eignet sich ebenso nach dem Hinzufügen oder Entfernen von Sprachen. Da der Algorithmus keine Netzwerkanfragen ausführt, bestätigt er weder Erreichbarkeit noch kanonischen Status oder inhaltliche Gleichwertigkeit eines Ziels; dafür sind separate Crawling- und Redaktionsprüfungen nötig. Sein enges Versprechen ist eindeutig: Jede dargestellte Seite muss alle anderen und sich selbst nennen. API-Anfragen verwenden den veröffentlichten Grundpreis von $0.002. Bewahren Sie Konflikte mit den Bereitstellungsnachweisen auf, damit jede Korrektur einer konkreten Quelle und einem fehlenden Ziel zugeordnet bleibt.
Anwendungsfälle
Mehrsprachiges Release prüfen
Prüfen Sie vor der Veröffentlichung, ob jede neue Sprachversion und jede bestehende Schwesterseite alle Alternativen angibt.
Plattformmigration kontrollieren
Vergleichen Sie neue Template-Zuordnungen und finden Sie Seiten, die Selbst- oder Rückverweise verloren haben.
SEO-Pipeline absichern
Machen Sie aus einem inkonsistenten Cluster eine deterministisch fehlgeschlagene Prüfung mit genauen Lücken.
Häufige Fragen
Wann ist ein Hreflang-Cluster konsistent?
Jede dargestellte URL muss alle URLs des Clusters einschließlich sich selbst angeben. Nur dann ist das Ergebnis wahr.
Ruft die Prüfung Seiten ab?
Nein. Sie vergleicht nur Ihre Zuordnungen und prüft weder HTTP-Status noch Canonical-Tags oder Inhalte.
Wie werden fehlende Quellseiten erkannt?
Die erwartete Gruppe vereint Quell- und Ziel-URLs. Eine URL, die nur als Ziel erscheint, wird deshalb ohne Deklarationen gemeldet.
Gelten doppelte Deklarationen als Konflikt?
Sie ändern die Vollständigkeit nicht. Ziele werden als Menge verglichen, die Anzahl umfasst aber alle übermittelten Datensätze.
Werden URL-Varianten normalisiert?
Nein. Nach Entfernung äußerer Leerzeichen erfolgt ein exakter Vergleich. Vereinheitlichen Sie Schema, Host, Pfad und Endschrägstrich.
Was kostet eine API-Anfrage?
Jede Anfrage nutzt den veröffentlichten Grundpreis von $0.002. Der Vergleich benötigt weder Netzwerk noch Modelle.
Für Entwickler — API-Zugang
Alles auf dieser Seite ist auch per API verfügbar. Dieser Abschnitt richtet sich an Teams, die es in ihre eigenen Systeme einbinden möchten; alle anderen nutzen einfach das Tool oben.
Endpunkt
Authentifizierung per Bearer-Token. Ein einziger POST stellt die Aufgabe in die Warteschlange; das Ergebnis erhalten Sie per Webhook oder über einen signierten Link.
Aufruf aus Ihrem Stack
curl -X POST https://api.kit.forhosting.com/seo/hreflang-conflict-check \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}'const res = await fetch("https://api.kit.forhosting.com/seo/hreflang-conflict-check", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/seo/hreflang-conflict-check",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/seo/hreflang-conflict-check", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/seo/hreflang-conflict-check", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Beispiel-Anfrage
{
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
}Beispiel-Antwort
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "seo.hreflang_conflict_check",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}Die API arbeitet asynchron: Sie erhalten sofort eine task_id. Polling ist mit 1 Anfrage pro Sekunde erlaubt.
Preis
Der Preis steht auf der Seite – keine Tokens, keine Credits. Fehlgeschlagene Aufgaben werden nicht berechnet.
Fehler
| HTTP | Code | Bedeutung |
|---|---|---|
401 | unauthorized | Der API-Schlüssel fehlt oder ist ungültig – prüfen Sie den Authorization-Header (Bearer). |
402 | insufficient_balance | Ihr Guthaben reicht für diese Aufgabe nicht aus – Aufladungen verfallen nicht. |
404 | unknown_type | Unbekannter Aufgabentyp – prüfen Sie das Feld „type“ gegen den Katalog. |
429 | rate_limited | Zu viele Anfragen – warten Sie kurz; Polling ist mit 1 Anfrage pro Sekunde erlaubt. |