mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 18:34:13 +00:00
docs(seo): update with production URLs and frontend integration examples
- Add Production API endpoints for frontend SEO data fetching - Update all URLs from pl.c2sgmbh.de to cms.c2sgmbh.de - Add Next.js Metadata API integration examples - Add verification meta tags example - Add Multi-Tenant SEO section with tenant domains - Add localization examples (de/en) - Add Production vs Development URL tables - Add SEO setup checklist per tenant - Update robots.txt example with production URL 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
624b3dc605
commit
d5afc43f9d
1 changed files with 218 additions and 13 deletions
|
|
@ -1,9 +1,60 @@
|
||||||
# SEO-Erweiterung
|
# SEO-Erweiterung
|
||||||
|
|
||||||
|
*Letzte Aktualisierung: 18. Dezember 2025*
|
||||||
|
|
||||||
## Übersicht
|
## Übersicht
|
||||||
|
|
||||||
Diese Dokumentation beschreibt die implementierten SEO-Features für das Payload CMS Multi-Tenant System.
|
Diese Dokumentation beschreibt die implementierten SEO-Features für das Payload CMS Multi-Tenant System.
|
||||||
|
|
||||||
|
**Wichtig:** Frontends verwenden die **Production-API** (cms.c2sgmbh.de) für SEO-Daten, um konsistente Meta-Tags und Structured Data zu gewährleisten.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API-Endpoints für Frontend
|
||||||
|
|
||||||
|
### SEO-Daten abrufen
|
||||||
|
|
||||||
|
| Endpoint | Beschreibung |
|
||||||
|
|----------|--------------|
|
||||||
|
| `GET /api/globals/seo-settings` | Globale SEO-Konfiguration |
|
||||||
|
| `GET /api/pages?where[slug][equals]=...` | Page-spezifische SEO (meta-Feld) |
|
||||||
|
| `GET /api/posts?where[slug][equals]=...` | Post-spezifische SEO |
|
||||||
|
|
||||||
|
### Beispiel: SEO-Settings laden
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Frontend: SEO-Defaults aus Production laden
|
||||||
|
const seoSettings = await fetch('https://cms.c2sgmbh.de/api/globals/seo-settings')
|
||||||
|
.then(r => r.json())
|
||||||
|
|
||||||
|
// Enthält:
|
||||||
|
// - metaDefaults (titleSuffix, defaultDescription, defaultImage)
|
||||||
|
// - organization (name, legalName, logo, foundingDate)
|
||||||
|
// - contact (email, phone, fax)
|
||||||
|
// - address (street, city, country, etc.)
|
||||||
|
// - socialProfiles (Array)
|
||||||
|
// - localBusiness (type, priceRange, openingHours)
|
||||||
|
// - robots (indexing, additionalDisallow)
|
||||||
|
// - verification (google, bing, yandex)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Beispiel: Page-SEO laden
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Page mit SEO-Daten laden
|
||||||
|
const page = await fetch(
|
||||||
|
'https://cms.c2sgmbh.de/api/pages?where[slug][equals]=about&where[tenant][equals]=4&locale=de'
|
||||||
|
).then(r => r.json())
|
||||||
|
|
||||||
|
// page.docs[0].meta enthält:
|
||||||
|
// - title (Page-spezifischer Titel)
|
||||||
|
// - description (Meta-Description)
|
||||||
|
// - image (OG-Image Override)
|
||||||
|
// - noIndex, noFollow (Indexierungssteuerung)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Implementierte Features
|
## Implementierte Features
|
||||||
|
|
||||||
### 1. Dynamische Sitemap (`/sitemap.xml`)
|
### 1. Dynamische Sitemap (`/sitemap.xml`)
|
||||||
|
|
@ -16,6 +67,7 @@ Die Sitemap wird dynamisch aus der Datenbank generiert und enthält:
|
||||||
- Alle veröffentlichten Posts mit typ-basierter URL (Priorität: 0.6, Änderungshäufigkeit: monatlich)
|
- Alle veröffentlichten Posts mit typ-basierter URL (Priorität: 0.6, Änderungshäufigkeit: monatlich)
|
||||||
|
|
||||||
**URL-Schema für Posts:**
|
**URL-Schema für Posts:**
|
||||||
|
|
||||||
| Post-Typ | URL-Prefix |
|
| Post-Typ | URL-Prefix |
|
||||||
|----------|------------|
|
|----------|------------|
|
||||||
| blog | `/blog/{slug}` |
|
| blog | `/blog/{slug}` |
|
||||||
|
|
@ -42,8 +94,8 @@ Allow: /
|
||||||
Disallow: /admin
|
Disallow: /admin
|
||||||
Disallow: /api
|
Disallow: /api
|
||||||
|
|
||||||
Host: https://pl.c2sgmbh.de
|
Host: https://cms.c2sgmbh.de
|
||||||
Sitemap: https://pl.c2sgmbh.de/sitemap.xml
|
Sitemap: https://cms.c2sgmbh.de/sitemap.xml
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Structured Data (JSON-LD)
|
### 3. Structured Data (JSON-LD)
|
||||||
|
|
@ -69,12 +121,26 @@ Bietet Helper-Funktionen für Schema.org-konforme JSON-LD Daten:
|
||||||
| `combineSchemas()` | Kombiniert mehrere Schemas |
|
| `combineSchemas()` | Kombiniert mehrere Schemas |
|
||||||
| `renderJsonLd()` | Sicheres Rendering von JSON-LD |
|
| `renderJsonLd()` | Sicheres Rendering von JSON-LD |
|
||||||
|
|
||||||
#### Verwendungsbeispiel
|
#### Verwendungsbeispiel (Frontend)
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
|
// src/components/seo/JsonLd.tsx
|
||||||
import { generateArticleSchema, renderJsonLd } from '@/lib/structuredData'
|
import { generateArticleSchema, renderJsonLd } from '@/lib/structuredData'
|
||||||
|
|
||||||
export default function BlogPost({ post }) {
|
interface BlogPostProps {
|
||||||
|
post: {
|
||||||
|
title: string
|
||||||
|
excerpt: string
|
||||||
|
slug: string
|
||||||
|
publishedAt: string
|
||||||
|
updatedAt: string
|
||||||
|
author?: { name: string }
|
||||||
|
featuredImage?: { url: string }
|
||||||
|
categories?: Array<{ title: string }>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BlogPost({ post }: BlogPostProps) {
|
||||||
const schema = generateArticleSchema({
|
const schema = generateArticleSchema({
|
||||||
title: post.title,
|
title: post.title,
|
||||||
description: post.excerpt,
|
description: post.excerpt,
|
||||||
|
|
@ -84,7 +150,7 @@ export default function BlogPost({ post }) {
|
||||||
author: post.author,
|
author: post.author,
|
||||||
featuredImage: post.featuredImage,
|
featuredImage: post.featuredImage,
|
||||||
categories: post.categories,
|
categories: post.categories,
|
||||||
}, 'https://example.com')
|
}, 'https://complexcaresolutions.de') // Tenant-Domain
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -149,6 +215,117 @@ Globale SEO-Konfiguration im Admin-Panel unter "Einstellungen > SEO Einstellunge
|
||||||
- Bing Webmaster Tools
|
- Bing Webmaster Tools
|
||||||
- Yandex Webmaster
|
- Yandex Webmaster
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Frontend-Integration
|
||||||
|
|
||||||
|
### Next.js Metadata API
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/app/[locale]/page.tsx
|
||||||
|
import type { Metadata } from 'next'
|
||||||
|
|
||||||
|
async function getSeoSettings() {
|
||||||
|
const res = await fetch('https://cms.c2sgmbh.de/api/globals/seo-settings', {
|
||||||
|
next: { revalidate: 3600 } // 1 Stunde Cache
|
||||||
|
})
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPage(slug: string, tenantId: number, locale: string) {
|
||||||
|
const res = await fetch(
|
||||||
|
`https://cms.c2sgmbh.de/api/pages?where[slug][equals]=${slug}&where[tenant][equals]=${tenantId}&locale=${locale}`,
|
||||||
|
{ next: { revalidate: 60 } }
|
||||||
|
)
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateMetadata({ params }): Promise<Metadata> {
|
||||||
|
const seoSettings = await getSeoSettings()
|
||||||
|
const pageData = await getPage(params.slug || 'home', 4, params.locale)
|
||||||
|
const page = pageData.docs[0]
|
||||||
|
|
||||||
|
const title = page?.meta?.title
|
||||||
|
? `${page.meta.title} ${seoSettings.metaDefaults?.titleSuffix || ''}`
|
||||||
|
: seoSettings.metaDefaults?.titleSuffix
|
||||||
|
|
||||||
|
const description = page?.meta?.description
|
||||||
|
|| seoSettings.metaDefaults?.defaultDescription
|
||||||
|
|
||||||
|
const image = page?.meta?.image?.url
|
||||||
|
|| seoSettings.metaDefaults?.defaultImage?.url
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
openGraph: {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
images: image ? [{ url: image }] : [],
|
||||||
|
type: 'website',
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: 'summary_large_image',
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
images: image ? [image] : [],
|
||||||
|
},
|
||||||
|
robots: {
|
||||||
|
index: !page?.meta?.noIndex,
|
||||||
|
follow: !page?.meta?.noFollow,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verification Meta Tags
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/app/layout.tsx
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const seoSettings = await getSeoSettings()
|
||||||
|
|
||||||
|
return {
|
||||||
|
verification: {
|
||||||
|
google: seoSettings.verification?.google,
|
||||||
|
// Bing und Yandex als other
|
||||||
|
other: {
|
||||||
|
'msvalidate.01': seoSettings.verification?.bing,
|
||||||
|
'yandex-verification': seoSettings.verification?.yandex,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Multi-Tenant SEO
|
||||||
|
|
||||||
|
Jeder Tenant hat eigene SEO-Konfigurationen. Die SEO Settings Global gilt pro Installation, aber Page/Post-SEO ist tenant-spezifisch.
|
||||||
|
|
||||||
|
### Tenant-spezifische Domains
|
||||||
|
|
||||||
|
| Tenant ID | Domain | Sitemap |
|
||||||
|
|-----------|--------|---------|
|
||||||
|
| 1 | porwoll.de | https://porwoll.de/sitemap.xml |
|
||||||
|
| 4 | complexcaresolutions.de | https://complexcaresolutions.de/sitemap.xml |
|
||||||
|
| 5 | gunshin.de | https://gunshin.de/sitemap.xml |
|
||||||
|
|
||||||
|
### Lokalisierung
|
||||||
|
|
||||||
|
SEO-Felder sind lokalisiert (de/en):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Deutscher Content
|
||||||
|
fetch('https://cms.c2sgmbh.de/api/pages?slug=about&tenant=4&locale=de')
|
||||||
|
|
||||||
|
// Englischer Content
|
||||||
|
fetch('https://cms.c2sgmbh.de/api/pages?slug=about&tenant=4&locale=en')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Datenbank-Tabellen
|
## Datenbank-Tabellen
|
||||||
|
|
||||||
Die Migration `20251130_150000_blocks_tables.ts` erstellt:
|
Die Migration `20251130_150000_blocks_tables.ts` erstellt:
|
||||||
|
|
@ -159,15 +336,43 @@ Die Migration `20251130_150000_blocks_tables.ts` erstellt:
|
||||||
- `seo_settings_local_business_opening_hours` - Öffnungszeiten
|
- `seo_settings_local_business_opening_hours` - Öffnungszeiten
|
||||||
- `seo_settings_robots_additional_disallow` - Ausgeschlossene Pfade
|
- `seo_settings_robots_additional_disallow` - Ausgeschlossene Pfade
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## URLs
|
## URLs
|
||||||
|
|
||||||
- **Sitemap:** https://pl.c2sgmbh.de/sitemap.xml
|
### Production (für Frontends)
|
||||||
- **Robots:** https://pl.c2sgmbh.de/robots.txt
|
|
||||||
- **SEO Settings:** https://pl.c2sgmbh.de/admin/globals/seo-settings
|
|
||||||
|
|
||||||
## Nächste Schritte
|
| Resource | URL |
|
||||||
|
|----------|-----|
|
||||||
|
| **API Base** | https://cms.c2sgmbh.de/api |
|
||||||
|
| **SEO Settings** | https://cms.c2sgmbh.de/api/globals/seo-settings |
|
||||||
|
| **Sitemap** | https://cms.c2sgmbh.de/sitemap.xml |
|
||||||
|
| **Robots** | https://cms.c2sgmbh.de/robots.txt |
|
||||||
|
| **Admin Panel** | https://cms.c2sgmbh.de/admin/globals/seo-settings |
|
||||||
|
|
||||||
1. SEO Settings im Admin-Panel konfigurieren
|
### Development
|
||||||
2. JSON-LD in Frontend-Templates einbinden
|
|
||||||
3. Meta-Tags in Layout integrieren
|
| Resource | URL |
|
||||||
4. Google Search Console einrichten
|
|----------|-----|
|
||||||
|
| **API Base** | https://pl.porwoll.tech/api |
|
||||||
|
| **SEO Settings** | https://pl.porwoll.tech/api/globals/seo-settings |
|
||||||
|
| **Admin Panel** | https://pl.porwoll.tech/admin/globals/seo-settings |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checkliste: SEO-Setup pro Tenant
|
||||||
|
|
||||||
|
- [ ] SEO Settings im Admin-Panel konfigurieren
|
||||||
|
- [ ] Organisation (Name, Logo, Beschreibung)
|
||||||
|
- [ ] Kontaktdaten und Adresse
|
||||||
|
- [ ] Social Media Profile hinzufügen
|
||||||
|
- [ ] Local Business aktivieren (falls relevant)
|
||||||
|
- [ ] Google Search Console Code eintragen
|
||||||
|
- [ ] JSON-LD in Frontend-Templates einbinden
|
||||||
|
- [ ] Meta-Tags in Layout integrieren
|
||||||
|
- [ ] Sitemap bei Google Search Console einreichen
|
||||||
|
- [ ] robots.txt prüfen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Letzte Aktualisierung: 18. Dezember 2025*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue