Skip to content

Managing Posts

Browsing and managing posts

With the Integration activated, Safe Publish → Manage opens the catalog of source content, named for the source it is reading from. Use the Type, Title or URL, Published Date, Local State, and Source Status controls to filter the table.

The Safe Publish Manage screen in WP Admin, listing source posts with their published date, local state, local status, and source status.

The Local State control provides 4 views:

  • All — every source post, including imported posts.
  • Not imported — the post does not currently have an active destination import.
  • Up to date — the post has been imported, and the source has not changed since.
  • Outdated — the post has been imported, but the source has changed since the last import. Re-import to bring the destination copy up to date.

Importing content

Safe Publish imports a single post or many posts at once. Both produce the same result for each post: media is downloaded to the destination, source URLs in the content are rewritten to point at the destination, taxonomy terms and metadata are applied, and the operation is recorded and can be rolled back.

Import a single post

  1. On Manage → Posts, use the Import row action.
  2. The import starts right away. If the destination post is already live — published or private — confirm the overwrite first, because it changes the live site immediately.

By default, importing a child post fails if its parent is not present on the destination, to avoid creating orphaned content. Developers can change this with the safe_publish_import_allow_orphans filter (see Filters).

Import multiple posts (bulk import)

  1. On Manage → Posts, select the posts to import.
  2. Review the confirmation, which names the affected posts grouped by what each group receives: posts imported as new drafts, and posts updated with the latest source content. The grouping predicts what the import will do; the results reported after the run are authoritative.
  3. Start the bulk import.

Safe Publish records the selected posts in one history session and reports each item’s result independently. If one post fails, the others are not rolled back. When the selection includes posts with parent–child relationships, the plugin orders the import so that parents are created before their children.

Previewing changes with Compare

The Compare action on Manage → Posts fetches fresh source content and compares it with the current destination post, covering the title, content, excerpt, featured image, metadata, and taxonomy terms, including each term’s parent and description.

The comparison is shown side by side, and block-editor content is compared block by block so editors can see which blocks were added, removed, or changed. The modal also offers an Update button that re-imports the post from the source.

Rolling back imports

Rollback reverses a single import:

  • If the post was newly created, the post is deleted.
  • If the post was updated, the previous content is restored. Safe Publish captures that content at import time; in the rare case where no copy was captured, the post is deleted instead.

A rollback reverses the changes made by that one import. If a post has gone through a series of changes, each change can be rolled back sequentially. Rolling back an update leaves the post imported. The row normally returns to Outdated, because the source still has the newer content, and the Edit action remains available.

Multiple rows can be selected on the Posts tab and rolled back in a single action.

Note: Rolling back a newly created post deletes that post on the destination, and the deletion cannot be undone. Confirm the affected posts before rolling back. The post remains on the source and can be imported again.

Needs attention

Manage → Needs attention collects post-import problems in one place, so a bulk run that mostly succeeded does not hide the few items that did not. Each row reports the Content it affects, a Type of Failed or Degraded, a Detail describing the problem, a Severity of Error or Warning, and when it happened. View opens the underlying record.

What lands in Needs attention

  • Failures. The import errored, and no local post was created, or a re-import of an existing post failed. Nothing on the destination changed.
  • Degradations. The post imported, but something could not be carried over. Typical causes are an unresolved block reference, a taxonomy the destination does not register, or term fields that could not be reconciled with the source.

A degradation that another import can resolve carries a hint saying whether that import has happened yet: Resolvable now means retrying will reconnect the reference, and Waiting on import means the post or term it points at is still missing from the destination. A degradation that only a site change can fix, such as a taxonomy on the source that is not registered on the destination, carries no hint and offers no Retry. Registering that taxonomy on the destination makes a retry available.

Clearing an item

  • Retry re-runs the reconciliation. Use it on a Resolvable now item directly. For a Waiting on import item, import the missing target first, then retry. A bulk Retry reports how many issues resolved, how many are still waiting on an import, and how many failed.
  • Ignore sets an item aside without deleting it, moving it to the Ignored view. Use it for a problem that has been identified and is not going to be fixed now.
  • Un-ignore returns an ignored item to the Open list. Ignoring is always reversible.
  • Remove permanently deletes a failure record. It is offered for failures only, because a degraded post still exists on the destination.

Fixing the underlying cause is what clears a degradation for good. Import a missing parent or referenced post, register a missing taxonomy on the destination, then retry.

