=== fepo Image & Font Optimizer – Compress Images to WebP/AVIF locally ===
Contributors: fepo, michaelpehl
Tags: image optimization, compress images, convert webp, optimize images, convert avif
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.1.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Compress images to WebP/AVIF on your own server. With PHP-Imagick: unlimited, free. Fonts subsetted by fepo (uses credits) — PHP cannot create WOFF2.

== Description ==

Compress your images to WebP and AVIF without sending them anywhere. If your server has
PHP-Imagick, the conversion happens right there — unlimited and free, and your images never
leave your server.

**Our "Server environment" test shows you if PHP-Imagick is enabled.** It runs a real test
conversion, so you see whether your server can actually create AVIF and WebP — not just whether
the extension is loaded. If it cannot, everything still works: fepo converts instead. Ask your
hosting provider to enable PHP-Imagick.

**Fonts are different:** subsetting needs to know which characters your pages use, so it always
runs on fepo's servers and uses credits. PHP cannot create WOFF2 files.

Every site starts with 50 free optimizations — no purchase, no account required. After that,
one-time credit packs keep you going, and credits never expire. Optimised files live on your own
server — no CDN, no monthly lock-in, and deactivating never breaks the site.

**The most important image loads first.** The second image in the page gets
`fetchpriority="high"` — usually the LCP element, the one Core Web Vitals
measures. Everything below it is deferred with `loading="lazy"`. Your theme's
own `loading` attribute is always respected, and an image already marked as
high priority is never lazy-loaded.

Originals are always kept as a fallback, so a page can never break.

*Coming soon: automatic conversion to WebP/AVIF on upload.*

How it works: `<img>` tags are wrapped in `<picture>` with AVIF/WebP sources (original kept as
fallback), CSS `background-image`s are served as AVIF via an injected style block, and web fonts
are subsetted and served locally — with the theme's Google Fonts request removed, so no visitor
IP is sent to Google for fonts.

= What gets optimised — and what doesn't =

So you know exactly what to expect — we'd rather under-promise:

* **Images from 10 KB** are converted to WebP/AVIF (original kept as fallback). Smaller images
  are left unchanged — the gain isn't worth it.
* **CSS `background-image`s** (raster jpg/png) are served as AVIF via an injected style block
  (no edits to your CSS).
* **Google Fonts from 50 KB** are subsetted to the characters your pages actually use and
  served locally; the matching Google Fonts `<link>` is removed (closing the GDPR concern of
  visitor IPs going to fonts.googleapis.com). All weights of a family come in one file;
  italic styles are not subsetted. Smaller fonts are treated as already optimised.
* **Fonts from other providers** (Adobe Fonts, MyFonts and the like) cannot be subsetted —
  their master files are not publicly available. They are reported, not changed.
* **Already-optimal formats are left untouched:** images already served as AVIF, and SVG
  (vector — stays as-is).
* **Only assets from your own domain** are optimised. Images and fonts embedded from third
  parties (maps, external widgets, etc.) are never touched — they stay on their original server.
* **Known limits:** images injected by JavaScript after page load (some sliders/lazy-loaders)
  and background `<video>` are not covered. A font is only replaced when a matching source is
  found. **Deleting the plugin** removes the on-the-fly rewrites (page returns to original) but
  leaves the optimised files in `wp-content/uploads/fepo/` (they belong to you).

== External services ==

This plugin connects to two external services. Both are described below.

= 1. portal.fepo.app (fepo optimization service) =

Operated by fepo, this service generates optimized images and subsetted fonts.

Font subsetting always runs on fepo's servers: it requires knowing which characters your pages
actually use, which means reading those pages. Image conversion runs on fepo's servers only when
your own server cannot do it — with PHP-Imagick available, images and CSS background images are
converted locally and their URLs are never sent anywhere.

**What is sent and when:**

* When you optimize fonts: the URLs of the pages being scanned, so fepo's server can fetch them and determine which characters are used.
* When images or CSS backgrounds have to be converted by fepo (no PHP-Imagick, or it could not produce a smaller file): the URLs of those images, so fepo's server can fetch and process them. Images converted locally are not sent.
* An anonymous site hash and your site's hostname, so your credit balance is tied to your account.
* Once a day, while the plugin is active: the same anonymous site hash, as a sign that this installation is still in use. Accounts with no activity for 60 days are deleted automatically (data minimisation), and since images are now converted locally there may otherwise be no contact for months. This daily signal starts only after an account exists, carries nothing but the hash, and stops when you deactivate the plugin.

