Spiegelt Beiträge aus einer oder mehreren WordPress-Quellen als gleichwertige, verlinkte Teaser-Posts in ein anderes WordPress. Die gespiegelten Beiträge erscheinen in Listen/Blog-Modulen und im RSS-Feed, verlinken aber – SEO-sicher und ohne Duplicate Content – auf das Original.
Quellen, Kategorien und die einzelnen Verhaltensweisen sind frei konfigurierbar. Jede Quelle bekommt ihre eigene Kategorie-Zuordnung; die Quellen werden unabhängig voneinander geholt und abgeglichen.
Das Plugin läuft auf dem Ziel-System und holt sich per WP-Cron die Beiträge über die
öffentliche REST-API jeder konfigurierten Quelle (/wp-json/wp/v2/posts). Es werden keine
Zugangsdaten benötigt (reiner Lesezugriff). Sind mehrere Quellen konfiguriert, wird jede
einzeln geholt und abgeglichen — ein Ausfall einer Quelle lässt die Spiegel der anderen
unberührt.
Pro Quellbeitrag wird ein lokaler post angelegt bzw. aktualisiert:
| Lokales Feld | Inhalt |
|---|---|
| Titel | Quelltitel |
| Auszug / Inhalt | Quell-Excerpt + „Weiterlesen"-Link zur Quelle (kein Volltext) |
| Datum | Quelldatum (korrekte Sortierung in Listen/RSS) |
| Autor | aus dem Quellsystem gematcht (siehe Autor-Zuordnung) |
| Kategorie | lokale Zielkategorie(n) gemäß Kategorie-Zuordnung |
| Featured Image | optional einmal in die Mediathek kopiert (Sideload), Re-Download nur bei Bildänderung |
Ein Beitrag wird nur aktualisiert, wenn sich modified_gmt der Quelle geändert hat.
Verschwindet ein Quellbeitrag (gelöscht/depubliziert), wird der lokale Post auf
Entwurf gesetzt (nie hart gelöscht).
Standardmäßig ist ein gespiegelter Post lokal sichtbar (Listing, Feed), verweist aber
überall auf das Original. Es entsteht keine zweite, konkurrierende Seite. Alle folgenden
Mechanismen greifen ausschließlich bei gespiegelten Posts (erkennbar am Postmeta
_netways_wp_postsync_source_url) und lassen sich mit einem Schalter
(„SEO-Weiterleitung", Setting seo_syndication) gemeinsam an- oder abschalten. Umgesetzt
in includes/class-netways-wp-postsync-frontend.php.
| Mechanismus | WordPress-Hook | Wirkung |
|---|---|---|
| Permalink zeigt aufs Original | post_link |
get_permalink() liefert für gespiegelte Posts die Quell-URL. Dadurch zeigen Listen-Titel, „Weiterlesen" und der RSS-<link>/<guid> direkt aufs Original. |
| 301-Redirect der lokalen Einzelseite | template_redirect |
Ruft jemand (oder der Googlebot) die lokale Einzel-URL auf, wird er per 301 dauerhaft aufs Original weitergeleitet. |
| Cross-Domain-Canonical | _yoast_wpseo_canonical (Postmeta) + wpseo_canonical (Filter) |
Sagt Google: „Das Original steht bei der Quelle." Ranking-Signale konsolidieren beim Original. |
| Ausschluss aus XML-Sitemaps | wp_sitemaps_posts_query_args (Core) + wpseo_exclude_from_sitemap_by_post_ids (Yoast) |
Die lokalen URLs stehen in keiner Sitemap. |
Kein noindex |
— | Bewusst weggelassen: noindex + Canonical sind widersprüchliche Signale. 301 + Canonical decken den Fall sauber ab. |
Schalter aus (
seo_syndication= aus): Die gespiegelten Beiträge werden zu ganz normalen, lokal auffindbaren Seiten (kein Redirect, kein Canonical, in der Sitemap enthalten). Nur sinnvoll, wenn die Quelle die Inhalte nicht selbst indexiert — sonst droht Duplicate Content. Der gespeicherte Inhalt bleibt in jedem Fall nur ein Teaser (Auszug + Link), nicht der Volltext.
- Redirect: lokale Einzel-URL eines gespiegelten Posts aufrufen → muss per 301 auf die
Quelle springen. (Redakteure können die lokale Kopie mit
?netways_wp_postsync_preview=1an der URL inspizieren, ohne weitergeleitet zu werden.) - Sitemap:
…/sitemap_index.xmlbzw.…/wp-sitemap.xmlöffnen → die gespiegelten Beiträge dürfen nicht enthalten sein. - Canonical: im Quelltext der lokalen Seite (bzw. via
?netways_wp_postsync_preview=1) steht<link rel="canonical" href="…Quelle…">.
Damit niemand einen gespiegelten Beitrag versehentlich bearbeitet (Änderungen würden beim
nächsten Sync überschrieben), markiert das Plugin sie im Adminbereich
(includes/class-netways-wp-postsync-admin.php):
- Status-Label „↗ Gespiegelt (PostSync)" neben dem Titel in der Beitragsliste.
- Spalte „Quelle" mit direktem Link zum Original (zeigt den Quell-Host).
- Warnhinweis oben auf der Bearbeiten-Seite.
- Optional (Einstellung „Editor sperren"): Bearbeiten dieser Beiträge im Backend ganz unterbinden. Der automatische Sync selbst ist davon nicht betroffen.
Der Autor wird bei jedem Sync aus dem Quellsystem ermittelt und einem lokalen Benutzer
zugeordnet. Reihenfolge (resolve_author() in includes/class-netways-wp-postsync-sync.php):
- Eingebetteter REST-Autor (Match per
slug, sonst Name) – sofern derusers-Endpoint der Quelle zugänglich ist. - Autorname aus Yoast (
yoast_head_json.author, ersatzweise derPerson-Knoten im Schema-Graph) – funktioniert auch bei gesperrtemusers-Endpoint. - Lokaler Match über Anzeigename (exakt, Groß-/Kleinschreibung egal), ersatzweise über den daraus abgeleiteten Slug/Login.
- Fallback-Autor (Einstellung, Default Admin), wenn kein lokaler Benutzer passt.
Wichtig: Das Plugin ändert keine Benutzerprofile – es matcht nur. Der lokal angezeigte Name ist der
display_namedes zugeordneten lokalen Kontos. Damit ein Autor korrekt zugeordnet wird, sollte er auf beiden Systemen denselben Anzeigenamen (oder Slug) haben. Eine E-Mail-basierte Zuordnung ist nicht möglich, weil die öffentliche REST-API keine Adressen herausgibt.
Bestehende Posts mit falschem Autor lassen sich per „Jetzt synchronisieren" mit der Option „Alle Felder neu schreiben (erzwingen)" korrigieren (siehe unten).
| Meta-Key | Zweck |
|---|---|
_netways_wp_postsync_source_id |
Quell-Post-ID (Teil des Lookup-Schlüssels) |
_netways_wp_postsync_source_host |
Quell-Host (Teil des Lookup-Schlüssels; unterscheidet gleiche Post-IDs verschiedener Quellen) |
_netways_wp_postsync_source_url |
Original-Permalink (Permalink-Filter + Canonical + Redirect-Ziel) |
_netways_wp_postsync_source_modified |
modified_gmt der Quelle (Änderungserkennung) |
_netways_wp_postsync_source_img_url |
Quell-Bild-URL (Re-Sideload nur bei Änderung) |
Die Identität eines gespiegelten Beitrags ist das Paar (Host, Quell-Post-ID). Dadurch können zwei Quellen denselben numerischen Post-ID verwenden, ohne sich gegenseitig zu überschreiben; der Abgleich (Depublizieren → Entwurf) läuft ebenfalls pro Quelle.
- Ordner
netways-wp-postsync/nachwp-content/plugins/auf dem Ziel-System hochladen. - Plugin aktivieren (legt den Cron-Job
netways_wp_postsync_sync_runan). - Unter Einstellungen → WP PostSync eine oder mehrere Quellen mit je eigener Kategorie-Zuordnung konfigurieren.
- Jetzt synchronisieren klicken für den ersten Lauf.
- Das Blog-/Listen-Modul auf die Zielkategorie(n) filtern.
Einstellungen → WP PostSync
| Option | Default | Beschreibung |
|---|---|---|
| Sync aktiv | an | Cron-Sync pausieren, ohne die Verlinkung vorhandener Posts zu verlieren |
| Quellen | – | Ein oder mehrere Quellen-Blöcke, je Block eine Basis-URL (ohne Slash, z. B. https://example.com) + eigene Kategorie-Zuordnung (siehe unten). „Weitere Quelle" fügt einen Block hinzu, „Entfernen" löscht ihn |
| Beitragsbilder importieren | an | Featured Image aus der Quelle sideloaden (aus = nur Text-Teaser) |
| Quell-Kategorien als Tags | aus | Quell-Kategorien zusätzlich als lokale Tags übernehmen |
| SEO-Weiterleitung | an | 301/Canonical/Permalink→Quelle/Sitemap-Ausschluss (siehe SEO) |
| WP Media Folder | aus | gesyncte Bilder einem WP-Media-Folder-Ordner zuordnen (+ Ordnername) |
| Fallback-Autor | Admin | nur falls der Quell-Autor lokal nicht existiert |
| Cron-Intervall | stündlich | Sync-Frequenz |
| Editor sperren | aus | Bearbeiten gesyncter Posts im Backend verhindern |
Jede Quelle ist ein eigener Block mit Basis-URL und einer eigenen
Kategorie-Zuordnung — so lässt sich a → b und c → d unabhängig abbilden (die
Kategorie-IDs sind pro Quellsystem verschieden). Über „Weitere Quelle" kommt ein Block
hinzu, „Entfernen" löscht ihn; leere Blöcke werden beim Speichern verworfen.
Die Zuordnung je Quelle legt fest, welche Quell-Kategorien geholt und in welche lokalen
Zielkategorien die Beiträge einsortiert werden. Eine Zuordnung pro Zeile, Format
Quell-ID => Zielkategorie:
12 => News
34 => Events
- Quell-Seite = ID (Kategorie-ID im Quellsystem). Grund: Die REST-API filtert Beiträge
ausschließlich nach Kategorie-ID, und IDs sind stabil. IDs ermittelst du z. B. über
https://<quelle>/wp-json/wp/v2/categories?search=<Name>. - Ziel-Seite = Name (lokale Kategorie). Existiert sie nicht, wird sie automatisch angelegt. Verschiedene Quellen dürfen auf dieselbe lokale Zielkategorie zeigen.
- Ein Beitrag landet in allen Zielkategorien, deren Quell-Kategorien er trägt.
- Sammelkategorie / alle Beiträge:
* => Namegilt für jeden geholten Beitrag der Quelle. Nur ein*-Eintrag (ohne IDs) holt alle Beiträge dieser Quelle in diese eine Kategorie. - Leer: alle Beiträge der Quelle werden geholt, ohne erzwungene Zielkategorie.
Der Button „Jetzt synchronisieren" startet sofort einen Lauf — auch wenn „Sync aktiv" aus ist. Er verhält sich wie der Cron-Lauf: unveränderte Beiträge werden übersprungen, sodass die Statistik „neu / aktualisiert / übersprungen" die tatsächlichen Änderungen zeigt.
Die Option „Alle Felder neu schreiben (erzwingen)" macht daraus einen erzwungenen
Lauf: er ignoriert den modified_gmt-Vergleich und schreibt alle Felder neu (Titel,
Auszug, Autor, Bild, Kategorie) — nützlich, um bestehende Beiträge nachträglich zu
korrigieren.
Über „Sync aktiv" lässt sich der automatische Cron-Sync abschalten.
Nicht dafür das Plugin deaktivieren! Dann fielen auch die Permalink-/301-/ Canonical-Filter weg und die gespiegelten Beiträge würden auf die lokalen Thin-Pages statt aufs Original zeigen — schlecht für SEO und Nutzer.
Der Schalter pausiert nur das Holen/Aktualisieren; vorhandene Posts bleiben sichtbar und korrekt verlinkt. „Jetzt synchronisieren" funktioniert auch im pausierten Zustand.
- WordPress ≥ 6.0, PHP ≥ 7.4
- Die Quelle muss ihre REST-API (
/wp-json/wp/v2/) öffentlich erreichbar bereitstellen. - Optional: Yoast SEO (Canonical/Sitemap-Ausschluss, Autorname), WP Media Folder (Bild-Ordner). Beide optional – fehlen sie, werden die jeweiligen Schritte sauber übersprungen.
Hinweis zu WP-Cron: WP-Cron läuft nur bei Seitenaufrufen. Bei wenig Traffic lohnt ein echter System-Cron (
wp cron event run --due-nowper Crontab) für zuverlässige Intervalle.
netways-wp-postsync/
├── netways-wp-postsync.php # Bootstrap, Aktivierung, Cron-Schedule
├── uninstall.php # vollständiges Aufräumen beim Löschen
├── LICENSE # Apache License 2.0
├── README.md
└── includes/
├── class-netways-wp-postsync-settings.php # Einstellungsseite + manueller Sync
├── class-netways-wp-postsync-sync.php # Fetch (REST) + Upsert + Autor-Zuordnung + Reconciliation
├── class-netways-wp-postsync-media.php # Featured-Image-Sideload + WP-Media-Folder-Zuordnung
├── class-netways-wp-postsync-frontend.php # Permalink/RSS/Canonical/301/Sitemap (Frontend & SEO)
└── class-netways-wp-postsync-admin.php # Kennzeichnung gesyncter Posts im Backend
Das Plugin unterscheidet klar zwischen Deaktivieren und Löschen:
- Deaktivieren (Plugins → Deaktivieren): entfernt nur den Cron-Job. Alle gespiegelten Posts und kopierten Medien bleiben erhalten — der Bestand übersteht ein vorübergehendes Abschalten unverändert.
- Löschen (Plugins → Löschen): führt
uninstall.phpaus und räumt vollständig auf.
Beim Löschen werden entfernt:
- der geplante Cron-Job,
- die Plugin-Optionen (
netways_wp_postsync_options,netways_wp_postsync_last_run), - alle gespiegelten Beiträge (erkannt am Meta
_netways_wp_postsync_source_id) inklusive ihres per Sideload kopierten Featured Images und der Sync-Meta.
Beim Löschen bewusst erhalten bleiben (können anderes enthalten, das die Seite weiter braucht):
- lokal angelegte Kategorien und Tags,
- WP-Media-Folder-Ordner (
wpmf-category), - die eigenen, nicht gespiegelten Beiträge und Medien der Seite.
Auf Multisite läuft die vollständige Bereinigung (Cron + Posts + Bilder + Optionen) für jede Seite im Netzwerk.
Apache License 2.0 — siehe LICENSE. © 2026 NETWAYS GmbH.