Found a bug? Have a great feature idea? Get on GitHub and tell us about it and we'll get right on it: https://eshop-optimizer.com


= 7.0 Product-page layout builder (block + classic themes), reusable product/variation picker, master Button Styles (padding/sizing/glass), side-cart mobile bar styling, wishlist & brand in the layout builder, sticky admin navigation (05/06/2026) =

* **Side-cart mobile bottom bar — fully theme-independent + styleable.** The mobile sticky bottom bar (Navigator / Search / AI Chat / Cart) gets its own controls on the Side Cart tab: bar background colour + height, icon colour, and the cart-count number + circle colours (each can differ from desktop). A new **glass effect** renders the bar semi-transparent with a frosted backdrop-blur (opacity + blur configurable) so the page shows through. New **per-option "selected" colours** (background / text / border for each of Navigator, Search, AI Chat, Cart) highlight an option while its panel is open. When ONLY the cart icon is enabled you can show it as a **floating bubble** (like the desktop cart) instead of a full-width bar, and a lone cart icon is now centred with its count badge correctly anchored.
* **Side-cart display owned by the runtime.** The whole side-cart surface (the floating shell, the mobile bar, the slide-out panel and its assets) moved into one shared class bundled in both plugins, so the runtime renders it even when the admin plugin is trimmed from a request; the admin module remains the standalone fallback.
* **Product Needs — new "Pills" display.** Alongside the stacked list, the product-needs taxonomy can now render as tag-style pills laid out side by side, with their own text size, corner radius, vertical / horizontal padding, gap, background, border (width + colour) and text colour.
* **Master Button Styles — padding, sizing and glass.** Every master button group (Primary / Secondary / Archive) now also controls **Top / Right / Bottom / Left text padding** and **min / max width + height** (0 = no constraint), plus an opt-in **glass effect** (transparent background via `color-mix` + backdrop blur, opacity + blur per group). The Secondary group gained full hover parity — a base border plus hover background / text / border colours — to match Primary and Archive.
* **Wishlist + Brand in the product-page layout builder.** "Add to Wishlist" is now a positionable element in the Display Order list with a **Beside image / Beside the product title / Under image** choice (the heart sits inline next to the title by default). Brand Display gained the same **"Beside the product title"** option, and the builder's placement is now authoritative over the per-module Brand position setting.
* **Admin polish.** Fixed the "AI Optimizer" toolbar icon occasionally stacking above its label (a theme `img{display:block}` rule). Reordered the AI Optimizer sidebar submenu to **Data Prep → e-shop Manager → AI Chat → Interactivity (IAPI) → Rec Cache** and removed the one-off Session Schema Migrator from the menu. The AIEO admin **top bar and the e-shop Manager / Analytics sub-tab navigation are now sticky**, staying visible as you scroll long settings pages.

* **Product-page layout builder — one list orders the whole product info column.** Storefront Display → Single Product Page → Dashboard now has a single drag-and-drop "Display Order" card that governs the vertical order of EVERYTHING in the product info column: the core elements (title, rating, short description, sale-eligibility and free-shipping messages, price, add-to-cart) AND the info modules (product meta, categories, brand, payment logos, trust badges, back-in-stock waitlist, free brand gifts, complementary products, product needs, role-pricing login). Each module also gets a per-item "Beside image / Under image" choice, so it can be moved beneath the gallery. The same saved order is honoured on BOTH the block (FSE) theme — via CSS `order` on the info-column flex children — and on classic themes (Botiga / FemmeFatale-V2), by re-prioritising the matching WooCommerce single-product-summary hooks (WC core templates + AIEO modules), so the two render identically. Core blocks that ignore `className` (rating, short description, add-to-cart) are now wrapped so their order always applies, and Brand Display's before/under-title placements follow the list instead of being pinned above the title.
* **Restored the product "ΚΑΤΗΓΟΡΙΕΣ" (Categories) line as its own positionable module.** When AIEO replaced WooCommerce's native product-meta block (SKU + categories + tags) with its SKU/barcode strip, the categories line was dropped. It is back as its own orderable module — a clickable comma-separated list, styled to match the SKU/Barcode rows (label and list flow as one inline stream, with uniform vertical spacing) — placeable before or after Product Meta. The Role-pricing "log in to see your price" message is likewise positionable within the info column. (Product Categories was also moved to the "Single Product Page" section of the Storefront Display menu, next to Product Meta.)
* **Reusable product / variation picker on every product-criteria field.** A shared modal browser — search by name, SKU or brand; pick simple products, whole variable products, or specific variations; drafts and deleted items shown greyed, variations badged — replaces the free-text ID/SKU/barcode boxes on the offer forms: **Product discounts, Free gifts and Free shipping** (both the "specific products" and the "excluded products" lists), plus the **Product Exchanger** feed builder and the **marketplace feed exporter**. Picked variations roll up to their parent so cart matching is unchanged, and existing saved selections migrate automatically. One shared implementation (`AIEO_DMM_Product_Picker`) drives them all.
* **Master "Button Styles" control (Tools).** A single card now sets the default background, text colour, border (colour + width), corner radius and hover state for every AIEO storefront button — with three masters: **Primary** (add-to-cart, checkout, "notify me", "add selected"…), **Secondary / neutral** (view cart, save / share cart, apply coupon) and **Archive** product-card buttons. Each button that already had its own colour picker — Back-in-Stock Waitlist, Complementary, Sticky Add-to-Cart, Side-Cart — now inherits the master by default and overrides it only when you set a value (a CSS custom-property fallback chain, so nothing you previously customised changes). The side-cart action buttons, the storefront "Save / share my cart" button, the coupon-Apply button and the variable-product multi-select "update cart" button were aligned to the same tokens. Also fixes a long-standing admin bug where the colour-picker swatches rendered blank on the DMM settings pages (a global rule forced the swatch background transparent) — every DMM colour picker now shows its colour.
* **Admin discoverability.** The Ctrl / ⌘-K quick navigator now indexes the product-page layout/positioning card and the Saved & Abandoned Carts report; the AI Insights assistant gained an abandoned-carts analysis playbook plus "where does this live" pointers for the layout builder, the carts report and the product picker.
* **Auto-restock — e-shop sales no longer counted as physical-store demand.** The "Stock Recovery" auto-restock signal mines physical-store sales from the ERP to find products that are out-of-stock online but still selling in shops. The e-shop's own sales — invoiced through the head-office branch with a distinct ERP invoice-type code — are excluded from that signal so they cannot inflate in-store demand and trigger false restocks. The contract is documented for multi-store setups (give the e-shop's ERP sales a distinct invoice type).
* **Stock Recovery — out-of-stock cancellations surfaced as a "failed restock" signal.** When an order line is cancelled with the reason "Out of stock", the affected products are reconciled against the restock activity and shown in the Failures KPI, so restocks that didn't actually prevent a lost sale are visible.

= 6.5 Stock Recovery basket-turnover halo + per-branch pickers, Missing Hot Sellers published-benefit accounting, ERP de-duplication (03/06/2026) =

* **Stock Recovery — basket-turnover halo.** A new column (and a "Basket turnover protected" KPI in Outcomes) shows the total value of the *whole* in-store orders each out-of-stock product appears in — not just its own line. It quantifies the product's pull on the entire basket: a missing item can send the shopper to buy *everything* elsewhere, so the figure (captured at restock time and summed across all restocks) is the real revenue you defend by keeping it available.
* **Stock Recovery — per-branch pickers + money-first sort.** Each row now lists the units sold per physical store *within the chosen window* (so pickers know which branch holds the stock), and the recovery queue is sorted by in-store turnover (money) by default.
* **Missing Hot Sellers — per-branch sales column** so you can see which stores are selling each not-yet-published SKU.
* **Missing Hot Sellers — "Published from this list" accounting.** When you publish a product from the list, we begin counting the real online sales it earns and surface it in a dedicated panel (products published, online units / turnover since publishing, vs the in-store demand it had). This quantifies the concrete payoff of acting on the list, mirroring the Stock Recovery outcomes view.
* **ERP de-duplication — corrects inflated in-store figures.** The store-orders feed re-appends every order on each sync (a fresh import timestamp + row id, identical lines), so a re-synced order accumulated duplicate copies and inflated every in-store turnover / unit figure. Detection now keeps only the latest import-day per order — collapsing the duplicate copies while preserving genuine multi-unit purchases — so recovery, gap and basket numbers are accurate.
* **Recency window** can now be set up to 365 days (previously capped at 180).

= 6.4 Missing Hot Sellers, variation descriptions on swatches, clean activation on a fresh database (02/06/2026) =

* **Missing Hot Sellers — control what counts as a "gap".** 
* **Exclude by name / SKU pattern.** A free-text list (one substring per line) removes any product whose **name OR SKU** contains the text — from both the list and the totals, for current *and* future ERP imports. Built for the recurring noise the import creates: promotional bundles ("Προσφορά …"), coupons, gift vouchers ("Δωροεπιταγή"), and catch-all accounting SKUs ("ΔΙΑΦΟΡΑ ΕΙΔΗ", `9.99.*`). Matching is a safe case-insensitive substring (`LIKE`), not a regex.
* **Dismiss is no longer one-way.** The per-row **Dismiss** still permanently removes a single SKU (persisted in a blocklist that survives the nightly candidate rebuild), but dismissed items now appear in a **"Excluded items & patterns" panel with a Restore link** next to each, so an accidental dismissal can be undone.
* All of the above is applied at **read-time** through one shared filter used by both the list and the totals — so changes take effect on the next page load with **no re-detection, no stored-procedure change, and no schema bump**. Stock Recovery is unaffected (it only considers published, currently-out-of-stock products).
* **Variation descriptions now appear on the image swatches.** Many variable products carry a product-specific description per variation (the WooCommerce variation "Description" field, e.g. "No100 Fair" on a foundation shade) that previously showed nowhere on the storefront. The swatch builder now reads that description and composes a "description - attribute" caption (e.g. "No100 Fair - Ανοιχτόχρωμο"), stored alongside the rest of the swatch payload in the cache (`variation_description` + `swatch_label` in `wp_aieo_dmm_swatches_cache.variations_json`). It is shown three ways, all from the preloaded cache (no render-time cost, no per-variation lookup): on **hover** of an image swatch (the tooltip/title now reads "description - attribute"); **under the product title** on selection (read instantly off a `data-swatch-label` attribute stamped on each swatch, so it works even for image swatches with the tooltip turned off — a "Variation name under product title" toggle was added to the Product Swatches settings); and in the **cart, checkout, order details and emails** as its own line alongside WooCommerce's attribute (default label "Variant", filter `aieo_dmm_swatch_cart_desc_label`). Attribute values resolve to their display labels (taxonomy term name, or the raw value for custom attributes); multi-attribute variations join their labels. A cache payload-version bump (`SWATCH_PAYLOAD_SUFFIX`) marks existing cached rows stale so they rebuild with the new fields.
* **Fixed activation warnings on a fresh database.** Activating against a brand-new database (observed on a fresh MySQL 8.4 install) printed a wall of `Undefined array key "index_type" / "index_name" / "index_columns" / "column_name"` warnings from `wp-admin/includes/upgrade.php`, then `Cannot modify header information - headers already sent` (the warning output broke the post-activation redirect). Root cause: WordPress's `dbDelta()` parses a `CREATE TABLE` line by line and is intolerant of **blank lines and `--` SQL comments inside the column list** — a blank line is treated as an empty index definition (so on PHP 8 every named capture is undefined), and a comment line is mistaken for a column (yielding a malformed `ALTER TABLE … ADD …`). Two of our well-documented schemas (Customer Surveys, Push customer-intelligence) used that readable formatting. A new `aieo_dbdelta()` wrapper strips blank/comment lines from the SQL just before handing it to core `dbDelta()`, so the source stays readable and dbDelta sees exactly one field or index per line. Verified: the raw SQL reproduces 4 warnings per blank line through core `dbDelta()`, and 0 through the wrapper. (Live MariaDB installs such as femme-fatale.gr never surfaced this; the wrapper is a no-op there.)

