EZ Page Sync
Push page edits from a staging WordPress instance to production with cryptographic validation, automatic media sideloading, and database rollback checkpoints.
Visit ezpagesync.comOverview
EZ Page Sync is a database-level, security-hardened WordPress plugin designed to sync content changes from staging environments to production in one click. It maps post assets, remaps links, and migrates layout files without needing complete database exports or manual search-and-replace queries.
HMAC Cryptographic Security
Every synchronization payload is signed using SHA-256 HMAC tokens. Replay attacks are stopped using time-to-live nonces, rate-limiting locks, and whitelisted IP addresses.
Automatic Rollback Snapshots
Before applying updates, the receiver backs up the existing target page. If anything fails (like media sideloading or ACF mismatches), it triggers an automated rollback.
Key Features
Full & Content-Only Sync
Choose between syncing everything (meta, ACF, media attachments, layouts) or push purely textual revisions (slug, title, body markdown) using "Content Only" selectors.
Dry Run Mode
Execute the entire synchronization pipeline—from validation schemas to media processing—without saving to the database. Displays a preview diff summary.
Url Rewriting
Rewrites references to the staging URL found inside your HTML blocks, custom fields, and layout configurations to use the production URL on arrival.
Media Sideloading
Extracts featured images and inline attachments from the post body. They are compressed, sent via secure base64 payloads, and sideloaded into the production library. Run Image Format Converter on the receiver to convert those sideloaded images to WebP/AVIF the moment they land.
ACF & Elementor Remapping
Parses Advanced Custom Fields (ACF) meta arrays and Elementor page configurations (_elementor_data), mapping referenced media IDs to the production media library.
Cache Clearing
Automatically clears cached instances of modified pages for common setups, supporting WP Rocket, LiteSpeed Cache, W3 Total Cache, and WP Super Cache.
How It Works
EZ Page Sync securely transfers data across environments. The staging server compiles and signs the payload, while the production server validates it, creates a backup snapshot, and saves the updates.
Outbound Dispatch Pipeline (Sender)
An editor clicks "Sync" or "Preview" inside the page metabox, or pushes pages in bulk from the dashboard.
Sender::build_payload() queries the page, custom post meta, taxonomies, ACF fields, and base64 media blocks.
The compiled JSON is signed using SHA-256 HMAC using the API secret key, adding a one-time nonce and timestamp.
The package is sent over HTTPS to the production receiver's registered endpoint via wp_remote_post().
Inbound Processing Pipeline (Receiver)
Receiver::verify_request() performs whitelisting checks, verifies rate limits, and validates the HMAC signature.
If the target page already exists, Rollback::create_snapshot() saves its current state in the custom logs table.
The post data is updated. Base64 media data is written to disk, re-indexed, and local URLs inside the content are remapped.
Page caches are cleared, a success code is returned to the sender, and the sync event is logged in the custom logs table.
Sync Architecture
This flowchart illustrates how the sender and receiver coordinate sync actions using the REST API:
- └─ build_payload()
- └─ sign (HMAC-SHA256)
- └─ wp_remote_post()──►
- └─ handle_sync()
- ├─ verify_request()
- ├─ validate_payload_schema()
- ├─ create_snapshot()
- ├─ find_or_create_production_post()
- ├─ apply_post_update()
- ├─ sync_post_meta()
- ├─ sync_media() ← EzPageSync\Media_Sync
- ├─ sync_acf_fields()
- ├─ sync_taxonomies()
- ├─ sync_yoast_meta()
- └─ log_sync_success()
Technical Component Breakdown
| File/Class Component | Role & Functionality |
|---|---|
| EzPageSync\Sender | Handles outbound sync. Queries metadata, maps dependencies, compiles JSON payloads, calculates HMAC signatures, and manages the admin metabox. |
| EzPageSync\Receiver | Handles incoming payloads. Validates formatting, resolves post matches on production, maps media IDs, and writes changes to the database. |
| EzPageSync\Auth | Handles HMAC validation, checks replay attack nonce tables, validates timestamp bounds, checks whitelisted IPs, and manages rate limiting. |
| EzPageSync\Media_Sync | Handles binary attachments. Converts inline images to base64, uploads them to the media library on the receiver, and rewrites URLs in content. |
| EzPageSync\Rollback | Tracks checkpoints. Serializes posts and meta keys into a custom database table before sync, and handles restoration if errors occur. |
| EzPageSync\Logger | Manages the custom wp_ez_ps_logs table. Logs events and handles automated pruning based on the configured log limits. |
Free vs Premium Feature Matrix
The Free version supports basic content sync for one destination, while the Premium version adds support for custom post types, page builders, and media sideloading.
| Feature | Free Tier | Premium Tier |
|---|---|---|
| Sync Destinations | 1 Site | Unlimited (Multi-destinations & Relay Chains) |
| Plugin Role | Sender OR Receiver (Fixed) | Both (Multi-role simultaneously) |
| Eligible Post Types | page, post | Any registered Custom Post Type (CPT) |
| Metadata & Custom Fields | — | Included (ACF, Yoast, Astra theme options) |
| Page-Builder Support | — | Included (Elementor layout, global widgets & templates) |
| Media Handling | — | Included (Featured image & inline body media) |
| Batch Bulk Sync | — | Included (Multi-select push from dashboard) |
| Rollback Manager | — | Included (Full snapshot history and restore controls) |
Configuration Reference
| Setting Key | Role Scope | Default | Description |
|---|---|---|---|
| ez_ps_role | Both | 'sender' | Role assignment: 'sender' (staging) or 'receiver' (production). |
| ez_ps_api_key | Both | — | Shared API Secret Key for HMAC signatures. Stored encrypted in DB. |
| ez_ps_allowed_ips | Receiver | '' | Comma-separated sender IP addresses or CIDR blocks. Empty matches all. |
| ez_ps_sync_post_types | Both | 'page, post' | Comma-separated list of post types eligible for synchronization. |
| ez_ps_overwrite_media | Receiver | false | If true, overwrites target media library files if duplicate filenames are found. |
| ez_ps_auto_rollback | Receiver | true | Automatically restores post snapshots if error exceptions throw mid-sync. |
| ez_ps_require_snapshot | Receiver | true | Aborts sync operations if backup snapshot generation fails. |
| ez_ps_max_log_entries | Both | 500 | Caps rows in custom log tables, pruning oldest entries first. |
| ez_ps_notify_email | Receiver | '' | Recipient email address for automated status alerts. |
Frequently Asked Questions
Does this plugin support WordPress Multisite?
No. Version 1 of the plugin is designed strictly for single-site WordPress installations.
How does the rollback system restore pages?
Before applying any incoming sync payload, the receiver serializes the existing post fields and metadata rows, saving them as an entry in the custom logs table. You can restore this version with one click in the **Rollback Manager** tab on the receiver site.
What happens during a "Dry Run"?
Dry Run runs the entire validation, media parsing, and payload delivery process, but rolls back database changes on the receiver at the end. This allows you to verify that dependencies resolve without saving changes to the live site.
How do I rotate key credentials safely?
Go to **EZ Page Sync → Settings** and click **Regenerate Key**. You must copy the new key to the other environment immediately. Any pings or sync requests sent using the old key will be rejected.
Why are debug messages not written to the Sync Log?
To prevent database bloat. Verbose logs and connection checks are routed directly to PHP's standard error logs (visible in your server logs when `WP_DEBUG_LOG` is enabled). The database log table is reserved for events like successful syncs, failures, and rollbacks.
Changelog
v1.1.37
July 3, 2026Free-Tier Safety & Reset Locks:
- Fixed role locks on Free tier. The
Admin::has_incoming_sync_history()check now tracks receiver connection pings using theez_ps_receiver_last_contacted_atoption, preventing role changes if a sender has established a connection. - Fixed options cleanup. Resetting a receiver now deletes
ez_ps_receiver_last_contacted_atalongside metadata keys to allow re-purposing the site as a sender. - Expanded PHPUnit coverage with new test assertions for options gating and reset actions.
v1.1.36
July 3, 2026API Key Rotation & Hardened Disconnection:
- Updated `Reset Sync Origin` to regenerate the API key when disconnecting. This prevents stale senders from re-establishing ownership after metadata resets.
- Updated settings interface to display the rotated key alongside confirmation prompts immediately after resets.
- Added validation checks to confirm the reset actions are restricted to administrators (
manage_options).
v1.1.35
July 3, 2026Free-Tier Receiver Locking:
- Locked the plugin role toggle on the Free tier when the site has received incoming sync entries, preventing accidental disruption of active staging senders.
- Added server-side sanitization to reject role modifications if role-change lock criteria are met.
