Weitere nĂĽtzliche Tools
diff --git a/src/pages/examples/AeoExample.tsx b/src/pages/examples/AeoExample.tsx
new file mode 100644
index 0000000..2e705ec
--- /dev/null
+++ b/src/pages/examples/AeoExample.tsx
@@ -0,0 +1,244 @@
+/**
+ * Example page demonstrating Answer Engine Optimization (AEO) implementation
+ * This shows how to integrate all AEO components for maximum AI citation potential
+ */
+
+import React, { useEffect } from 'react';
+import Canonical from '@/components/seo/Canonical';
+import JsonLd from '@/components/seo/JsonLd';
+import ContentMeta from '@/components/seo/ContentMeta';
+import {
+ buildArticleJsonLd,
+ buildFAQPageJsonLd,
+ buildHowToJsonLd,
+ buildBreadcrumbJsonLd,
+ exampleFAQs,
+ exampleHowTo
+} from '@/lib/schema';
+import { queueCurrentPage } from '@/lib/indexnow';
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
+import { CheckCircle, ArrowRight, Info } from 'lucide-react';
+
+const AeoExample: React.FC = () => {
+ // Page metadata for Article schema
+ const articleData = {
+ headline: 'Solaranlage installieren lassen - Vollständiger Leitfaden 2025',
+ description: 'Schritt-für-Schritt Anleitung: Wie Sie die richtige Solaranlage finden, Installateure vergleichen und Förderungen optimal nutzen.',
+ datePublished: new Date('2024-12-01'),
+ dateModified: new Date('2025-01-04'),
+ author: {
+ name: 'EnergieProfis Redaktion',
+ url: 'https://energie-profis.de/team',
+ jobTitle: 'Energie-Experten',
+ organization: 'EnergieProfis'
+ },
+ publisher: {
+ name: 'EnergieProfis',
+ description: 'FĂĽhrendes Verzeichnis fĂĽr erneuerbare Energien',
+ url: 'https://energie-profis.de',
+ logo: 'https://energie-profis.de/favicon.ico'
+ },
+ images: [
+ 'https://energie-profis.de/solar_banner.png',
+ 'https://energie-profis.de/sun_flow_banner.png'
+ ],
+ url: 'https://energie-profis.de/solaranlage-installieren-lassen-leitfaden'
+ };
+
+ // Breadcrumb navigation for better structure
+ const breadcrumbs = [
+ { name: 'Home', url: 'https://energie-profis.de/' },
+ { name: 'Solar', url: 'https://energie-profis.de/solar' },
+ { name: 'Installation Guide', url: 'https://energie-profis.de/solaranlage-installieren-lassen-leitfaden' }
+ ];
+
+ useEffect(() => {
+ // Queue page for IndexNow submission
+ queueCurrentPage();
+ }, []);
+
+ return (
+ <>
+ {/* AEO Components - These don't render visible content */}
+
+
+
+
+
+
+ {/* Visible Page Content */}
+
+
+
+ {/* Breadcrumb Navigation */}
+
+
+ {breadcrumbs.map((crumb, index) => (
+
+
+ {crumb.name}
+
+ {index < breadcrumbs.length - 1 && (
+
+ )}
+
+ ))}
+
+
+
+ {/* Article Header */}
+
+
+ {/* Main Article Content */}
+
+
+ {/* Introduction with rich context */}
+
+ Warum eine professionelle Solaranlage-Installation?
+
+ Die Installation einer Solaranlage ist eine der wichtigsten Investitionen fĂĽr nachhaltige
+ Energieversorgung. Mit steigenden Strompreisen und verbesserten Förderprogrammen wird
+ Solarenergie 2025 noch attraktiver. Dieser Leitfaden hilft Ihnen dabei, die richtige
+ Entscheidung zu treffen.
+
+
+
+
+
+
+ Wichtige Vorteile 2025
+
+
+
+
+
+
+ BAFA-Förderung bis 500€ für Balkonkraftwerke
+
+
+
+ KfW-Kredite mit gĂĽnstigen Zinsen
+
+
+
+ Wegfall der EEG-Umlage fĂĽr Eigenverbrauch
+
+
+
+
+
+
+ {/* HowTo Section - Structured for AI understanding */}
+
+ {exampleHowTo.name}
+ {exampleHowTo.description}
+
+
+ {exampleHowTo.steps.map((step, index) => (
+
+
+
+ Schritt {index + 1}: {step.name}
+
+
+
+ {step.text}
+
+
+ ))}
+
+
+
+
Geschätzte Kosten und Zeitaufwand
+
Kosten: {exampleHowTo.estimatedCost}€
+
Zeitaufwand: 2 Wochen (von Planung bis Installation)
+
+
+
+ {/* FAQ Section - Optimized for AI answers */}
+
+ Häufig gestellte Fragen zur Solar-Installation
+
+ {exampleFAQs.map((faq, index) => (
+
+
+ {faq.question}
+
+
+ {faq.answer}
+
+
+ ))}
+
+
+
+ {/* Expert Insights for Authority */}
+
+ Expertentipps fĂĽr 2025
+
+
+ Aktuelle Marktentwicklungen
+
+
+ • Modulpreise sind 2025 um 20% gefallen
+ • Neue Speichertechnologien mit längerer Lebensdauer
+ • Vereinfachte Anmeldeverfahren in allen Bundesländern
+ • Smart Home Integration wird Standard
+
+
+
+
+
+ {/* Call to Action */}
+
+
+
+
+ Bereit fĂĽr Ihre Solaranlage?
+
+
+ Finden Sie qualifizierte Installateure in Ihrer Region und
+ erhalten Sie kostenlose Angebote.
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default AeoExample;
\ No newline at end of file
diff --git a/tests/e2e/canonical.spec.ts b/tests/e2e/canonical.spec.ts
new file mode 100644
index 0000000..06bd69c
--- /dev/null
+++ b/tests/e2e/canonical.spec.ts
@@ -0,0 +1,59 @@
+import { test, expect } from '@playwright/test';
+
+test.describe('Canonical URL Validation', () => {
+ test('homepage should have exactly one canonical link', async ({ page }) => {
+ await page.goto('/');
+
+ const canonicalLinks = await page.locator('link[rel="canonical"]').all();
+ expect(canonicalLinks.length).toBe(1);
+
+ const href = await canonicalLinks[0].getAttribute('href');
+ expect(href).toBe('https://energie-profis.de/');
+ });
+
+ test('all main pages should have proper canonical URLs', async ({ page }) => {
+ const pages = [
+ { path: '/', expected: 'https://energie-profis.de/' },
+ { path: '/solar', expected: 'https://energie-profis.de/solar' },
+ { path: '/wind', expected: 'https://energie-profis.de/wind' },
+ { path: '/installateur-finden', expected: 'https://energie-profis.de/installateur-finden' },
+ { path: '/kostenlose-beratung', expected: 'https://energie-profis.de/kostenlose-beratung' },
+ { path: '/unternehmen-listen', expected: 'https://energie-profis.de/unternehmen-listen' }
+ ];
+
+ for (const { path, expected } of pages) {
+ await page.goto(path);
+
+ // Should have exactly one canonical link
+ const canonicalLinks = await page.locator('link[rel="canonical"]').all();
+ expect(canonicalLinks.length).toBe(1);
+
+ // Should have the correct href
+ const href = await canonicalLinks[0].getAttribute('href');
+ expect(href).toBe(expected);
+ }
+ });
+
+ test('canonical should not have query parameters or fragments', async ({ page }) => {
+ // Test with query parameters
+ await page.goto('/?utm_source=test&ref=social');
+
+ const canonicalLinks = await page.locator('link[rel="canonical"]').all();
+ expect(canonicalLinks.length).toBe(1);
+
+ const href = await canonicalLinks[0].getAttribute('href');
+ expect(href).toBe('https://energie-profis.de/');
+ expect(href).not.toContain('utm_source');
+ expect(href).not.toContain('ref=');
+ });
+
+ test('canonical should be absolute URL with https', async ({ page }) => {
+ await page.goto('/solar');
+
+ const canonicalLink = await page.locator('link[rel="canonical"]').first();
+ const href = await canonicalLink.getAttribute('href');
+
+ expect(href).toMatch(/^https:\/\//);
+ expect(href).toContain('energie-profis.de');
+ });
+});
\ No newline at end of file
diff --git a/tests/e2e/robots.spec.ts b/tests/e2e/robots.spec.ts
new file mode 100644
index 0000000..0e75452
--- /dev/null
+++ b/tests/e2e/robots.spec.ts
@@ -0,0 +1,37 @@
+import { test, expect } from '@playwright/test';
+
+test.describe('Robots.txt AEO Compliance', () => {
+ test('should allow PerplexityBot and GPTBot', async ({ page }) => {
+ const response = await page.goto('/robots.txt');
+ expect(response?.status()).toBe(200);
+
+ const content = await page.textContent('pre') || await page.textContent('body');
+
+ // Check for PerplexityBot
+ expect(content).toContain('User-agent: PerplexityBot');
+ expect(content).toContain('Allow: /');
+
+ // Check for GPTBot
+ expect(content).toContain('User-agent: GPTBot');
+ expect(content).toContain('Allow: /');
+
+ // Check for sitemap reference
+ expect(content).toContain('Sitemap: https://energie-profis.de/sitemap.xml');
+
+ // Ensure no blanket disallow that would block AI bots
+ expect(content).not.toMatch(/User-agent: \*[\s\S]*?Disallow: \//);
+ });
+
+ test('should maintain existing bot permissions', async ({ page }) => {
+ const response = await page.goto('/robots.txt');
+ expect(response?.status()).toBe(200);
+
+ const content = await page.textContent('pre') || await page.textContent('body');
+
+ // Check that existing bots are still allowed
+ expect(content).toContain('User-agent: Googlebot');
+ expect(content).toContain('User-agent: Bingbot');
+ expect(content).toContain('User-agent: Twitterbot');
+ expect(content).toContain('User-agent: facebookexternalhit');
+ });
+});
\ No newline at end of file
diff --git a/tests/e2e/schema.spec.ts b/tests/e2e/schema.spec.ts
new file mode 100644
index 0000000..a2ec842
--- /dev/null
+++ b/tests/e2e/schema.spec.ts
@@ -0,0 +1,98 @@
+import { test, expect } from '@playwright/test';
+
+test.describe('JSON-LD Schema Validation', () => {
+ test('homepage should have valid Organization and WebSite schema', async ({ page }) => {
+ await page.goto('/');
+
+ // Find JSON-LD script tags
+ const jsonLdScripts = await page.locator('script[type="application/ld+json"]').all();
+ expect(jsonLdScripts.length).toBeGreaterThan(0);
+
+ let hasWebSite = false;
+ let hasOrganization = false;
+
+ for (const script of jsonLdScripts) {
+ const content = await script.textContent();
+ if (content) {
+ const data = JSON.parse(content);
+
+ if (data['@type'] === 'WebSite') {
+ hasWebSite = true;
+ expect(data.name).toBe('EnergieProfis');
+ expect(data.url).toMatch(/energie-profis\.de/);
+ expect(data.potentialAction).toBeDefined();
+ expect(data.potentialAction['@type']).toBe('SearchAction');
+ }
+
+ if (data['@type'] === 'Organization') {
+ hasOrganization = true;
+ expect(data.name).toBe('EnergieProfis');
+ expect(data.logo).toBeDefined();
+ }
+ }
+ }
+
+ expect(hasWebSite).toBe(true);
+ expect(hasOrganization).toBe(true);
+ });
+
+ test('FAQ sections should have valid FAQPage schema', async ({ page }) => {
+ await page.goto('/');
+
+ // Look for FAQ content on homepage
+ const faqSection = await page.locator('text=Häufige Fragen').first();
+ if (await faqSection.isVisible()) {
+ const jsonLdScripts = await page.locator('script[type="application/ld+json"]').all();
+
+ let hasFAQPage = false;
+ for (const script of jsonLdScripts) {
+ const content = await script.textContent();
+ if (content) {
+ const data = JSON.parse(content);
+
+ if (data['@type'] === 'FAQPage') {
+ hasFAQPage = true;
+ expect(data.mainEntity).toBeInstanceOf(Array);
+ expect(data.mainEntity.length).toBeGreaterThan(0);
+
+ // Validate each FAQ item
+ for (const item of data.mainEntity) {
+ expect(item['@type']).toBe('Question');
+ expect(item.name).toBeDefined();
+ expect(item.acceptedAnswer).toBeDefined();
+ expect(item.acceptedAnswer['@type']).toBe('Answer');
+ expect(item.acceptedAnswer.text).toBeDefined();
+ }
+ }
+ }
+ }
+
+ // FAQ schema should exist if FAQ content is present
+ if (await faqSection.isVisible()) {
+ expect(hasFAQPage).toBe(true);
+ }
+ }
+ });
+
+ test('all JSON-LD should be valid JSON', async ({ page }) => {
+ const pages = ['/', '/solar', '/wind', '/installateur-finden'];
+
+ for (const pagePath of pages) {
+ await page.goto(pagePath);
+
+ const jsonLdScripts = await page.locator('script[type="application/ld+json"]').all();
+
+ for (const script of jsonLdScripts) {
+ const content = await script.textContent();
+ if (content) {
+ // This should not throw if JSON is valid
+ expect(() => JSON.parse(content)).not.toThrow();
+
+ const data = JSON.parse(content);
+ expect(data['@context']).toBe('https://schema.org');
+ expect(data['@type']).toBeDefined();
+ }
+ }
+ }
+ });
+});
\ No newline at end of file
diff --git a/tests/e2e/sitemap.spec.ts b/tests/e2e/sitemap.spec.ts
new file mode 100644
index 0000000..3529169
--- /dev/null
+++ b/tests/e2e/sitemap.spec.ts
@@ -0,0 +1,77 @@
+import { test, expect } from '@playwright/test';
+
+test.describe('Sitemap XML Validation', () => {
+ test('should serve valid sitemap.xml', async ({ page }) => {
+ const response = await page.goto('/sitemap.xml');
+ expect(response?.status()).toBe(200);
+ expect(response?.headers()['content-type']).toMatch(/xml/);
+
+ const content = await page.textContent('urlset') || await page.textContent('body');
+
+ // Should be valid XML
+ expect(content).toContain('');
+ expect(content).toContain('
');
+ expect(content).toContain(' ');
+ });
+
+ test('should include all main pages with lastmod', async ({ page }) => {
+ await page.goto('/sitemap.xml');
+
+ const content = await page.textContent('urlset') || await page.textContent('body');
+
+ const expectedUrls = [
+ 'https://energie-profis.de/',
+ 'https://energie-profis.de/solar',
+ 'https://energie-profis.de/wind',
+ 'https://energie-profis.de/installateur-finden',
+ 'https://energie-profis.de/kostenlose-beratung',
+ 'https://energie-profis.de/unternehmen-listen'
+ ];
+
+ for (const url of expectedUrls) {
+ expect(content).toContain(`
${url} `);
+ }
+
+ // Check for lastmod tags
+ expect(content).toMatch(/
\d{4}-\d{2}-\d{2}<\/lastmod>/);
+ });
+
+ test('should have proper priority and changefreq values', async ({ page }) => {
+ await page.goto('/sitemap.xml');
+
+ const content = await page.textContent('urlset') || await page.textContent('body');
+
+ // Homepage should have highest priority
+ expect(content).toMatch(/https:\/\/energie-profis\.de\/<\/loc>[\s\S]*?1\.0<\/priority>/);
+
+ // Should have valid changefreq values
+ const validChangeFreqs = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'];
+ const changefreqMatches = content.match(/([^<]+)<\/changefreq>/g) || [];
+
+ for (const match of changefreqMatches) {
+ const value = match.replace(/<\/?changefreq>/g, '');
+ expect(validChangeFreqs).toContain(value);
+ }
+ });
+
+ test('should have valid date format for lastmod', async ({ page }) => {
+ await page.goto('/sitemap.xml');
+
+ const content = await page.textContent('urlset') || await page.textContent('body');
+
+ // Extract all lastmod dates
+ const lastmodMatches = content.match(/([^<]+)<\/lastmod>/g) || [];
+ expect(lastmodMatches.length).toBeGreaterThan(0);
+
+ for (const match of lastmodMatches) {
+ const dateString = match.replace(/<\/?lastmod>/g, '');
+
+ // Should be in YYYY-MM-DD format (ISO date)
+ expect(dateString).toMatch(/^\d{4}-\d{2}-\d{2}$/);
+
+ // Should be a valid date
+ const date = new Date(dateString);
+ expect(date.toString()).not.toBe('Invalid Date');
+ }
+ });
+});
\ No newline at end of file