MADGP XML Sync
WordPress plugin syncing property listings from an XML feed into Easy Property Listings (EPL), with per-property change detection, geocoding cost optimization, and a chunked, resumable import pipeline.
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/tchakoumi/madgp-xml-sync/archive/refs/heads/main.zipWordPress plugin that syncs property listings from an XML feed (AC3-Distribution / Immo-Facile format) into Easy Property Listings (property and rental post types), replacing an older WP All-Import based pipeline.
Why this exists
The previous pipeline (theme-level cron scripts + WP All-Import) re-downloaded and re-processed the entire feed on every run, geocoded every property on every run regardless of whether its address had changed, and had no visibility into whether a scheduled run actually executed. This plugin was built to fix all three:
- Per-property change detection — a property whose feed data is byte-identical to last run is skipped entirely; only new/changed/removed properties reach the WordPress import step.
- Geocoding as a last resort, not a default — the feed already supplies coordinates for effectively every property. Google Geocoding is only called when the feed gives none and no still-valid cached result exists for that property (cache keyed by an address fingerprint, so a real address change is still detected).
- A single, persistent run-history table in the admin UI, so a silently-failed cron trigger is visibly distinguishable from a normal no-op run.
Architecture
Two-part pipeline, run as separate WP-Cron-scheduled steps so neither one risks hitting a PHP execution-time limit:
- Fetch (
Madgp_Sync_Fetcher) — downloads the raw feed, flattens/normalizes each property the same way the old theme script did, diffs against the last-seen hash per property, resolves coordinates (feed-first, geocode-fallback), and writesnf_sell.XML/nf_rent.XMLcontaining only what changed. - Import (
Madgp_Sync_Runner) — chunked and resumable: reads the two files above, upserts changed properties into EPL viaMadgp_Sync_Upserter, syncs images viaMadgp_Sync_Images, and deletes listings no longer present in the feed. Chunking means a large first-run image backfill can't time out a single request — it picks up where it left off on the next WP-Cron tick.
Both steps are triggered by hitting one REST endpoint (/wp-json/madgp-sync/v1/run, token-authenticated) from an external cron service; WP-Cron's own opportunistic nature (it only fires on real pageviews) means a second external ping at wp-cron.php is recommended as a backstop on low-traffic sites.
Key files
| File | Responsibility |
|---|---|
includes/class-madgp-sync-fetcher.php |
Step 1: download, normalize, diff, geocode-if-needed, split into sell/rent |
includes/class-madgp-sync-runner.php |
Step 2: chunked upsert + delete-missing, resumable via stored state |
includes/class-madgp-sync-parser.php |
Feed XML → normalized PHP array, field mapping mirrors the proven All-Import config |
includes/class-madgp-sync-upserter.php |
Normalized array → EPL post + postmeta, dry-run capable |
includes/class-madgp-sync-images.php |
Matches/downloads/reorders/deletes property images, sets featured image |
includes/class-madgp-sync-image-cleanup.php |
One-off tool for duplicate images left over from the old pipeline |
includes/class-madgp-sync-geocoder.php |
Google Geocoding API wrapper |
includes/class-madgp-sync-run-history.php |
Persistent run log (status, duration, stats) shown in the admin UI |
includes/class-madgp-sync-paths.php |
Standalone working-file location (see below) |
includes/rest-endpoint.php |
Trigger endpoint + diagnostic routes (/dry-run, /review-batch, connectivity test) |
includes/admin-page.php |
Two-tab admin UI: Suivi (operational) / Configuration (settings) |
Requirements
- WordPress with Easy Property Listings active (
property/rentalpost types and their meta fields). - An external cron service (e.g. cron-job.org) to hit the trigger URL on a schedule — WP-Cron alone is not reliable on low-traffic sites.
- A Google Geocoding API key, only needed as a fallback for properties the feed doesn't supply coordinates for.
Setup
- Activate the plugin.
- Go to Settings → MADGP XML Sync → Configuration:
- Set the XML feed source URL (only needs changing if the feed provider's URL ever changes).
- Set the Google Geocoding API key.
- Choose whether newly-imported properties are created as Draft or Published.
- Generate a trigger token, then copy the trigger URL into your external cron service.
- On an install migrated from an older version of this plugin, use "Migrer vers les fichiers autonomes" on the Configuration tab to copy any working files still sitting at the legacy theme-coupled location into the new standalone one.
Operational notes
- Working files live in
wp-content/uploads/madgp-xml-sync/, not inside any theme — deliberately, so a theme switch, theme update, or theme deletion can never affect this plugin's state. Seeclass-madgp-sync-paths.php. - Single entry point, no bypass: only one way to start a run (the REST trigger) and only one way to recover a stuck one (the admin page's "Libérer le verrou bloqué"). This is intentional — running the fetch and import steps concurrently would corrupt the intermediate
nf_sell.XML/nf_rent.XMLfiles. - Self-healing: if a property is deleted directly in wp-admin (bypassing this plugin) but the feed still lists it, the next run detects and recreates it, even if the feed's data for that property hasn't changed.
- The only plugin dependency is EPL. Two postmeta keys (
property_building_carrez,property_level) are written specifically because the current site's theme template reads those exact keys for display — harmless on another theme, just inert.