Metamanager pairs WordPress's media library with OS-level daemons to deliver truly lossless image compression, bidirectional EXIF/IPTC/XMP metadata sync, GPS coordinate import, and automatic Schema.org and Open Graph output — all managed natively from your dashboard.
wget -qO- https://raw.githubusercontent.com/richardkentgates/metamanager/main/install.sh | sudo bash
PHP can't do lossless compression or write IPTC and XMP. Metamanager can.
JPEG files are optimised with jpegtran — no re-encoding, no quality loss, no pixel changes. PNG files are processed by optipng. Files are only replaced if the result is smaller.
Write EXIF, IPTC, and XMP simultaneously via ExifTool — the industry standard. Every tag written in all three formats at once for maximum compatibility across editing software, search engines, and CMS platforms.
On upload, embedded EXIF/IPTC/XMP tags are read from the file and used to pre-populate WordPress fields automatically. User-set values are never overwritten. Edit fields in WordPress and the daemon writes them back into the file.
When clients shoot with location services enabled, Metamanager reads GPS latitude, longitude, and altitude directly from the camera's EXIF data. No manual entry — coordinates are imported and stored automatically at upload time.
Every attachment page and post with a featured image automatically receives an ImageObject JSON-LD block and Open Graph tags. When GPS data is present, a full GeoCoordinates object is included — everything Google Images and social platforms need.
Custom fields on every image edit screen. A live compression-status column in the Media Library. Searchable job history. All inside WordPress — no separate admin interface to learn.
Image uploads never slow down. Jobs are queued as JSON files. Two inotifywait-powered daemons process them immediately in the background. Results feed back into WordPress via WP-Cron.
Bulk actions are limited to injecting Publisher and Website — neutral site provenance only. Creator, Copyright, and Owner are individual fields, intentionally never overwritten in bulk.
Every failed job appears in the history table with a one-click Re-queue button. No manual file hunting, no WP-CLI commands needed to recover from a temporary failure.
Integrates with the WordPress update pipeline. New releases published to GitHub appear automatically in Dashboard → Updates — update with one click, just like any other plugin. A manual “Check for Updates” link is also available on the Plugins page.
PHP coordinates. The OS executes. Clean separation of responsibility.
On upload, embedded metadata is read from the file into WordPress fields. On edit, changed fields are queued for writing back to the file.
Metamanager writes a small JSON job file to the queue directory. PHP does nothing else.
inotifywait detects the new file. The daemon processes the image with jpegtran, optipng, or ExifTool.
The daemon writes a result JSON to the completed folder. WP-Cron picks it up every minute and records it in the database.
WordPress (PHP) OS (Bash Daemons)
──────────────── ──────────────────────────────────
Upload image
│
▼
import_from_file() ◄── ExifTool reads embedded tags
populates empty WP fields (EXIF / IPTC / XMP / GPS)
│
▼
Write job JSON to ◄── inotifywait detects new file
metamanager-jobs/ │
compress/ or meta/ ▼
Process image:
jpegtran / optipng [compression]
ExifTool [metadata write]
│
WP-Cron (60s) ◄──── result JSON ────────┘
reads, inserts to DB,
updates history table
Two methods — choose what fits your workflow.
Metamanager integrates with the native WordPress update system. When a new release is tagged on GitHub, it appears in Dashboard → Updates automatically within 12 hours. Click Update now — exactly the same as any other plugin.
A Check for Updates link is available next to the plugin on Plugins → Installed Plugins for an immediate check.
Use --update to sync only PHP, JS, and asset files. Daemons keep running, dependencies are not reinstalled, and systemd services are not restarted — zero downtime for the compression and metadata pipelines.
sudo bash install.sh --update
Every logical field writes to all three standards simultaneously.
| Field | Set By | EXIF | IPTC | XMP |
|---|---|---|---|---|
| WordPress Native — bidirectional sync | ||||
| Title | WP Post Title | Title |
ObjectName |
Title |
| Description | WP Post Content | ImageDescription |
Caption-Abstract |
Description |
| Caption | WP Excerpt | — | Caption-Abstract |
Caption |
| Alt Text | WP Alt Field | — | — | AltTextAccessibility |
| Attribution & Rights — per-image only, never bulk | ||||
| Creator | Per-image | Artist |
By-line |
Creator |
| Copyright | Per-image | Copyright |
CopyrightNotice |
Rights |
| Owner | Per-image | OwnerName |
— | Owner |
| Editorial | ||||
| Headline | Per-image | — | Headline |
Headline |
| Credit | Per-image | — | Credit |
Credit |
| Classification | ||||
| Keywords | Per-image | — | Keywords |
Subject |
| Date Created | Per-image | DateTimeOriginal |
DateCreated |
DateCreated |
| Rating (0–5) | Per-image | — | — | Rating |
| Location — IPTC Photo Metadata Standard | ||||
| City | Per-image | — | City |
City |
| State / Province | Per-image | — | Province-State |
State |
| Country | Per-image | — | Country-PrimaryLocationName |
Country |
| GPS — read-only, auto-imported from camera EXIF | ||||
| Latitude | GPS Auto | Composite:GPSLatitude |
— | — |
| Longitude | GPS Auto | Composite:GPSLongitude |
— | — |
| Altitude (m) | GPS Auto | Composite:GPSAltitude |
— | — |
| Site Provenance — bulk-safe, neutral | ||||
| Publisher | Site Name (auto) | — | Source |
Publisher |
| Website | Site URL (auto) | — | Source |
WebStatement |
Per-image fields are never touched by bulk actions. Only Site auto fields (Publisher + Website) can be injected in bulk — neutral provenance, not an ownership claim. GPS Auto fields are imported from the camera at upload time and are never editable in the UI.
Every image page gets structured data automatically — no configuration required.
ImageObjectA full JSON-LD block is emitted in <head> on attachment pages and any post with a featured image. Includes name, description, creator, copyright, keywords, date, location, and GPS coordinates when available. Eligible for Google Images rich results and Google Discover.
Correct og:image, og:image:alt, og:image:width, og:image:height, and og:image:type tags are written for every image. Social platforms — Facebook, LinkedIn, Slack, iMessage — use these to generate accurate link previews.
When a copyright value is set, Metamanager emits <link rel="license"> for URL-format values (e.g. Creative Commons URIs) or <meta name="copyright"> for plain-text notices — giving crawlers and aggregators a machine-readable rights signal.
ImageObject JSON-LD output{
"@context": "https://schema.org",
"@type": "ImageObject",
"url": "https://example.com/wp-content/uploads/2026/01/photo.jpg",
"contentUrl": "https://example.com/wp-content/uploads/2026/01/photo.jpg",
"width": 4032,
"height": 3024,
"name": "Sunrise over the ridge",
"description": "Morning light breaking through the canyon walls.",
"headline": "Golden Hour in Red Rock Canyon",
"creditText": "Jane Doe / Mountain Light Photography",
"creator": { "@type": "Person", "name": "Jane Doe" },
"copyrightNotice": "© 2026 Jane Doe",
"copyrightHolder": { "@type": "Organization", "name": "Mountain Light Photography" },
"keywords": ["landscape", "sunrise", "canyon", "nature"],
"dateCreated": "2026-01-15",
"locationCreated": {
"@type": "Place",
"name": "Boulder, CO, USA",
"geo": {
"@type": "GeoCoordinates",
"latitude": 40.014984,
"longitude": -105.270546,
"elevation": 1655.0
}
},
"contentLocation": { "@type": "Place", "name": "Boulder, CO, USA", "geo": { ... } },
"thumbnail": { "@type": "ImageObject", "url": "https://example.com/.../photo-300x225.jpg" },
"mainEntityOfPage": { "@type": "WebPage", "@id": "https://example.com/?attachment_id=42" }
}
Works on Ubuntu 22.04+, Debian 12+, RHEL/Rocky 9+. Requires systemd and root access.
wget -qO- https://raw.githubusercontent.com/richardkentgates/metamanager/main/install.sh | sudo bash
sudo bash install.sh --wp-path /var/www/html
wget -qO- https://raw.githubusercontent.com/richardkentgates/metamanager/main/install.sh | sudo bash -s -- --update
jpegtran, optipng, exiftool, inotify-tools, and jq via apt or dnfwp-content/plugins/metamanager/WP_CONTENT_DIR — no hardcoded pathswww-dataMetamanager is built on the shoulders of these outstanding open source projects. Full credit and gratitude to their authors and maintainers.
The backbone of all metadata work in Metamanager. ExifTool reads and writes EXIF, IPTC, and XMP tags across virtually every image format in existence. We use it to import embedded metadata on upload and to write all metadata fields back to the file.
jpegtran performs lossless JPEG optimisation — reordering Huffman tables and enabling progressive scan without decoding or re-encoding a single pixel. The IJG created the original implementation; libjpeg-turbo maintains and accelerates it.
optipng tries multiple DEFLATE parameters and filter combinations to find the smallest lossless PNG representation. No pixels are changed. We use -o2 -preserve to balance speed and compression while retaining all file metadata.
inotifywait is what makes the daemons instant-response rather than polling. When a job file is written, inotifywait fires immediately — no sleep loops, no latency. The Linux kernel's inotify subsystem watches; inotify-tools provides the userspace interface.
jq is used inside the Bash daemons to parse job JSON files written by PHP — extracting field values by key without requiring any additional runtime. Lightweight, dependency-free in execution, and universally available on our supported Linux distributions.
The compression and metadata daemons run as systemd services. systemd manages process lifecycle, automatic restart on failure, boot-time startup, and journal-based logging. We use a PID-file pattern so the WordPress plugin never needs systemctl privileges.
Metamanager is a WordPress plugin and relies on the WordPress API — hooks, post meta, REST API, WP-Cron, the admin UI framework, media handling, and the plugin update pipeline. WordPress is itself GPL v2+, the reason Metamanager is GPLv3 (a compatible later version).
The typefaces used on this website. Inter (Rasmus Andersson) for UI text; JetBrains Mono (JetBrains) for code samples. Both are served via Google Fonts and are not bundled with the plugin itself.