Nutze diese Schritte als Arbeitsliste und passe sie an Belege, Umfang und Einschränkungen des Projekts an.
Praktische Hinweise
- Öffne die zu prüfende Seite und die Entwicklerkonsole des Browsers. Aktiviere für die Prüfung mobiler Überläufe zuerst die responsive Ansicht.
- Prüfe den Code, füge das vollständige Skript in die Konsole ein und drücke Enter. Es liest die aktuelle Seite; nur Sitemap-Audit und Linkprüfungen senden begrenzte Anfragen an denselben Ursprung.
- Prüfe die Konsolenausgabe oder die heruntergeladene CSV/JSON-Datei. Browserrichtlinien, Anmeldung und nicht unterstützte Servermethoden können Ergebnisse uneindeutig machen.
(async () => {
const MAX_VARIANTS = 30;
const deadline = Date.now() + 30000;
const currentCanonical = new URL(document.querySelector('link[rel="canonical"]')?.href || location.href, location.href).href;
const tags = [...document.querySelectorAll('link[rel="alternate"][hreflang][href]')].slice(0, MAX_VARIANTS);
const rows = [];
for (const tag of tags) {
const target = new URL(tag.href, location.href);
const item = { language: tag.hreflang, url: target.href, sameOrigin: target.origin === location.origin, reciprocal: 'not checked' };
if (item.sameOrigin) {
if (Date.now() >= deadline) { item.reciprocal = 'skipped: 30-second runtime limit'; rows.push(item); continue; }
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), Math.min(5000, deadline - Date.now()));
try {
const response = await fetch(target.href, { credentials: 'omit', redirect: 'follow', signal: controller.signal });
if (!response.ok || new URL(response.url).origin !== location.origin) throw new Error('HTTP ' + response.status + ' or cross-origin redirect');
const doc = new DOMParser().parseFromString(await response.text(), 'text/html');
const reciprocal = [...doc.querySelectorAll('link[rel="alternate"][hreflang][href]')].some((link) => {
try { return new URL(link.href, target.href).href === currentCanonical; } catch { return false; }
});
item.reciprocal = reciprocal ? 'yes' : 'missing';
} catch (error) { item.reciprocal = error.name === 'AbortError' ? 'timeout' : 'could not check'; }
finally { clearTimeout(timer); }
}
rows.push(item);
}
console.table(rows);
console.info('Current canonical:', currentCanonical, '· hreflang variants found:', tags.length);
if (Date.now() >= deadline) console.warn('The 30-second runtime limit was reached; remaining links were not checked.');
if (tags.length >= MAX_VARIANTS) console.warn('Only the first ' + MAX_VARIANTS + ' language variants were checked.');
if (!tags.length) console.warn('No link rel=\"alternate\" hreflang entries were found.');
console.info('Cross-origin and inaccessible pages are not fetched. A “missing” reciprocal link may also result from a canonical URL variant or redirect; review it manually.');
})();Prüfe den Code vor der Ausführung. Er liest die aktuelle Seite; nur Sitemap- und Linkprüfungen senden begrenzte Anfragen an denselben Ursprung ohne Cookies. Website-Inhalte werden nicht geändert.