**What is NOT sent:** no personal data of your visitors, no content from posts, pages, or comments, no database contents, and no file contents of images or fonts that are not being optimized.

The optimization itself is performed by fepo's server fetching the given page or image URLs (like any browser would) and returning WebP/AVIF images or subsetted fonts. No private endpoints are accessed. The optimized files are then stored on your own server — not on a CDN — and delivered directly from there.

You must explicitly consent to this data transmission via a checkbox before the first optimization. The consent is stored locally and can be revoked at any time by deactivating the plugin.

**Terms of service:** [https://fepo.app/agb](https://fepo.app/agb)
**Privacy policy:** [https://fepo.app/datenschutz](https://fepo.app/datenschutz)

= 2. Google Fonts (fonts.googleapis.com) =

To show the real download size of a Google Font on the Fonts tab, the plugin asks Google's Fonts API — from your WordPress server, in wp-admin — how large the browser-loaded WOFF2 files for a given font family are.

**What is sent and when:** only the font family name and its weights (e.g. "Roboto" with weights 400,700), and only while you are viewing the Fonts tab in the admin. No visitor data, no personal data, and no site content are sent. The request is made server-to-server (from your host to Google), not from your visitors' browsers.

**Terms of service:** [https://policies.google.com/terms](https://policies.google.com/terms)
**Privacy policy:** [https://policies.google.com/privacy](https://policies.google.com/privacy)

== Disclaimer ==

This plugin is provided "as is", without warranty of any kind. fepo is not liable for any damage, data loss, or downtime arising from its use. Your originals are always kept as a fallback, so an optimization can never break your page.

== Installation ==

1. Upload the plugin ZIP via Plugins → Add New → Upload, or copy the folder to wp-content/plugins/.
2. Activate it. Open "fepo Optimizer" in the admin menu and optimize your pages.

== Screenshots ==

1. The "Server environment" section — whether your server can create AVIF and WebP itself, and what that means for credits.
2. The Images tab after a Media Library scan — found, to-optimize, optimized and skipped counts.
3. The summary after a run — how many images were optimized and how much was saved.
4. The Fonts tab — detected Google Fonts and the download-size saving from subsetting.

== Changelog ==
= 1.1.1 =
* **Bilder werden auf Ihrem eigenen Server umgewandelt, wenn PHP-Imagick verfügbar ist — und verbrauchen dann keine Credits.** Das ist schneller, und Ihre Bilder verlassen Ihren Server nicht. Credits brauchen nur noch die Fonts: für das Subsetting muss bekannt sein, welche Zeichen Ihre Seiten verwenden, und das kann Imagick nicht ermitteln. CSS-Hintergrundbilder gelten als Bilder und laufen ebenfalls lokal. Ohne PHP-Imagick läuft alles wie bisher über fepo; Ihr Hosting-Anbieter aktiviert die Erweiterung meist auf Anfrage.
* Der neue Abschnitt „Server environment" zeigt, ob Ihr Server AVIF und WebP selbst erzeugen kann.
* Brauchen Sie derzeit keine Credits, hält sich der Kaufbereich zurück und sagt, warum. Kaufen bleibt einen Klick entfernt.
* Ihr Zugang bleibt erhalten, solange das Plugin aktiv ist: das Plugin meldet sich dafür einmal täglich mit einer anonymen Kennung — nur mit Ihrer Einwilligung, nur wenn ein Zugang besteht, und es endet mit der Deaktivierung. Ihre optimierten Dateien sind nie betroffen, die liegen auf Ihrem Server. Weil die bisherige Einwilligung diesen Hinweis nicht beschrieb, fragt das Plugin einmalig erneut nach Ihrer Zustimmung.
* Der Kauf von Credits funktioniert jetzt auch vor der ersten Optimierung (brach zuvor mit „Could not start checkout" ab). Schlägt er fehl, erscheint eine Meldung im Plugin mit Grund und nächstem Schritt statt eines Hinweisfensters.
* Zwei Zahlen in den „Wussten Sie?"-Hinweisen waren falsch: Die Core-Web-Vitals-Angabe nennt jetzt den belegten Wert (rund die Hälfte aller Websites, 48 % mobil — HTTP Archive Web Almanac 2025) statt „etwa 33 %". Der Hinweis zur durchschnittlichen Ladezeit wurde entfernt; die genannten 2,5 Sekunden waren ein Grenzwert, kein Messwert.
* Nach einem Lauf fasst ein Fenster zusammen, wie viele Dateien optimiert wurden und wie viel Sie gespart haben — mit einer Schaltfläche zum Neuladen.
* Der Guthaben-Stand zeigt nur noch den Topf, aus dem gerade bezahlt wird: die Gratis-Optimierungen, solange welche übrig sind, danach die gekauften Credits.
* Sind keine Credits mehr da, sagt das Plugin das deutlich und bietet die Pakete an — statt zu fragen, ob ein Lauf starten soll, der nichts ausrichten kann.
* Klarere Angaben rund um Credits: was wohin übertragen wird und was etwas kostet. Eine Schriftfamilie zählt als ein Credit, unabhängig von der Zahl ihrer Schnitte; kursive Schnitte und Schriften anderer Anbieter werden nicht verkleinert, und übersprungene Familien kosten nichts.
* Behoben: Das Löschen des Plugins konnte bei „Deleting…" hängen bleiben. Die Deinstallation räumt jetzt auch Einstellungen älterer Versionen mit ab.
* Behoben: Nach einem erfolgreichen Lauf konnte die Seite noch den Stand von davor zeigen — veraltete Zahlen, fehlende Schaltflächen.
* Getestet mit WordPress 7.1.

= 1.1.0 =
* Die optimierten Bilder und Fonts werden jetzt auf jeder Domain ausgeliefert — die frühere Domain-Bindung der Auslieferung wurde entfernt. Ihre lokal gespeicherten Dateien gehören Ihnen und funktionieren auch nach einem Umzug der Website.
* Die eingebettete CSS (@font-face und CSS-Hintergründe) wird jetzt auf dem WordPress-Standardweg über wp_add_inline_style() ausgegeben.
* Der Front-End-Ausgabepuffer wird am shutdown-Hook ausdrücklich geschlossen.
* Sicherheit: Beim Import einer ZIP-Datei werden ausschließlich Bild- und Font-Dateien übernommen; unerwartete Dateitypen werden nach dem Entpacken entfernt.
* Der Abschnitt „External services" in der readme dokumentiert jetzt zusätzlich die Nutzung der Google-Fonts-API (zur Anzeige der Download-Größe im Fonts-Tab).
* Übersetzungen werden künftig über translate.wordpress.org bereitgestellt; mitgelieferte Sprachdateien wurden entfernt.

= 1.0.9 =
* Intern: Text-Domain und Plugin-Slug an den WordPress.org-Slug „fepo-image-font-optimizer" angeglichen (behebt die Text-Domain-Warnungen des Plugin-Checks). Keine Änderung an Funktion oder gespeicherten Daten.

= 1.0.8 =
* Korrektur: Der Hinweis beim Credit-Kauf ohne Zustimmung nennt keine Richtung mehr („oben") — die Formulierung passt jetzt unabhängig von der Position der Zustimmungs-Box.

= 1.0.7 =
* Verbessert: Die Zustimmung zur Datenverarbeitung wird jetzt gut sichtbar oben angezeigt (statt in einem Tab versteckt). Die Optimierungs-Tabs erscheinen erst nach der Einwilligung — so ist klar erkennbar, dass vor der Zustimmung nichts übertragen wird.

= 1.0.6 =
* Behoben: „Credits kaufen" zeigte vor Ihrer Zustimmung einen leeren Kasten (die Kaufpakete werden erst nach Einwilligung geladen). Jetzt erscheint stattdessen ein Hinweis, dass zuerst die Zustimmung nötig ist.

Ältere Versionen: https://wordpress.org/plugins/fepo-image-font-optimizer/advanced/
