Older versions of affilinode

= 0.66.0 =
* Changed: Internal restructuring without visible changes – every box type has its own class (`includes/Boxes/`), the data cache runs on one shared core, translations are split by area and language files are generated at build time. Output and cache keys are unchanged.
* Fixed: When a box refreshes its cached data right away (loader mode or stalled background tasks), comparisons, lists, price histories, spare parts, alternatives, "at a glance", "A vs B" and tariff boxes now show the fresh data immediately instead of the previous copy.
* Fixed: An expired "not found" for lists, comparison tables and the other box types is fetched again right away (as for products), so newly created lists or products appear without waiting for the background refresh.
* Fixed: Background refreshes of alternatives, "at a glance" and "A vs B" boxes always update the same cache entry that is read, regardless of how query values are typed.
* New: affilinode → Old shortcodes rewrites the old `[ac_…]` shortcodes and `affiliate-central/…` blocks (up to version 0.29) to `[affilinode_…]` and `affilinode/…` in posts, pages, reusable blocks, theme templates and widgets – only on click, attributes unchanged, with a revision per post, in batches and with a log to undo it. Also as `wp affilinode legacy status|rewrite|undo`.
* New: A notice in the admin shows when old shortcodes, blocks or hook names (`affiliate_central_…`) are still in use.
* Deprecated: The old shortcode names `[ac_…]`, the blocks `affiliate-central/…`, the hooks `affiliate_central_…` and the other names from affiliate-central will be removed in version 1.0. Old shortcodes and blocks now also trigger a deprecation notice (only with WP_DEBUG).
* Security: The API key is now stored encrypted (libsodium, key derived from the WordPress salts) like the webhook secret, the Cloudflare token and the MaxMind licence key. Existing keys are encrypted automatically on the first page load after the update – for the network settings and every site of a multisite network. The settings field, WP-CLI and the settings export never show the key (the export includes it in plain text only when you choose "Include secret keys").
* Changed: If the saved API key can no longer be decrypted (for example after new security keys in wp-config.php), administrators see a notice to enter the API key again; until then the plugin behaves as without a key instead of failing silently. Demo mode is unchanged.

= 0.65.0 =
* Security: Confirmation and unsubscribe links of price alerts and "Back in stock" notifications did not work – the token in the link was lowercased while it is stored in mixed case; one-click unsubscribe answered "ok" without removing the address. Links that have already been sent work again after the update.
* Security: At most 3 confirmation emails per address and day (price alert and "Back in stock" together); further sign-ups change nothing and do not reset an existing alert. Prevents sending masses of emails to strangers via the sign-up form.
* Security: Sign-ups only remember published posts (no permalinks of private or scheduled posts in emails).
* Security: Reporting and the "Commission (30 days)" column are only visible from the editor role up (filter `affilinode_reporting_capability`).
* Security: Requests to the affilinode API no longer follow redirects, so the API key is never sent to another host.

= 0.64.0 =
* New: Price freshness. Below the price of every offer the boxes show "Price updated 2 hr. ago" (product box, card, lists, comparison, price comparison) – calculated by the browser from the time stamp, so it stays correct in page caches; without JavaScript and on AMP pages the date and time. Settings → Affiliate disclosure: "Price update time" (relative, date and time, off) and its position (below the price or only in the price note); per box `price_age="relative|datetime|off"`.
* New: Attribute `max_age` (hours) per box – older prices are hidden, the button reads "Check current price" (German: „Aktuellen Preis ansehen“). The lazy loader and the browser respect the maximum age of each box, also for pages from a page cache.
* Changed: Amazon prices are never shown when older than 24 hours, even when "Maximum price age" allows more.
* New: Notice on the settings page when the prices of a shop or feed are out of date (as reported by affilinode, at most every 12 hours).
* New: Geo short links for social media. affilinode → Products → "Geo short link" creates one short link for a product (channel Instagram, TikTok, YouTube, Pinterest, newsletter or WhatsApp) that leads every visitor to the right offer in their country – with the tracking IDs of this site, following the rules of the site from the affilinode dashboard. Optionally the link always shows an overview page with the price comparison of the visitor's country. Rules per country and clicks per country, shop and target: affilinode dashboard → Links. Amazon is never reached through a redirect, only via the overview page with a clearly labelled Amazon button.
* New: Language follows the page. Box texts, data sheet labels, product titles and descriptions as well as buttons and notes of the boxes come in the language of the page – from the post language of Polylang or WPML, the request language of Polylang, WPML or TranslatePress, otherwise the site language (in a multisite network per site) – no longer in the language of the logged-in editor (editor preview, shortcode generator). The lazy loader keeps the language of the page it came from (language prefixes such as `/en/`). Setting texts (button text, disclosures) are also translated with WPML String Translation. Where a translation is missing, the text comes in the base language (German) with a matching `lang` attribute. Filter `affilinode_page_locale` for own language setups.
* Changed: The language only decides the texts, never the country. Geolocation always comes first (CDN header → MaxMind); without it "Country per language" (if set) → default country → region of the language. Until now Polylang used the region of the language (e.g. en_GB → GB) before the default country – enter such countries under Settings → Languages & countries → "Country per language".
* New: Disclosure check before publishing. The block editor ("affilinode: products in this post" → "Disclosure" and a pre-publish panel) and the classic editor (notice above the editor) check posts with affiliate links – also links inserted by hand to Amazon (with partner tag, amzn.to …), Awin, Tradedoubler, ADCELL, Webgains, CJ, eBay Partner Network, AliExpress, affilinode short links, /go/ links of the site and own short domains (Settings → Affiliate disclosure → "Further affiliate domains"): "Ad" label at the beginning of the post (or an asterisk at every link with an explanation), the Amazon Associates disclosure on the page (in the post, below a box with Amazon offers, in a widget, a footer template or the footer of the front page), `rel="sponsored"` on every affiliate link, no price history, price alerts or deals next to Amazon links without a written exception, and prices in the text without a date. One-click fixes "Insert notice" (in the language of the page with its own wording for Germany, Austria and Switzerland; own "Ad" label and Amazon text from the settings take precedence) and "Add rel="sponsored"" – in the block editor in the unsaved post, otherwise saved with a revision first; never without a click. Publishing is never blocked; the warning can be switched off ("Check the disclosure before publishing"). affilinode → Post check lists the findings of all published posts (hourly with the post check). REST: `POST affilinode/v1/disclosure/fix`; filters `affilinode_disclosure_hosts` and `affilinode_disclosure_site_notice`.
* New: Product pages per language with Polylang or WPML. The automatic synchronisation creates one product page per language (title and excerpt in that language) and links them as translations, so Polylang and WPML output hreflang and their language switcher; existing pages without a language count for the default language. Product pages are translatable with Polylang (registered automatically) and WPML (`wpml-config.xml`, product ID, type and central ID are copied). Category hubs use the translation of the hub page in the current language; hreflang and the language switcher point to the same hub in the other language.
* New: "A vs B" comparisons: `[affilinode_versus a="…" b="…" (c="…")]` and the block "“A vs B” comparison" (also Elementor, shortcode generator with suggested partners, AMP). Verdict per area only from data sheet values with the direction of the category (numbers from a 5 % difference), price as its own area (left out with Amazon best prices on websites under the Amazon policy), "Who should buy which", FAQ with FAQPage markup. Optional own pages: "Page for “A vs B” comparisons" and "Comparison pairs" (with suggestions) under Settings → Product pages – /comparison/a-vs-b/ with canonical, breadcrumbs along the category hubs, sitemap (WordPress, Yoast SEO, Rank Math); category hubs list their comparisons. New box type "“A vs B” comparison" for tracking and statistics.
* New: Successor notice for editors. affilinode → Post check gets the section "Successor available": products in your posts for which a confirmed successor is available, grouped per product ("The successor is available in 4 posts") with a comparison old/new – release date, best price, key specifications – and the evidence (your own choice or a source such as Wikidata, manufacturer data or the same model series; never guesses: other sources only count with the same product type or category and the same brand). Per post or for all: "Replace", "Add second box" (the successor appears as a second box below the old one, in multi-product boxes behind it in the list) or "Add note" (a line "Successor: …" with a text link below the box), "Ignore". Every change is saved as a revision and can be undone. Opening an affected post in the block editor shows a notice; the sidebar "affilinode: products in this post" compares old and new and replaces or adds the successor right in the editor. The weekly report lists new cases under "Successors released". "Successor available" findings disappear once the post shows the successor. REST `POST affilinode/v1/link-guard/replace` takes `mode` (`replace`, `add`, `hint`); `LinkGuard::replace_product()` takes `$mode` as sixth parameter, the log entry and the action `affilinode_link_replaced` carry `mode`.

