=== Brainwerk SEO Suite ===
Contributors: brainwerk, stefankogelgruber, freemius
Tags: seo, analytics, sitemap, redirect, gdpr
Requires at least: 6.2
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 0.7.5
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Privacy-first SEO + visitor analytics. Sitemap, Schema.org, redirects, 404 log, on-page analyzer. Multisite-ready, made in EU.

== Description ==

**Brainwerk SEO Suite** is an all-in-one, privacy-first SEO suite for WordPress. It combines server-side visitor analytics, a Schema.org/Open-Graph meta engine, an XML sitemap, a redirect manager, a 404 log and an on-page SEO analyzer — all without sending any data to third parties, all GDPR-friendly by default.

= Core features (Free) =

* **Local visitor analytics** — server-side pageview tracking, no cookies, no Google Analytics, no Facebook Pixel
* **Source attribution** — search engines, social, referrers, UTM parameters, direct
* **Top pages, entry/exit pages, device + browser + OS breakdown**
* **Meta engine** — `<title>`, meta description, Open Graph, Twitter Cards, canonical, per-post overrides
* **Schema.org JSON-LD** — Article, Organization, BreadcrumbList, WebSite
* **XML sitemap** — `/seoforge-sitemap.xml` with chunked URL sets + custom robots.txt
* **Redirect manager** — 301 / 302 / 307 / 308 with exact and prefix matching
* **404 log** with one-click "create redirect"
* **On-page SEO analyzer** — score 0–100 across 9 checks incl. focus-keyword, alt text, internal links, Flesch-DE readability
* **AI suggestions (bring-your-own Anthropic key)** — titles, meta descriptions, focus keywords, internal links
* **Migration wizard** — import existing metadata + redirects from Yoast SEO, RankMath, AIOSEO
* **Multisite-aware** — network activation, network-wide settings, per-site overrides

= Privacy & GDPR =

* IP anonymization on by default (IPv4 last octet, IPv6 /64)
* Daily-rotating SHA-1 visitor hash — no cross-day / cross-site identifier
* Respects `DNT` (Do-Not-Track) header
* No cookies, no third-party requests, no remote phone-home
* Configurable retention (visits, sessions, 404s)
* All tables can be dropped automatically on uninstall (opt-in)

= Coexistence =

Already using Yoast, RankMath, AIOSEO, The SEO Framework or SEOPress? Brainwerk SEO Suite auto-detects them and stands down its meta/schema/sitemap modules, so you get **analytics + 404 log + redirects + analyzer** as an add-on without duplicate output. One toggle to force takeover whenever you want.

= Pro =

The Pro tier unlocks (via Freemius license):

* Google Search Console sync (clicks, impressions, queries, position)
* Bing Webmaster sync
* Country / Geo-Lookup (MaxMind GeoLite2)
* Slack / Discord / MS-Teams webhook notifications
* Anomaly detection on hourly traffic (Z-score baseline, 3σ alerts)
* Multisite-aggregate dashboard
* White-label branding
* Priority support

== 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.

= Do I need to add a cookie banner? =

Not because of Brainwerk SEO Suite. The plugin doesn't drop any cookies, doesn't use a cross-site identifier, anonymizes IPs and respects DNT by default. 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 seoforge stats`, `wp seoforge purge`, `wp seoforge cleanup`, `wp seoforge aggregate`, `wp seoforge export`, `wp seoforge import-redirects`, `wp seoforge seed-demo` and `wp seoforge license`.

= Where is data stored? =

Six tables under the network prefix (`wp_seoforge_visits`, `_sessions`, `_redirects`, `_404`, `_meta`, `_daily`) 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 ==

This plugin connects to one external third-party service. It is **opt-in** and only used when you explicitly configure it.

**Anthropic (Claude) API — `https://api.anthropic.com`**

* **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 Anthropic 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. The plugin sends nothing else — no user identifiers, no site-wide content, no analytics.
* **How to disable:** Leave the Anthropic API key field empty in *Brainwerk SEO Suite → AI* settings, or toggle the AI feature off on the same page. With no key, the plugin never contacts Anthropic.
* **Provider:** Anthropic PBC — [Terms of Service](https://www.anthropic.com/legal/commercial-terms) — [Privacy Policy](https://www.anthropic.com/legal/privacy)
* **API documentation:** [https://docs.anthropic.com/](https://docs.anthropic.com/)

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.

== Screenshots ==

1. Dashboard — KPIs, sparkline, top pages, top sources, devices.
2. On-page SEO analyzer with focus-keyword scoring.
3. Redirect manager.
4. 404 log with quick-redirect button.
5. Privacy / GDPR settings.

== Changelog ==

= 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 seoforge ...`).
* 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 ==

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