2 min read
SEOTechnical SEO Checklist
Komplette Technical SEO Checklist für 2026. Crawling, Indexierung, Site Structure und Performance-Optimierung für bessere Rankings.
Technical SEOSEO ChecklistCrawlingIndexierungSite StructurePage Speed

Technical SEO Checklist
Meta-Description: Komplette Technical SEO Checklist für 2026. Crawling, Indexierung, Site Structure und Performance-Optimierung für bessere Rankings.
Keywords: Technical SEO, SEO Checklist, Crawling, Indexierung, Site Structure, Page Speed, Mobile SEO, SEO Audit
Einführung
Technical SEO bildet das Fundament für erfolgreiche Suchmaschinenoptimierung. Ohne saubere technische Basis nützt der beste Content wenig. Diese Checklist deckt alle wichtigen Aspekte ab – von Crawling bis Performance.
Technical SEO Overview
┌─────────────────────────────────────────────────────────────┐
│ TECHNICAL SEO PYRAMID │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ │
│ │ Content │ │
│ │ & UX │ │
│ └────┬────┘ │
│ ┌─────────┴─────────┐ │
│ │ On-Page SEO │ │
│ │ (Title, Meta,H1) │ │
│ └─────────┬─────────┘ │
│ ┌──────────────┴──────────────┐ │
│ │ Site Architecture │ │
│ │ (URLs, Internal Links) │ │
│ └──────────────┬──────────────┘ │
│ ┌───────────────────┴───────────────────┐ │
│ │ Crawling & Indexing │ │
│ │ (robots.txt, sitemap, canonicals) │ │
│ └───────────────────┬───────────────────┘ │
│ ┌──────────────────────┴──────────────────────┐ │
│ │ Server & Performance │ │
│ │ (HTTPS, Speed, Core Web Vitals, Mobile) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ Priority Levels: │
│ 🔴 Critical - Must fix immediately │
│ 🟡 Important - Fix soon │
│ 🟢 Nice to have - Optimize when possible │
│ │
└─────────────────────────────────────────────────────────────┘Server & Security
// lib/seo/audit/server.ts
interface ServerAuditResult {
https: boolean;
httpToHttpsRedirect: boolean;
wwwRedirect: 'www' | 'non-www' | 'inconsistent';
responseTime: number;
serverHeaders: Record<string, string>;
issues: string[];
}
async function auditServer(url: string): Promise<ServerAuditResult> {
const issues: string[] = [];
// HTTPS Check
const https = url.startsWith('https://');
if (!https) {
issues.push('🔴 Site is not using HTTPS');
}
// HTTP to HTTPS Redirect
const httpUrl = url.replace('https://', 'http://');
const httpResponse = await fetch(httpUrl, { redirect: 'manual' });
const httpToHttpsRedirect = httpResponse.status === 301 &&
httpResponse.headers.get('location')?.startsWith('https://');
if (!httpToHttpsRedirect) {
issues.push('🔴 HTTP does not redirect to HTTPS');
}
// WWW Consistency
const withWww = url.includes('www.');
const testUrl = withWww
? url.replace('www.', '')
: url.replace('://', '://www.');
const wwwResponse = await fetch(testUrl, { redirect: 'manual' });
const wwwRedirect = wwwResponse.status === 301 ? (withWww ? 'www' : 'non-www') : 'inconsistent';
if (wwwRedirect === 'inconsistent') {
issues.push('🟡 WWW and non-WWW versions not properly redirected');
}
// Response Time
const start = Date.now();
await fetch(url);
const responseTime = Date.now() - start;
if (responseTime > 500) {
issues.push(`🟡 Server response time is slow: ${responseTime}ms`);
}
// Security Headers
const response = await fetch(url);
const serverHeaders: Record<string, string> = {};
response.headers.forEach((value, key) => {
serverHeaders[key] = value;
});
const requiredHeaders = [
'strict-transport-security',
'x-content-type-options',
'x-frame-options'
];
requiredHeaders.forEach(header => {
if (!serverHeaders[header]) {
issues.push(`🟢 Missing security header: ${header}`);
}
});
return {
https,
httpToHttpsRedirect,
wwwRedirect,
responseTime,
serverHeaders,
issues
};
}// middleware.ts - Security Headers
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const response = NextResponse.next();
// Security Headers
response.headers.set('X-DNS-Prefetch-Control', 'on');
response.headers.set('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');
response.headers.set('X-Content-Type-Options', 'nosniff');
response.headers.set('X-Frame-Options', 'SAMEORIGIN');
response.headers.set('X-XSS-Protection', '1; mode=block');
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
// Permissions Policy
response.headers.set(
'Permissions-Policy',
'camera=(), microphone=(), geolocation=(self), interest-cohort=()'
);
return response;
}Crawling & Indexing
// app/robots.ts - Optimized robots.txt
import { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com';
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: [
'/api/',
'/admin/',
'/_next/',
'/private/',
'/*.json$',
'/*?*', // Query Parameter
'/search?*'
]
},
{
userAgent: 'Googlebot',
allow: '/',
disallow: ['/admin/', '/api/']
},
{
// Block bad bots
userAgent: ['AhrefsBot', 'SemrushBot', 'DotBot'],
disallow: '/'
}
],
sitemap: `${baseUrl}/sitemap.xml`,
host: baseUrl
};
}
// app/sitemap.ts - Dynamic Sitemap
import { MetadataRoute } from 'next';
import { getAllPages, getAllPosts, getAllProducts } from '@/lib/content';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com';
// Static Pages
const staticPages: MetadataRoute.Sitemap = [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1.0
},
{
url: `${baseUrl}/about`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8
},
{
url: `${baseUrl}/contact`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.5
},
{
url: `${baseUrl}/blog`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 0.9
}
];
// Dynamic Pages
const pages = await getAllPages();
const dynamicPages: MetadataRoute.Sitemap = pages.map(page => ({
url: `${baseUrl}/${page.slug}`,
lastModified: new Date(page.updatedAt),
changeFrequency: 'monthly',
priority: 0.7
}));
// Blog Posts
const posts = await getAllPosts();
const blogPosts: MetadataRoute.Sitemap = posts.map(post => ({
url: `${baseUrl}/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly',
priority: 0.8
}));
// Products
const products = await getAllProducts();
const productPages: MetadataRoute.Sitemap = products.map(product => ({
url: `${baseUrl}/products/${product.slug}`,
lastModified: new Date(product.updatedAt),
changeFrequency: 'daily',
priority: 0.9
}));
return [...staticPages, ...dynamicPages, ...blogPosts, ...productPages];
}// lib/seo/canonical.ts - Canonical URL Helper
export function getCanonicalUrl(path: string, locale?: string): string {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com';
// Remove trailing slash
const cleanPath = path.replace(/\/$/, '');
// Remove query parameters for canonical
const pathWithoutQuery = cleanPath.split('?')[0];
// Add locale if needed
if (locale && locale !== 'de') {
return `${baseUrl}/${locale}${pathWithoutQuery}`;
}
return `${baseUrl}${pathWithoutQuery}`;
}
// Usage in page
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
return {
alternates: {
canonical: getCanonicalUrl(`/blog/${params.slug}`)
}
};
}URL Structure
// lib/seo/url-utils.ts
export function createSEOFriendlyUrl(title: string): string {
return title
.toLowerCase()
.trim()
// Umlaute ersetzen
.replace(/ä/g, 'ae')
.replace(/ö/g, 'oe')
.replace(/ü/g, 'ue')
.replace(/ß/g, 'ss')
// Sonderzeichen entfernen
.replace(/[^a-z0-9\s-]/g, '')
// Mehrere Leerzeichen zu einem
.replace(/\s+/g, ' ')
// Leerzeichen zu Bindestrich
.replace(/\s/g, '-')
// Mehrere Bindestriche zu einem
.replace(/-+/g, '-')
// Max Länge
.substring(0, 60);
}
// URL Audit
interface URLAuditResult {
url: string;
issues: string[];
suggestions: string[];
}
export function auditURL(url: string): URLAuditResult {
const issues: string[] = [];
const suggestions: string[] = [];
// Length check
if (url.length > 75) {
issues.push('🟡 URL is too long (> 75 characters)');
}
// Uppercase check
if (url !== url.toLowerCase()) {
issues.push('🟡 URL contains uppercase characters');
}
// Underscore check
if (url.includes('_')) {
issues.push('🟡 URL contains underscores (use hyphens instead)');
}
// Double slashes
if (url.includes('//') && !url.startsWith('http')) {
issues.push('🔴 URL contains double slashes');
}
// Query parameters
if (url.includes('?')) {
suggestions.push('Consider using clean URLs without query parameters');
}
// Trailing slash consistency
if (!url.endsWith('/') && !url.includes('.')) {
suggestions.push('Consider adding trailing slash for consistency');
}
return { url, issues, suggestions };
}On-Page SEO
// lib/seo/audit/onpage.ts
interface OnPageAuditResult {
title: { value: string; length: number; issues: string[] };
metaDescription: { value: string; length: number; issues: string[] };
h1: { count: number; value: string; issues: string[] };
headings: { h2: number; h3: number; h4: number; issues: string[] };
images: { total: number; withoutAlt: number; issues: string[] };
links: { internal: number; external: number; broken: number; issues: string[] };
}
async function auditOnPage(html: string, url: string): Promise<OnPageAuditResult> {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
// Title
const title = doc.querySelector('title')?.textContent || '';
const titleIssues: string[] = [];
if (!title) titleIssues.push('🔴 Missing title tag');
else if (title.length < 30) titleIssues.push('🟡 Title too short (< 30 chars)');
else if (title.length > 60) titleIssues.push('🟡 Title too long (> 60 chars)');
// Meta Description
const metaDesc = doc.querySelector('meta[name="description"]')?.getAttribute('content') || '';
const metaDescIssues: string[] = [];
if (!metaDesc) metaDescIssues.push('🔴 Missing meta description');
else if (metaDesc.length < 120) metaDescIssues.push('🟡 Meta description too short');
else if (metaDesc.length > 160) metaDescIssues.push('🟡 Meta description too long');
// H1
const h1Elements = doc.querySelectorAll('h1');
const h1Issues: string[] = [];
if (h1Elements.length === 0) h1Issues.push('🔴 Missing H1 tag');
else if (h1Elements.length > 1) h1Issues.push('🟡 Multiple H1 tags found');
// Heading Structure
const h2Count = doc.querySelectorAll('h2').length;
const h3Count = doc.querySelectorAll('h3').length;
const h4Count = doc.querySelectorAll('h4').length;
const headingIssues: string[] = [];
if (h2Count === 0) headingIssues.push('🟡 No H2 headings found');
// Images
const images = doc.querySelectorAll('img');
const imagesWithoutAlt = Array.from(images).filter(
img => !img.getAttribute('alt')
).length;
const imageIssues: string[] = [];
if (imagesWithoutAlt > 0) {
imageIssues.push(`🟡 ${imagesWithoutAlt} images missing alt text`);
}
// Links
const links = doc.querySelectorAll('a[href]');
const baseUrl = new URL(url);
let internalLinks = 0;
let externalLinks = 0;
const linkIssues: string[] = [];
links.forEach(link => {
const href = link.getAttribute('href') || '';
if (href.startsWith('/') || href.includes(baseUrl.hostname)) {
internalLinks++;
} else if (href.startsWith('http')) {
externalLinks++;
// Check for nofollow on external links
const rel = link.getAttribute('rel') || '';
if (!rel.includes('nofollow') && !rel.includes('sponsored')) {
// Suggestion, not issue
}
}
});
return {
title: { value: title, length: title.length, issues: titleIssues },
metaDescription: { value: metaDesc, length: metaDesc.length, issues: metaDescIssues },
h1: { count: h1Elements.length, value: h1Elements[0]?.textContent || '', issues: h1Issues },
headings: { h2: h2Count, h3: h3Count, h4: h4Count, issues: headingIssues },
images: { total: images.length, withoutAlt: imagesWithoutAlt, issues: imageIssues },
links: { internal: internalLinks, external: externalLinks, broken: 0, issues: linkIssues }
};
}Complete SEO Checklist
// lib/seo/checklist.ts
export const technicalSEOChecklist = {
server: [
{ id: 'https', priority: 'critical', item: 'HTTPS enabled', automated: true },
{ id: 'http-redirect', priority: 'critical', item: 'HTTP redirects to HTTPS (301)', automated: true },
{ id: 'www-redirect', priority: 'important', item: 'WWW/non-WWW consistency', automated: true },
{ id: 'response-time', priority: 'important', item: 'Server response < 500ms', automated: true },
{ id: 'security-headers', priority: 'nice', item: 'Security headers configured', automated: true }
],
crawling: [
{ id: 'robots-txt', priority: 'critical', item: 'robots.txt exists and valid', automated: true },
{ id: 'sitemap', priority: 'critical', item: 'XML Sitemap exists', automated: true },
{ id: 'sitemap-submitted', priority: 'important', item: 'Sitemap submitted to Search Console', automated: false },
{ id: 'no-crawl-errors', priority: 'critical', item: 'No crawl errors in Search Console', automated: false },
{ id: 'canonical-tags', priority: 'critical', item: 'Canonical tags on all pages', automated: true }
],
indexing: [
{ id: 'indexable', priority: 'critical', item: 'Important pages are indexable', automated: true },
{ id: 'noindex-correct', priority: 'important', item: 'noindex only on non-important pages', automated: true },
{ id: 'no-duplicate-content', priority: 'critical', item: 'No duplicate content issues', automated: true },
{ id: 'hreflang', priority: 'important', item: 'hreflang tags for multilingual sites', automated: true }
],
urlStructure: [
{ id: 'url-readable', priority: 'important', item: 'URLs are human-readable', automated: true },
{ id: 'url-lowercase', priority: 'important', item: 'URLs are lowercase', automated: true },
{ id: 'url-hyphens', priority: 'nice', item: 'URLs use hyphens (not underscores)', automated: true },
{ id: 'url-length', priority: 'nice', item: 'URLs under 75 characters', automated: true },
{ id: 'no-parameters', priority: 'nice', item: 'Clean URLs without parameters', automated: true }
],
onPage: [
{ id: 'title-tag', priority: 'critical', item: 'Unique title tag (50-60 chars)', automated: true },
{ id: 'meta-description', priority: 'critical', item: 'Meta description (150-160 chars)', automated: true },
{ id: 'h1-tag', priority: 'critical', item: 'Single H1 per page', automated: true },
{ id: 'heading-hierarchy', priority: 'important', item: 'Proper heading hierarchy', automated: true },
{ id: 'image-alt', priority: 'important', item: 'All images have alt text', automated: true },
{ id: 'internal-links', priority: 'important', item: 'Internal linking structure', automated: false }
],
performance: [
{ id: 'lcp', priority: 'critical', item: 'LCP < 2.5s', automated: true },
{ id: 'inp', priority: 'critical', item: 'INP < 200ms', automated: true },
{ id: 'cls', priority: 'critical', item: 'CLS < 0.1', automated: true },
{ id: 'mobile-friendly', priority: 'critical', item: 'Mobile-friendly design', automated: true },
{ id: 'page-size', priority: 'important', item: 'Page size < 3MB', automated: true }
],
structuredData: [
{ id: 'jsonld', priority: 'important', item: 'JSON-LD structured data', automated: true },
{ id: 'valid-schema', priority: 'important', item: 'Schema validates in Rich Results Test', automated: false },
{ id: 'breadcrumbs', priority: 'nice', item: 'Breadcrumb schema', automated: true }
]
};
// Generate Audit Report
export function generateSEOReport(results: Record<string, boolean>): string {
let report = '# Technical SEO Audit Report\n\n';
Object.entries(technicalSEOChecklist).forEach(([category, items]) => {
report += `## ${category.charAt(0).toUpperCase() + category.slice(1)}\n\n`;
items.forEach(item => {
const status = results[item.id];
const emoji = status ? '✅' : (item.priority === 'critical' ? '❌' : '⚠️');
report += `${emoji} ${item.item}\n`;
});
report += '\n';
});
return report;
}Checklist Summary
| Category | Critical | Important | Nice to Have |
|---|---|---|---|
| **Server** | HTTPS, Redirects | Response time | Security headers |
| **Crawling** | robots.txt, Sitemap | Search Console | Crawl budget |
| **Indexing** | Canonical, No duplicates | hreflang | Coverage report |
| **URLs** | - | Readable, lowercase | Short URLs |
| **On-Page** | Title, Meta, H1 | Alt text, Headings | Schema |
| **Performance** | Core Web Vitals | Page size | Resource hints |
Fazit
Technical SEO Checklist erfordert:
- Server-Basics: HTTPS, Redirects, Security
- Crawling: robots.txt, Sitemap, Canonical
- On-Page: Title, Meta, Headings, Images
- Performance: Core Web Vitals optimieren
Regelmäßige Audits sichern die technische Basis.
Bildprompts
- "SEO audit dashboard showing checklist items, green checkmarks"
- "Technical SEO pyramid diagram, layered structure"
- "Search Console crawl stats visualization, data charts"