= 0.63.0 =
* New: Offers per visitor country. Shortcode attributes `shops` (only these shops – shop type such as `amazon`, `awin` or a shop ID), `prefer` (preferred partner, several in order) and `countries` (countries of this box for the visitor country and the country switcher) override the rules of the website from the affilinode dashboard per box. A preferred partner only counts with an offer that can be bought and – for Amazon – a link with your partner tag; otherwise the cheapest of the listed shops is shown. The rules of the website itself (prefer Amazon, fall back to the cheapest of a list, shops and partners per country) are applied by affilinode. Geolocation always comes before the language: CDN header → MaxMind → default country.
* New: Revenue per post. The post and page lists get the column "Commission (30 days)" with the commission of the affiliate networks per post and currency, below it the open and the cancelled amount (one request per list view, cached for 15 minutes; only for users who can edit posts). The box "affilinode: figures for this post" in the editor also shows the commission by status – confirmed, open, cancelled – and the EPC where the network reports clicks.
* New: Links of Tradedoubler (`epi`), ADCELL (`subId`), Webgains (`clickref`) and CJ (`sid`) carry post, product and box type behind the site's sub-ID: `<sub-ID>_a<post>_p<product>_b<box type>` – only letters, digits, `_` and `-`, at most 50 characters (box type, then product are left out if it gets longer; the product is shortened to 12 characters, a network post `3:1187` is written as `3-1187`). A sub-ID with other characters or one that is already assigned is left as it is. affilinode now fetches the transactions of these networks and assigns them to posts and boxes.
* New: Back-in-stock notification for readers (off by default: Settings → Price alerts). While a product is not available from any shop other than Amazon, readers leave their e-mail address – `[affilinode_stock_alert]`, block, Elementor, shortcode generator, or `stock_alert="1"` below a product box or card; on AMP pages via amp-form. Double opt-in, exactly one e-mail with the offer link (tracking IDs of the site, reader's country, click counted via `stock-alert/go`), one-click unsubscribe – same table, sending routes (WordPress, affilinode mail server, own SMTP) and bounce handling as the price alerts. Amazon offers never trigger it; with an Amazon account it stays off without a written exception. Suggested privacy policy text, personal data export/erasure, statistics under Reporting (sign-ups, confirmed, e-mails, clicks; without personal data).

= 0.62.0 =
* Fixed: Boxes could stay empty or outdated for visitors while the editor showed the product. Expired data was only renewed in the background – on fully cached sites (LiteSpeed, Cloudflare) WP-Cron hardly runs, so an old "not found" stayed. Now an expired "not found" is never served again but fetched right away; the lazy loader in the browser renews expired data directly; and when scheduled renewals have not run for 15 minutes (background tasks stalled), the plugin renews them directly during the page view (at most 4 per view).
* New: Clear page caches after product changes. When affilinode reports changed or deleted products, lists or comparison tables (webhook), the posts with these boxes are cleared in LiteSpeed Cache, WP Rocket, W3 Total Cache, WP Super Cache, WP Fastest Cache, SiteGround Optimizer, Breeze, Nginx Helper and Cloudflare – in the background, after the product data has been reloaded, price changes at most once an hour per post. Cloudflare via its plugin or an optional API token (Settings → Cache & performance, stored encrypted, zone found automatically from the domain, purge by address in batches of 30 with a pause at Cloudflare's rate limit). The settings show the detected cache layers and the last purge; "Clear page caches now" clears them for this site. Action `affilinode_purge_urls` for own cache layers.
* Fixed: A box of a product that was not found yet (requested, still importing) stayed empty for visitors as long as a page cache or Cloudflare kept the page. Such pages are now cached for 5 minutes only, and the plugin checks every 10 minutes whether the product has arrived and then clears the page. With a Cloudflare token, a saved post is also cleared at Cloudflare.
* New: Link guard. The post check also reports the product IDs of the checked posts to affilinode (Settings → Post check & weekly report → "Link guard: suggest replacements", on by default) and gets back the reason – discontinued, not in stock anywhere (for at least 3 days), shop page dead, only at shops without access, gone from the shop feed, successor available – and replacement suggestions: successor, confirmed alternatives, better equipped or cheaper alternatives. affilinode → Post check lists them per post and product with the clicks of the last 30 days; "Replace" (single or for all selected) rewrites the product ID in the affilinode shortcodes and blocks of the post (`id`, `ids`, `compare`, `asin`, `ean`) – never in shortcodes of other plugins. The previous version is kept as a revision; "Undo" under "Recent replacements" restores it as long as the post has not been edited since. "Hide" hides a finding here and in the affilinode dashboard. Replacements requested in the affilinode dashboard ("Link guard") are carried out at the next post check. Posts are never changed without a click unless "Replace automatically if the successor is unambiguous" is switched on (off by default; only for products that can no longer be bought, never again after an undo). REST: `POST affilinode/v1/link-guard/replace`, `/undo`, `/ignore`; action `affilinode_link_replaced` after every replacement. The weekly report lists new findings.
* New: Self-updating comparison tables from the product search. Below `[affilinode_search]` logged-in editors see "Save as comparison table": it opens the affilinode dashboard with the current product type, search term, filters and sorting. The dashboard saves the query, not a fixed list – affilinode re-checks it every hour, swaps products when the result changes, keeps a change log and notifies the site via the webhook `compare_table.updated`. Products can be pinned, excluded or the selection frozen. Shown as before with `[affilinode_compare table="<ID>"]`, embedded, in Ghost and Discourse.

= 0.61.1 =
* Fixed: The product search and the list overview in the shortcode generator used the 3-second limit meant for page views; slower answers of the affilinode API ended as "HTTP 502" (shown by Cloudflare as an HTML page). Editor requests now wait up to 12 seconds, no longer put the boxes of the whole website into the 60-second pause after an API error (and are not blocked by it), and report the actual reason. Errors of the API are answered with 503 instead of 502, which proxies pass through unchanged.

= 0.61.0 =
* Fixed: The product search in the shortcode generator often failed with "Unexpected token '<' … is not valid JSON" on busy shared hosting or behind a firewall. A running search is now cancelled when you keep typing (no parallel searches), results are cached, an answer that is not data is retried once and otherwise explained with its HTTP status.
* New: Price alert e-mails via affilinode. Settings → Price alerts → "Sending of price alerts": WordPress (wp_mail, as before, default) or affilinode. With affilinode, confirmation, notification and unsubscribe confirmation are built by affilinode in the language of the site (text and HTML) and sent through the route set up in the affilinode dashboard under "Email sending": the affilinode mail server – optionally with your own sender domain signed with DKIM – or your own SMTP server. The settings show the chosen route, sender and monthly quota; "Send test email to me" checks it. If affilinode cannot send right now (not set up, paused, quota used up, no connection), the mail goes out via wp_mail – switch off with "Fall back to WordPress"; blocked addresses never fall back. Mails via affilinode carry `List-Unsubscribe` with one-click unsubscribe (RFC 8058); the unsubscribe route also accepts POST. Addresses that cannot be delivered or reported a mail as spam arrive via webhook (`price_alert.mail_failed`) and their alerts are switched off. The suggested privacy policy text names affilinode as processor when this route is chosen. The Amazon policy is unchanged: with an Amazon account price alerts stay off.
* New: After unsubscribing via the link in a mail, a short confirmation is sent ("Price alert deleted") – only for confirmed alerts and not for one-click unsubscribes from the mail program.
* New: Pack sizes. Box `[affilinode_packs id="…"]` (block "Pack sizes", Elementor, shortcode generator): per pack size (single, 2-pack, 3-pack …) the cheapest available offer with total price, price per piece and saving per piece compared with the cheapest single item, shop and button; the best price per piece is highlighted. Options `sort="unit"`, `only_available="1"`, `title`, `heading`, `tracking`. Price comparison `[affilinode_offers packs="tabs"]`: tabs per pack size ("Single" preselected, arrow keys; without JavaScript and on AMP pages as sections) and a note like "In a 3-pack, one piece costs 4.99 € – 1.20 € (19 %) less than buying singly", `packs="hint"` only the note – also in product boxes. Settings → Display: "Pack sizes in the price comparison" (off by default), "Pack note from a saving of … % per piece" (3 %), "Show pack sizes below product boxes" (off by default; per box `packs_box="1"`). Box type "packs" for click tracking and click statistics. affilinode also recognises more pack notations (3-pack up to 12-pack, "Set of 3", multipack, "x3" …).

= 0.60.0 =
* New: Import products straight from the shortcode generator (block, classic editor button, "affilinode link" format button and generator page). When the search finds nothing – or via "Not found? Import a new product" – enter an ASIN, EAN/GTIN, MPN, product URL or search term; the import uses the same requests, quota and rights as affilinode → Product import, shows its status while you keep working, can stop waiting, and offers "Choice needed" right in the dialog. The imported product is selected at once, so shortcode and preview use its ID. A 2- or 3-pack never becomes a product of its own: it is added as a multipack offer of the single product ("2-pack of …"), otherwise the choice stays open. A device with contract ("iPhone 16 with o2 Mobile M") becomes a tariff of the device ("Tariff for …") with a suggestion for the "Device + tariffs" box. Product import and open choices share the same code.
* New: SEO building blocks for product pages.
* New: FAQ from the data sheet – `[affilinode_faq id="…" limit="6"]` and a section "Frequently asked questions" on product pages below the technical data (Settings → Product pages → "Show FAQ", on by default). Every question is based on exactly one value of the data sheet ("Galaxy A55: NFC?" – "Yes, according to the data sheet."; "What does the data sheet of Galaxy A55 state for “Battery capacity”?" – "Battery capacity: 5,000 mAh."); key values first, detail values left out, nothing generated or made up. Output as schema.org FAQPage – one per page, duplicate questions only once – switchable with "FAQ as structured data" and per shortcode with `schema="0"`/`schema="1"`; needs "Output structured data". Filter `affilinode_faq_items` for your own questions.
* New: Category hubs – choose a page under Settings → Product pages → "Page for the category hubs" (e.g. "Categories"). It shows an overview of all categories with products; below it every category gets its own hub, e.g. `/categories/smartphone/`, with subcategories, "Best in category", the product search with filters and links to the product pages of the category. Cross-links between categories (a category shown under a second parent) always link to the main location; the canonical of a hub is always its clean address (also with Yoast SEO and Rank Math); unknown and empty categories return 404. Also `[affilinode_category_hub type="…" top="1" search="1" pages="1"]` on any page. Hubs with products are listed in the WordPress sitemaps (own provider `wp-sitemap-affilinodehubs-1.xml`) or – when active – in the page sitemap of Yoast SEO or as an own sitemap `affilinodehubs-sitemap.xml` in the sitemap index of Rank Math. Category hubs are also styled on AMP pages.
* New: Breadcrumbs along the categories (Settings → Product pages → "Breadcrumbs along the categories", on by default): Home › Categories › Electronics › Smartphones › product. With Yoast SEO or Rank Math the categories are added to their breadcrumbs through their filters – no second BreadcrumbList; with other SEO plugins that output breadcrumbs (All in One SEO, SEOPress, The SEO Framework) the plugin adds nothing; without an SEO plugin it outputs its own BreadcrumbList in its structured data. Visible with `[affilinode_breadcrumbs]` or `affilinode_breadcrumbs()` in the theme. Category links need the hub page.
* New: Related product pages – at the end of a product page links to the product pages of alternatives, accessories and spare parts ("Fits" for parts) and further products of the same category, only to published product pages of this website (Settings → Product pages → "Link related product pages", on by default).
* Changed: Product pages remember the product type and the central product ID (meta `_affilinode_product_type`, `_affilinode_product_ref`), set when the page is shown and by the automatic synchronisation.
* New: Voucher box `[affilinode_coupons]`: current vouchers and deals of the merchants from Awin, Tradedoubler, Webgains and CJ (fetched by affilinode every 6 hours) or your own from the affilinode dashboard, as cards with value, merchant, validity, minimum order value, "Exclusive" and conditions. "Show code" reveals and copies the code and – where the network allows it – opens the shop in a new tab; without JavaScript and on AMP pages the code is visible next to the link. Filters `merchant`, `product`, `shop`, `kind`, `limit`; block "Vouchers", Elementor and shortcode generator. Optionally below every product box (Settings → Display → "Show vouchers of the merchant below product boxes", off by default; per box `coupons="1"`/`"0"`). Box type "coupons" for click tracking and click statistics. Never vouchers from Amazon.

= 0.59.1 =
* Fixed: Fatal error "Call to a member function using_index_permalinks() on null" when the plugin loads on multisite installations with pretty permalinks (the webhook address in the settings was built before WordPress had set up its rewrite rules).

= 0.59.0 =
* Fix: "Reconcile tracking IDs" and saving a post now also find your own Amazon tracking IDs in the modules for Divi and WPBakery (field of the chosen box type, e.g. `product_tracking`) and in Beaver Builder layouts (post meta `_fl_builder_data`/`_fl_builder_draft`).
* New: The shortcode generator offers your own templates from affilinode → Templates: "Custom template" for product boxes (all four layouts), the product grid and lists, and as further values of "Layout" for category views and deals. The shortcode then gets `template="custom:<slug>"` instead of the layout of the chosen tile.
* New: AAWP compatibility takes over sorting and filtering: `orderby`/`order` of several boxes, bestseller and new-release lists become `sort` (`order` in `[affilinode_amazon_list]`), `filterby="price" filter="available"` becomes `only_available="1"` and `filter="offer"` becomes `min_discount="1"`. Excluding filters, price limits and filters by title or ASIN are not reproduced.

= 0.58.0 =
* New: Modules for Divi, WPBakery Page Builder and Beaver Builder. One module "affilinode" per builder with a choice of every box type from the blocks and only the options of that type (Divi `show_if`, WPBakery `dependency`, Beaver `toggle`), language, country and loading mode on their own tab. Output through the shortcode renderer (same templates, caching, loading mode, tracking, click statistics, A/B test). Server-side preview in the builder (Divi Visual Builder via Ajax rendering, WPBakery frontend editor, Beaver Builder partial refresh) with notices instead of empty spaces. WPBakery has the product, list and category search below the ID fields; Divi and Beaver Builder an ID field with a hint. Only loaded when the builder is active (`et_builder_ready`, `vc_before_init` with `vc_map()`, `FLBuilder`).

= 0.57.0 =
* New: Template editor in the admin. Under affilinode → Templates you design your own product boxes, cards and list entries in HTML with placeholders – `{{title}}`, `{{price}}`, `{{#offers}}…{{/offers}}`, `{{#if rating}}…{{else}}…{{/if}}`, `{{{button}}}` – in the WordPress code editor, with a clickable list of all placeholders, error messages with line numbers and a live preview with sample products. Start from the built-in box, card or row, or from an empty template; duplicate, delete, export and import templates as JSON (also part of the settings export). Use them with `template="custom:<slug>"` in `[affilinode_product]`, `[affilinode_products]`, `[affilinode_list]`, `[affilinode_amazon_list]`, `[affilinode_deals]` and `[affilinode_context]` or choose them as "Layout" in the blocks and Elementor widgets. Safe by design: no PHP, its own small parser without `eval`, values escaped by default (as URL in `href`/`src`), `{{{…}}}` only for ready-made parts of the plugin, output through `wp_kses` with an extended allowlist unless the author has `unfiltered_html`. Affiliate links only through `{{{button}}}` and `<a {{{link_attrs}}}>` (tracking ID, sub-IDs, /go/ redirects, Amazon cart and click tracking stay intact), `rel="sponsored nofollow"` on every link of a template, and the ad label, disclosure, price date, Amazon notice and data sources are added below single boxes when a template leaves them out. Each template can have its own CSS (cleaned like "Custom CSS"). On AMP pages templates with their own script, style, images or form elements fall back to the built-in layout. Faulty or missing templates also fall back (with a note for editors). The mini card on text links keeps its fixed layout.

= 0.56.0 =
* New: AMP output of the boxes. AMP pages of the official AMP plugin (all modes) and of "AMP for WP" are detected (other AMP solutions: filter `affilinode_is_amp`). There every box is rendered on the server (no Ajax/hybrid loading, no placeholder), no JavaScript of affilinode is loaded, and the styles come as a compact AMP-compliant variant of only the needed stylesheets as inline styles (Reader templates: `amp_post_template_css`), together with the product JSON-LD. Search, product advisor and compatibility check work as forms with `action`/`target`, the price alert via amp-form (`action-xhr`), the tariff calculator as a form to the provider where the link allows it; running costs with default assumptions, price-performance chart with its table opened, comparison picker with the preselected comparison, carousels as a scrollable row without buttons, no mini card on text links. Images always have width and height. Click tracking, box statistics and the A/B test do not run on AMP pages; affiliate links there carry `data-vars-affilinode-*` for your own amp-analytics.

= 0.55.0 =
* New: Export and import settings: Settings → "Export and import settings" downloads all affilinode settings of the site (including automatic linking and tariff calculators) or of the network as a JSON file. Secret keys (API key, webhook secret, MaxMind licence key) only with "Include secret keys", with a warning. Importing shows a preview of every value that changes before anything is saved; all values go through the same checks as the settings form, missing values and empty keys keep what is saved. Multisite: network and site settings stay separate, sites never take over network-only settings. Only for administrators (`manage_options`, in the network `manage_network_options`).
* New: WP-CLI: `wp affilinode status` (version, connection, cache, scheduled tasks, syncs), `wp affilinode cache flush [--network]`, `wp affilinode sync [product-pages] [content] [--queue]`, `wp affilinode migrate <source>` (ATKP, AAWP, AffiliateTheme, Lasso, AmaLinks, ASA, SiteStripe in batches with a progress bar, `--analyse`, `--batches`, `--restart`, `--blog`; resumes after an interruption), `wp affilinode settings export|import` (with `--dry-run`, `--yes`, `--with-secrets`, `--network`) and `wp affilinode tracking sync [--send-only]`. Only loaded when WP-CLI runs; the commands use the same functions as the buttons in the admin.
* New: Carousel for lists and grids: `view="carousel"` (or `template="carousel"`) on `[affilinode_list]`, `[affilinode_products]`, `[affilinode_amazon_list]`, `[affilinode_deals]` and `[affilinode_context]`, also as layout "Carousel" in the blocks, Elementor and the shortcode generator. CSS scroll snap with previous/next buttons, arrow keys, Home/End and a screen reader status line, following the WAI-ARIA carousel pattern; no library, fixed card widths, works without JavaScript. No automatic slide change by default; `autoplay="<seconds>"` adds one with a stop button, pause on hover, stop on focus and never with reduced motion.
* New: Mini card on text links (off by default): Settings → Layout → "Mini card when hovering over text links" shows image, title, price with its date and the affiliate notice when the mouse pointer rests on `[affilinode_link]`, `[affilinode_field field="link"]` or an automatic product link, or when it gets keyboard focus. Prices only while current, Amazon prices at most 24 hours old. One floating card (no layout shift), dismissible with Escape, nothing on touch screens. Per link `preview="1"`/`"0"`, also in the "Text link" block and the shortcode generator.
* New: "Amazon buttons: add to the Amazon cart directly" (off by default): buttons to current, available Amazon offers in product boxes and `[affilinode_button]` use Amazon's add-to-cart form (`/gp/aws/cart/add.html?AssociateTag=…&ASIN.1=…&Quantity.1=1`) and say "Add to the Amazon cart" (also in the A/B test and instead of a custom button text). Text links, images, the price comparison and other shops are unchanged; links without ASIN or tracking ID stay normal links.

= 0.54.0 =
* New: "Running costs": `[affilinode_energy id="…" compare="…" years="5" price="…"]` and the block "Running costs" (also in Elementor and the shortcode generator) show electricity (and water) consumption and costs per year and over the chosen period from the values of the EU energy label (EPREL): washing machines, dishwashers and tumble dryers per 100 cycles with cycles per week, fridges per year, TVs and monitors with hours per day, other products roughly from their power rating. Optionally compared with a second appliance of the same kind ("In 5 years about 148 € less electricity and water costs than …"). Assumptions are always visible and visitors can change them live (energy.js); without JavaScript the defaults apply. Never uses purchase prices. New settings "Electricity price for running costs" (default 35 ct/kWh) and "Water price for running costs" (default 4.50 €/m³), new box type "Running costs" for tracking and statistics. Washing machines, dishwashers and tumble dryers need the affilinode server update with the field "energy consumption per 100 cycles" (filled from EPREL).

= 0.53.0 =
* New: Price-performance chart: `[affilinode_scatter type="…" field="…" highlight="…"]` and the block "Price-performance chart" (also in Elementor and the shortcode generator). A scatter chart without a library: current best price against a technical value, one point per product, each a keyboard-accessible link to the offer whose price it shows (with tracking); tooltip on hover and focus, highlighted product with ring, label and legend, line explaining which direction is better, outliers left out, table of all values to expand (also without JavaScript), responsive, dark mode and high-contrast mode. On websites under the Amazon Associates policy only shown when no price in it comes from Amazon (editors see a note). New box type "Price-performance chart" for tracking and the statistics.

= 0.52.0 =
* New: "At a glance": `[affilinode_glance id="…" count="6"]` and the block "At a glance" (also in Elementor and the shortcode generator) show the most important key values of a product as tiles with an icon per field group, the value with its unit and – where it can be ranked – five levels and a short text such as "better than 80 % of smartphones". The ranking compares with the central technical data of the whole category (at least 20 values); fields without a direction are only shown. `fields` picks the fields, `button="1"` adds a button to the best offer, otherwise the box has no affiliate links. Optionally in every product box (Settings → Display → "Show “At a glance” below product boxes", off by default; per box `glance="1"`/`"0"`, also in the product box block). Each tile has a text alternative for screen readers. New box type "At a glance" for tracking and statistics; cached with background refresh.

= 0.51.0 =
* New: "Best in category" – automatic top 3: `[affilinode_top type="smartphone" by="rating" limit="3"]` and the block "Best in category" (also in Elementor and the shortcode generator). Ranks the products of a category by test score (`by="rating"`), value for money (`by="value"`: key technical values per euro, or `by="value:<field>"`, e.g. most mAh per euro) or a technical value (`by="field:<field>"`, direction from the category). Shown as a podium (place 1 in the middle), cards or rows with the place number in medal colours, a badge on place 1 ("Test winner", "Best value", "Best: <value>", own text with `badge`) and "Why it ranks here" for each place. Updates itself (ranking cached for five minutes). Value for money only with current prices and never on websites under the Amazon Associates policy (editors see a note). New box type "Best in category" for tracking and the statistics.

= 0.50.0 =
* New: Alternatives: `[affilinode_alternatives id="…" kinds="cheaper,better,successor"]` and the block "Alternatives" (also Elementor and the shortcode generator) show small cards labelled "Cheaper alternative", "Better equipped" and "Successor" with the reason ("Battery capacity: 5,000 instead of 4,000 mAh") and any trade-off. Optionally below every product box (Settings → Display → "Show alternatives below product boxes", off by default; per box `alternatives="1"`/`"0"`, also in the product box block). Only products of your affilinode account, optionally only those of this website (`scope="site"`). No price signals: the reasons never mention prices or savings, and with Amazon prices the card only says "Alternative" unless Amazon granted a written exception. Tracking and click statistics with the new box type "Alternatives"; cached like spare parts with background refresh.
* Changed: The check marks of "Why it fits" (product advisor) use the full green for better contrast.

= 0.49.0 =
* New: Compatibility check "Does it fit my …?": `[affilinode_compat]` and the block "Compatibility check" (also in Elementor and the shortcode generator). Visitors choose their system – smart home hub (Home Assistant, Zigbee2MQTT, ZHA, deCONZ, Z-Wave JS, ESPHome, Tasmota, openHAB …), ecosystem or voice assistant (Matter, Alexa, Google Home, Apple Home, SmartThings), wireless protocol, battery platform of power tools, CPU socket or lens mount – from a list with a search field and see the matching products as cards or rows with the badge "Compatible according to <source>". With `product="…"` the box answers yes, no or unknown with the reason and the sources (links only to the public device lists, never to Amazon) and shows the product with its offers. Only systems for which your products have data can be chosen. The state is part of the address (`acc_system`, `acc_page`) and works without JavaScript; new box type "Compatibility check" in the statistics; accessible labels and status messages.

= 0.48.0 =
* New: Product advisor / buying guide quiz: `[affilinode_advisor id="…" view="grid"]` and the block "Product advisor" (also Elementor and the shortcode generator). Questions, answers and rules are built in the affilinode dashboard (Content → Product advisors, with suggested questions and a live test). Visitors answer one question at a time with a progress bar, back and start over; the result shows the usual cards or rows with "Why it fits" (check list), a match score and the badge "Best choice", plus a note when rules had to be relaxed. Without JavaScript all questions are one normal form; answers are part of the address (`aca_*`) and can be shared. Accessible: fieldsets with legends, focus moves to each question and to the result, a live region announces progress and the number of matches. Tracking and click statistics with the new box type "Product advisor"; the answer distribution (daily totals per question and answer, no personal data) is shown in the affilinode dashboard. Questions are cached for five minutes, results for one minute; the public route is rate-limited per IP and only runs advisors whose settings are signed by the server.

= 0.47.0 =
* New: Migration from Lasso and Lasso Lite, AmaLinks Pro and ASA1/ASA2. Compatibility mode (Settings → Compatibility, automatic by default, never while the original plugin is active or another plugin uses the shortcode name): `[lasso …]` and the Lasso block, `[amalinkspro …]`/`[amalinkspro_autoshowcase]`, `[asa]ASIN[/asa]`, `[asa_collection]`, `[asa2 …]`, `[asa2_img]`, `[asa2_textlink]` render as affilinode boxes, buttons, text links, images, grids or comparison tables; their tracking IDs stay per box. Lasso links to other shops stay links with exactly the same target. Move page: analysis, transfer of the ASINs as product requests, tracking IDs reported for the reports (also the standard tracking IDs from the ASA1 and AmaLinks Pro settings).
* New: Move page source "Amazon links (SiteStripe)": finds text and image links, old iframe image links, amzn.to/amzn.eu short links and Amazon addresses on their own line, lists them with post, ASIN and tracking ID, requests the ASINs and reports the tracking IDs. Short links are only resolved on click (throttled, robots.txt checked, affilinode user agent, redirect not followed).
* New: Step 4 "Convert posts" on the Move page for Lasso, AmaLinks Pro, ASA and Amazon links: preview of every place with its replacement, convert single posts or a selection, undo via the revision saved before the change (as long as the post was not edited afterwards). Amazon links become text links or boxes (choice), optionally keeping their tracking ID.

= 0.46.0 =
* New: Product search with filters (like the search & filter of Affiliate Toolkit): `[affilinode_search type="cordless_drill_driver" facets="brand,price,availability,field:voltage" per_page="12" view="grid"]` and the block "Product search". A search field with live results while typing, filters with counts in a sidebar (brand, current price from/to, availability, and the technical data of the chosen category: choices and yes/no as checkboxes, numbers as from/to), sorting (best match, popularity, price, name) and pages. On phones the filters open as a dialog. The search state is part of the address (`acs_q`, `acs_f[…]`, `acs_sort`, `acs_page`), so filtered results can be shared and work without JavaScript as a normal form. Results use the usual cards or rows with tracking and click statistics (new box type "Product search"); the number of results is announced to screen readers. `scope="site"` searches only the products used on this website. Only current prices count for the price filter and sorting (Amazon: at most 24 hours old; eBay API offers do not count), and there are no price signals. Answers are cached for two minutes, the public route is rate-limited per IP and only runs searches whose settings are signed by the server.

= 0.45.0 =
* New: Sidebar widget "affilinode" (`WP_Widget`): product box (compact or card), product list (stacked or grid), price comparison or deals for sidebars and footers, with product, list and category search in the widget form. Renders through the same shortcodes (`Shortcodes::call()`); clicks count as the new box type "Sidebar widget" (`box_kind="widget"`: click statistics, Awin clickref4, eBay "~bwidget"). Registered always – the block widget editor offers it as a legacy widget, the Customizer too. On single posts the clicks are assigned to the post, on archives to no post.
* New: Own redirects (off by default, Settings → Own redirects): affiliate links as `/go/<product>-<shop>` (readable) or `/go/<code>` (short) on your own domain. The plugin counts the click on the server (daily totals per link and post; no bots, link previews, prefetching or HEAD; no IP, cookie or user agent) and forwards with a 302 to the same affiliate link the box would show, including Awin clickref2–4 and the eBay custom ID. Amazon links are never redirected (Associates Program Policies). `/go/` is noindex (`X-Robots-Tag`), in the virtual robots.txt, excluded from speculative loading and never cached (`Cache-Control: no-store`, `DONOTCACHEPAGE`, LiteSpeed). New section "Redirects" under Reporting; filter `affilinode_go_link`; analytics click events keep the target domain (`link_domain`). Nothing is sent to affilinode.

= 0.44.0 =
* New: Amazon sales rank: `[affilinode_field field="sales_rank"]` shows the Amazon Best Sellers Rank in the main category ("No. 197 in Electronics"), and the new setting "Show Amazon sales rank" (Layout, off by default) adds it to product boxes showing the Amazon offer and below the Amazon offer in the price comparison. Only when Amazon provides a rank, and like Amazon prices never older than 24 hours. Needs the affilinode server update with migration 0137.
* New: Appearance settings (Settings → Layout): button size (small, medium, large), corner radius in px, button colour on hover (automatic or your own), badge colours for "test winner" badges, "value for money" badges and all others, and a "Custom CSS" field (only for administrators allowed to edit CSS, i.e. with `unfiltered_html`; HTML and `<` are removed, loaded only together with the affilinode styles). Everything works through the CSS variables of the boxes (`--acp-btn-h`, `--acp-btn-radius`, `--acp-radius`, `--acp-cta-hover`, `--acp-badge-winner` …); text colours of buttons, hover and badges are chosen automatically for sufficient contrast. A live preview with sample products shows the changes before saving. Badges are typed by their text ("Testsieger", "Preis-Leistung", "Preistipp" …), adjustable with the filter `affilinode_badge_type`.
* Changed: AAWP `[amazon fields value="prime"]` and `[affilinode_field field="prime"]` show editors a clear note: Amazon's Creators API no longer provides Prime eligibility, so affilinode shows no Prime label instead of guessing.

= 0.43.0 =
* New: Automatic links (off by default, affilinode → Automatic links): product names and category names in posts are linked automatically – products to the best offer or to the chosen shops in order ("Amazon first, otherwise Awin"), categories to the Amazon search with your tracking ID or to your own page of the same name, plus your own keyword list. At most N links per post (default 3), first occurrence only, whole words only (Unicode-safe, compounds stay whole), never in headings, links, code, captions, tables of contents or affilinode output. Per post type, per post (editor sidebar) and per category. Links like text links (rel, tracking, click statistics with the new box type "Automatic link", affiliate notice), never with a price, not in feeds. Settings page with preview and click figures. Terms are fetched daily and on demand.

= 0.42.0 =
* New: Sorting and filtering per shortcode (like `orderby`/`filter` in AAWP): `[affilinode_list]`, `[affilinode_products]` and `[affilinode_amazon_list]` take `sort` (`order` in the Amazon list) = `price|-price|rating|discount|title|position`, `only_available="1"`, `min_discount="…"` (percent) and `brand="…"`; `[affilinode_products]` also takes `limit`. `[affilinode_deals]` takes `sort` and `brand`, `[affilinode_offers]` takes `only_available="1"`. With sorting or filtering the whole list is loaded and shortened to `limit` afterwards. Only current shop prices count; eBay offers from the eBay API stay in their own block and never count for price or discount. With Amazon (no written exception) `sort="discount"` and `min_discount` are ignored as price signals, with a note for editors. Blocks, Elementor and the shortcode generator ("Advanced") offer the new options.
* New: `hide_unavailable="1"` on `[affilinode_product]`, `[affilinode_button]`, `[affilinode_link]` and `[affilinode_field]` and the setting "Hide unavailable single boxes" (off by default, product boxes and buttons): an unavailable product without an available replacement is left out; logged-in editors see a note. Hidden products are not added to the structured data.
* Fixed: A box loaded afterwards (Ajax/hybrid) that has nothing to show now disappears instead of keeping its loading skeleton (or outdated server HTML).
* Changed: In the offers table the separate "On eBay" block now sits directly below the price comparison (still visually separated, as eBay's terms require).

= 0.41.0 =
* New: Test rating (like the test score of Affiliate Toolkit): `[affilinode_rating id="…"]` and the block "Test review" show your own test – score in large print with scale and verdict in five steps (very good, good, satisfactory, adequate, poor), test date, verdict text, criteria as bars, pros and cons, badge and a button to the best offer. Scales: school grade 1.0–6.0, points 0–10 or 0–100, stars 0–5. The rating comes from the affilinode dashboard (product → "Test review", per language and website) or from the new post sidebar "affilinode: test rating" (meta box in the classic editor), which overrides it for one post or one product in the post. Always rendered on the server; accessible (score as text, bars and colours only decorative).
* New: `rating="1"` in `[affilinode_product]` and `[affilinode_products]` adds the test score to the box; comparison tables have the standard row "Test rating" (`review`, also in tables saved in the dashboard).
* New: Optional schema.org `Review` with `reviewRating`, `author` (post author or website name), `datePublished`, `reviewBody` and pros/cons (`positiveNotes`/`negativeNotes`) in the product's JSON-LD – only for `[affilinode_rating]` and only with the new setting "Test ratings as review in the structured data" (off by default, see the note about Google's guidelines). A product with a review is listed even if it only has Amazon offers (without price).

= 0.40.0 =
* New: eBay offers from the eBay API (field `ebayOffers`) appear in a separate, labelled block "On eBay" below the product box and the price comparison – never mixed with other shops, never the best price, no savings badge, and only while at most 6 hours old (eBay API License Agreement). `[affilinode_button shop="ebay"]` and `[affilinode_link shop="ebay"]` pick the cheapest eBay offer from that block.

= 0.39.0 =
* New: Click tracking for Google Analytics 4, Google Tag Manager and Umami next to Matomo (Settings → Analytics click tracking, formerly "Matomo tracking"). Each target can be switched on separately and is off by default; GA4, Tag Manager and Umami each take their own event name (default `affiliate_click`). The plugin only uses trackers your site already loads (`gtag`, `dataLayer`, `umami`, `_paq`/`_mtm`) and sends nothing if they are missing. Uniform event data: shop, product (affilinode ID), product_name (shortened), box_kind, position, post_id, link_domain (never the full affiliate URL) and, with "Event value: Price", value and currency. One click handler for all boxes, text links, fields and reloaded (Ajax/hybrid) boxes; middle and Ctrl clicks count, double clicks count once, navigation is never delayed (GA4 with `transport_type: 'beacon'`).
* Changed: The Matomo setting and its `_mtm` event name `acp_affiliate_click` are unchanged; content tracking (impressions) stays Matomo-only. The filter `affilinode_track_clicks` now switches all targets.

= 0.38.0 =
* New: Tracking IDs for the reports. The plugin reports the Amazon tracking IDs, Awin clickrefs, eBay campaign IDs and network sub IDs (Tradedoubler, ADCELL, CJ) it finds to affilinode, so that sales with older or additional IDs are assigned to the right website and subsite: when a post is saved (post field, `tracking="…"` in shortcodes and blocks, affiliate links in the content), during the move from AAWP (standard tracking ID from the AAWP settings, `tracking_id="…"`) and Affiliate Toolkit (tracking ID, clickref or campaign ID of each shop; the most used one as standard) and with "Reconcile tracking IDs now" (Settings → Matomo tracking, all posts in batches). Sent in bundles in the background, per subsite on multisite; errors and "no shop yet" are retried later. The status is shown in the settings and on the Move page.
* Changed: The move from Affiliate Toolkit now reads the tracking ID of the ATKP shops (still never keys or secrets); the move from AAWP reads the standard tracking ID from the AAWP settings.

= 0.37.0 =
* New: Comparison tables saved in the affilinode dashboard: `[affilinode_compare table="<ID>"]` shows the products in the saved order with the chosen rows – standard rows (image, title, price, button, rating, pros, cons, highlights), fields of the technical data and own text or yes/no rows – and the highlighted product with its badge (e.g. "Test winner"). Cached like lists; the webhook `compare_table.updated` refreshes it. Demo mode contains a sample table (ID `00000000-0000-4000-8000-00000000c0de`).
* New: `[affilinode_compare]` takes `rows="price,rating,field:display_size,…"` (rows and their order), `highlight="<position or product ID>"` and `badge="…"` for ad-hoc tables; without `rows` the comparison looks as before, now optionally with a highlighted column.
* New: The block "Product comparison", the Elementor widget and the shortcode generator ("Saved comparison table") have the fields table, rows, highlight and badge.

= 0.36.0 =
* New: Amazon tracking ID per box and per post. Every shortcode and block with affiliate links takes `tracking="…"` (also in the block sidebar, the Elementor widget, the shortcode generator and `affilinode_link()`/`affilinode_field()`); posts get the field "Amazon tracking ID for this post" (block editor sidebar, classic editor box, post meta `_affilinode_tracking` in the REST API for users who may edit the post). Box before post before the website's tracking ID from the dashboard; only the `tag` parameter of Amazon links changes. Invalid values are ignored and editors see a note.
* New: AAWP `tracking_id="…"` is no longer dropped: the compatibility mode keeps it as the box's Amazon tracking ID (`[amazon box|link|fields|table|bestseller|new]` and AAWP blocks).
* Changed: Ajax placeholders and hybrid boxes carry the tracking ID in their signed payload, the comparison picker passes it to its comparison table – so cached and reloaded boxes keep the right tag.

= 0.35.0 =
* New: `[affilinode_link id="…"]` – a text link to the best or a chosen shop (`shop="amazon|ebay|awin"`) in running text; `text="…"` or enclosed text sets the link text, `price="1"` adds the current price.
* New: `[affilinode_field id="…" field="…"]` – a single value of a product: price, title, link, button, url, shop, availability, stars, rating, reviews, image, thumb, brand, description, list price, savings, last update or ASIN. Both work with `id`, `asin` or `ean` and are always rendered with the page.
* New: PHP functions for themes, `affilinode_field( $product, $field, $args )` and `affilinode_link( $product, $args )`, returning escaped HTML (protected by `function_exists`).
* New: "affilinode link" in the format toolbar of paragraphs opens the shortcode generator with the text link and inserts the shortcode in place of the selected text. Also new: the blocks "Text link" and "Product field", both views in the shortcode generator and in the Elementor "affilinode box" widget.
* New: Clicks on text links and linked fields count in the click statistics like box clicks (box types "Text link" and "Product field", also in the Awin `clickref4` and eBay assignment).
* Changed: Prices from `[amazon fields value="price"]`, `[price]` and the new shortcodes show the "last updated" time and the affiliate notice as a tooltip (with an asterisk while the affiliate notice is on); the AAWP and AffiliateTheme fields now use the same output as `[affilinode_field]`.

= 0.34.0 =
* New: `[affilinode_amazon_list keyword="…" sort="bestseller|new" limit="10"]` – bestsellers or new releases on Amazon for a search term (optionally narrowed with `node="<browse node ID>"`), also as the block "Amazon bestsellers" and in the Elementor "affilinode box" widget. affilinode creates the list on first view, updates it at most every 24 hours via your own Amazon account and adds missing products within your product quota. While the list is being built, editors see a short note and the cache asks again after two minutes.
* New: AAWP migration – `[amazon bestseller="…"]` and `[amazon new="…"]` (with `items`, `grid`, `template` and a browse node plus `keywords`) now show such a dynamic Amazon list instead of a note for editors. Only a browse node without a search term still shows the note.
* New: AAWP migration – `[amazon fields]` also renders `image` (image address only, `image="2"` for the second image), `thumb`, `description`, `rating`, `star_rating`, `reviews`, `list_price`, `amount_saved`, `percentage_saved` and `last_update`. Price fields stay empty when the price is out of date, ratings only appear when the API supplies one.
* New: Send posts to affilinode for "Related to this article" (Settings → Related to this article, off by default). Title, address and text of public posts (without HTML and shortcodes, shortened) are sent in batches in the background when they are published or updated; deleted, unpublished or password-protected posts are reported as removed. Product pages and attachments are never sent. affilinode analyses each version once, so the context box only needs the page address.
* New: "Send all posts now" transfers all published posts once, in batches of 50 in the background, with progress, last transfer and last error in the settings.
* New: `[affilinode_context limit="3"]` – matching products for the current post, with Contextual Ads+ each suggestion shows its reason ("Matches: Zigbee, under €50"). Also available as a block.

= 0.33.0 =
* New: A product page for every product. Settings → Product pages → "Create a product page for every product automatically" reads the catalogue changes (`/v1/catalog/changes`) every hour and creates a page for each active product without one – title and excerpt from affilinode, as a draft or published ("Status of new product pages"). Large catalogues are worked through in several runs. Existing pages (also those linked by ASIN or EAN, drafts and pages in the trash) are never changed or duplicated, deleted pages are not created again, and pages of products deleted in affilinode are set to draft.
* New: "Synchronise now" in the settings and "Create product pages for all products" above the product list start a run immediately; both show the last run, the totals and the last error.
* New: `[affilinode_details]` – description (long text, otherwise the short one), pros and cons and the data sheet as a table per group, with `show="description,proscons,specs"` and `heading="2|3"`. Also available as a block and in the Elementor "affilinode box" widget. Empty sections are left out; rendered on the server so search engines see the text.
* Changed: The product page now reads box, "Description", your own text, "Price comparison" (up to ten offers), "Technical data" and price history. The box on the product page has no "Learn more" when the description follows below. New settings "Show description" and "Show technical data" (both on).
* New: `[affilinode_product … more="0"]` hides the "Learn more" section of the box.
* New: Structured data contain the product's short description; product pages always carry their product, also in Ajax mode.
* Fixed: When a box falls back to loading afterwards because the API was unreachable, the loader script is now always enqueued.

= 0.32.0 =
* New: Earnings per box type. Awin links get the box type in `clickref4` (product, products, list, offers, compare, button, tariffs, deals, price_history …), eBay partner links get it as `~b<type>` at the end of the custom ID. Parameters that are already set – for example by the affilinode API – are never overwritten.
* New: Reporting → "Group by" offers "By box type": clicks, orders, revenue and commission per box type, from the same network reports as the figures per post.

= 0.31.0 =
* New: Elementor widgets in their own "affilinode" category – "affilinode box" with a choice of every box type and only the options that type knows, plus product box, product list and price comparison as their own widgets. They use the shortcode renderer, so output, caching, loading mode, click statistics and tracking are the same as with the shortcodes.
* New: Product, list, category view and category search below the ID fields in the Elementor panel (via the plugin's own REST routes; the API key stays on the server).
* New: In the Elementor editor the boxes are rendered server-side; a notice appears instead of an empty space while nothing is chosen, while neither an API key nor demo mode is set up, or when there is nothing to show.
* New: Elementor stores the equivalent shortcode as the post's plain content, so the post check, prefetching and early loading of the stylesheets also find boxes on Elementor pages – and the boxes keep working if Elementor is switched off.
* New: The plugin knows which features your affilinode plan includes. "Device + plans" boxes and comparison calculators show editors a short note instead of an empty space if the plan does not include them; the transfer from AAWP, AffiliateTheme and Affiliate Toolkit says so before it starts (the analysis keeps working).

= 0.30.0 =
* Changed: Unique prefix "affilinode" everywhere – options, network options, transients, database tables, scheduled tasks, hooks, Ajax actions, nonces, the product page post type (`affilinode_product`) and its meta field, script handles, JavaScript globals, block names (`affilinode/…`) and the REST namespace (`affilinode/v1`). Existing installations are converted once on the first request after the update (per site on multisite).
* Changed: The shortcodes are now called `[affilinode_product]`, `[affilinode_list]` and so on. The generator, the blocks and the migrations write the new names. The old `[ac_…]` names stay registered as aliases (Settings → Compatibility, on by default) unless another plugin uses them.
* Changed: Blocks from earlier versions (`affiliate-central/…`) still render and can be converted to the new blocks; they no longer appear in the inserter.
* Changed: The REST routes are also available under the former namespace `affiliate-central/v1` (webhooks, cached pages, links in price alert emails).
* Changed: Template overrides are read from `your-theme/affilinode/` first, then from `your-theme/affiliate-central/`.
* Deprecated: Hooks named `affiliate_central_…` – use `affilinode_…`. Callbacks on the old names still run and trigger a deprecation notice.
* Changed: All texts in the source code are English. German (de_DE, de_DE_formal) ships as a translation, including the JavaScript of the shortcode generator; other German variants (de_AT, de_CH …) fall back to it.

= 0.29.0 =
* Prepared for wordpress.org: plugin slug and text domain "affilinode", English readme.
* New: `[ac_tariffs]` block "Device + tariffs" – the device without contract from the shops and, below it, offers with a mobile contract sorted by effective monthly price; also as a block and in the shortcode generator.
* Changed: Tariff calculators are now your own box (postcode and consumption fields, opens the partner's results). Embed codes of comparison portals are no longer executed.
* New: Amazon Associates policy 6(y) – with an Amazon account, price history, price alerts, deal lists and price signals are off unless a written exception is confirmed.
* New: Data sources with an attribution duty are shown under product boxes and comparison tables.
* Changed: Matomo click tracking is off by default.
* Fixed: Scheduled tasks are removed on deactivation.
* New: Migration from AAWP – `[amazon box|link|fields|table]` shortcodes and AAWP blocks are rendered with affilinode boxes once AAWP is deactivated; their ASINs can be requested on the Umzug (migration) page.
* New: Migration from AffiliateTheme – the theme's product shortcodes are rendered with affilinode boxes when another theme is active; the theme's products (title, ASIN, EAN) can be requested on the Umzug (migration) page.
* New: Product data for taken-over AAWP and AffiliateTheme shortcodes and blocks is preloaded in one batch per page, and the post check covers them too.
* Changed: Templates receive all variables as `$args` in addition to the individual variables; overridden templates in `your-theme/affiliate-central/` keep working.
* Changed: Template output is escaped at the point of output; the markup of the boxes is unchanged.
* Changed: The webhook route checks the HMAC signature in its permission callback.

= 0.28.0 =
* Changed: The API address is fixed (https://api.affilinode.com); only the API key needs to be entered.

= 0.27.0 =
* New: affilinode logo as menu icon.

= 0.26.0 =
* New: Readers' wish prices in topic ideas, adopt the A/B test winner, replace products directly in the editor, product boxes in the posts RSS feed.

= 0.25.0 =
* New: Editor sidebar that checks the products of the current post, internal link suggestions, deals RSS feed.

= 0.24.0 =
* New: Deals box, post statistics with weak boxes, topic ideas.

= 0.23.0 =
* New: Post check and weekly report by e-mail.

= 0.22.0 =
* New: Structured data (schema.org), click statistics per box type, category views in the shortcode generator.
