=== Brainwerk SEO Suite ===
Contributors: brainwerk
Tags: seo, analytics, gdpr, privacy, ai
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.10.3
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Verify the plugin's own numbers against your access log, with a tamper-evident history chain. EU-based, cookie-free.

== Description ==

**Verify the plugin's own numbers — don't just trust them.**

Brainwerk SEO Suite is a WordPress SEO and analytics toolkit built around a claim most plugins never make: that you can independently check what it counted. A *Verify* tab lets you compare the plugin's numbers against your own server's raw access log for any date or time range, run a determinism self-test, and catch gaps in your history. Every history row is chained to the one before it with a tamper-evident hash, so a later edit — or a deleted or reordered row — becomes detectable instead of silent. An optional, off-by-default external notarization service checkpoints that chain with an outside witness once a day, so you can also prove nothing was changed *after* the fact. All of this runs against your own server and your own database; nothing is sent anywhere unless you explicitly turn notarization on.

Alongside that, it's a full SEO and analytics toolkit that keeps **100 % of your data on your own server** — no third-party or tracking cookies, no external analytics services, no ad-tech tracking pixels, no "anonymous" data brokering. Clear, honest insight into how people find and use your site, plus everything you need to rank in search *and* in AI answer engines.

= 🇪🇺 Made in Europe. Made for Europe. =

**Brainwerk SEO Suite is the European answer for privacy-first SEO and analytics — the solution built in the EU, for the EU.**

Engineered in the EU, to EU standards, with **privacy-by-design built into every query** — never bolted on afterwards. Your analytics never leave your infrastructure, so you stay in control of your data and your visitors' trust.

* **Privacy-focused by default** — IP anonymisation, daily-rotating visitor hashes, DNT-aware, configurable retention and one-click erasure. These are technical data-minimisation measures; whether a cookie/consent banner is required depends on your configuration and jurisdiction and should be legally reviewed.
* **Built for NIS2-era governance** — everything self-hosted, auditable and under your control, to support your GDPR and NIS2 data-governance obligations.
* **EU-based AI, optional** — AI suggestions run on **Mistral AI 🇪🇺** with your own key, so even your AI workflow stays in Europe.
* **High-tech under the hood** — pre-aggregated daily tables for sub-millisecond dashboards even past 100k+ visits/month, hardened `%i` SQL, cached sitemap & meta output, a REST API and full WP-CLI control.
* **Independently verifiable, not just self-reported** — see the Verify tab above: it also finds and fills in missing days in your captured history, and the optional external notarization is detailed under External notarization below.

= Get found by search engines *and* AI =

Search is changing. Brainwerk SEO Suite covers classic SEO **and** the new world of AI answer engines:

* **Generative Engine Optimization (GEO/AEO)** — control which AI crawlers may use your content (GPTBot, Google-Extended, ClaudeBot, PerplexityBot and more) straight from robots.txt, publish an `llms.txt` content manifest, add per-post FAQ schema (FAQPage + speakable), and see traffic arriving from ChatGPT, Gemini, Copilot, Perplexity & Claude as its own source.
* **Meta engine** — title, meta description, Open Graph, Twitter Cards, canonical, per-post overrides.
* **Schema.org JSON-LD** — Article, Organization, BreadcrumbList, WebSite, FAQPage.
* **XML sitemap** — chunked URL sets + custom robots.txt.
* **On-page SEO analyzer** — score 0–100 across 9 checks (focus keyword, alt text, internal links, readability).

= Privacy-first analytics, built in =

* **Local visitor analytics** — server-side pageviews, no third-party or tracking cookies, no external analytics services, no ad-tech tracking pixels.
* **Source attribution** — search, social, referrers, UTM, direct, and AI answer engines.
* **Visitor countries** — offline IP→country lookup from a bundled database, no external calls (works on locked-down servers).
* **Top pages, entry/exit pages, device + browser + OS breakdown.**
* **Redirect manager** — 301 / 302 / 307 / 308 with exact & prefix matching, plus a **404 log** with one-click "create redirect".
* **AI suggestions** — bring your own Mistral key for titles, meta descriptions and focus keywords.
* **Migration wizard** — import metadata + redirects from Yoast, RankMath, AIOSEO.
* **Multisite-aware** — network activation, network-wide settings, per-site overrides.
* **Benchmark network — honest progress, not a placeholder** — until enough sites join to compare safely, the dashboard shows exactly how many sites currently participate and how many are needed (currently 20) before industry comparisons switch on, instead of a silent "not available" gap; once your own industry/region has enough peers, the comparison appears automatically.
* **Compare yourself to yourself** — a daily local snapshot (analyzer score trends, meta-description/alt-text/word-count fail rates, traffic shape, AI-crawler activity) lets you see how your own site is trending week over week, month over month — works from day one, on every install, whether or not you've joined the benchmark network. Nothing here ever leaves the site. On the dashboard this shows up as four widgets — analyzer trend, traffic shape (hour of day / day of week), AI-crawler development per family, and headline-number deltas — with an honest "still filling up" message until enough history has built up.

= Plays nicely with Yoast, RankMath & co. =

Already running another SEO plugin? Brainwerk SEO Suite auto-detects it and stands down its meta, schema and sitemap modules — so you keep **analytics, the 404 log, redirects and the analyzer** as a clean add-on, with no duplicate output. One toggle forces full takeover whenever you're ready to switch.

= Go Pro =

The Pro tier (via Freemius license) adds:

* Google Search Console & Bing Webmaster sync
* Region & city geolocation drill-down (Free already covers countries)
* Slack / Discord / MS-Teams webhook alerts
* Traffic anomaly detection (Z-score baseline, 3σ alerts)
* Multisite-aggregate dashboard, white-label branding, priority support

= 🇪🇺 Auf Deutsch — kurz & knapp =

**Die europäische Antwort für datenschutzfreundliches SEO & Analytics — die Lösung aus der EU für die EU.**

Brainwerk SEO Suite ist das All-in-one-SEO- und Analytics-Tool für WordPress, das **100 % deiner Daten auf deinem eigenen Server** behält. Keine Tracking-Cookies, keine externen Analytics-Dienste, keine Ad-Tech-Tracking-Pixel, kein Datenhandel — nur ehrliche Insights und alles, was du brauchst, um in Suchmaschinen **und** in KI-Antwortmaschinen gefunden zu werden.

