Skip to content

Latest commit

 

History

History
270 lines (203 loc) · 13.2 KB

File metadata and controls

270 lines (203 loc) · 13.2 KB

NETWAYS WP PostSync

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.


Funktionsweise (Pull-Modell)

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).


Frontend & SEO — die „SEO-Weiterleitung"

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.

So prüfst du den SEO-Modus

  1. 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=1 an der URL inspizieren, ohne weitergeleitet zu werden.)
  2. Sitemap: …/sitemap_index.xml bzw. …/wp-sitemap.xml öffnen → die gespiegelten Beiträge dürfen nicht enthalten sein.
  3. Canonical: im Quelltext der lokalen Seite (bzw. via ?netways_wp_postsync_preview=1) steht <link rel="canonical" href="…Quelle…">.

Backend — Kennzeichnung für Redakteure

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.

Autor-Zuordnung

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):

  1. Eingebetteter REST-Autor (Match per slug, sonst Name) – sofern der users-Endpoint der Quelle zugänglich ist.
  2. Autorname aus Yoast (yoast_head_json.author, ersatzweise der Person-Knoten im Schema-Graph) – funktioniert auch bei gesperrtem users-Endpoint.
  3. Lokaler Match über Anzeigename (exakt, Groß-/Kleinschreibung egal), ersatzweise über den daraus abgeleiteten Slug/Login.
  4. 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_name des 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).


Sync-State (Postmeta)

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.


Installation

  1. Ordner netways-wp-postsync/ nach wp-content/plugins/ auf dem Ziel-System hochladen.
  2. Plugin aktivieren (legt den Cron-Job netways_wp_postsync_sync_run an).
  3. Unter Einstellungen → WP PostSync eine oder mehrere Quellen mit je eigener Kategorie-Zuordnung konfigurieren.
  4. Jetzt synchronisieren klicken für den ersten Lauf.
  5. Das Blog-/Listen-Modul auf die Zielkategorie(n) filtern.

Einstellungen

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

Quellen & Kategorie-Zuordnung

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: * => Name gilt 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.

Manueller Sync / erzwungener Lauf

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.


Sync pausieren

Ü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.


Abhängigkeiten

  • 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-now per Crontab) für zuverlässige Intervalle.


Dateiübersicht

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

Deinstallation

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.php aus 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.


Lizenz

Apache License 2.0 — siehe LICENSE. © 2026 NETWAYS GmbH.