= 6.3 Paid-social attribution (Facebook · TikTok · Google), offer-targeting correctness, archive-query hardening (02/06/2026) =

* **Paid-social attribution — full Facebook, TikTok and Google ad capture.** When a visitor lands from a paid ad, the session attribution now records the raw **click id** (`fbclid` / `ttclid` / `gclid` / `gbraid` / `msclkid` / …) — ready for Facebook Conversions API and Google offline-conversion uploads — *plus* the whole **campaign → ad set / ad group → ad** hierarchy (Meta `ad_id` / `adset_id` / `campaign_id`; Google and TikTok call the middle tier the "ad group", `adgroup_id`). Four self-healing columns (`entry_click_id`, `entry_ad_id`, `entry_adset_id`, `entry_ad_campaign_id`) are added to `wp_aieo_sessions_statics` and back-filled by the existing channel-resolution pass. Channel detection was widened too: TikTok (`ttclid` / `utm_source=tiktok`) → **paid_tiktok**, Google's iOS click ids (`gbraid` / `wbraid`) → **paid_google**, while organic Instagram shares (`igshid`) correctly stay **social** rather than being mis-tagged as paid. The browser still receives the full URL, so client-side pixels/trackers are unaffected — only the server-side cache key normalises these params, which is why capturing them here matters.
* **Offer targeting — exclusions now act as a true cart-level veto.** Across Product discounts, Free gifts and Free shipping, when the cart contains *any* product matching an excluded brand / category / need / specific-product, the offer no longer applies at all — exactly as the editor describes ("when the cart contains any product matching one of these, the discount does NOT apply"). Previously an excluded line was merely skipped from the matched subtotal while the offer still applied to the rest of the cart.
* **Offer targeting — the "Specific products" whitelist is now enforced.** An offer that lists specific products only applies when the cart actually contains at least one of them (and a products-only offer targets exactly those products). Previously the positive whitelist was ignored, so a "Brand = MUA, only if SKU-X is in the cart" rule discounted the whole brand regardless of SKU-X.
* **Product discounts now honour exclusions and stop applying conditional rules unconditionally.** The per-product price path now reads every gate field and skips a rule whenever the product itself is excluded; rules that depend on the cart (a minimum qualifying subtotal, or a specific-products requirement) are no longer applied per-product, so a "spend €50, get 10%" promo can never silently discount a €12 cart. (Live cart-level *application* of those conditional discounts remains the next step; until then they simply don't fire rather than firing incorrectly.)
* **Fixed a double-discount on cart lines.** With "apply the discount recipe to the main product price" enabled, a cart line could have the percentage applied twice (once baked onto the cart item, once again when the cart re-read the price), yielding `price × (1 − pct)²`. The redundant cart-item mutation was removed; cart lines are now priced once, through the standard WooCommerce price filters.
* **Free-gift awards respect exclusions and the specific-products whitelist.** A gift is no longer auto-added when the cart contains an excluded product, and a gift that requires a specific product is only granted when that product is present.
* **Brand-only discount ROI attribution fix.** Legacy brand discounts (stored with a single brand id) were being read as "no brand targeting" by the offer-attribution reports and credited against every line of an order; they now resolve to the correct brand.
* **Smarter duplicate detection on save.** Adding a product discount that differs from an existing one only by an exclusion, threshold, scope or specific-products list is no longer mistaken for a duplicate and silently dropped; gift offers are now de-duplicated on save so a double-click can't create two identical rows (which would have stacked the gift).
* **Performance.** Product brand/category/need lookups used by the offer engine are memoised within a request, cutting repeated taxonomy reads during cart and shipping calculation.
* **Archive-query hardening.** Hiding "sample" gift products from shop and search pages no longer appends a `NOT EXISTS` / `!=` meta-query that forced two `wp_postmeta` self-joins on every front-end product query — on large catalogues that could pin the database for minutes. Sample products are now excluded via a cached id list (one indexed lookup, refreshed on product save), with identical visible results.
* **Stock Recovery — windowed vs all-time demand made explicit.** The panel now reports in-store demand for BOTH the recency window (the last N days — the recent, recoverable demand that drives the suggested restock quantity) AND the all-time total since each product went out of stock, clearly labelled on the headline figures and on every row. Previously the prominent number was the all-time-since-OOS total while the suggested quantity was (correctly) based on recent demand, so a product with strong lifetime sales but little recent movement looked inconsistent (e.g. "39 units" but a suggested qty of 1 — because only 2 of those 39 sold within the window). A new windowed in-store-turnover figure backs the headline "in-store sales in the last N days" card.
* **New — Multi-Attribute Variations tool (master-switched).** Under Catalog Sync → Stock Management, a report lists every variable product whose attributes mark **more than one** as "Used for variations" (e.g. Colour × Size) — the setup that, when unintended, multiplies into a combinatorial blow-up of variations (Colour × Size × Material → hundreds of auto-generated combinations) and bogs down the product editor, feeds and stock management. Detection counts the `is_variation` flags in each product's `_product_attributes` and lists them with the flagged attribute names, variation count, SKU and an edit link. A **master switch on the tab** decides whether the store treats this as an error: it is **OFF by default**, so multi-attribute variations are allowed and the report is purely informational — right for shops that sell on two axes such as clothing (colour × size); turn it ON to make the product editor block saving such a product (client-side guard plus a non-destructive admin-notice backstop) and flag them in the report to fix. Catalog Sync was reorganised into a two-column Stock Management / Sync & Feeds layout to house it.

= 6.2 Flat-vitals SKU/barcode sourcing, schedulable predictor, recovery insights (01/06/2026) =

* **SKU & barcode (GTIN) indices moved into the flat product-vitals table.** `sku_index` and `barcode_index` are now precomputed columns on `wp_aieo_core_product_vitals`, rolled up per parent during the variation-combine build step (one `GROUP_CONCAT` per parent over its children), and a `parent_id` index was added. SKU/barcode lookups (e.g. product-meta) now read a single flat row instead of joining the legacy `wp_pods_product_vitals` table — keeping the query off the slow path, per the "always query a flat table" principle. Both the full "Analyze Data" run and the hourly Data-Prep build maintain the columns.
* **Sales / out-of-stock predictor is now schedulable.** The staged (Prepare → batches → Finalize) build that the "Run now" button uses now also drives the *scheduled* run path, so the predictor can be placed on a schedule (WP-Cron / system cron) without the parent-grain pass running long enough to stall. Previously only the manual UI run was batched; the scheduled path used the monolithic build that could hang at scale.
* **Stock Recovery — recovery-value headline card.** A new card sums the in-store sales of products the eshop currently has out of stock, shown alongside the predictor's pessimistic / average / optimistic estimates of the sales value recoverable by restocking them.
* **Missing Hot Sellers — missing-revenue total.** A new card totals the in-store sales currently missing online (products, units, net turnover) so the size of the gap is visible at a glance.
* **Confidence-threshold help.** Every Stock Recovery confidence-threshold setting now has a plain-language hover tooltip explaining what it controls and how to tune it — written to be readable by a non-technical operator.
* **Faster bulk COGS apply.** Bulk cost-of-goods writes now suppress the heavy per-`save()` reindex hooks (search / filtering / marketplace feeds / embeddings) for the duration of the run (with a CLI batch runner for very large catalogues), so applying COGS across thousands of products completes in a fraction of the time instead of re-indexing on every write.
* **Translation fix — bundled translation now wins over an incomplete wp.org pack.** WordPress loads language packs from `wp-content/languages/plugins/` *before* a plugin's own `languages/` dir and returns early, so an incomplete GlotPress pack (e.g. a 10-string Greek pack from translate.wordpress.org) was shadowing our full bundled translation and leaving the admin menus in English. A `load_textdomain_mofile` filter now redirects our text domain to the bundled file whenever we ship one for the active locale; other locales keep using their wp.org packs.

= 6.1 Physical-Demand Recovery + Missing Hot Sellers (31/05/2026) =

* **Stock Recovery (false-OOS).** Mines the physical-store ERP orders to find products the eshop marks out-of-stock that the stores are still selling — a sale dated after the OOS date proves it exists. Optional auto-restock with manager confidence thresholds (min units/days, recency, qty cap, cooldown), respecting each product's existing stock mode. Tracks the eshop sales it recovers (units + net €) and a success/failure precision so the automation can be trusted/tuned.
* **Missing Hot Sellers.** A priority list of SKUs selling well in-store but not live online — auto-imported drafts still needing image/description/categories/brand, or products absent entirely — ranked by physical net turnover, each with a direct "Edit in Woo" link.
* **Catalog Sync** reorganised into a two-column panel: Stock Management / Sync & Feeds.
* **Sales / out-of-stock predictor** "Run now" rebuilt to run in batches so it no longer times out from the admin UI; grain/anchor controls realigned.
* All **Insights reports (wpDataTables)** re-pointed off the legacy Pods/wiz tables onto the clean AIEO schema; added two **Insights-chat skills** (`aieo/stock-recovery`, `aieo/missing-hot-sellers`).
* Fixed a harmless "Duplicate column name 'entry_source'" notice that could appear when deactivating/reactivating the plugin.

= 6.0 Block-checkout COD gating suite, BoxNow Partner API, payment-method reactivity (29/05/2026) =

* **Cash-on-Delivery gating by destination country.** New multiselect inside the COD card (Free Shipping tab) disables the COD gateway for the chosen *billing* countries — driven by the checkout country switcher, so a customer who flips to Cyprus loses COD live, while Greece keeps it. Works on BOTH classic and block (Store API / roosterx) checkout. Because the admin plugin is stripped from the WC Store API whitelist, a runtime delegate (`AIEO_Runtime_COD_Country_Block`) mirrors the server-side gate and a `registerPaymentMethodExtensionCallbacks` `canMakePayment` callback removes COD reactively in the block UI on every country/shipping change — no page reload.
* **COD gating by shipping method / courier.** Same card adds per-courier checkboxes (built from your active table-rate carriers — e.g. tick "Box Now" to forbid COD whenever Box Now is the chosen method). Rate IDs are normalised (the `_rule_{id}` table-rate suffix is stripped) before matching so both table-rate and native method IDs resolve to the right carrier.
* **Per-courier COD fee override.** Each courier can carry its own COD surcharge that overrides the default fee when that method is selected; a `{cod_fee}` placeholder in the COD gateway description resolves to the courier-specific amount. Decimal entry accepts both `.` and `,` (locale-safe `inputmode="decimal"` field, no HTML5 number-step trap).
* **Zero-overhead fast path.** The whole gating layer only registers its filters / enqueues its block JS when at least one country, courier, or fee override is configured — stores using plain default COD pay no runtime cost.
* **Payment Gating (cheque-on-pickup) now works on block checkout** and moved under the COD card on the Free Shipping tab (its standalone tab is gone). Rewritten as a standalone gate (filter priority 1002) with a matching runtime delegate so the Store API path honours it too.
* **BoxNow Partner API driver (full integration).** The Fulfillment BoxNow driver graduated from mirror-only to the real BOX NOW Partner API (manual v7.2): OAuth2 `client_credentials` auth, create delivery-request → parcel voucher, label PDF, cancel, and locker/destination listing. Verified end-to-end on production (create → label → cancel, test parcels cleaned up). The order-edit "Print" action now appears for BoxNow vouchers. Credentials live in the `courier_boxnow` fulfillment settings (never hardcoded); `build_voucher_payload()` now passes `order_id` so the driver can read the customer's chosen locker (`_boxnow_locker_id`).
* **Skroutz / Shopflix feeds — `color` + `additional_image` for the "Μόδα" (fashion) category.** Both fields are now sourced from `wp_aieo_core_product_vitals` and emitted on every product. Skroutz wraps `color` in CDATA (Greek colour names) and emits a self-closing `<color/>` when a product has no colour, satisfying the marketplace's "field present even when empty" rule.
* **Checkout landing message spans the content width.** The landing-message wrapper now carries the theme's `alignwide` class so the callout lines up with the checkout/cart rows below it instead of sitting in a narrower column.
* **Chat model selection — registry-validated save.** Picking a newly released model (e.g. Claude Opus 4.8) no longer silently reverts to the previous choice; the Save handler validates against `AI_eShop_Chat_Model_Registry::is_valid_model()` instead of a hardcoded whitelist.
* **Fatal-error hardening.** Fixed an `array_map(): Argument #2 must be of type array, string given` crash on the chat-model save path, plus four more `(array) sanitize_text_field($_POST[...])` array-swallowing anti-patterns (embedding manager, ratings, TRS zone admin, DMM social login) that mangled array POSTs.
* **Removed the deprecated legacy shipment-tracking module.** AIEO's own Fulfillment tracking fully supersedes it; the orphaned option was cleaned up. No dependency remained.


= 5.10 Shopflix voucher endpoint fix + admin list-table per-page caps (28/05/2026) =

* **Shopflix voucher PDFs now render with the correct layout.** The print endpoint's path placeholder is the `trackingNumber`, not the `orderId` — confirmed by Shopflix support 2026-05-28. We now capture `trackingNumber` from the create response (with an `/orders/{id}` fallback when the shipment already exists) and call print correctly. Vouchers now respect the merchant-portal-selected label format instead of falling back to a wrongly-rotated default.
* **Admin list-table per-page caps.** New card on Tools tab sets a hard ceiling on Screen Options' "Items per page" for the All Orders + All Products lists (defaults 200 / 200). Hooks `get_user_option_edit_orders_per_page`, `…edit_shop_order_per_page`, and `…edit_product_per_page` so the cap applies on read regardless of what's stashed in `user_meta`. Operators below the cap keep their value untouched; only those above (e.g. shop managers running at 500–600) get clamped on the next render. Setting a cap to 0 disables enforcement for that screen.
* **Admin-only with frosted lock-overlay.** The caps card is administrator-only (`install_plugins`, not `manage_options` — many stores elevate shop_manager with the latter). Shop managers see the card with current values but it's overlaid with a frosted "Administrator only" lock; inputs are server-side `disabled` and the AJAX save re-checks the cap so DOM tampering still hits a 403.


= 5.9 AS async runner restored, admin-bar menu, Shopflix error decoder, re-ship of ACS driver (28/05/2026) =

* **Ensures the ACS Courier driver fixes actually ship.** The 5.8 wp.org package was built from a snapshot that predated the ACS driver rewrite; sites updating from 5.8 didn't get the 10 fixes documented in the 5.8 changelog. 5.9 re-bundles them properly. If you're on 5.8 and your ACS vouchers were still mis-printing (`Weight: 5,00`, `COD: 602,00`), update to 5.9 — that's the fix.
* **Action Scheduler async runner re-enabled.** Pending actions now drain continuously instead of waiting for the 5-minute system-cron window. AS's own background AJAX runner is allowed to fire on every page load; regular page rendering stays unaffected (concurrent_batches=0 on web). One prod site went from 150 overdue actions to 81 in under a minute after the fix; the queue stays near-empty under normal load now.
* **Admin-bar menu — quick-jump from any page.** The "AI Optimizer" icon now appears in the WordPress admin toolbar with dropdown shortcuts to Data Prep, e-shop Manager, and AI Chat. Saves the operator a sidebar-scroll on every screen.
* **Shopflix accept errors are now human-readable.** The Shopflix API returns errors under `error.message` + `error.code`, but our parser was reading `error.errorMessage` and falling back to the useless "HTTP 400". Now surfaces the actual ACS-style message ("Cannot Accept Order (10303)" etc.) so operators know whether to retry, contact Shopflix support, or skip the order.


= 5.8 COD surcharge fix, Skroutz webhook repair, ACS Courier driver rewrite, AS dedup hardening (24/05/2026 - 26/05/2026) =

* **COD gateway force-visible when AIEO COD enabled.** Pre-empts WC's "Enable for shipping methods" whitelist and any third-party filter (Box Now, COD-Plus) that hides COD based on shipping method. Runtime + admin both updated.
* **COD fee now overwrites a legacy fee with the same label** instead of skipping via idempotency. Operator-set €X is authoritative.
* **Marketplace Order Importer — Skroutz webhook repaired end-to-end.** Parser accepts both wrapped `{event_type, order:{…}}` and flat `{event_type, id, code, …}` payload shapes; falls back to `order.code` when Skroutz omits the numeric `id`; uses Skroutz's current line-item field names (`product_name` / `unit_price` / `total_price`); Mapper survives orphaned product references via try/catch + free-form line-item fallback.
* **MOI — `REGISTERED` added to Accept/Reject button allowlist** so Shopflix orders in the initial state actually show the action buttons.
* **ACS Courier driver — complete rewrite of request shaping and response parsing.** Ten fixes audited against the official ACS Rest API docs: full envelope preserved (so `ACSExecution_HasError` + per-row `Error_Message` reach the operator UI); response traversal corrected; address split into street + number; Greek phone landline/cell split with `+30` stripping; `Charge_Type` defaults to `2`, auto-switches to `4` when COD; `Acs_Delivery_Products` auto-appends `COD` when `cod_amount > 0`; print uses the correct `ACS_Print_Voucher` alias and decodes the base64 PDF; cancel uses the correct `ACS_Delete_Voucher` alias; `Weight` + `Cod_Ammount` now sent as JSON numbers (was being parsed by ACS with Greek locale, multiplying decimals by 10 on the printed label).
* **Recompute queue — atomic dedup at the AS schedule layer.** New `pre_as_schedule_*` filters with MySQL `GET_LOCK` short-circuit `as_schedule_*` calls when a pending/in-progress action exists. Closes the dedup-bypass that let parallel recurring chains accumulate (one prod site had 225 pending ticks for a single hook before the fix).
* **Session Tracker — defensive add-to-cart handler.** Guards `$button.*` access and falls back to page context when callers fire `added_to_cart` without the 4th `$button` arg. Fixes the spinner-stuck symptom on the swatches bulk-add path.
* **Fulfillment vouchers — `postal_code` column** stored at voucher creation. Migration is idempotent and runs on plugin upgrade.
* **Stock import — UTF-8 BOM stripping, Windows-1253 / ISO-8859-7 transcoding, headerless-CSV autodetection.** Greek-locale Excel exports now import without manual conversion.
* **Price export — Stock column + Vitals fast-path.** Reading from the vitals cache turns a 90-minute export on a 25k-SKU catalogue into about 2 minutes; Live path unchanged.
* **Marketplace feeds — field parity with the wpwoof reference + universal `?cf-no-cache=1` cache-bust on every emitted URL.** Fixes the long-standing `g:price` bug that was emitting the sale price instead of the regular price.
* **Geniki — monthly invoice CSV reconciliation.** New card on Fulfillment → Reports. Matches invoice rows to voucher rows; surfaces orphans either direction. Pattern is carrier-agnostic; Geniki is the first integrated.
* **Bulk fulfillment actions — memory-protected.** Lifts the practical limit from ~40 orders to 200–500+ depending on the carrier API.
* **WC 10.9 compat migration — infinite-loop fix.** Replaces the broken "_product_image_gallery missing" gate with explicit `_aieo_variation_migrated` markers (one prod site ran the loop 153,219 times across 2.5 days). New operator UI in DMM → Variations gallery exposes the migration state.
* **Variation image storage — WC 10.9 two-hop join.** Vitals SP now resolves variation `imagepath` via `_product_image_gallery` → `_thumbnail_id` → parent featured. Fixes the "variation image renders as the 40×40 swatch chip" regression.
* **Star rating CSS — mobile non-FSE alignment + caption wrap.** Defeats Botiga's universal `button { min-width: ... }` rule that pushed empty stars onto a second row on mobile.


= 5.7 Runtime-only brand blocks + engagement-gated Web Push + admin polish (24/05/2026) =

* **Web Push — engagement-gated opt-in banner (Chrome quiet-UI mitigation):** the banner no longer mounts on a flat 10-second timer. It now waits for AIEO Session Tracker to dispatch an engagement milestone (2nd page-view in session, 25% scroll, add-to-cart, 30s on page, etc.) before asking for permission. Chrome's quieter notification UI auto-denies prompts on domains with low acceptance rates; asking bounce visitors poisons that reputation. By only prompting engaged visitors, the per-prompt acceptance rate climbs and Chrome's quiet UI fires less aggressively over time. Hard-cap fallback at 90s so visitors who never hit a milestone but stay around still see the banner. Falls back to the original flat-timer when AIEO Session Tracker is disabled (no install regresses). The "Show delay (ms)" admin setting becomes a minimum-wait floor.
* **Brand blocks now exposed to runtime — admin plugin no longer required on storefront pages that render them:** the six `aieo/brand-*` server-rendered blocks (A-Z directory, slider, rails, related, archive-hero, story) are registered by a new runtime delegate at init priority 29, so pages with brand sliders / related-brands rails / brand A-Z directories render correctly even when admin isn't in the request's plugin whitelist. Single source of truth — block.json + render.php stay in admin; `AIEO_Core_Brand_Vitals` autoloads via the mu-plugins autoloader. Admin's block loader now checks `WP_Block_Type_Registry::is_registered()` before its own registration so the runtime + admin paths coexist with no duplicate-registration notices.
* **Fix — Session Tracker JS 404 on every front-end page:** the `aieo-session-tracker.js` asset was left in the admin plugin when the `AIEO_Session_Tracker` class moved to the runtime plugin (Phase 1.5). Browsers logged "Refused to execute script ... MIME type 'text/html' is not executable" on every page load. The JS now ships in both plugin directories so the runtime-first autoloader path finds its own asset.
* **Critical fix — Web Push opt-in pipeline broken by three unrelated layers:** WP Rocket's "Delay JavaScript execution" was treating the opt-in script as load-on-interaction (silent fail for bots / remote-desktop / deep-link visitors); Edge's Tracking Prevention threw on `localStorage.getItem()` killing the IIFE; an infra-level Nginx config gap returned HTTP 404 for `/aieo-push-sw.js` causing SW registration to crash. All three fixed in code: plugin auto-injects WP Rocket exclusions via `rocket_delay_js_exclusions`, JS wraps storage access in try/catch, install doc §4 covers the Nginx block. Added a silent re-subscribe path so historical "permission granted but never POSTed" users heal themselves on next page load.
* **Data Prep Schedule — `product_attributes` stage added:** the hourly data-prep cron now runs an extra stage between `category_hierarchy` and `product_vitals` that calls `AIEO_InsertCoreProductAttributes` with the operator-configured brand / vendor / size / colour attribute taxonomies — resolving parent `brand_id` from term assignments. Brand blocks now populate automatically every hour without the operator needing to manually tick "Please recreate the product core attributes and principal categories" in the Operational Efficiency Settings UI (that checkbox stays available for manual full-rebuild interventions). Variations continue to inherit brand via the existing `propagate_brand` stage.
* **Data Prep Schedule — Notes column:** the Last-run table now shows per-stage metrics (e.g. "194 brands w/ products · top: NIOBE (307)", "45414 eligible across 1 surfaces") so operators can see at a glance what each stage actually produced.
* **Google Reviews — single-location auto-fallback + clearer empty states:** the `aieo/google-reviews` block in "Single location" mode now auto-uses the operator's only configured location when exactly one exists, so single-store SMB clients no longer need to pick a slug for every block instance. Multi-location merchants get a count-aware error message that steers them to either pick a slug or switch to All-locations / Cards-grid mode. Replaces the cryptic "Set a location slug, or place this block on a page bound to a location row" empty state.
* **Google Reviews — shortcodes for non-FSE themes:** the `aieo/google-reviews` block now has shortcode counterparts so classic themes / widget areas / page-builder pages can render Google Reviews without FSE block-template editing. `[aieo_google_reviews]` (all locations mixed by default, or `location="downtown"` for a single store) and `[aieo_google_locations_grid]` (per-location cards grid). Both delegate to the same `render()` method the block uses — identical markup, cache, and CSS handle.
* **Admin polish:** Database Performance Optimization card now interpolates the actual detected version ("MariaDB 11.8.7 detected!") instead of the hardcoded "MariaDB 11.4+ detected!". Google Reviews → Locations admin no longer ships Femme-Fatale-specific placeholder text (`piraeus` slug, `Femme Fatale Πειραιάς` display name) — replaced with generic translatable strings (`e.g. main-store, downtown, branch-2`, `Customer-facing label for this location`).


= 5.6 Fulfillment polish + two production hotfixes + CSV round-trip cleanup (23/05/2026) =

* **Production hotfix:** site-wide HTTP 500 on category pages caused by `Undefined constant "AIEO_VERSION"` in the Runtime wishlist enqueue. Defensive `defined()` fallback chain added so the runtime survives a partial-bootstrap load order. Surfaced on prod femme-fatale.gr `/me-ammonia/` immediately after the 5.5 upgrade.
* **Performance:** AIOSEO Pro's Product schema graph is now suppressed on archive and taxonomy pages. AIOSEO was iterating every product in the loop and calling `$product->get_available_variations()` once per row, which on Iconic Variation Swatches triggered a `$wpdb->get_results()` per variation — ~900 queries to render one category. Single-product pages keep the full JSON-LD (where Google rich results actually matter). Measured render time on `/me-ammonia/`: 9.4s → 3.2s.
* **Fulfillment — order edit:** Add Voucher carrier dropdown now lists only enabled carriers (was showing every registered carrier including disabled ones). The carrier mapped to the order's shipping method is pre-selected on open. Button labels are now mode-aware ("Save tracking" / "Generate voucher", paired with "+ mark completed" variants for the single-click flow). Pressing Enter in the tracking-number input no longer submits the outer order form and navigates to Downloaded products. Custom carriers with no API integration (`create_mode = 'manual'`) now persist the tracking number and fire the customer email instead of erroring with "driver does not support create_voucher".
* **Fulfillment — Carriers without API:** inline Edit button next to Remove on every row. The operator-saved `tracking_url_template` field is now honored when the driver builds the public tracking URL (was being silently ignored). New `aieo_custom_carriers` filter lets themes / plugins register carriers from `functions.php`, mirroring WooCommerce Shipment Tracking's `wc_shipment_tracking_get_providers`.
* **Fulfillment — Settings:** new "Backfill customer shipping paid" card — one-shot retrospective pass that populates `_aieo_customer_shipping_paid` on historical orders so Shipment Cost reports' income column is filled for past periods, not only orders placed after cost tracking went live.
* **Shipment Cost reports:** sortable column headers on the results table — click to sort by orders / income / our cost / free-shipping subsidy.
* **Role-based pricing CSV — round-trip cleanup:** import strips a leading UTF-8 BOM (Excel-on-Windows leaves one — was producing false "must include sku column" errors). Import auto-detects the separator (`,` / `;` / `\t`) by counting candidates in the first line, so Greek-locale Excel exports work without manual conversion. Import error messages now state the detected separator and the parsed header row. Export no longer prepends a BOM, so cross-environment round-trips and `cat` / `awk` / `diff` stay clean.
* **Critical fix — Social Login settings silently wiped on Save:** the Social Login admin tab's save handler used the `sanitize_text_field( $array )` anti-pattern to validate the POSTed `providers` and `intents` arrays. Because `sanitize_text_field()` on an array returns an empty string, the validity check was always false and every Save click overwrote the saved configuration with empty providers + every-intent-off. Symptom: operators enabled Google / Facebook / etc. for login / checkout / my-account, clicked Save, got a success toast — and the buttons never appeared on the front-end because the DB row was blank. Re-enter the Social Login settings once after upgrading.
* **Marketplace Order Importer — webhook setup guide on the Vendors tab:** every vendor whose provider accepts a webhook URL now gets a "Setup help" card showing the URL prominently with a one-click Copy button, deep-links to the exact merchant-panel page, names the field to paste it into, and walks through the rest. For Skroutz: includes the deactivate-the-legacy-WPSlash-plugin reminder. Poll-only providers (Shopflix, eMag) skip the card — nothing for the operator to do.
* **Marketplace Order Importer — webhook tokens derived from your Rooster API key:** new vendors get a stable, install-unique webhook URL by default (`substr(hash('sha256', $rooster_key . '|moi-webhook|' . $vendor_slug), 0, 20)`). Hashing means the token never exposes any portion of the Rooster key, while being regenerable from the Rooster key alone — losing the vendor row no longer means re-pasting random tokens into every marketplace panel. Existing vendors keep their current tokens; a "Use Rooster-derived token" button on the setup card migrates them on demand.
* **Product Display — classic-theme info-column ordering:** the operator-saved Display Order (Product Meta / Payment Logos / Trust Badges / …) was only honored on FSE themes; on classic themes those three modules were hardcoded to WC `woocommerce_single_product_summary` priorities 30 / 35 / 40 so Product Meta always rendered last regardless of operator intent. Classic themes now re-prioritise the callbacks per the saved order, mirroring the recommendations-ordering pattern.
* **Deprecation notice:** the `AIEO_DMM_Shipment_Tracking` module is renamed to "Shipment Tracking (legacy)" in the admin sidebar with a yellow deprecation banner. The new Fulfillment → Carriers system supersedes it end-to-end; the legacy module will be removed in a future release.


= 5.5 WooCommerce 10.9 ready + critical variation-attribute wipe fix + third-party gallery filter (23/05/2026) =

* **Critical fix:** products whose variation attribute is type Image or Button no longer lose their variations when the parent product is saved. A long-standing bug silently dropped the "Used for variations" flag on save, making variations disappear from the editor (and from the customer's view). One-shot auto-repair on upgrade reconstructs the missing declaration from each variation's stored attribute, so already-broken products heal automatically when the new version activates.
* **Forward-compatible with the upcoming WooCommerce core variation features:** when WC 10.9's experimental "Variation gallery" and "Color swatches for attributes" toggles roll out (Settings → Advanced → Features), AIEO's data is already in WC's canonical place — no migration window, no operator action, no broken stores. AIEO continues to render videos and gradient / multi-colour swatches that WC core doesn't support.
* **New filter for custom variation-gallery storage:** sites that store variation images outside AIEO's default keys — Iconic Variations, the retired WooCommerce.com Additional Variation Images extension, custom themes — can now hook `aieo_variation_gallery_image_ids` from `functions.php` to point AIEO at their storage. One filter covers the admin picker, the front-end gallery block, marketplace feeds, and the import/export round-trip. Full documentation in the plugin's `docs/FILTER_VARIATION_GALLERY_IMAGE_IDS.md`.
* **Marketplace feeds now ship variation gallery URLs:** Google Shopping `g:additional_image_link`, Skroutz `<additional_image>`, Shopify `images` and Facebook Catalog all pick up the full per-variation gallery automatically.
* **Custom carriers — inline Edit + new `aieo_custom_carriers` filter:** the "Carriers without API" table in Fulfillment settings now has an Edit button next to Remove (label + tracking-URL template editable in place, slug preserved). A new `aieo_custom_carriers` filter lets themes/plugins register carriers from `functions.php` — same pattern as WooCommerce Shipment Tracking's `wc_shipment_tracking_get_providers`.
* New `wp aieo migrate wc-compat` WP-CLI command for manual / observable re-runs of the WC-compat migration.
* Tested with WooCommerce 10.9-dev nightly; declared compatible with WooCommerce 10.9.


= 5.4 Skroutz Smart Cart Orders API + legacy importer (23/05/2026) =

* Receive Skroutz Smart Cart orders directly in WooCommerce — accept, reject, and mark ready-for-dispatch from the order edit screen, with the courier voucher pulled in automatically.
* Import historical Skroutz orders from the older `skroutz-marketplace-xml-for-woocommerce` plugin in one click, into the same unified marketplace inbox.
* Declared compatible with WordPress 7.0.


= 5.3 Marketplace category mapping, fulfillment overhaul, custom carriers (22/05/2026) =

* Map your WooCommerce categories once to Google + Facebook product taxonomies — the mapping cascades to every product and every relevant feed automatically.
* Four new marketplace feed templates: Facebook Product Catalog, Facebook Marketplace, Amazon Inventory Loader, eBay File Exchange. Google Shopping template substantially richer.
* Orders list rebuilt for warehouse pickers — one-click Packing Slip / Voucher / Invoice buttons per row, with print-tracking colour states; voucher modal pre-fills the carrier based on the order's shipping method; "Notify customer" sends a tracking-link email in the same click.
* Add unlimited "Carriers without API" yourself (just a label + tracking URL template) and link each one to a WooCommerce shipping method.
* Packing slip template redesigned for warehouse pickers — order number as the header, cash-on-delivery highlighted in red, SKU-sorted line items so the picker walks the shelf in order.


= 5.2 Export-lock hotfix + maintenance (22/05/2026) =

* Customers now see live shipment tracking in their order emails, on the my-account page, and in newsletter campaigns (new `[aieo_tracking_block]` shortcode for newsletters).
* Marketplace feeds and the data-prep pipeline now hold per-job locks — concurrent runs no longer duplicate jobs or corrupt rebuilt tables.
* Historical marketplace orders pulled via Reconcile land as `completed` (so they don't clog operator queues) and never fire customer emails.
* Verified clean-install on WordPress 7.0 + WooCommerce 10.7.


= 5.1 Custom Slots, Recommendations Ordering, WP 7.0 hardening (21/05/2026) =

* Custom Slots — add Tolstoy widgets, embed scripts, or any HTML / shortcode block alongside the built-in product-page recommendation rails.
* Drag-and-drop Recommendations Ordering — reorder Up-sells, Cross-sells, Related, Recently Viewed and Same Needs (plus your custom slots) on every product page. Works identically on FSE and classic themes.
* Tolstoy carousel clicks now attribute cross-tab into your add-to-cart analytics.
* WooCommerce block-based cart and checkout reach feature parity with the classic shortcodes.
* Critical post-WordPress-7.0 cache purge — clears stale serialised core-class transients that were crashing sites with out-of-memory errors after the WP 7.0 upgrade.


= 5.0 Insights Chat, Attribution Engine, Retention & Pro Tier (15/05/2026) =

** 🎯 MAJOR RELEASE: Conversational Analytics, Joint Session × Attribution Intelligence, and the Pro Tier **

This release is the largest single update to AI eShop Optimizer to date. Three months of work consolidate into four product-level deliverables: an in-admin Claude-powered Insights Chat with 33 purpose-built data abilities; a Session-Tracker × Attribution-Engine bridge that unlocks joint analytics across engagement, conversion, blog content, and customer needs; a four-layer retention strategy that keeps the local database under 1 GB indefinitely while streaming the full event history to an operator-owned analytics database; and a formal Pro-tier gating layer with frosted-glass overlays on the thirteen tabs that are now membership-only.

** 💬 Insights Chat — Claude-powered, in-admin **
* NEW: AIEO_Merchant_Chat — in-admin chat page under Tools → Insights Chat, powered by the existing AI Chat Anthropic API key (no separate subscription)
* NEW: 33 purpose-built Claude abilities registered via the WordPress Abilities API, discoverable at /wp-json/wp-abilities/v1/abilities
* NEW: Categorized accordion suggestion chips covering 11 question groups — Customers, Brand portfolio, Recommendation rails, Attribution & archives, Product needs audit, Star ratings, Content & blog, Cross-skill, Store analytics, Promotions / launches / sales, Newsletters & campaigns
* NEW: Tool-use loop with bidirectional slashless tool-name mapping (aieo/list-brands ↔ aieo_list_brands) for Anthropic compatibility
* NEW: Translated suggestion chips for sales-per-view ratio, new-product performance, complementary-product impact, sale-period products, newsletter × needs correlation, abandoned-cart triage, blog-to-product conversion, and engagement-bucket buy-probability
* NEW: Server-side ability execution with manage_woocommerce capability gating; permissions enforced before every tool call

** 🔗 Session Tracker × Attribution Engine Integration **
* NEW: AIEO_Session_Attribution_Bridge — query helpers that JOIN wp_aieo_sessions × wp_aieo_addcart_events × ratings × needs by session_id and product_id
* NEW: AIEO_Conversion_Probability_Model — engagement-bucket conversion table; scores the current session's P(cart-add) based on scroll depth, time on page, and mouse activity
* NEW: 'blog_post' added to AIEO_Attribution::VALID_SOURCES — clicks from blog posts to products now attribute correctly with source_meta.post_id
* NEW: Blog-post detection in aieo-attribution-client.js (body.single-post / article.post)
* NEW: 11 new abilities — aieo/attribution-with-engagement, aieo/addcart-funnel, aieo/blog-engagement-leaderboard, aieo/blog-to-product-conversion, aieo/buy-probability-by-engagement, aieo/buy-probability-leaderboard, aieo/abandoned-cart-triage, aieo/cart-removal-analysis, aieo/rating-conversion-correlation, aieo/need-conversion-correlation, aieo/top-converting-pairs
* Improved: AIEO_Attribution::log_event() now respects AIEO_Session_Tracker consent state (GDPR alignment — previously wrote regardless)
* Improved: session_id validity guard in log_event() prevents the "session_id = 1" regression we hit in May
* Improved: Both engines key off the same aieo_session_id cookie; documented in the bridge's contract

** 🗄️ Four-Layer Retention Strategy & Remote DB Streaming **
* NEW: AIEO_Remote_Export_Manager — streams raw analytics events to an operator-owned MariaDB / MySQL via the existing AIEO_ERP::for_connection_id() factory
* NEW: AIEO_DMM_Remote_Export module ("Insights Remote DB Settings" tab) — admin UI for picking connection + tables + export frequency, dry-run "Test export" button, per-table lag dashboard
* NEW: aieo_remote_export_run cron with configurable frequency (15 min / hourly / daily)
* NEW: wp_aieo_remote_export_state bookkeeping table — one row per (connection_id, table_name) tracking last_exported_ts
* NEW: Idempotent INSERT IGNORE on the remote so repeated runs never duplicate
* NEW: 5 pre-aggregated daily rollup tables — wp_aieo_engagement_daily, wp_aieo_attribution_daily, wp_aieo_conversion_buckets, wp_aieo_blog_engagement_daily, wp_aieo_cart_removal_daily
* NEW: aieo_aggregate_rollups nightly cron — chat abilities query the rollups, never the raw event tables, keeping admin response times in the single-digit milliseconds
* NEW: Tightened hot retention — 14 days for wp_aieo_sessions, 30 days for wp_aieo_reco_events, 365 days for wp_aieo_addcart_events (cart-adds are conversion evidence and kept longer)
* NEW: aieo_archive_run unified archive hook generalises the existing weekly cron to cover AE + reco event tables alongside sessions
* NEW: Local-purge failsafe — hot rows are NOT deleted until the remote-export bookkeeping confirms the row was received, preventing data loss when the remote is briefly unreachable
* Improved: Net stable DB footprint ~1.1 GB regardless of how many years the plugin has been running (was unbounded — wp_aieo_sessions alone projected to hit 6-8 GB by year 2 before this work)

** 🌟 Star Ratings → SEO Schema Bridge **
* NEW: AIEO_Ratings_Schema — bridges AIEO star ratings into AIOSEO, Yoast, and RankMath JSON-LD via their schema filter hooks (aioseo_schema_output, wpseo_schema_product, rank_math/snippet/rich_snippet_product_entity)
* NEW: Fallback head-injected JSON-LD aggregateRating when no SEO plugin is detected
* NEW: Enable/disable toggle on the Star Ratings admin page (seo_schema_enabled setting)
* Improved: Pages now surface aggregateRating to Google Rich Results without the operator needing to manually configure each SEO plugin

** 🛒 Floating Mini Side-Cart, Sticky ATC & Free-Shipping Bar **
* NEW: AIEO_DMM_Side_Cart — two-column floating mini-cart styled after the Rey theme: left column "You might like" recommendations, right column Shopping Bag / Recently Viewed tabs, free-shipping progress bar right under the tab header, ± quantity stepper per line, SUBTOTAL + coupon + CART / CHECKOUT buttons
* NEW: Fast-path cart updates — 500 ms debounced quantity AJAX → 400-byte JSON → optimistic client-side bar recompute → no full cart recalculation on the server. Session-level HTML cache keyed by cart_hash (30 s TTL). WC fragments integration keeps every other widget in sync
* NEW: Side-cart recommendations sourced from the DMM product-bundle endpoint so the same cached HTML powers the product page AND the mini-cart
* NEW: Brand-gift lines get locked-qty / hidden-remove-link treatment — same UX as the Brand Gifts module already applies to the standard WC cart page
* NEW: AIEO_DMM_Sticky_ATC — sticky Add-to-Cart bar (DOM classes + JS global kept verbatim so the shipped CSS/JS bundle works without modification)
* NEW: AIEO_DMM_Free_Shipping admin — threshold + product / brand exclusions; registers the package-rates filter that strips free-shipping rates when any excluded item is in the cart

** 💰 Pricing Engine — Role Pricing, Brand Discounts, Loyalty Classes **
* NEW: AIEO_DMM_Role_Pricing — per-role price overrides via CSV upload; staged batch validation → AJAX batches process rows into wp_aieo_dmm_role_prices; mirrors into the legacy wp_om_role_based_pricing table so the existing om-role-pricing frontend keeps working byte-for-byte
* NEW: AIEO_DMM_Brand_Discounts — % discounts per brand term with optional date window; read by the pricing engine at runtime
* NEW: AIEO_DMM_Loyalty_Classes — loyalty class definitions + user assignments applied in the global pricing recipe by AIEO_DMM_Pricing_Engine
* NEW: Pricing engine evaluates Role Pricing → Brand Discount → Loyalty Class as a stacking recipe so each customer sees the strongest applicable price

** 🎁 Conversion Boosters — Brand Gifts & Exit-Intent **
* NEW: AIEO_DMM_Brand_Gifts — brand-based free-gift offers stored in wp_aieo_dmm_brand_gift_offers; cart-side hooks add a gift (price = 0) when cart subtotal of the offer's brand(s) crosses min_subtotal within the date window. Bypasses the is_purchasable filter for programmatic gift adds so sample-flagged products work
* NEW: AIEO_DMM_Exit_Intent — configurable modal that fires on cursor exit-intent after a per-page warm-up delay. Two HTML bodies: a generic site-wide offer + an upgraded checkout-specific offer. Optional restriction to checkout-only and/or anonymous visitors. Session-storage dismissal so it doesn't reappear in the same browsing session. Excludes the order-received endpoint (post-purchase context defeats the offer)
* NEW: AIEO_DMM_Exit_Intent auto-imports legacy options from the standalone `exit-intent-offer` plugin on first read and deactivates it — operators don't need to migrate by hand

** 📦 Marketplace Connectors & Shipping **
* NEW: AIEO_MOI_Admin (Marketplace Order Importer) — pulls Skroutz / e-shop / Amazon orders into WooCommerce as native orders so attribution, stock, customer profiles, and fulfillment stay unified. Webhook + manual reconcile flow with vendor-namespaced order meta. Inbound-log table with 30-day retention and visible event detail (last 200 events surfaced in the admin)
* NEW: Per-vendor webhook URLs with rotatable tokens, configurable SKU strategy (SKU / product post ID / custom postmeta key), default order status per vendor
* NEW: AIEO_DMM_Marketplace_Feeds — streaming feed generator that handles 35k-product catalogues without blowing memory. Per-feed cron registration on save; include/exclude rules by product or brand ID; XML or CSV output; configurable field map and target path
* NEW: AIEO_DMM_Shipment_Tracking — cleans up the WooCommerce Shipment Tracking provider list, drops the US/UK/Canada/Germany carriers we never ship to, adds the Greek + Cypriot carriers + Stoferno.gr that the WC plugin doesn't know by default. No-op if the WC Shipment Tracking plugin isn't installed
* NEW: AIEO_DMM_Smart_Shipping_Label — table-rate aware checkout shipping label. Guests / postcode-less carts see "Carrier (Από €X.XX)" with the minimum rate from the table-rate config — so they know shipping isn't free without seeing a misleading default. Once a real postcode is entered, exact rates appear (standard WC behaviour). When the cart qualifies for free shipping, method prices are hidden and only the carrier name is shown — and the generic "Free shipping" pseudo-method is removed (customer still picks a real carrier, just with €0). Greek postcodes formatted "184 53" auto-normalize to "18453"

** 👥 Customer Intelligence + Web Push + Voice-of-Customer **
* NEW: AIEO_DMM_Web_Push — Customer Intelligence + Web Push module. Reads from AIEO's pre-built snapshot tables (wp_aieo_temp_orders / wp_aieo_YYYY_MM_orders) rather than re-querying HPOS from scratch, so the omnichannel customer view (eshop + in-store merged in step 6 of the data-prep pipeline) is the source of truth
* NEW: wp_aieo_customer_intelligence (schema v2) — keyed by eponymous_id (AIEO's canonical customer identity), with secondary wp_user_id and source_table columns so anonymous → logged-in stitching has a single home
* NEW: aieo_sp_recompute_customer_intelligence_batch stored procedure — chunked recompute over the chosen snapshot table; "Recompute now" admin button + top-50-by-LTV preview table for sanity-checking before push campaigns go out
* NEW: Behavioural segments derived from the intelligence table — Top customers, Lost cohort, Lookalikes, Abandoned-cart, reactivation
* NEW: Triggered web-push flows — welcome, reactivation, price-drop, back-in-stock — with full dispatch log + per-subscriber delivery + click attribution
* NEW: AIEO_DMM_Surveys — Customer Survey Intelligence. Two-tier model: wp_aieo_survey_responses (mirror of Gravity Forms entries 18 + 20) + wp_aieo_survey_intelligence (per-customer aggregation + composite Voice-of-Customer score). 7 high-signal metrics tracked: nps_class (promoter/passive/detractor), overall_satisfaction (1-5), is_professional_verified, personal_priorities (prices/quality/speed/etc), discovery_channel (store/google/ad/wom/multi), gift_category_preference, personal_profile (hair/eye/skin/silhouette/height)
* NEW: Survey ingest happens three ways — gform_after_submission hook (real-time), daily WP-Cron (safety net), "Ingest now" admin button (manual trigger). Surveys table is the ONLY place we touch Gravity Forms tables
* NEW: voc_score (0-100) per customer derived from NPS + satisfaction + UX average + repurchase intent
* NEW: AIEO_DMM_Waitlist — "Notify me when back in stock" subscription. Out-of-stock product pages render the signup form; jQuery keeps the form in sync with variation changes. Stock watcher hooked on woocommerce_product_set_stock_status — when a product flips back to instock, emails every subscribed row and marks them notified. One-shot migration from the legacy wp_om_ppe_waitlist table. Legacy AJAX endpoint kept as a compat shim so cached HTML from the PPE era keeps working
* NEW: AIEO_DMM_Wishlist (analytics) — read-only admin views over wp_aieo_wishlist answering: how many items sit in wishlists right now, which products are most-wishlisted, which surfaces drive wishlist adds (source_type breakdown), which specific pages / categories drive them (source_id + source_name)

** 🔒 Pro Tier — Frosted-Glass Overlays on 13 Admin Tabs **
* NEW: AIEO_DMM_Module_Base::is_pro_locked() + get_pro_promo() — extension points subclasses override to lock a tab behind the Pro membership
* NEW: AIEO_DMM_Module_Base::render_pro_locked_screen() — Apple-glass frosted overlay with PRO badge, custom title + description + bullet list per feature, "Upgrade to Pro" CTA pointing at rooster.systems/get-aieo/
* NEW: Pro overlay on 13 tabs — Attribution Dashboard, Advertising Campaigns (Attribution group), Web Push, Customer Intelligence Surveys, Insights Chat, Shipment Cost Reports, Insights Remote DB Settings, Action Scheduler Cleanup, ERP Bridge, ERP Database, Order Documents & Couriers (Fulfillment), Marketplace Order Importer, Branch Stock Scanner, Order Cancellations
* NEW: Each locked tab carries its own promo copy — title, 1-paragraph description, 3-4 bullet feature list — so the upsell is feature-specific, not generic
* Improved: Locked tabs do NOT execute the real render_subtab() — no heavy backfills, no credential exposure, no database queries fire for non-Pro operators

** 🔑 Single Canonical Pro Detection Helper **
* NEW: AIEO_DMM_Module_Base::is_aieo_pro_user() — single source of truth for "is the operator on Pro?"
* NEW: Recognises BOTH licensing paths — (1) logged into eshop-optimizer.com with Pro membership, or (2) connected to rooster.systems via the Content Connector API key. Either is sufficient
* Improved: Refactored inline duplicates in assets/pages/ai-eshop-chat.php and assets/pages/ai-eshop-optimizer.php to call the helper — no more copy-pasted option-pair checks scattered across admin pages

** 🧭 Attribution Menu Restructure **
* NEW: New top-level "Attribution" menu group at priority 50 (between Customer Profiling and Storefront Display)
* Improved: Attribution Dashboard moved into the Attribution group (was a standalone top-level pill)
* Improved: Advertising Campaigns moved from Pricing & Offers into the Attribution group — same dropdown as the dashboard it shares data with
* NEW: Campaigns auto-populate from utm_campaign via AIEO_DMM_Campaigns::touch() — operator never has to pre-register campaigns; new slugs appear as auto_draft rows the next time the dashboard renders
* Improved: AIEO_Attribution::backfill_session_channels() now calls touch() on every newly-resolved campaign slug; promo_surfaces stay in Pricing & Offers via the existing alias map

** 🗣️ Greek Translation Pass + i18n Hygiene **
* NEW: All 11 admin-navigator group labels wrapped in __()
* NEW: All Pro-overlay strings translatable — PRO badge, "Upgrade to Pro" CTA, every locked-tab title/description/bullet
* NEW: All Insights Chat suggestion chips translatable per accordion group
* Improved: 117 i18n errors fixed across the plugin
* Improved: Greek (el) .po updated to cover the ~70 new msgids introduced by this release

** ✅ Plugin-check & Security Hygiene **
* Improved: Plugin-check ERRORs reduced from 132 to 0 (excluding the agreed-upon DB stored-procedure rules — these are intentional by design and acknowledged in writing by the WordPress.org plugin review team)
* Improved: 27 files received documented phpcs:disable headers with explanatory comments for the exceptions
* Improved: All AJAX handlers route through a centralised nonce verifier; admin GET reads on capability-gated pages remain nonce-free per the documented exception
* Improved: All $wpdb interpolations either use $wpdb->prepare or hardcoded $wpdb->prefix-derived table names
* Improved: Secure-by-default: every new DB-touching ability has min/max input bounds and sanitize_key on all string keys

** 📐 Architectural Improvements **
* NEW: Module V2 manifest pattern — data/admin/frontend/compute split scaffolding (Phase F of the architectural reset; migration is opt-in per module, no forced sweep)
* NEW: docs/v2-pattern.md documents the V2 layout for future module migrations
* NEW: docs/BUILD_AND_DISTRIBUTION.md documents the SVN deploy workflow and the .distignore mechanism
* NEW: .distignore file at plugin root — excludes dev tooling, internal docs, the Claude Code skill pack, and editor metadata from the wp.org distribution package while keeping everything in Git for development
* Improved: includes/ runtime path now contains only loadable PHP — the inline _v2_pattern.md was moved to docs/

** 🗂️ Database Changes **
* NEW: wp_aieo_remote_export_state — bookkeeping for the streaming export (connection_id, table_name, last_exported_id, last_exported_ts, last_status, last_error)
* NEW: wp_aieo_engagement_daily, wp_aieo_attribution_daily, wp_aieo_conversion_buckets, wp_aieo_blog_engagement_daily, wp_aieo_cart_removal_daily — pre-aggregated rollup tables consumed by the new abilities
* Improved: wp_aieo_addcart_events.source enum widened to include 'blog_post'
* Improved: New indexes on (date, product_id) and (date, source) for every rollup table

** 📁 New Files **
* includes/chat/class-aieo-merchant-chat.php — in-admin Insights Chat
* includes/dmm/modules/class-aieo-dmm-insights-chat.php — DMM wrapper delegating to the merchant chat
* includes/dmm/modules/class-aieo-dmm-remote-export.php — Remote DB streaming admin
* includes/claude/class-aieo-claude-bootstrap.php — registers the 33 abilities
* includes/claude/abilities/class-*-ability.php — the ability classes (21 original + 11 added in this release + 1 pre-existing)
* includes/class-aieo-session-attribution-bridge.php — joint analytics query helpers
* includes/class-aieo-conversion-probability-model.php — engagement-bucket scoring
* includes/class-aieo-remote-export-manager.php — paged INSERT-batch streaming to remote DB
* includes/class-aieo-ratings-schema.php — SEO plugin schema bridge
* includes/cron/class-aieo-aggregate-cron.php — nightly rollup builder
* includes/cron/class-aieo-archive-handlers.php — AE / reco retention with remote-export gating
* includes/cron/class-aieo-remote-export-cron.php — configurable export cron
* includes/class-aieo-retention-bootstrap.php — top-level retention wiring
* includes/sql/sql-aggregate-rollups.php — DDL for the 5 rollup tables
* includes/sql/sql-remote-export-state.php — DDL for the bookkeeping table
* assets/pages/dmm/remote-export.php — admin page template
* docs/v2-pattern.md — V2 module pattern reference
* docs/BUILD_AND_DISTRIBUTION.md — build / SVN deploy strategy
* .distignore — wp.org distribution package filter

** ⚠️ Operator Notes **
* On first activation of 5.0 the new aggregate rollup tables are created and the nightly aieo_aggregate_rollups cron begins back-filling history; expect 1-3 nightly runs before the chat abilities reach full historical coverage
* Operators who configure the Insights Remote DB export should leave "Hold local archive deletes until the remote confirms" ON (the default) — the failsafe prevents data loss when the remote is briefly unreachable
* The 13 Pro-locked tabs are visible to free-tier operators with a frosted overlay; the underlying database tables are still created on activation so a later Pro upgrade has zero migration cost
* No customer-facing front-end changes — this is an admin-side and analytics-side release


= 4.2 Products for the Same Needs (28/01/2026) =

** 🎯 NEW FEATURE: Need-Based Product Recommendations **

This release introduces "Products for the Same Needs" - a powerful new recommendation system that suggests products fulfilling the same customer needs. Unlike traditional cross-sells and upsells, these recommendations are based on matching customer needs (via the pa_need product attribute), ranked by actual sales performance.

** 🛒 Products for the Same Needs **
* NEW: Automatic product suggestions based on matching customer needs (pa_need taxonomy)
* NEW: Intelligent matching algorithm finds products sharing primary or secondary needs (optimized for performance)
* NEW: Rankings powered by pre-computed TotalItemSales from product catalogue for maximum performance
* NEW: Smart exclusion of existing upsells and cross-sells to prevent duplicate recommendations
* NEW: Stores up to 6 optimized suggestions per product in wp_aieo_product_need_suggestions table
* NEW: Match scoring system - products with more shared needs rank higher
* Improved: Variations automatically inherit need suggestions from their parent products

** 🎨 Display Configuration **
* NEW: Display checkbox in Display Preferences: "Please display Products for the same needs"
* NEW: Displays FIRST on product pages (priority 10) - appears before upsells, cross-sells, and related products
* NEW: Skeleton loading animation with WooCommerce placeholder images while fetching via AJAX
* NEW: Empty sections automatically hidden when no matching products exist (no blank titles)
* NEW: Translatable section title: "Products for the Same Needs"
* Improved: Consistent styling with other AIEO recommendation sections

** ⚙️ Generation & Operational Efficiency **
* NEW: Generation checkbox in Operational Efficiency: "Please generate products with the same needs"
* NEW: Runs as final step in Operational Efficiency batch processing (after UUID generation)
* NEW: Batch processing with configurable batch size (default 100 products per batch)
* NEW: Progress logging shows products processed and suggestions created
* NEW: AI_eShop_Need_Suggestions generator class with singleton pattern
* Improved: Leverages existing wp_aieo_core_product_vitals table for need data
* Improved: Uses wp_aieo_temp_product_catalogue for pre-computed TotalItemSales (faster, no aggregation needed)

** 🚀 Performance & Caching **
* NEW: same_needs added to AIEO_Recommendations_Cache valid relation types
* NEW: Multi-tier caching: Object Cache (Redis/Memcached) + Database table
* NEW: Cache automatically invalidated when products are updated
* NEW: Seamless integration with existing AJAX lazy loading infrastructure
* Improved: Suggestions stored as JSON array for fast retrieval
* Improved: Database indexes on product_id for optimal query performance

** 🗄️ Database Changes **
* NEW: wp_aieo_product_need_suggestions table with columns:
  - id (auto-increment primary key)
  - product_id (unique index for fast lookups)
  - suggested_products (JSON array of up to 6 product IDs)
  - match_score (number of needs matched with best suggestion)
  - created/modified timestamps
* NEW: Table created automatically on plugin activation
* NEW: Default options: aieo_create_need_suggestions, aieo_display_same_needs

** 📁 New Files **
* includes/class-need-suggestions.php - Generator class with methods:
  - generate_all_suggestions() - Batch generate for all products
  - generate_suggestions_for_product() - Generate for single product
  - get_suggestions() - Retrieve suggestions for display
  - find_matching_products() - SQL query for matching products
  - get_excluded_product_ids() - Get upsells/crosssells to exclude

** 🔧 Technical Implementation **
* Uses pa_need product attribute (configurable via aieo_core_attribute_need option)
* Queries wp_aieo_core_product_vitals for primary_need_id and secondary_need_id only (no string parsing needed)
* Ranks by pre-computed TotalItemSales from wp_aieo_temp_product_catalogue (requires catalogue to be generated first)
* Excludes products from _upsell_ids and _crosssell_ids post meta
* Preserves suggestion order (by sales ranking) when displaying
* Generation checkbox appears at end of Operational Efficiency list to ensure dependencies are met


= 4.0 Dynamic AI Models + Database Collation + Anonymous Chat Logging (27/11/2025) =

** 🎉 MAJOR UPDATE: 50+ AI Model Flavours **

This release introduces dynamic AI model selection from the database, comprehensive database collation fixes for maximum compatibility, and fixes for anonymous user chat logging.

** 🤖 Dynamic AI Model Registry **
* NEW: Dynamic model selection from database - over 50 AI model flavours now available
* NEW: All Anthropic Claude models dynamically loaded (Claude 4, Opus 4.5, Sonnet 4.5, Haiku 4.5, and all versions)
* NEW: All OpenAI models dynamically loaded (GPT-5.1, GPT-5, GPT-4, GPT-o1, GPT-3.5, and all variants)
* NEW: All embedding models (Voyage AI, OpenAI) dynamically populated from wp_aieo_ai_models table
* NEW: Admin panel model dropdowns now populate directly from database registry
* Improved: Adding new AI models no longer requires code changes - simply update the database
* Improved: Model selection uses get_models() method with provider/type filtering

** 🗄️ Database Collation Compatibility **
* Fixed: aieo_create_core_product_attributes_table() now uses aieo_get_charset_collate()
* Fixed: aieo_create_core_product_vitals_table() now uses aieo_get_charset_collate()
* Fixed: aieo_create_core_variation_vitals_table() now uses aieo_get_charset_collate()
* Fixed: All AIEO tables now consistently use utf8mb4_uca1400_ai_ci (or database default)
* Fixed: Removed BINARY comparison from AIEO_InsertCoreProductAttributes stored procedure
* Improved: Full compatibility with MariaDB 11.4, MariaDB 11.8, MySQL 5.7, and MySQL 9
* Improved: Tables no longer created with latin1_swedish_ci collation

** 💬 Anonymous User Chat History **
* Fixed: Chat exchange logging now works correctly for anonymous (non-logged-in) users
* Fixed: Session tracking properly handles anonymous user conversations
* Fixed: Re-ranking system properly logs all chat exchanges regardless of user status
* Improved: Chat history storage works for both authenticated and guest users

** 🌐 Translation Improvements **
* Fixed: Frontend chatbox now correctly loads translations from plugin languages directory
* Fixed: Translation loading hook priority changed to 0 for earliest execution
* Improved: Fallback translation loading from WP_LANG_DIR/plugins/, plugin /languages/, and standard WordPress location
* Improved: load_textdomain() now checks multiple paths before falling back to load_plugin_textdomain()

** 🔑 API Key Validation & Credit Check **
* NEW: "Validate API Keys & Check Credits" button in AI Chat settings
* NEW: One-click validation of all configured API keys (Anthropic, OpenAI, Voyage AI)
* NEW: Automatic detection of exhausted credits with clear warning messages
* NEW: Direct links to each provider's billing dashboard for easy credit top-up
* NEW: Status indicators: ✓ Valid, ✗ Invalid, ⚠️ No Credits, — Not Configured
* Improved: Helps diagnose why chat/embeddings may not be working

** 🔧 Technical Improvements **
* Enhanced: AI Chat settings page now uses AI_eShop_Chat_Model_Registry::get_instance()
* Enhanced: Chat model and embedding model dropdowns use get_models('provider', 'type', false) for all models including inactive
* Enhanced: Stored procedure taxonomy comparison simplified (removed BINARY and COLLATE)
* Code: Updated ai-eshop-chat.php model dropdown population (lines 666-669, 1026-1029)
* Code: Updated ai-eshop-chat-addon.php translation loading (lines 143-167)

** 📊 Database Index Optimization **
* NEW: Added 6 missing Graph UUID indexes for optimal export performance
* NEW: idx_graph_ppid for Parent Product UUID lookups
* NEW: idx_graph_orderid for Order UUID lookups
* NEW: idx_graph_prodid for Product UUID lookups
* NEW: idx_graph_epoid for Customer UUID lookups
* NEW: idx_graph_o_epo for Order-Customer relationship lookups
* NEW: idx_graph_pp_epo for Product-Customer relationship lookups
* NEW: idx_product_stats_filter for aggregate_product_stats WHERE clause optimization
* Improved: Database optimization now creates 20 indexes (up from 13) for MariaDB and MySQL 8


= 3.6 MySQL 8 Compatibility + Re-ranking + Error Detection (13/11/2025) =

** 🎉 MAJOR UPDATE: 100% MySQL 8 Support **

This release brings complete MySQL 8.0+ compatibility, advanced search re-ranking, and comprehensive embedding error detection. The plugin now works flawlessly on both MariaDB 11.4+ and MySQL 8.0+ with automatic detection and optimization.

** 🗄️ MySQL 8 & Database Compatibility **
* Complete MySQL 8.0+ support - all SQL syntax converted to cross-compatible code
* Auto-detection of MySQL 8 vs MariaDB with appropriate optimization strategies
* MySQL 8 histogram statistics support for 20-30% faster query optimization
* Descending indexes for MySQL 8 to optimize recent-order queries
* Fixed all 52+ DROP INDEX IF EXISTS syntax errors (MariaDB-specific)
* Fixed CREATE OR REPLACE FUNCTION errors - converted to drop-then-create pattern
* Binary logging privilege handling with graceful degradation
* Helper functions for cross-database compatibility (aieo_drop_index_if_exists, aieo_drop_function_if_exists)
* New file: includes/sql/apply_mysql8_indexes.php - MySQL 8 specific optimizations
* Expected 38-48% performance improvement on MySQL 8 after optimization (tested: 9.5min → 5-6min for 37K products)
* 13 composite indexes + histogram statistics on 6 key columns

** 🔍 Advanced Search Re-ranking System **
* Configurable re-ranking weights for hybrid semantic + keyword search
* Dedicated "Re-ranking Weights" configuration UI in AI Chat settings
* Semantic similarity weight slider (0-100%) with real-time preview
* Keyword matching weight slider (0-100%) with automatic normalization
* Visual feedback with color-coded weight distribution indicators
* Three preset configurations: Semantic-focused (70/30), Balanced (50/50), Keyword-focused (30/70)
* Database schema migration for re-ranking weights storage
* Search results now intelligently combine embedding similarity with keyword matching
* Better handling of product variations vs parent products in rankings

** 🚨 Embedding Error Detection & Reliability **
* Comprehensive failure tracking system - new wp_aieo_chat_embedding_failures table
* Real-time statistics: success rate, average latency, failure breakdown by type
* Automatic retry logic with exponential backoff for transient errors
* Smart error categorization: Rate Limits, Timeouts, Network Errors, Invalid Input, Unknown
* Failure trend analysis with 30-day time-series data
* Visual error rate graphs with severity indicators (green <1%, yellow 1-5%, red >5%)
* Detailed error logs with timestamps, error types, and affected content IDs
* Automatic recovery suggestions based on error patterns
* Failed items flagged for priority retry in next training batch
* Training progress now shows retry attempts and detailed error messages
* API quota management with intelligent retry delays (60s for rate limits, 30s for timeouts)
* Batch processing handles partial failures gracefully - continues with remaining items

** 📊 Database Performance Optimization **
* New MySQL 8-specific index optimization strategy
* Histogram-based query planning (MySQL 8 exclusive feature)
* Performance indexes for customer statistics queries
* Optimized covering indexes for product catalog queries
* DESC indexes for latest-order queries (MySQL 8 native support)
* Auto-detection in "Database Performance Optimization" admin section
* Different benefits messaging for MySQL 8 vs MariaDB users

** 🔧 Technical Improvements **
* Enhanced logging throughout embedding and search processes
* Better error handling with actionable user feedback
* Database query optimization for embedding statistics
* Code organization with separate MySQL 8 file for maintainability
* Improved variation enrichment with better parent product handling
* Embedding statistics now accurately reflect all content types

** 📝 Documentation Updates **
* MYSQL8-COMPATIBILITY-FIX.md - Complete MySQL 8 compatibility guide
* Performance tuning recommendations for MySQL 8
* Re-ranking configuration best practices
* Error detection monitoring guide

** 🐛 Bug Fixes **
* Fixed variation enrichment handling of missing parent data
* Fixed embedding statistics accuracy across post types
* Fixed stored function creation on MySQL 8 with binary logging enabled
* Fixed database migration for re-ranking weights default values
* Fixed undefined variable warnings in embedding error tracking


= 3.5 Advanced Session Tracking & Analytics (07/11/2025) =

** ✨ New Session Tracking Features **
* Added custom class-based event tracking - define custom CSS selectors to track clicks on any element (buttons, swatches, divs, etc.)
* Added click event throttling option to prevent database flooding while maintaining accurate click counts
* Added cookie consent bypass mode - option to enable tracking without waiting for user consent (GDPR compliance toggle)
* Custom rules take precedence over standard tracking to prevent double-counting events
* Product image click tracking with 5-second debounce window to avoid duplicate events from lightbox interactions
* Automatic version bumping with variable-length strings for aggressive cache busting
* Admin textarea for easy custom tracking rule configuration (format: event_name | .css-selector)

** 🔧 Session Tracking Technical Improvements **
* Generated JavaScript code is "baked in" as inline scripts for better performance (not computed dynamically)
* Custom tracking rules override standard click tracking to prevent duplicate event recording
* Improved click counting: throttled mode counts only significant clicks, non-throttled counts all clicks
* Enhanced product image detection across different theme gallery structures
* Version string uses random lengths (8-19+ digits) for superior cache invalidation

= 3.3.2 Performance & Reliability Release (04/11/2025) =

** 🐛 Critical Bug Fixes **
* Fixed embedding training duplicate product ID issue causing infinite loops and HTTP 524 timeouts
* Fixed AI Chat warning modal not disappearing after data analysis completion
* Fixed sessionStorage persistence across page reloads for warning state

** 🚀 Performance Improvements **
* Added performance indexes (lookup_idx, stats_idx) to embeddings table for 10-20x faster queries
* Optimized database queries with DISTINCT/GROUP BY to prevent duplicate results
* Changed index checks from transients to static variables (eliminates wp_options writes)
* Reduced embedding batch processing time from 60-120 seconds to 20-30 seconds for 50 products
* Object cache bypass during critical operations to prevent interference from misconfigured Redis/Memcached

** 🔧 Technical Improvements **
* Multi-layer duplicate protection: SQL DISTINCT, array_unique() at entry/exit, GROUP BY aggregation
* All 8 priority metrics (TotalItemSales, DistinctOrderSales, TotalTurnover, etc.) now use optimized queries
* Query existence checks now use fast `USE INDEX` method instead of INFORMATION_SCHEMA
* Added comprehensive error logging for database operations (can be toggled)
* Chat addon updated to v1.1.1 with improved sessionStorage handling

** 📚 Developer Documentation **
* Added DATABASE-INDEX-OPTIMIZATION.md - Complete index strategy and performance guide
* Added DUPLICATE-FIX-SUMMARY.md - Technical documentation of all duplicate prevention fixes
* Added INDEX-CHANGES-SUMMARY.md - Quick reference for index changes and rollback
* Added SESSION-SUMMARY.md - Complete session work summary
* Added OBJECT-CACHE-CONFIG.md - wp-config.php object cache exclusion instructions

= 3.3.1 Admin Styling & WordPress.org Compliance (03/11/2025) =

** 🐛 Bug Fixes **
* Fixed admin panel styling issues - cleaned up overlapping CSS rules and consolidated chat admin styles
* Fixed plugin description exceeding 150 character limit - reduced to 114 characters for WordPress.org compliance

** 🔧 Technical Improvements **
* Chat addon CSS version bumped to 1.1.0 to force cache refresh for style updates
* Improved CSS organization and eliminated redundant style declarations

= 3.3 Standalone Mode & Enhanced Flexibility (03/11/2025) =

** ✨ Major New Features **
* Plugin now works standalone without WooCommerce - perfect for corporate sites and merchant information pages
* Intelligent menu placement - integrates seamlessly with WooCommerce when available, creates standalone top-level menu otherwise
* Custom network icon for better visual identification in WordPress admin
* Customizable AI Chat input placeholder text in settings

** 🎨 UI/UX Improvements **
* Shortened menu labels ("AI Optimizer") to prevent UI wrapping on smaller screens
* Added descriptive submenu items with emoji icons for better navigation
* AI Chat tab warning now shows on hover for better user guidance
* AI Chat warning only displays on WooCommerce sites (not needed for standalone content sites)
* AI Chat tab warning automatically refreshes after data analysis completes

** 🔧 Technical Improvements **
* Updated to use future-proof Claude model alias (claude-sonnet-4-5)

** 🐛 Bug Fixes **
* Fixed chat wrapper now properly fills custom popup width without margins
* Fixed send button arrow now points right (horizontally flipped)
* Fixed JavaScript errors with e.target.closest() when clicking on text nodes in theme files

= 3.2.1 Embedding Generation Bug Fixes (02/11/2025) =

** 🐛 Critical Bug Fixes **
* Fixed deduplication mode setting not saving correctly when changed via Training Mode dropdown - now properly respects user selection
* Fixed product prioritization querying wrong table - now correctly pulls sales metrics from temp_orders table instead of product_vitals
* Fixed embedding statistics showing incorrect counts - now accurately counts only parent products and excludes individual variations
* Fixed inconsistent product counts between training and statistics - all queries now use matching data sources (product_vitals table)
* Fixed draft/trash products being included in counts - all queries now filter by post_status='publish' for accuracy

** 🔧 Technical Improvements **
* Enhanced query consistency across embedding generation, statistics, and product prioritization
* Improved data source alignment to prevent count mismatches during training
* Better filtering logic to ensure only published parent products are processed

= 3.2 Major Feature Update (01/11/2025) =

** ✨ New Features **
* Support for Pages and Posts in visual editors (Elementor, WP Bakery, TagDiv Composer) - AI Chat now intelligently extracts and processes content from popular page builders for enhanced semantic search capabilities
* Added helpful documentation links throughout the interface to guide users on metric meanings and business implications

** 🌟 New PRO Features **
* Process Automation - Schedule automatic data analysis and embedding updates with flexible daily/weekly timing options for hands-free optimization
* Contextual Metadata - AI Chat now leverages device profile, browsing history (configurable page depth), and user preferences to deliver hyper-personalized product recommendations
* AI Session Tracker (Beta) - Track customer engagement depth, product interactions, scroll behavior, and cart activity with surgical precision analytics that cost $0 vs $100+/month for Google Analytics BigQuery exports

** 🎨 UI/UX Improvements **
* Enhanced HTML structure for better visual consistency across AI Chat configuration sections
* Fixed Posts & Pages configuration header to extend properly across full width, matching Products section styling
* Improved admin panel layout with better spacing and alignment throughout
* Better visual hierarchy in settings pages for easier navigation

** 🐛 Bug Fixes **
* Various minor UI/UX refinements and polish
* Improved CSS consistency across admin panels

= 3.1.2 Referral Tracking Enhancement (31/10/2025) =

** ✨ New Features **
* Added referral links tracking for better affiliate program management
* Enhanced tracking capabilities for referral campaigns
* Better analytics for referral link performance

= 3.1.1 Installation Fix (31/10/2025) =

** 🛠️ Bug Fixes **
* Fixed plugin installation issues ensuring all required files are properly included
* Resolved missing file dependencies during fresh installations
* Improved plugin activation reliability

= 3.1 Maintenance Release (31/10/2025) =

** 🔧 Technical Updates **
* Version bump to ensure all files are properly distributed
* Verification of file structure and package completeness

= 3.0 AI Chat & Major Enhancement Update (30/10/2025) =

** 🎉 Major New Feature: AI-Powered Chat **
* FREE AI Chat with support for latest models from Anthropic and OpenAI
* Cutting-edge AI models: Claude Opus 4.1, Claude Sonnet 4.5, Claude Haiku 4.5
* OpenAI support: GPT-5, GPT-4, GPT-o1, GPT-3.5
* Advanced embedding engines for semantic product search
* Voyage AI embeddings: voyage-3.5-large, voyage-3.5-lite, voyage-3-lite, voyage-finance-2
* OpenAI embeddings: text-embedding-3-large, text-embedding-3-small, text-embedding-ada-002
* Smart product search powered by AI semantic similarity matching
* Context-aware responses using customer behavior data
* Customizable chat templates for different use cases
* Product catalog integration with AI embeddings

** 🎨 Chat Customization **
* Two visual themes: Rounded (Modern with shadows) and Square (Clean and minimal)
* Dynamic color customization for complete branding control
* Header gradient automatically uses brand colors
* Send button styling matches brand colors
* Chat input no longer inherits theme styles for consistent appearance
* Mobile-responsive chat design
* Floating chat widget with adjustable positioning (bottom-left/right, top-left/right)
* Customizable welcome bubble messages

** 🔧 Technical Improvements **
* WordPress coding standards compliance - all 54+ coding standard issues resolved
* Enhanced database query preparation with proper $wpdb->prepare() usage
* Translator comments added for all translatable strings
* Ordered placeholders (%1$s, %2$d) for better translation support
* Date/time functions now use timezone-safe gmdate()
* Proper nonce escaping with esc_js() throughout
* POT file updated with all new translation strings
* Version bumped to 3.0 reflecting major feature additions

** 🛡️ Privacy & Performance **
* AI Session Tracker (Beta) now disabled by default for better privacy
* Cron job properly configured to clean up old session data (retention period)
* Console logging cleaned up - all debug messages commented out
* Optimized AJAX requests for chat statistics
* Improved error handling and validation

** 🐛 Bug Fixes **
* Fixed chat input inheriting unwanted theme styles (size, borders, positioning)
* Fixed send button icon direction - now points right instead of up
* Fixed deduplication mode persistence across page reloads
* Fixed last trained engine settings not being remembered
* Fixed embedding statistics display for different engine types
* Removed deprecated load_plugin_textdomain() for WP 4.6+
* Fixed unlink() usage - replaced with wp_delete_file() where appropriate

** 📚 Documentation **
* Updated readme.txt with comprehensive AI chat feature descriptions
* Detailed changelog with all improvements and fixes
* Updated plugin descriptions highlighting latest AI capabilities
* Better organization of feature lists


= 1.0 Initial Release (3/8/2023) =
* Initial plugin release
* AI-powered product recommendations via eshop-optimizer.com
* Export product catalog and order data
* Import upsell and cross-sell recommendations
* Google GA4 integration for performance tracking
* Support for WooCommerce HPOS (High-Performance Order Storage)
* Privacy-centric data export options


= 2.0 Core Update (17/10/2024) =

** Major Features **
* Local Analytics Engine: Analyze your product performance using local data without requiring external AI processing
* Smart Product Tips: Get valuable insights about your most important products based on local sales patterns
* Performance Boost: Significantly improved data processing speed with optimized database queries

** Database Compatibility **
* Enhanced compatibility with MariaDB 11+ and MySQL 9.0
* Universal database support - works with all major database versions
* Removed hardcoded collation statements for better database compatibility

** Performance Improvements **
* Optimized stored procedures (v2 and v3 batched versions)
* Smart batch processing for large datasets
* Improved query execution speed
* Enhanced memory management for large order exports

** New Features & Enhancements **
* Advanced customer-centric statistics and analytics
* Improved product vitals tracking
* Better variation handling and processing
* Enhanced reciprocal product recommendations

** Technical Improvements **
* PHP 8.4 compatibility
* Prefixed admin CSS classes to prevent plugin conflicts
* Refactored codebase for better maintainability
* Improved error handling and logging

** Bug Fixes **
* Fixed database collation issues on various hosting environments
* Resolved CSS conflicts with other plugins
* Various minor bug fixes and stability improvements


= 2.1 Performance & Localization Update (18/10/2024) =

** Performance Enhancements **
* Major performance optimizations for faster data export and processing
* Optimized database queries for handling large product catalogs
* Improved stored procedure efficiency
* Enhanced memory usage for bulk operations

** New Features **
* Full localization support - plugin is now translation-ready
* Database collation compatibility helper for WooCommerce installations with mixed collations
* Enhanced support for complex product attributes including multi-valued attributes
* Support for hierarchical attribute structures

** Attribute Handling Improvements **
* Improved handling of brands, sizes, colors, and custom attributes
* Better support for product variations with complex attribute structures
* Enhanced processing of multi-valued attributes
* Improved handling of special characters in product attributes

** Compatibility & Fixes **
* Resolved issues with mixed database collations in multi-language installations
* Better handling of edge cases in attribute processing
* Improved compatibility with various WooCommerce configurations
* Fixed attribute export issues in certain hosting environments

** Code Quality **
* Refactored attribute processing for better maintainability
* Improved code organization and documentation
* Enhanced error handling and validation
* Optimized code paths for common operations