* **Made in Europe, made for Europe** — in der EU nach EU-Standards entwickelt, Privacy-by-Design in jeder Abfrage
* **Datenschutzfreundlich ab Werk** — IP-Anonymisierung, täglich rotierende Besucher-Hashes, DNT-treu, konfigurierbare Aufbewahrung und Ein-Klick-Löschung. Ob ein Cookie-/Consent-Banner nötig ist, hängt von Ihrer Nutzung ab und ist rechtlich zu prüfen.
* **Für die NIS2-Ära gebaut** — alles selbst gehostet, auditierbar und unter deiner Kontrolle
* **EU-KI** — AI-Vorschläge laufen optional über **Mistral AI 🇪🇺** mit deinem eigenen Key
* **GEO/AEO** — KI-Crawler steuern (GPTBot, Google-Extended, ClaudeBot …), `llms.txt`, FAQ-Schema, KI-Traffic-Tracking (ChatGPT, Gemini, Perplexity, Claude)
* **Echte Anonymität im Benchmark-Netzwerk** — unter 50 Seitenaufrufen/Tag, unter 10 Core-Web-Vitals-Messungen oder unter 5 analysierten Beiträgen wird der jeweilige Wert gar nicht erst gesendet; Werte wie KI-Crawler-Traffic werden nur gebändert (nie als exakte Zahl) übertragen — deshalb ist **kein AV-Vertrag** für diese Funktion nötig
* **Ehrlicher Netzwerk-Fortschritt statt Blackbox** — bis genug Seiten teilnehmen, zeigt das Dashboard genau, wie viele Seiten aktuell dabei sind und wie viele nötig sind (aktuell 20), statt die Funktion einfach kommentarlos auszublenden; sobald für deine Branche/Region genug Vergleichsdaten da sind, erscheint der Vergleich automatisch
* **Vergleich mit dir selbst** — ein täglicher lokaler Schnappschuss (Analyzer-Score-Verlauf, Fehlerquoten bei Meta-Description/Alt-Text/Wortanzahl, Traffic-Verlauf, KI-Crawler-Aktivität) zeigt, wie sich deine eigene Seite über Wochen und Monate entwickelt — funktioniert vom ersten Tag an, auf jeder Installation, unabhängig vom Benchmark-Netzwerk. Diese Daten verlassen die Seite nie. Im Dashboard zeigt sich das als vier Widgets — Analyzer-Trend, Traffic-Verlauf (Tageszeit / Wochentag), KI-Crawler-Entwicklung pro Familie und Kennzahlen-Deltas — mit einem ehrlichen "wird noch aufgefüllt"-Hinweis, solange noch nicht genug Verlauf vorliegt.
* **Neu ab 1.8.0 — signaturgeprüfte Branchenvergleiche** — das Benchmark-Netzwerk holt jetzt zusätzlich einen Ed25519-signierten Feed vom Hub zurück, damit du Absprungrate, Sitzungsdauer und Analyzer-Checks mit anonymisierten Branchen-Peers vergleichen kannst; ungeprüfte oder veraltete Feeds werden grundsätzlich verworfen. Das Netzwerk ist **standardmäßig aktiv** und lässt sich jederzeit mit einem Klick abschalten — frühere Formulierungen, die "standardmäßig deaktiviert" behaupteten, waren falsch und wurden korrigiert.
* **Neu ab 1.8.1 — Report-Dateien mit unrätbarem Dateinamen** — erzeugte SEO-Reports (wöchentlich/monatlich/individuell) trugen bisher einen vorhersehbaren Dateinamen, der auf manchen Serverkonfigurationen direkt über die Adresse erreichbar war. Reportdateien bekommen jetzt zusätzlich ein langes Zufalls-Token im Namen, bestehende Reports werden beim Update automatisch umbenannt — kein Handlungsbedarf, einfach aktualisieren.
* **Neu ab 1.8.2 — Übersetzungs-Fix für leere Admin-Texte** — auf italienischen, spanischen und französischen (und teils auch englischen) Installationen konnten seit 1.8.1 einzelne Admin-Texte leer statt lesbar erscheinen, weil eine fehlerhafte Übersetzungsdatei nicht übersetzte Texte nicht korrekt auf das englische Original zurückfallen ließ. Am stärksten betroffen war Italienisch (fast die gesamte Oberfläche). Update wird allen empfohlen, besonders auf nicht-englischen Seiten.
* **Neu ab 1.9.0 — Eigenvergleich als Dashboard-Widgets, ehrlicherer Netzwerk-Fortschritt, Sicherheits-Härtung** — der tägliche lokale Schnappschuss für den Vergleich mit dir selbst erscheint jetzt als vier Dashboard-Widgets (Analyzer-Trend, Traffic-Verlauf, KI-Crawler-Entwicklung, Kennzahlen-Deltas). Zusätzlich: CSV-Exporte sind jetzt gegen Formel-Injection in Excel/LibreOffice/Sheets abgesichert, die SSRF-Schutzprüfung deckt jetzt auch zwei Pro-Module ab und verankert die aufgelöste IP für die Dauer der Anfrage, und ein Multisite-Fehler, der Subseiten-Einstellungen unnötig vom Netzwerk abkoppeln konnte, ist behoben (bestehende Installationen werden beim Update automatisch bereinigt). **Dieses Release legt beim Update eine neue Datenbanktabelle an** (`wp_seoforge_history`), automatisch, ohne Handlungsbedarf.
* **High-Tech im Maschinenraum** — Sub-Millisekunden-Dashboards, gehärtetes SQL, REST-API & WP-CLI
* **Alles aus einer Hand** — Analytics, Meta, Schema.org, Sitemap, Redirects, 404-Log, Analyzer

Bereits Yoast oder RankMath im Einsatz? Brainwerk erkennt das automatisch und schaltet seine Meta-/Schema-/Sitemap-Module ab — du behältst **Analytics, 404-Log, Redirects und Analyzer** als sauberes Add-on, ohne Doppelausgabe.

== Installation ==

1. Upload the `seoforge` folder to `/wp-content/plugins/` (or install via the WordPress Plugin Directory).
2. **Activate** the plugin on the Plugins page, or **Network Activate** on Multisite.
3. Open *Brainwerk SEO Suite* in the admin menu and complete the 3-step setup wizard.
4. (Optional) On the *License* tab, activate a Pro license to unlock Pro modules.

== Frequently Asked Questions ==

= Does Brainwerk SEO Suite work with Yoast / RankMath / AIOSEO already installed? =

Yes. Brainwerk SEO Suite auto-detects the active SEO plugin and stands down its meta, schema, sitemap and robots modules so there's no duplicate output. Analytics, the 404 log, redirects and the on-page analyzer keep working side by side. A single toggle on the *Privacy / GDPR* tab forces takeover whenever you want.

= How do I know the numbers are actually correct? =

You don't have to take them on faith. The Verify tab lets you compare what the plugin counted against your own server's raw access log for any date or time range you pick, and run a determinism self-test. From there on, every history row is chained to the previous one with a tamper-evident hash, so a later change to a stored row — or a missing/reordered one — is detectable. An optional external notarization service (off by default) checkpoints that chain with an outside witness once a day, so you can also prove nothing was altered after the fact. It proves the chain wasn't changed after notarization, not that the original numbers were correct — that's what the access-log comparison and determinism test are for.

= Does this plugin add tracking cookies? =

Brainwerk SEO Suite uses no third-party or cross-site tracking cookies (only a first-party session cookie), anonymizes IPs and respects DNT by default. Whether your site needs a consent banner overall depends on all services you run and your jurisdiction — please assess this yourself, if needed with legal advice. The bundled privacy snippet documents exactly what is stored so you can paste it into your own privacy policy.

= Is the analytics data accurate without JavaScript? =