How media and content are processed

When a post is imported, Safe Publish processes its content so that it renders correctly on the destination without depending on the source site:

  • Featured images and inline media referenced from the source site are downloaded and added to the destination’s media library. This includes media in img, video, audio, and source elements, and file links in classic HTML and in block markup.
  • Source URLs are rewritten to point at the destination’s copies, so the imported content no longer links back to the source.
  • Media is deduplicated by its original URL. If Safe Publish has already imported the same source file, it reuses the existing attachment on the destination instead of downloading it again.
  • Third-party media is left untouched. Safe Publish does not download files hosted on domains other than the source site; it preserves their original URLs as written.

Safe Publish records where imported content came from in post metadata — including the source post ID and source permalink — so that subsequent imports of the same post update the existing post rather than duplicating it.

Author attribution

Safe Publish attributes each imported post to a user on the destination site, matched by the source author’s email address. The matched user becomes the imported post’s author.

If the source author’s email does not match any user on the destination, Safe Publish does not guess. By default, the import stops with an error identifying the unmatched author, so an administrator can create a matching user and re-import. Developers can relax this with the safe_publish_import_allow_author_fallback filter: when enabled, a new post whose author cannot be matched is attributed to the user running the import, an updated post keeps its existing author, and a warning is recorded in the import history.

The source author’s email and username are stored in post metadata for reference, regardless of how attribution is resolved.

Audit events

Safe Publish writes an audit log of security- and content-relevant actions to the destination site. Logged events include authenticated cross-site requests, content exports, the result of each imported item, rollbacks, and changes to the connection settings.

Each event records a channel (such as authentication, content, export, import, or media), a severity level (informational, warning, or error), the event type, a timestamp, and structured details. The export history is surfaced in the admin interface; the full log is available to developers through the plugin’s query interface and through the safe_publish_event_logged action (see Filters).

Custom post types

Safe Publish imports any registered post type, not only posts and pages. The source catalog can be filtered by post type, and custom post types are imported the same way as standard ones.

For a post type to appear in the source catalog, it must be registered on the source with show_in_rest set to true and public set to true. Both values must be the boolean true: a truthy value such as 1 registers the REST route but excludes the type from the catalog. Safe Publish additionally allows wp_navigation and wp_block, which are not public but whose posts are content. Attachments are excluded because they are files rather than content posts.

The catalog reports each type’s REST API base, which can differ from its registered slug, and which of the title, content, and excerpt raw fields the type supports. Import and Compare require only the fields the source declares, so a type that does not support all three — a navigation post, which has no excerpt — imports without reporting a missing field.

A post type registered with a custom rest_controller_class must expose a standard WordPress item schema, and each supported field must declare a properties.raw definition. A field absent from both the catalog metadata and the response is treated as unsupported.

A custom post type must be registered with the same slug on the destination for its content to import cleanly. Safe Publish does not remap a source post type slug to a different slug on the destination; if the slugs differ, the import will not place the content under the destination’s post type.

Filters

Safe Publish exposes the following filters for developers.

FilterDefaultPurpose
safe_publish_import_ksesfalseEnable wp_kses sanitization of imported content.
safe_publish_import_kses_allowed_htmlwp_kses_allowed_html( 'post' )Customize the allowed HTML used when safe_publish_import_kses sanitization is enabled. Receives the allowed-tags array and the name of the field being sanitized.
safe_publish_import_allow_orphansfalseAllow importing a child post when its parent is not present on the destination.
safe_publish_import_allow_author_fallbackfalseWhen the source author cannot be matched on the destination, attribute new posts to the importing user and keep the existing author on updates, instead of aborting the import.
safe_publish_auth_max_time_diff300Maximum allowed difference, in seconds, between a signed request’s timestamp and the current time.
safe_publish_request_timeout10Timeout, in seconds, for HTTP requests to the source site.
safe_publish_request_argsCustomize the arguments passed to the HTTP request made to the source site.
safe_publish_dev_ssl_verifyfalseDevelopment only: skip SSL verification for requests to non-localhost hosts. Leave disabled in production.

The safe_publish_event_logged action fires each time an audit event is recorded, receiving the channel, event type, and event data. Use it to forward audit events to external monitoring.

add_action(
	'safe_publish_event_logged',
	function ( string $channel, string $event, array $data ): void {
		// Forward the event to an external log or monitoring service.
	},
	10,
	3
);

Last updated: September 02, 2026