{"id":387655,"date":"2026-11-04T05:33:30","date_gmt":"2026-11-04T05:33:30","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/content-observer\/"},"modified":"2026-11-04T05:33:19","modified_gmt":"2026-11-04T05:33:19","slug":"palasthotel-content-change-observer","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/palasthotel-content-change-observer\/","author":14867054,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.0.0","stable_tag":"2.0.0","tested":"7.1.4","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"Palasthotel Content Change Observer","header_author":"Palasthotel","header_description":"Efficiently observe content changes between WordPress instances.","assets_banners_color":"6f706f","last_updated":"2026-11-04 05:33:19","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/palasthotel.de\/","header_plugin_uri":"https:\/\/github.com\/palasthotel\/wp-palasthotel-content-change-observer","header_author_uri":"https:\/\/palasthotel.de","rating":0,"author_block_rating":0,"active_installs":0,"downloads":119,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"2.0.0":{"tag":"2.0.0","author":"palasthotel","date":"2026-11-04 05:33:19","revision":3783123}},"upgrade_notice":{"1.2.4":"<p>Security release. A site without an API key no longer accepts requests from other sites - set a key under Content Change Observer \u2192 Settings before updating if the field is empty.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3783123,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3783123,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3783123,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3783123,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["2.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3783123,"resolution":"1","location":"assets","locale":"","width":1280,"height":800},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3783123,"resolution":"2","location":"assets","locale":"","width":1280,"height":800},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3783123,"resolution":"3","location":"assets","locale":"","width":1280,"height":800},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3783123,"resolution":"4","location":"assets","locale":"","width":1280,"height":800}},"screenshots":{"1":"Modifications fetched from an observed site, with buttons to apply them from a point in time","2":"Manage page: the sites observing this one and the sites it observes, each with a connection test","3":"Connect a new site with its URL, slug, API key and relation type","4":"Settings: this site's API key and the WP-Cron schedules"}},"plugin_section":[],"plugin_tags":[529,2275,441,1558,4574],"plugin_category":[51],"plugin_contributors":[85158,274076,138992],"plugin_business_model":[],"class_list":["post-387655","plugin","type-plugin","status-publish","hentry","plugin_tags-content","plugin_tags-developer","plugin_tags-multisite","plugin_tags-sync","plugin_tags-wp-cli","plugin_category-multisite","plugin_contributors-edwardbock","plugin_contributors-janaeggebrecht","plugin_contributors-palasthotel","plugin_committers-palasthotel"],"banners":{"banner":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/banner-772x250.png?rev=3783123","banner_2x":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/banner-1544x500.png?rev=3783123","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/icon-128x128.png?rev=3783123","icon_2x":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/icon-256x256.png?rev=3783123","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/screenshot-1.png?rev=3783123","caption":"Modifications fetched from an observed site, with buttons to apply them from a point in time"},{"src":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/screenshot-2.png?rev=3783123","caption":"Manage page: the sites observing this one and the sites it observes, each with a connection test"},{"src":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/screenshot-3.png?rev=3783123","caption":"Connect a new site with its URL, slug, API key and relation type"},{"src":"https:\/\/ps.w.org\/palasthotel-content-change-observer\/assets\/screenshot-4.png?rev=3783123","caption":"Settings: this site's API key and the WP-Cron schedules"}],"raw_content":"<!--section=description-->\n<p>Content Change Observer tells one WordPress site what changed on another. The observed site records modifications - saved and deleted posts, and anything a theme or plugin reports - and the sites observing it receive them and react in their own code, for example to refresh a cached teaser list or a mirrored menu.<\/p>\n\n<p>The plugin moves no content by itself. It transports the modification (content id, content type, create\/update\/delete and time); what happens next is up to the <code>content_observer_on_modifications<\/code> action on the observing site.<\/p>\n\n<ul>\n<li>Connect sites as observer, observable or both, secured by an API key<\/li>\n<li>Modifications are pushed hourly (notify) or pulled on demand (fetch)<\/li>\n<li>Admin pages to manage connections and inspect and apply modifications<\/li>\n<li>WP-CLI commands for every step, so a system cron can replace WP-Cron<\/li>\n<\/ul>\n\n<p>Typical uses:<\/p>\n\n<ul>\n<li>A portal clears its cached teaser list as soon as an article on the news site changes<\/li>\n<li>Several sites rebuild a mirrored navigation when the main site's menu changes<\/li>\n<li>A central search site re-indexes changed posts and drops deleted ones<\/li>\n<li>An archive site stores a copy of every article, so it survives a later deletion<\/li>\n<\/ul>\n\n<p>Developer documentation: <a href=\"https:\/\/github.com\/palasthotel\/wp-palasthotel-content-change-observer\">github.com\/palasthotel\/wp-palasthotel-content-change-observer<\/a><\/p>\n\n<h3>External services<\/h3>\n\n<p>The plugin only talks to the WordPress sites an administrator connects under Content Change Observer \u2192 Manage. It sends them this site's URL, its API key and the list of modifications, and requests theirs. No other service is contacted.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install the plugin on every site that observes or is observed, from Plugins &gt; Add New or by uploading <code>palasthotel-content-change-observer.zip<\/code><\/li>\n<li>Activate it<\/li>\n<li>Enter an API key under Content Change Observer \u2192 Settings on each site<\/li>\n<li>Connect the sites under Content Change Observer \u2192 Manage<\/li>\n<li>React to the <code>content_observer_on_modifications<\/code> action in your theme or plugin<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20it%20copy%20posts%20between%20sites%3F\"><h3>Does it copy posts between sites?<\/h3><\/dt>\n<dd><p>No. It reports which content changed. Copying or refreshing content is done by your own code reacting to the modifications.<\/p><\/dd>\n<dt id=\"can%20i%20record%20changes%20other%20than%20posts%3F\"><h3>Can I record changes other than posts?<\/h3><\/dt>\n<dd><p>Yes. <code>content_observer_add_modification( Modification::build( $id, 'my-type' )-&gt;update() )<\/code> records a modification of any content type.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>2.0.0<\/h4>\n\n<p><strong>\u26a0 BREAKING CHANGES<\/strong>\n* the plugin folder is palasthotel-content-change-observer instead of content-observer. WordPress treats it as a new plugin: install it, deactivate and delete the old one, then activate the new one. Settings, connected sites and modifications stay, as options and tables keep their names.<\/p>\n\n<p><strong>Features<\/strong>\n* rename the plugin to Palasthotel Content Change Observer (c40e088)<\/p>\n\n<p><strong>Bug Fixes<\/strong>\n* show log notices only on the plugin's own admin pages (5acb3b4)<\/p>\n\n<h4>1.2.4<\/h4>\n\n<p><strong>Bug Fixes<\/strong>\n* connection test can no longer make the site request arbitrary URLs (4f494f5)\n* escape admin notice logs and keep API keys out of them (08b8c06)\n* escape the API key field on the settings page (8fc9ae1)\n* modifications page disappears after applying modifications (c3f6bb8)\n* protect Fetch, Notify and Apply against cross-site requests (1ae6a34)\n* reject requests to other sites' routes when no API key is set (7775e3d)<\/p>\n\n<h4>1.2.3<\/h4>\n\n<ul>\n<li>Major library updates<\/li>\n<li>all js(x) files converted to typescript<\/li>\n<li>fix: use admin_url passed from php for ajax calls<\/li>\n<\/ul>\n\n<h4>1.2.1<\/h4>\n\n<ul>\n<li>Feature: Admin notices logger<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>New modifications page<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Library update<\/li>\n<li>all js api calls are cors independent<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First release<\/li>\n<\/ul>","raw_excerpt":"Efficiently observe content changes between WordPress instances.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/387655","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=387655"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/palasthotel"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=387655"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=387655"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=387655"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=387655"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=387655"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=387655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}