The server-side mode catches all real requests, including users who block JavaScript or use strict tracking-protection. It does count fewer "bot-like" visits than JS-based analytics because we filter known crawler user agents. A JS beacon mode for time-on-page and scroll depth is included if you want the extra signal.

= Will Brainwerk SEO Suite slow down my site? =

The tracker only inserts one row per pageview (no joins, no remote calls). All dashboards read from a pre-aggregated daily table, so the admin pages are sub-millisecond even at 100k+ visits per month. The sitemap and meta output are cached.

= Is there a wp-cli command? =

Yes — `wp brainwerk-seo-suite stats`, `wp brainwerk-seo-suite purge`, `wp brainwerk-seo-suite cleanup`, `wp brainwerk-seo-suite aggregate`, `wp brainwerk-seo-suite export`, `wp brainwerk-seo-suite import-redirects`, `wp brainwerk-seo-suite seed-demo` and `wp brainwerk-seo-suite license` (`wp seoforge seed-demo` and `wp seoforge import-redirects` also work as short aliases).

= Where is data stored? =

Tables under the network prefix (`wp_seoforge_visits`, `_sessions`, `_redirects`, `_404`, `_meta`, `_daily`, `_history`, and `_audit` for Pro) and a settings option. Nothing leaves the server (Pro modules use opt-in external APIs).

= Where is the license server? =

Licensing is handled by Freemius (Merchant of Record). All license traffic goes to `api.freemius.com`. There is no Brainwerk SEO Suite-operated license server.

== External services ==

The optional AI features connect to **one external AI provider, Mistral AI (EU-based)**. They are **opt-in** and only used when you explicitly enter your own API key.

**Mistral AI API — `https://api.mistral.ai`** (EU-based)

* **What it is used for:** Generating AI suggestions for SEO titles, meta descriptions, focus keywords and internal-link recommendations when you click the "✨ Suggest with AI" buttons in the on-page meta box or the AI tab.
* **When data is sent:** Only when an editor clicks one of the AI-suggestion buttons in the WordPress admin. No data is sent on the front-end, during normal page views, or in cron jobs.
* **What data is sent:** Your own Mistral API key (you supply it; the plugin does not bundle one), the post title and the post body content of the post you are editing, plus a short instruction prompt. Nothing else — no user identifiers, no site-wide content, no analytics.
* **How to disable:** Leave the API key field empty in *Brainwerk SEO Suite → AI* settings, or toggle the AI feature off. With no key, the plugin never contacts any AI provider.
* **Provider:** Mistral AI (France/EU) — [Terms of Service](https://mistral.ai/terms/) — [Privacy Policy](https://mistral.ai/terms/#privacy-policy)
* **API documentation:** [https://docs.mistral.ai/](https://docs.mistral.ai/)

**SEO benchmark network — `https://shieldforge-intel.brainwerk.at`** (EU-based) — **on by default, disclosed during onboarding**

* **What it is used for:** The plugin sends one aggregate snapshot per day so you can compare your site against anonymised peers in your industry, and (Multisite) pulls back a signature-verified peer-benchmark feed. Enabled from install so the benchmark data is populated from day one; you can turn it off at any time.
* **When data is sent:** Only after the site has completed a lightweight registration step with the hub (shown during onboarding, or under *Brainwerk SEO Suite → Tools → SEO network*). That one-time registration transmits only this site's web address (used as a label) and gets back a pseudonymous site ID and secret in return — nothing else, and nothing before registration completes. You can disconnect any time.
* **What data is sent:** Aggregate figures only, all counts and percentages over the whole site for one UTC day — visit/session totals, traffic-source/device/bot-share percentages, p75 Core Web Vitals, on-page-analyzer score distribution and per-check pass/fail rates, an hour-of-day/day-of-week traffic profile, AI-crawler visibility (which recognised crawler families visited, banded — never the exact count — plus your robots.txt/llms.txt configuration), a declared/suspect/cloaked bot mix, coarse comparability bands (PHP major version, WordPress minor version, site-size and traffic bands, whether a page cache is active) and an optional self-declared industry label. On a Multisite network, the subsite's hostname is included so snapshots can be told apart (not shared publicly). **Below 50 pageviews in a day, or below 10 Core Web Vitals samples, or below 5 analysed posts, the corresponding figures are suppressed entirely rather than sent** — at that volume a percentage would describe one visitor, not a population. **Never** an individual visitor, IP address, URL or any personal data.
* **Also exposed:** a read-only *inbound-pull* REST route (`GET /wp-json/seoforge/v1/relay/snapshot`) for sites whose server cannot make outbound requests — the hub fetches the same daily snapshot instead, authenticated with a secret you (or the hub operator) configure; disabled unless a relay secret is set. A companion *inbound feed* endpoint (the hub's `GET /v1/seo/intel`) lets this site pull back an Ed25519-signature-verified peer-benchmark/bot-reputation feed once a day — the fetch carries no visitor data, only the site's existing HMAC identity. That feed also always carries a network-participation count (how many sites contribute overall, and how many are needed before industry comparisons switch on) even on days the peer-benchmark figures themselves are withheld for k-anonymity, so the dashboard can show honest progress instead of a blank card.
* **How to disable:** Turn it off, or click *Disconnect*, under *Tools → SEO network*. When off, the plugin never contacts the hub and the inbound-pull route returns 404.
* **Provider:** Brainwerk (Austria/EU) — [Privacy Policy](https://brainwerk.at/datenschutz/)

**External notarization — `https://shieldforge-intel.brainwerk.at`** (EU-based) — **opt-in, off by default, independent of the SEO benchmark network above**

* **What it is used for:** Lets you prove your locally-verified integrity chain (see the *Verify* tab) hasn't been retroactively tampered with, by checkpointing it with an outside witness once a day and letting you compare your local chain against that witness's record at any time.
* **When data is sent:** Only while *Verify → External notarization → "Notarize this site's integrity chain daily"* is switched on (default off, independent of the benchmark opt-in above — enabling one does not enable the other). If the site hasn't already registered with the hub for the benchmark network, turning this on performs the same lightweight one-time registration step by itself — transmitting only this site's web address (used as a label), nothing else.
* **What data is sent:** Only the head of the local hash chain (a SHA-256 hash), the date range it covers, and a row count. **Never a measurement, never the content of a history row, never visitor data.**
* **How to disable:** Switch the opt-in off under *Verify → External notarization*. When off, the plugin never contacts the hub for this purpose.
* **Honest limits, stated in the admin UI itself:** it protects against retroactive tampering only from the first accepted checkpoint onward — history before that has nothing external to compare against — and it proves the chain wasn't altered *after* notarization, not that its content was correct to begin with.
* **Provider:** Brainwerk (Austria/EU) — [Privacy Policy](https://brainwerk.at/datenschutz/)

Licensing for the optional Pro tier is handled by Freemius (Merchant of Record). License-validation traffic — only performed when you activate a Pro license on the *License* tab — goes to `https://api.freemius.com`. See the [Freemius Terms of Service](https://freemius.com/terms/) and [Privacy Policy](https://freemius.com/privacy/). With no Pro license entered, the plugin never contacts Freemius.

**Visitor-country lookup is offline.** The Free country-level geolocation uses a compact IP→country database **bundled inside the plugin** and resolved locally — it makes **no external requests**. The bundled data is derived from the **DB-IP IP-to-Country Lite** database by DB-IP, licensed under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). IP Geolocation by [DB-IP](https://db-ip.com). The Pro region/city drill-down uses MaxMind's GeoLite2 City database (downloaded once to your server when you enable it); this product includes GeoLite2 data created by MaxMind, available from [https://www.maxmind.com](https://www.maxmind.com).

== Screenshots ==

1. Verify — check the plugin's counted numbers against your own server log, with a tamper-evident hash chain over your history.
2. Dashboard — health score, open action items and a live-visitor count at a glance.
3. Traffic sources — direct, search, social, referral and AI answer engines.
4. Bot & AI-crawler traffic — your declared/suspect/cloaked crawler mix at a glance.
5. On-page SEO analyzer — per-post scoring across 9 checks, with focus-keyword breakdown.
6. Compare yourself to yourself — analyzer trend, traffic shape and headline-number deltas over time, entirely local.
7. Privacy / GDPR — tracking, retention and exclusion controls, built without tracking cookies.

== Changelog ==

= 1.10.3 — 2026-08-13 =
* **Fix — bundled country table no longer packed**: the geolocation table used for the free "visitor country" lookup was shipped as a compressed archive and unpacked into `wp-content/uploads` the first time it was needed. It's now shipped ready to use, so there's nothing to unpack on first use and no extra copy left behind in `wp-content/uploads`. If your site already created that copy under an older version, it's removed automatically on update.

= 1.10.2 — 2026-08-13 =
* Corrected the German translations (`de_DE`, `de_AT`): three remaining texts in the Verify tab's notarization area were still using the formal "Sie" form, inconsistent with the informal "Du" form used throughout the rest of the German translation. No functional change.

= 1.10.1 — 2026-08-08 =
* **Transparency, no behavior change**: clearly discloses, for the first time, that turning on the SEO benchmark network *or* external notarization triggers a one-time registration with the hub, transmitting only this site's web address. This was already happening; it just wasn't explained anywhere before. New "Hub registration" card on the Privacy tab, a new explanatory paragraph on the Verify tab's notarization card, a note added to the onboarding benchmark opt-in text, and the `== External services ==` entries below made explicit about it. No database schema change.

= 1.10.0 — 2026-08-08 =
* **New — prove your history hasn't been tampered with, to an outside witness**: the *Verify* tab gains an *External notarization* card, a separate opt-in from the SEO benchmark network — off by default, and you can turn one on without the other. Once a day, the plugin sends only the head of your tamper-evident history chain (a SHA-256 hash), the date range it covers and a row count — never a measurement, never row content — to the same hub the benchmark network already talks to. A "Compare with hub" button re-checks your local chain against the hub's last accepted checkpoint and tells you match or mismatch, pinned to the exact date they diverge. This makes retroactive tampering detectable against an independent outside record, not just against your own database — but only from the first checkpoint onward, and only that the chain wasn't altered afterward, not that it was correct to begin with; the tab states both limits plainly.
* Adds automated regression tests covering the above (325 tests total).

= 1.9.1 — 2026-08-05 =
* **New — check the plugin's own numbers against your server, and prove your history hasn't been tampered with**: a new *Verify* tab lets you compare what the plugin counted against your site's raw nginx access log for any date and time range you choose, so you can see for yourself how closely the two line up. It also checks your captured history for missing days — and lets you fill in any that are still recoverable — and every history row captured from now on is chained to the one before it with a tamper-evident hash, so a later change to a stored row, or a deleted/reordered row, becomes detectable rather than silent. Everything runs locally against your own server and your own database; nothing is sent anywhere. **This release adds two columns to the existing `wp_seoforge_history` table on update**, handled automatically.
* Adds automated regression tests covering the above (300 tests total).

= 1.9.0 — 2026-08-05 =
* **New — compare your site to its own past ("Eigenvergleich")**: a daily local snapshot now builds a history of your on-page-analyzer score, meta-description/alt-text/word-count fail rates, traffic shape and AI-crawler activity, and the dashboard gains four new widgets — analyzer trend, traffic shape (hour of day / day of week), AI-crawler development per family, and headline-number deltas — so you can see how your site is trending week over week and month over month. Works from day one, on every install, whether or not you've joined the SEO benchmark network, and nothing here ever leaves the site. Shows an honest "still filling up" message until enough history has built up. **This release creates a new database table (`wp_seoforge_history`) on update**, handled automatically.
* **Improved — honest benchmark progress instead of a blank card**: until enough sites have joined the SEO benchmark network to compare safely, the dashboard now says plainly how many sites currently participate and how many are needed before industry comparisons switch on, instead of a silent "not available" gap.
* **Security hardening**: CSV exports (visits, sessions, 404s, redirects, audit log) are now protected against formula/DDE injection when opened in Excel/LibreOffice/Sheets. The outbound-request safety guard (SSRF protection) now also covers the Search Console sync and GEO-database download Pro modules, and pins the resolved IP for the duration of the request to close a DNS-rebinding window. On Multisite, saving settings on a subsite no longer silently freezes that subsite out of future network-wide setting changes; existing installs with a stale full copy are cleaned up automatically on update.
* Adds automated regression tests covering all of the above (259+ tests total).

= 1.8.2 — 2026-08-05 =
* **Fix — some admin interface texts could show up blank**: on sites using Italian, Spanish or French — and even on some English installs — a bug in the plugin's translation files could cause a number of admin-screen texts to render blank instead of readable text. Untranslated strings now correctly fall back to the English original instead of an empty string. Italian was affected the most (nearly the entire admin UI); Spanish and French lost around 174 strings each; English installs lost around 238. Recommended for everyone, especially non-English sites. No database changes.

= 1.8.1 — 2026-08-03 =
* **Security — report files now use unguessable filenames**: generated SEO reports (weekly/monthly/custom) were previously saved under a predictable filename that could be reached directly by guessing the address on some server configurations. Report filenames now carry a long random token, and any existing report files are renamed to the new scheme automatically the next time an admin visits wp-admin after updating — no action needed. Users are recommended to update.

= 1.8.0 — 2026-08-01 =
* **New — signature-verified peer benchmarks**: the SEO benchmark network now pulls back an Ed25519-signed feed from the hub as well as sending your own snapshot, so the dashboard can show how your bounce rate, session length and on-page-analyzer checks compare with anonymised peers in your industry. The feed is verified against pinned public keys before anything is trusted; it fails closed (silently ignored, never accepted unverified) if it can't be verified, is out of date, or looks like a replay of an older feed. A new "Pull feed now" button sits next to the existing push controls under *Tools → SEO network*.
* **New — AI-crawler and bot-traffic visibility**: the dashboard gains a "Bot & AI-crawler traffic" card showing your declared/suspect/cloaked bot mix and crawl-to-referral ratio, plus (once the peer feed is available) a read-time reputation note when traffic claims to be a known AI crawler but doesn't behave like one. Nothing here is inferred until the peer feed actually supplies it.
* **New — richer, still-anonymous benchmark snapshot**: the daily aggregate snapshot now also includes on-page-analyzer score distribution and per-check failure rates, an hour-of-day/day-of-week traffic profile, AI-crawler visibility (banded, never an exact count) with crawl-to-referral, your declared-bot mix, and coarse comparability bands (PHP/WordPress version, site size, traffic volume). All of it is counts, percentages and bands — never a single visitor, IP, URL or raw crawler string.
* **Improved — stronger anonymity guarantees**: days under 50 pageviews (or under 10 Core Web Vitals samples, or under 5 analysed posts for the analyzer figures) now send no metrics for that figure at all, rather than a low-confidence number. Small-sample countries are dropped from the country breakdown. Versions, site size and traffic are only ever sent as coarse bands, never exact values.
* **Corrected — consent wording**: earlier release notes and onboarding copy described the SEO benchmark network as "off by default." That was wrong — it has been **on by default since 1.4.0**, with a one-click switch-off in onboarding and under *Tools → SEO network*. The copy now says this plainly; nothing about the actual default has changed, only the description of it.
* **Clarified — external-service disclosures**: the *External services* section below now documents the new inbound feed pull and the Multisite inbound-pull relay route, alongside the existing outbound snapshot.
* **Fix — the benchmark network now actually works for everyone, not just our own sites.** Self-registration with the hub silently failed for every install that never pasted a token by hand, because no default registration token shipped with the plugin — the opt-in looked "on" but never connected. A rate-limited, publicly-scoped registration token (isolated to the SEO benchmark channel, no access beyond that) now ships with the plugin, and a failed registration is now shown in the admin card instead of failing silently.
* Adds automated regression tests covering all of the above (152 tests total). No database changes.

= 1.7.1 — 2026-08-01 =
* **Security — Multisite: sites can no longer see or affect each other.** On a Multisite network, an administrator of one site could previously view another site's analytics via the site selector, change settings for the whole network by saving on their own site, and delete other sites' records with the "Clean up now" tool. All three are now correctly limited to the site the administrator actually manages; the network-wide view and network-wide settings remain available to Super Admins as before. **Single-site installations were never affected by any of these.**
* **Privacy — the analytics beacon now honours "Do Not Track".** The server-side tracker already respected the browser's Do-Not-Track signal; the JavaScript beacon (time on page, scroll depth, Core Web Vitals, outbound clicks) did not. Both now use the same rule, so a visitor sending DNT is not recorded at all.
* **Fix — Search Console sync (Pro) works again.** The sync silently did nothing because the license key was never passed through; it now runs, and any failure is reported in the admin instead of failing quietly.
* Adds automated regression tests covering all of the above (78 tests total). No database changes.

= 1.7.0 — 2026-07-30 =
* **Fix — accurate visitor countries behind a proxy or CDN**: sites served through a reverse proxy (e.g. nginx) or a CDN like Cloudflare were attributing most or all visits to a single wrong country (the proxy/edge location). The plugin now detects the real client IP from the standard forwarded headers when the request comes through a trusted local proxy, so country stats are correct again. Manual override via `SEOFORGE_TRUSTED_PROXIES` still works.
* **New — the on-page SEO analyzer now explains every check**: alongside the score, each check shows what was measured, whether it passed, and a concrete tip to improve it — in the post editor and as an expandable breakdown in the SEO list.
* **New — consistent, clear Pro labelling**: every Pro-only feature now carries the same "Pro" badge and a proper upsell card (region & city geolocation, Search Console & Bing sync, traffic-spike alerts, the network-aggregate dashboard and the full audit log), so it's always obvious what's included in your plan.
* **Fix — region & city drill-down is now correctly Pro-gated**: the country → region/city detail was being returned to Free installs; it is now enforced server-side as the Pro feature it is.
* **Change — the overview refreshes in place**: switching the date range or site scope now updates just the dashboard widgets instead of reloading the whole page (with a graceful fallback if JavaScript is unavailable).
* **New — traffic-source tooltips**: Direct, Internal, Search, Referral, Social, Campaign and AI answer engines each have a one-line explanation, so it's clear what every source means.
* **Improved — clearer AI answer engines section**: a better explanation of AEO/GEO traffic (visits arriving from ChatGPT, Gemini, Copilot, Perplexity, Claude and others).
* **Fix — mobile layout**: wide tables and stat grids no longer overflow the screen on phones; tables scroll and grids reflow.
* **Improved — German translations completed**: 113 previously-English admin strings are now translated for German (de_DE) and Austrian German (de_AT).
* Assorted i18n and licensing-consistency hardening. No database changes.

= 1.6.0 — 2026-07-30 =
* **Security — Multisite data reset is now per-site**: the *Tools* reset actions (visitor stats and 404 log) now clear only the current site's rows instead of the shared network-wide tables, so a single-site admin can no longer wipe another site's analytics on a Multisite network.
* **Fix — scheduled reports use the correct time window**: the automatic weekly/monthly report crons now compute their date range in UTC (matching how visits are stored), so reports on non-UTC servers no longer drift. The monthly report e-mail is now correctly labelled (was mislabelled "weekly"), and report e-mail subjects are unified under the Brainwerk SEO Suite name.
* **Hardening — outbound webhooks & settings import**: Pro webhook alerts and imported settings now refuse URLs that resolve to internal/loopback/link-local addresses, closing a server-side request forgery (SSRF) vector.
* **Hardening — analytics beacon**: the public beacon endpoint now also requires a rotating, site-signed token, on top of the existing origin check and per-IP rate limit.
* **Fix — race-free 404 logging**: concurrent first hits to the same missing URL are now recorded with a single atomic upsert, so no hit is lost.
* **Fix — uninstall respects a per-site "keep data" choice**: on Multisite, the shared data is kept if any site opted to keep it.
* **Polished report e-mails**: dark-mode-aware colour scheme, hidden preview (preheader) text, accessible logo alt text, a document language attribute, and a "Manage e-mail reports" footer link.
* **European positioning**: refreshed EU messaging ("the European answer — from the EU, for the EU") and removed third-party product comparisons from the marketing copy.
* Assorted i18n and defense-in-depth cleanups. No database changes.

= 1.5.0 — 2026-07-29 =
* **New — settings & action audit log**: a new *Audit Log* tab records who changed what and when (settings saved, redirects created/deleted, license/tier changes, the uninstall data-deletion choice, manual data resets, SEO-network opt-in/opt-out) — a short human-readable summary only, never a raw diff of your data, so the privacy footprint stays small. The free build shows your last 5 entries with a Pro upsell; **Pro** gets full pagination and CSV export. A new *Privacy → Audit log retention* setting (default 180 days) keeps it tidy automatically.
* **Changed — weekly digest e-mail is now consent-first**: on a fresh install, the weekly digest no longer looks "on" while silently sending nothing — it now defaults to off, matching the daily digest, until you explicitly enable e-mail reports (in onboarding or under *Tools → E-mail reports*). Existing installs are unaffected.
* **Changed — network admins can manage Reports**: a network admin without their own admin rights on the active site can now open and use the Reports tab, matching how every other admin screen already behaves on Multisite.
* **Fix — Reports tab is now fully translatable**: the last hardcoded UI strings on the Reports screen now go through the plugin's translation files, so nothing falls back to English on a translated site (source strings added to all 5 language catalogs).
* Assorted internal hardening and documentation cleanup; see `CHANGELOG.md` for the full list.

= 1.4.0 — 2026-07-20 =
* **New — periodic review reminder**: a friendly, dismissible admin notice invites you to rate the plugin, starting 14 days after activation. Snooze it for another 14 days, or dismiss it for good — your choice is remembered.
* **Changed — SEO network sensor is on by default on fresh installs**: the opt-in benchmark sensor (see *External services* below) now defaults to enabled for new installs, so benchmark data starts building from day one. It still transmits nothing until the site completes registration, and can be turned off any time under *Tools → SEO network*. Existing installs keep whatever they already had configured.

= 1.3.1 — 2026-07-06 =
This is the first wp.org release since 1.2.0; it delivers everything from 1.3.0 to the public build plus one fix.
* **New — true PDF export for reports (Pro)**: on Pro, both the standard report and the Executive (CEO/CTO) report download as real, server-generated PDF files through a bundled PDF engine — no more relying on the browser's "Save as PDF". The free build is unchanged: it keeps the printable HTML report you save as PDF from your browser.
* **Fix — bundled translations now load**: the plugin again registers its own `/languages` folder (via `load_plugin_textdomain()` on `init`), so the shipped German, Spanish and French catalogs are actually used. Previously the admin stayed in English even on a translated site: wp.org's slug-based auto-loader only scans the global `wp-content/languages/plugins/` folder, never the plugin's own bundled `/languages` directory — so the catalogs shipped in the plugin were never picked up. Re-registering the folder is the wp.org-supported way to load bundled translations.
* **New — Austrian German (de_AT)**: adds a `de_AT` catalog so Austrian-German sites are no longer shown in English (they previously got no German at all, because WordPress does not fall back from `de_AT` to `de_DE`).
* **Fix — Reports tab is reachable again**: the Reports screen and its handlers existed but the tab was never registered in the admin tab list, so its menu entry had no link and `?tab=reports` silently fell back to the Dashboard. The tab is now wired into the *System* group.

= 1.3.0 — 2026-07-04 =
* **New — true PDF export for reports (Pro)**: on Pro, both the standard report and the Executive (CEO/CTO) report now download as real, server-generated PDF files through a bundled PDF engine — no more relying on the browser's "Save as PDF". The Executive report gains a one-click *Download as PDF* button. The free build is unchanged: it keeps the printable HTML report you save as PDF from your browser.
* **Fix — bundled translations now load**: the plugin again registers its own `/languages` folder, so the shipped German, Spanish and French catalogs are actually used. Previously the admin stayed in English even on a translated site because WordPress' just-in-time loader only scans the global translations folder. Adds an **Austrian German (de_AT)** catalog so `de_AT` sites are no longer shown in English.

= 1.2.0 — 2026-07-01 =
* **New — settings survive uninstall & reinstall**: your configuration is now kept in a private database backup, so if you delete and later reinstall the plugin, all your settings are restored automatically — no reconfiguring. The backup holds only your settings (never visitor data) and is never placed in a public folder. It even survives the "delete all data on uninstall" option. A new *Privacy → Remember settings for reinstall* toggle (on by default) lets you turn it off for a complete wipe.

= 1.1.0 — 2026-07-01 =
* **New — SEO benchmark network (opt-in)**: contribute one aggregate snapshot per day (counts, percentages and p75 Core Web Vitals only — never a single visitor, IP or URL) and see how your site compares to anonymised peers in your industry. Strictly opt-in and off by default: a clear consent step in onboarding, plus a one-time invitation on the plugin's own screens. Available on every tier. Manage or disconnect any time under *Tools → SEO network*. Fully documented under *External services*.
* **New — pull transport for locked-down servers**: sites whose PHP cannot make outbound HTTPS can still take part — the hub fetches the daily snapshot from an authenticated, read-only endpoint instead (the site makes no outbound connections).

= 1.0.1 — 2026-07-01 =
* **Fix**: connecting to the optional "SEO network" sensor could fail with "missing_register_token" — the registration token, industry and enable toggle were silently dropped when saving settings. These are now persisted correctly, so connecting works.

= 1.0.0 — 2026-06-30 =
* **Printable reports, no PDF software required**: the report generator now produces a self-contained, branded HTML report that any browser saves as PDF. This removes an external PDF library dependency, so reports work on every install — including locked-down servers.
* **Reports now include visitor countries**: the report gained a "Top countries" block (flags + share bars) alongside the KPI grid, trend, sources and devices.
* **Onboarding**: a new "AI search readiness (GEO/AEO)" step lets you switch on the llms.txt manifest and FAQ schema right from the setup wizard.
* **Accessibility**: clearer screen-reader labels on the redirect, 404 and visitor-country controls; decorative icons are now correctly hidden from assistive tech.
* **Hardening**: database schema migrations now run only in the admin context (never triggered by a public front-end request), with a lock against concurrent runs.
* **Pro**: opt-in "SEO network" sensor pushes one aggregate snapshot per day to power an agency fleet overview and anonymous peer benchmarks (counts and percentages only — never per-visitor data). Search Console performance (clicks, impressions, position, top queries) now has its own card.

= 0.9.0 — 2026-06-29 =
* **Generative Engine Optimization (GEO/AEO)** — a new toolkit to get your content surfaced and cited by AI answer engines:
  * **AI-crawler controls**: one-click allow/block for GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, PerplexityBot, Google-Extended, Applebot-Extended, Bytespider, CCBot and more — written straight into robots.txt.
  * **llms.txt manifest**: optionally publish `/llms.txt` (+ `/llms-full.txt`), a Markdown map of your key pages and posts for AI crawlers — generated automatically and cached.
  * **FAQ schema**: add question/answer pairs per post/page in the editor; output as FAQPage JSON-LD (plus `speakable` on articles) for rich results and AI answers.
  * **AI-engine traffic**: visits arriving from ChatGPT, Gemini, Copilot, Perplexity, Claude and other assistants are now classified as their own "AI answer engines" source, with a dedicated breakdown on the Sources tab.
* **Fix**: saving settings on the Meta/Schema tab silently did nothing after a slug rename (the form data was read under the wrong key). Settings now save correctly again.

= 0.8.0 — 2026-06-29 =
* **Visitor geolocation, now in Free**: the Visitors tab gets a "Visitor countries" breakdown with flags and share-of-traffic bars, and recent visits show a country column. Country resolution runs entirely **offline** from a compact IP→country database bundled inside the plugin (built from DB-IP Lite, CC BY 4.0) — no external requests, so it works on locked-down/firewalled servers too. Covers both IPv4 and IPv6.
* **Pro — region & city drill-down**: with a Pro license, click any country to expand its top regions and cities, powered by MaxMind's GeoLite2 City database (read with a bundled, dependency-free reader). Country-level data stays available on Free.
* **Schema**: visits and sessions gain `region` + `city` columns (DB upgrade to v4, applied automatically).
* **Demo data**: the demo seeder now emits internally-consistent country/region/city so the new geolocation views look populated out of the box.

= 0.7.7 — 2026-06-24 =
* **Every e-mail now shares the same polished design**: the traffic-spike alert, the scheduled report cover e-mails (auto weekly/monthly and re-sends) and the "send test" e-mail were plain text or a bare one-liner — they now use the same branded HTML shell as the digests (navy gradient header with logo, status-coloured hero band, clean facts table, call-to-action button and the made-in-EU footer). Consistent look across every notification the plugin sends.
* **Richer traffic-spike alert**: the anomaly alert now leads with a colour-coded hero (amber for a spike, red for an extreme spike) and a tidy breakdown — hour, human pageviews, z-score, rolling baseline and your alert threshold — plus a one-click button into the live dashboard. Slack/Discord/Teams webhook payloads are unchanged.
* **Fix — `/favicon.ico` no longer counted as a page**: favicon requests (and any other static asset that gets routed through WordPress) were recorded as visits and could top the "Top pages" report. They are now excluded from tracking (via `is_favicon()` plus a static-file-extension guard), so the report only shows real pages.
* **Fix — broken in-app links ("Sorry, you are not allowed to access this page")**: links that pointed to the old `admin.php?page=seoforge` slug — the onboarding "Start setup" button, Site Health fixes, the dashboard widget, report/e-mail buttons and others — led to a permission error because the admin page slug is `brainwerk-seo-suite`. All ~40 links now use the correct slug.

= 0.7.6 — 2026-06-21 =
* **E-mail reports — graphical daily & weekly digests**: the report e-mails are now beautifully designed HTML (brand header, KPI tiles with period-over-period trend arrows, traffic-source bars, top pages, Core Web Vitals ratings, human-vs-bot split) — everything at a glance. New **daily** digest in addition to the weekly one; configure recipient + cadence and send a test from *Tools → E-mail reports*.
* **Fix — Core Web Vitals, engagement & new-visitor tracking now actually work**: these metrics queried database columns that were never created or populated (they silently returned 0 and logged "unknown column" errors). The schema now includes `lcp_ms`/`cls_x1000`/`inp_ms`/`is_engaged`/`is_new_visitor` (DB upgrade to v3, applied automatically), new-visitor detection runs server-side, engagement + Core Web Vitals (LCP/INP/CLS, real field data) are captured via the front-end beacon (beacon/hybrid tracking mode). Verified on a staging install.
* **Hardening & cleanup** (from an internal audit): Multisite isolation fix so a subsite admin can no longer delete/toggle another site's redirect by id; removed a dead "link check" cron that fired into the void; report crons are now cleared on deactivation; minor robustness fixes.
* **AI — Mistral AI support (EU-based) + provider choice**: AI suggestions can now run on Mistral AI — an EU-based provider, so your content stays in the EU — in addition to Anthropic (Claude). Choose your provider and model in the AI tab; Mistral is the new default for fresh installs. Still bring-your-own-key, encrypted at rest, fully opt-in.
* **Pro — Executive report (CEO / CTO)**: a one-click, print-ready branded report for leadership. Pick an Executive (CEO), Technical (CTO) or Full/Board preset, choose a period, and present it or save it as PDF from the browser. Includes period-over-period deltas, human-vs-bot split, traffic mix, geographic reach, top/entry/exit pages, Core Web Vitals ratings (overall and by device), new-vs-returning audience and a privacy/compliance summary — rendered entirely from your own first-party data, no external service. The Free build shows a preview/upsell.
* **Multisite**: the analytics tabs (Dashboard, Visitors, Sources, Pages) and the at-a-glance dashboard widget now scope visitor stats per site. A new site selector lets you switch between **this site**, the **entire network** (aggregated), or any **single subsite**; the choice is remembered per user. Previously every subsite admin saw network-wide totals.
* **Multisite**: the network Dashboard adds a per-site breakdown table (pageviews / unique visitors / sessions per subsite) with a one-click drill-down into each site.
* **Fix**: `SEOFORGE_VERSION` was still reporting `0.7.4`; it is now back in sync with the plugin header.

= 0.7.5 — 2026-06-19 =
* **Security/SQL**: every plugin-owned table name that was previously interpolated into a query string is now passed through the `$wpdb->prepare()` `%i` identifier placeholder (WordPress 6.2+) instead of string interpolation. Conditional `WHERE` builders and the breakdown/percentile switches were restructured so each `$wpdb->prepare()` call receives a string literal with placeholders only — no SQL string is built in a variable. The only remaining interpolation is the dynamic `post_type IN (...)` list, which uses generated `%s` placeholders bound through `prepare()` (an `IN()` list cannot use `%i`). Requires at least WordPress 6.2.

= 0.7.4 — 2026-06-14 =
* **Security**: removed the last two cases of a column identifier being interpolated into SQL. The breakdown query (`Seoforge_Stats::group_count()`) and the Core Web Vitals percentile query (`Seoforge_Reports::percentile()`) now select a separate, fully literal query string per allowed column — the SQL identifier is never taken from a variable. All values continue to be bound through `$wpdb->prepare()`.

= 0.7.3 — 2026-06-13 =
* **Enqueue**: the Reports tab no longer outputs an inline `<script>`; its quick-range helper moved into the enqueued `assets/js/admin.js`.
* **i18n**: the last `seoforge` text-domain string now uses `brainwerk-seo-suite`, matching the plugin slug.
* **Security**: report admin-post handlers sanitize the nonce with `sanitize_text_field( wp_unslash() )` and unslash/sanitize all request values; the post meta box sanitizes its submitted array at input.

= 0.7.2 — 2026-06-10 =
* **Security**: table names passed to the internal table-resolver are now validated against the fixed whitelist of plugin tables before being used in SQL.
* **Security**: the migration coordinator builds its post-type `IN (...)` list from dynamically generated `%s` placeholders via `$wpdb->prepare()` instead of escaping + interpolation.
* **Security**: internal report/stats helpers validate metric and group-by column names against fixed whitelists before using them as SQL identifiers.

= 0.7.1 — 2026-06-03 =
* **Security**: Schema.org JSON-LD is now emitted with slash-escaping (no `JSON_UNESCAPED_SLASHES`), so a value containing `</script>` can no longer break out of the inline `application/ld+json` block. `\/` and `\uXXXX` remain valid JSON-LD.

= 0.7.0 — 2026-05-21 =
* **Rebranded** to Brainwerk SEO Suite (was: SEOForge). Display name + text-domain + plugin filename updated.
* **Security**: nonce verification in the post meta box now goes through `sanitize_text_field( wp_unslash() )` (pluggable-function hardening).
* **Security**: `$_COOKIE` reads in the tracker now go through `sanitize_text_field( wp_unslash() )` in addition to the existing hex-filter.
* **Security**: SVG sparkline attributes in the dashboard widget now use `esc_attr()` for chart coordinates.
* **Security**: WP-CLI `export --out=<path>` is now restricted to a `wp-content/uploads/seoforge/` subdirectory (and writes only the basename) so it cannot clobber arbitrary paths.
* **wp.org compliance**: removed the Pro-only bearer-key path from the REST `permission_callback`. The Free REST API is admin-cookie/nonce only. Pro external dashboards stay in the separate Premium build.
* **wp.org compliance**: removed `load_plugin_textdomain()` — WordPress 4.6+ auto-loads translations for plugins hosted on wp.org by slug.
* **wp.org compliance**: weekly digest now uses `admin_url()` instead of a hard-coded `/wp-admin/` path.
* **Docs**: readme now documents the optional Anthropic (Claude) API integration as an `== External services ==` section, with what is sent, when, how to disable, and links to Anthropic's Terms / Privacy.

= 0.6.0 — 2026-05-19 =
* Freemius integration live-wired end-to-end (real product IDs, SDK in `freemius/`, `is_live=true`).
* Paid plans Starter (€59/yr, 1 site) and Agency (€199/yr, 25 sites) with auto-generated pricing table.
* New sanity row in the Tools tab reports SDK / opt-in / license state.
* Premium build script (`bin/build-premium.sh`) for Freemius Deploy.
* Fix: `Seoforge_License::is_pro()` now uses `is_paying()` so Pro modules load in both Free and Premium builds with a valid license.
* `uninstall.php` logic migrated to Freemius `after_uninstall` hook (per Freemius Deploy guideline).

= 0.5.0 — 2026-05-10 =
* CI alignment with the ShieldForge UX (Hero banner, tab groups, action items, iOS toggles, tooltips, dark mode, mobile, sanity card).
* `bin/bump-version.{sh,ps1}` + `bin/build-free.{sh,ps1}` + `.distignore`.
* Pre-launch sanity check (17 checks across versioning, cron, DB, privacy, tracking, sitemap, coexistence, file hygiene, readme, translations).
* i18n: POT + de_DE PO/MO shipped.
* PHPUnit tests for `Seoforge_Crypto` + `Seoforge_Analyzer`.

= 0.4.0 — 2026-05-07 =
* Migration wizard for Yoast / RankMath / AIOSEO (metadata + redirects).
* JS-beacon tracking mode with scroll depth + outbound clicks.
* `Seoforge_Health` setup-health score on the Dashboard.
* UX polish for non-technical site owners.

= 0.3.0 — 2026-05-07 =
* Pre-aggregated daily table for O(1) dashboard queries.
* Transient caches with auto-flush on mutations.
* License-key encryption at rest (AES-256-CBC).
* Streamed CSV exports (visits, sessions, 404, redirects).
* Bulk redirect import from CSV.
* WP-CLI commands (`wp brainwerk-seo-suite ...`).
* Demo seeder + live-visitors widget.
* REST API (`/wp-json/seoforge/v1/...`).

= 0.2.0 — 2026-05-07 =
* Coexistence layer detects Yoast / RankMath / AIOSEO / The SEO Framework / SEOPress and stands down passively.
* License + Pro module foundation.
* Pro stubs: Geo-Lookup, webhooks, anomaly detection, Search Console.
* Marketing landing page (`landing/index.html`).

= 0.1.0 — 2026-05-07 =
* Initial release: tracker, sessions, stats, meta, schema, sitemap, robots, redirects, 404 log, on-page analyzer, weekly digest, onboarding wizard, tools tab.

== Upgrade Notice ==

= 1.9.1 =
Adds a *Verify* tab: check the plugin's counted numbers against your server's own access log for any date/time range, spot and fill in missing days in your history, and a tamper-evident hash chain so later edits to stored history rows become detectable. Runs entirely on your own server. Adds two columns to the existing `wp_seoforge_history` table automatically on update — recommended for everyone who wants that assurance.

= 1.9.0 =
Adds a local "compare yourself to yourself" history with four new dashboard widgets, honest benchmark-progress messaging, and security hardening (CSV export injection, wider SSRF coverage with DNS pinning, Multisite settings fix). Creates a new database table (`wp_seoforge_history`) automatically on update — recommended for everyone.

= 1.8.2 =
Fixes a translation bug from 1.8.1 that could render some admin interface texts blank on Italian, Spanish, French and some English installs; untranslated strings now correctly fall back to the English original. Recommended for everyone, especially non-English sites. No database changes.

= 1.8.0 =
Adds a signature-verified peer-benchmark feed and AI-crawler/bot-traffic visibility to the dashboard, richer (still fully anonymous) aggregate snapshot data, and corrects release notes that wrongly described the SEO benchmark network as off by default — it has been on by default since 1.4.0. Also fixes self-registration with the benchmark hub, which previously never worked without manually pasting a token. No database changes.

= 1.7.1 =
Security fix for Multisite networks: one site's administrator could read, reconfigure and delete other sites' data. Recommended for all Multisite users. Single-site installations are unaffected but should still update — this release also makes the analytics beacon respect Do Not Track and repairs Search Console sync (Pro). No database changes.

= 1.7.0 =
Fixes visitor-country accuracy behind proxies/CDNs, adds per-check SEO analyzer explanations, makes Pro features consistently labelled (and closes a region/city data leak), refreshes the overview without a full reload, improves mobile layout, and completes the German translation. No database changes.

= 1.6.0 =
Security & hardening release: Multisite data reset is now correctly scoped per-site, scheduled reports use UTC, webhooks and the analytics beacon are hardened, and report e-mails are polished. No database changes. Recommended for everyone, especially Multisite networks.

= 1.5.0 =
Adds a settings/action audit log (Free: last 5 entries, Pro: full history + CSV export) and makes the weekly digest e-mail opt-in by default on fresh installs. Includes a database upgrade (new audit-log table) that runs automatically on activation.

= 1.4.0 =
Adds a periodic review reminder (dismissible) and switches the opt-in SEO network sensor to on-by-default for fresh installs only — existing installs keep their current setting unchanged.

= 1.2.0 =
Your settings now survive an uninstall and are restored automatically on reinstall. Nothing to do — it's on by default (toggle under Privacy).

= 1.1.0 =
Adds the optional SEO benchmark network — contribute anonymous aggregate stats and compare against peers. Strictly opt-in, off by default. Nothing is sent unless you enable it.

= 1.0.1 =
Fixes connecting to the optional "SEO network" sensor (registration token is now saved correctly). Recommended if you use the SEO network / fleet feature.

= 1.0.0 =
Version 1.0! Reports are now dependency-free printable HTML (with a visitor-countries block), onboarding gains a GEO/AEO step, accessibility is improved and schema migrations are hardened. Existing installs upgrade automatically.

= 0.9.0 =
Generative Engine Optimization arrives: control AI crawlers, publish llms.txt, add FAQ schema and track AI-answer-engine traffic — plus free visitor-country analytics. Existing installs upgrade automatically.

= 0.7.6 =
Multisite stats are now per-site: a new site selector switches between this site, the whole network, or any single subsite. Single-site installs are unaffected.

= 0.6.0 =
Freemius integration is live. Existing Free installs keep working unchanged; Pro features require a license.
