=== WFY24 Weather Widget === Contributors: wfy24 Tags: weather, widget, forecast, embed, temperature Requires at least: 6.0 Tested up to: 7.1 Requires PHP: 8.1 Stable tag: 2.5.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Free, embeddable weather widget for your WordPress site: current conditions and a 5-day forecast. One-click activation, 51 languages, auto location. == Description == WFY24 Weather Widget embeds a free weather widget from [wfy24.com](https://www.wfy24.com) in any post, page or widget area with the `[wfy24_weather]` shortcode. The settings screen can also publish a "Weather" page with the widget, or put the widget in your first sidebar as a Text widget that holds the shortcode. = Zero-friction setup = Activating the plugin opens **Settings → WFY24 Weather**, one screen with everything on it: 1. **Activate now (free)** — check the pre-filled admin email and your defaults (city, language, theme, units) and click once. The plugin registers your site with wfy24.com and the widget is live. No external signup, no copy/paste. 2. **Connect an existing WFY24 widget** — already have a key from an earlier install, from the wfy24.com widget builder, or from the main site of your Multisite? Paste it instead. 3. **Quick actions** on the dashboard — publish a "Weather" page with the widget ready to go, or add the compact widget to your first sidebar (a Text widget that holds the shortcode; offered only for themes with classic widget areas), each with one click. = Features = * **Free** — no credit card, no fees, no paid plan, no ads in the widget. Each widget shows a small "wfy24.com" credit link; see "Attribution" below * **One script** — `widget.js` from wfy24.com, added to the footer of the pages that show a widget (loaded asynchronously on WordPress 6.3 and later) * **Current conditions and a 5-day forecast** — temperature, feels-like, conditions, wind and humidity (each layout shows its own selection), fetched in the visitor's browser and refreshed every 10 minutes while the page is open in a visible tab * **51 languages** — the widget defaults to your site language; pick any of the 51 per site or per widget * **Admin interface in 15 locales** — the settings screen and activation form are translated into Bulgarian, Czech, Dutch, French, German (de_DE / de_AT / de_CH), Greek, Hungarian, Italian, Polish, Portuguese (pt_PT / pt_BR), Spanish and Swedish (strings added in 2.5.0 read in English until the catalogues are refreshed), and the activation link opens wfy24.com in your own language * **Auto location** — pin a city, or leave it empty for the visitor's approximate location (worked out by wfy24.com from the IP address of the request, no browser prompt); precise location with the visitor's permission is an opt-in toggle that applies only when no city is set * **Light / Dark / Auto theme** — Auto follows the visitor's light or dark system setting * **7 layouts** — Classic, Compact, Minimal, Badge, Forecast, Air Quality, Air Quality + Weather (wide) * **Shadow DOM isolation** — zero CSS conflicts with your theme * **Zero dependencies** — no jQuery, no React, no bloat * **Forecast from numerical weather models** — the forecast is wfy24.com's, based on DWD ICON (ICON-D2, ICON-EU or ICON global, depending on the region), ECMWF and NOAA GFS; air quality from the Copernicus Atmosphere Monitoring Service (CAMS) = Usage = Shortcode: `[wfy24_weather]` Override per instance: `[wfy24_weather city="paris-fr17807753" theme="dark" variant="forecast" lang="fr"]` In the block editor, put the shortcode in a Shortcode block. Version 2.5.0 also registers a **WFY24 Weather Widget** block, but its editor script fails to load, so that block cannot be inserted from the editor. = Attribution = Each widget shows a small credit link whose text is `wfy24.com`. It opens the wfy24.com forecast page of the place the widget shows, in a new tab; the place name in the widget links to the same page. The activation screen says so above the "Activate now (free)" button, before anything is set up. Version 2.5.0 has no setting that removes the credit link, and no paid plan is on sale. = External services = This plugin uses the WFY24 weather service at `https://www.wfy24.com`, which is served through Cloudflare. None of the requests below is a WP-Cron job. From your WordPress server (User-Agent `WFY24-WP-Plugin/2.5.0`; the activation and checkout requests add your site's address to it): * **Activation** — only when you click "Activate now (free)": a POST to `/api/widget/register-from-plugin` with the email address you confirmed in the activation form (pre-filled from Settings → General), your site's name and domain, the WordPress and plugin versions and the site locale. wfy24.com answers with your widget key and keeps the email address, site name and domain with it (the key itself only as a hash). If wfy24.com already holds a widget for that email and domain, it answers with the first characters of that key and a replacement-key link, and the plugin shows the "Connect an existing WFY24 widget" form instead of creating a duplicate. Pasting a key into that form sends nothing. * **City search** — admin only, while you type in a Default city field: the plugin's REST route `/wp-json/wfy24/v1/cities` sends the text you typed and the language of the admin screen to `/api/places/search`, server to server, so your browser does not call wfy24.com for it. Results are cached for 5 minutes per query. * **Structured data** — on by default ("SEO structured data (Schema.org JSON-LD)" under Advanced). When a page with a widget that has a city is rendered — that is, during your visitors' page loads, unless a page cache serves the page — your server asks `/api/places/search` for the place's name, sending only the city and the widget's language. Answers are cached for 24 hours, misses for 5 minutes. The search does not find a city given as a slug, which is what the settings store, so in 2.5.0 the structured data falls back to generic wording and the lookup repeats at most every 5 minutes per city and language. * **Pro status** — once a key is stored, at most once an hour, on a wp-admin request by an administrator (an open admin tab is enough: the WordPress heartbeat is such a request), the plugin GETs `/api/widget/pro/status` with the first 12 characters of your key. The answer decides whether the widget shows the wfy24.com credit link (a key on a Pro plan hides it; no paid plan is on sale). After a failed request it waits an hour. Version 2.5.0 has no setting that turns this check off. * **Pro checkout and billing portal** — only on an administrator's click. "Upgrade now" (hidden unless `WFY24_PRO_ENABLED` is defined as `true` in `wp-config.php`) POSTs the key prefix, the site's admin email address and its domain to `/api/widget/pro/checkout`; "Manage subscription" (shown only for a key on Pro) POSTs the key prefix and the full key to `/api/widget/pro/portal`. wfy24.com answers with a Stripe Checkout or Billing Portal page, which then opens in your browser. In your visitors' browsers (and in yours: the settings screen loads the same script for its live preview, before activation too): * **The widget** loads `https://www.wfy24.com/widget.js` and asks `/api/widget/data` for the weather with your widget key, the city when one is set, the language and the units — and again every 10 minutes while the page is open in a visible tab. The two Air Quality layouts also ask `/api/air-quality/current` (the city or the coordinates, no key). With a city set, no visitor location is used. With no city and "Auto-detect visitor location" off (the default), the browser first asks `/api/widget/ip-location`, where wfy24.com works out an approximate position from the IP address of the request, and then asks for the weather at that position; there is no browser prompt. With the toggle on, the browser asks the visitor for permission and, if it is granted, sends the latitude and longitude it reports; otherwise the IP-based position is used. The widget sets no cookies and stores nothing in the visitor's browser. What wfy24.com keeps: * **Web server logs.** For every request that reaches it, wfy24.com's web server (nginx) logs the IP address it came from, the time, the requested address, the Referer header (for the widget, normally just your site's address) and the User-Agent. In the widget's requests the key is cut to its first 12 characters; the city, or the latitude and longitude, stay as sent. The logs are kept for about 52 days, for security and troubleshooting, and then deleted. * **Error log.** The widget service's own log, kept for about a week, records an IP address only when no position can be found for it, coordinates only when no place is found near them, the email address and domain of an activation that fails, and, when a widget key is refused, the host name of the site the request came from and the first 12 characters of the key. * **With your key:** the email address, site name and domain from the activation, a request count for the current month and the times of first and last use. Nothing per visitor is stored beyond the logs above. Links: * WFY24 Terms of Service: [https://www.wfy24.com/en/terms](https://www.wfy24.com/en/terms) * WFY24 Privacy Policy: [https://www.wfy24.com/en/privacy-policy](https://www.wfy24.com/en/privacy-policy) * Cloudflare Privacy Policy: [https://www.cloudflare.com/privacypolicy/](https://www.cloudflare.com/privacypolicy/) * Stripe Privacy Policy (checkout and billing portal only): [https://stripe.com/privacy](https://stripe.com/privacy) == Installation == 1. Upload the plugin to `/wp-content/plugins/wfy24-weather-widget/`, or install via Plugins → Add New. 2. Activate the plugin via the Plugins menu. 3. **Settings → WFY24 Weather** opens automatically. Check the pre-filled email and your defaults, click **Activate now (free)**. Done — then use the quick actions (Create Weather page, Add to sidebar) or add `[wfy24_weather]` anywhere. If you already have a key (an earlier install of this plugin, the [wfy24.com widget builder](https://www.wfy24.com/en/widgets), or the main site of a sub-directory Multisite): 1. Go to **Settings → WFY24 Weather**. 2. Open **Connect an existing WFY24 widget** and paste the key (it looks like `wfy24_` followed by 32 letters and digits). A value of any other shape is rejected and nothing is changed. 3. Add `[wfy24_weather]` to any post, page, or widget area. == Multisite Support == The plugin is multisite-compatible. All settings (API key, defaults, page) are stored per-subsite using `get_option()`/`add_option()`, so each subsite operates independently. * **Network Activation does not contact wfy24.com.** It only loads the plugin code on every subsite. No `admin_email` is sent, no API key is created, no automatic phone-home occurs. * **Each subsite admin activates individually.** When the admin opens Settings → WFY24 Weather on a subsite and clicks "Activate now (free)", the plugin sends *that subsite's* domain and the email address confirmed in the form (pre-filled from `Settings → General → Email Address`) to wfy24.com to obtain a domain-bound API key, together with the other activation values listed under "External services". Before the click, the form shows the domain and the email address and names the other values — no consent is collected on behalf of admins of other subsites. * **New subsites added later remain inactive** until their admin activates them. The widget will not render on a subsite that has not been activated or connected. Nothing is sent for a subsite until its admin uses its settings screen: opening it loads widget.js from wfy24.com in the admin's browser for the live preview, typing in the Default city field searches wfy24.com, and only the "Activate now (free)" click registers the subsite. * **No centralized network admin panel** exists in this version — each subsite has its own settings page. * **API keys are domain-bound.** A key issued for `site-a.example.com` will not function on `site-b.example.com`, which means subdomain and domain-mapped multisite installs work correctly out of the box (each subsite gets its own key for its own domain). * **Sub-directory installs share one host.** On `example.com/site-a`, `example.com/site-b` … every subsite reports the same domain, `example.com`, so wfy24.com sees one site. Activate the main site normally; on each further subsite open **Connect an existing WFY24 widget** and paste the main site's key (the main site shows it under Settings → WFY24 Weather → Advanced). A second "Activate" with the same email on the same host is answered with "already registered" and the connect form, not a second key. == Frequently Asked Questions == = Is it really free? = Yes. No credit card, no trial, no paid plan, no ads in the widget. Fair-use rate limits apply (plenty for normal sites). = Do I need to create an account manually? = No. When you click "Activate now (free)", the plugin registers your site with wfy24.com using the email address in the form (pre-filled with your WordPress admin email). If you already have a key — from an earlier install, from the wfy24.com widget builder, or from another subsite — paste it into **Connect an existing WFY24 widget** on the same screen. = Can I revoke / change my key later? = Yes — visit [wfy24.com/en/widgets](https://www.wfy24.com/en/widgets) to manage keys (the "Lost it? request a replacement" link on the activation screen takes you to the same place). A replacement key issued there must be pasted into **Connect an existing WFY24 widget** in this plugin; the old key stops working within about 30 minutes. = What data is sent to wfy24.com? = See "External services" above. Two requests reach wfy24.com from your server without a click: the Pro status check (at most hourly while an administrator uses wp-admin, with the first 12 characters of your key) and the structured-data place lookup (when a page with a widget that has a city is rendered). Everything else from your server follows a click or your typing: activation, the city search, the Pro buttons. Your visitors' browsers load the widget from wfy24.com on every page that shows one. The plugin schedules no WP-Cron job and sends no analytics. = Can I customize the look? = The widget uses Shadow DOM for style isolation, so it won't clash with your theme. Choose from 7 layouts (Classic, Compact, Minimal, Badge, Forecast, Air Quality, Air Quality + Weather wide) and 3 themes (Auto, Light, Dark). = What languages are supported? = 51 languages. The site default follows your WordPress site language (choose another in Settings → WFY24 Weather); set the `lang` attribute on a shortcode to override it per widget with any of the 51 ISO 2-letter codes. = How do I find a city slug? = The Default city field in Settings → WFY24 Weather finds it for you and stores it. For a single widget, go to [wfy24.com](https://www.wfy24.com), search for the city and copy the last part of its forecast page's address: `www.wfy24.com/en/weather/paris-fr17807753` → `paris-fr17807753`. = Does it work with caching plugins? = Yes. The widget loads client-side, so full-page cache has no impact on weather freshness. = Does it work with Gutenberg / block editor? = Yes, through the shortcode: add a Shortcode block with `[wfy24_weather]`. The "WFY24 Weather Widget" block that 2.5.0 registers (Widgets category) fails to load in the editor, so it cannot be inserted there. = What data sources does WFY24 use? = The forecast is wfy24.com's, based on numerical weather prediction models: DWD ICON (ICON-D2, ICON-EU or ICON global, depending on the region), ECMWF and NOAA GFS. Air quality comes from the Copernicus Atmosphere Monitoring Service (CAMS). = Is there an attribution / "powered by" link? = Yes: one small link with the text `wfy24.com` in each widget, to the wfy24.com forecast page of the place shown. The activation screen says so above the "Activate now (free)" button. See "Attribution" above. = Can I remove the wfy24.com link? = No. Version 2.5.0 has no setting for it, and no paid plan is on sale. == Screenshots == 1. The welcome screen after activation — live widget preview and the activation status 2. The welcome screen on first open — "Activate now (free)" or enter a key manually 3. Classic widget layout rendered on a live WordPress page == Changelog == = 2.5.0 = * **Connect an existing WFY24 widget.** The activation screen gains a second form: paste a key you already have (from an earlier install of this plugin, from the wfy24.com widget builder, or from the main site of a sub-directory Multisite) and the dashboard opens at once. The key's shape is checked in the browser and again before saving; a malformed value is rejected and nothing changes. "I have a key — enter manually" now opens this form instead of leaving the site. * **Re-activation no longer dead-ends.** When wfy24.com already has a widget for this site and email, the plugin says so, shows the first characters of that key, opens the connect form and links to the replacement-key page — instead of printing "Could not activate". * **Widget language follows your site.** New installs and the activation form default to the WordPress site language (a German site gets a German widget) instead of English. Saved settings are untouched. * **Armenian.** The language list now matches the 51 languages the widget speaks. * **No more "Enable location" box on a fresh install.** With no default city and visitor geolocation off, the widget shows the weather for the visitor's approximate (IP-based) location, without a browser prompt. Turn on "Auto-detect visitor location" only if you want the browser's precise location with the visitor's permission; set a default city to pin one place. * **Structured data no longer prints the city slug.** The JSON-LD `name` and `description` were meant to use the resolved place name ("Weather forecast for Paris"); the lookup does not match a city given as a slug, so they use the generic wording. * **Attribution stated on the activation screen again** (it had dropped out of the unified screen in 2.0.0): the free widget shows a small wfy24.com link, and the screen says so above the Activate button. * **Pro checkout hidden.** The upgrade button, price and feature list are hidden; a "Pro is coming — notify me" link takes their place (defining `WFY24_PRO_ENABLED` as `true` in wp-config.php shows the old checkout; no paid plan is on sale). A key already marked Pro keeps rendering without the credit link. Checkout and portal failures are now shown as admin notices instead of failing silently, the hourly status check backs off for an hour after a failed request instead of retrying on every admin page load, and the billing-portal request identifies the site with its full key. * **Activation is stricter about what it stores.** An activation answer without a valid key is reported as an error and is never saved as an empty key. * Readme: outdated descriptions and claims removed; screenshot captions match the images; sub-directory Multisite is documented. * Readme corrected on 7 November 2026, with no code change: every request to wfy24.com and what wfy24.com keeps are documented, and statements that did not match what 2.5.0 does are gone. = 2.4.0 = * **Admin interface in 15 locales.** Adds Bulgarian, Czech, Dutch, French, Greek, Hungarian, Italian, Polish, Portuguese (European and Brazilian), Spanish and Swedish to the German set. Each one uses its own WordPress core admin vocabulary rather than a literal translation — Apparence → Widgets, Vzhled → Widgety, Външен вид → Джаджи — because that is what the person reading the screen already knows. * Separate European and Brazilian Portuguese, for the same reason the German set is split three ways: WordPress does not fall back between regional variants, and definições/configurações, guardar/salvar and ecrã/tela are different words in exactly the vocabulary an admin screen uses. * Tested up to WordPress 7.1. = 2.3.0 = * **German admin interface** — settings screen, setup wizard and all notices translated, with separate files for Germany (de_DE), Austria (de_AT) and Switzerland (de_CH). WordPress does not fall back from de_AT or de_CH to de_DE, so a site set to "Deutsch (Österreich)" or "Deutsch (Schweiz)" would otherwise have stayed in English; de_CH uses ss for the eszett throughout. * **Activation link now opens in your own language.** The "activate" and "manage keys" buttons pointed at the English page for every site in every language; they now follow your WordPress admin language to the matching wfy24.com page, falling back to English for languages the widget does not speak. * Translation template rebuilt from source: it covered 44 strings, 22 of which no longer existed in the plugin, against 98 strings actually in the code. Anyone translating from the old template was working from a file that was 22% complete and partly fictional. = 2.2.0 = * Completely redesigned widget: crisp SVG icons (no more emoji), condition-tinted accents, temperature range bars in the 5-day forecast, stat meters, and a refreshed light/dark look. * Country names now localized in all 50 languages (was: always Greek). * 5-day forecast (was 3), correct day/night icons worldwide, per-place local noon for daily icons. * Full right-to-left layout for Arabic, Hebrew, Farsi and Urdu. * Accessibility: reduced-motion support, screen-reader labels, WCAG AA contrast for text. * Imperial mode now converts precipitation (in/h) as well. * Faster and lighter on the host page: no more page-wide DOM observers, refreshes pause in background tabs, geolocation resolved once per page view. * Block editor: width control now cache-busts correctly; admin live preview reflects width and Pro attribution. = 2.1.1 = * **Fixed: aqi-wide live preview crushed in the 360px sticky sidebar.** When the saved/selected variant is `aqi-wide`, the settings-page preview now breaks out of the right-hand sidebar and renders in a full-width row above the form, so the horizontal weather + AQI bar has room to show its actual layout. On the published page nothing changes — the variant has always rendered correctly when given content-width room. = 2.1.0 = * **NEW: Wide AQI variant (weather + air quality side-by-side).** A new `variant="aqi-wide"` style places the location, current weather (icon, temperature, conditions, feels-like, daily high/low) on the left and a horizontal European-AQI bar (0–100+) with category label on the right. Designed for embeds that span the full content width, where the compact AQI card looks too narrow. * **NEW: User-controlled width.** All variants now accept a `width` attribute — `[wfy24_weather variant="aqi-wide" width="800px"]` or `width="100%"`. Accepts `400`, `400px`, `80%`, `100%`; invalid values are dropped silently. Set a site-wide default in *Settings → WFY24 Weather Widget → Default width* or override per shortcode / Gutenberg block. Empty value keeps each variant's built-in default. * Tested up to WordPress 7.0. = 2.0.2 = * **Fixed: Badge variant truncated text mid-word.** The badge layout has `overflow:hidden` and `white-space:nowrap`, but the segments inside didn't carry `data-fit-priority` hints — so when the embed sat in a narrow column (e.g. the admin's live-preview sidebar) the fit observer didn't know which parts to hide and the "Powered by WFY24" link was clipped mid-letter. Now the powered-by link, the description, the "Feels like" segment, and their dividers each have priorities; the observer hides them cleanly in priority order until everything fits. * **Fixed: "Add to sidebar" quick action shown for block-based themes.** On themes like Twenty Twenty-Three that register no classic sidebars, the action would always end in "Could not auto-add to sidebar — please add the widget manually from Appearance → Widgets". The button is now hidden on block-theme installs and replaced with a short note pointing to the Site Editor and the shortcode option. * **Requires PHP 8.1 (was 7.4).** PHP 7.4 reached end-of-life in November 2022 and is no longer receiving security patches. 8.1 is the lowest version Plugin Check / WordPress.org still recommends. = 2.0.1 = * **Fixed: AQI variant chips unreadable in dark theme.** The pollutant chips (PM2.5, PM10, O₃, NO₂) were using a translucent overlay that resolved to near-invisible against the dark theme's navy backdrop, leaving the value text floating on what looked like the bare widget bg. The chip background, text, and border now use solid theme-aware colors (slate-700 on navy in dark, white on pale-blue in light), and the chip text reads from a dedicated set of CSS variables that stay legible regardless of the cascade. * Version bump also serves as a Cloudflare-cache buster — the `?ver=2.0.0` query had been cached on the CDN with the original 2.0.0 bundle, so even after the widget.js fix landed on the origin, sites embedding the script kept loading the stale copy. `?ver=2.0.1` is a fresh cache key. = 2.0.0 = * **NEW: Air Quality (AQI) widget variant.** A new `variant="aqi"` style renders European-AQI air quality for the configured city — the big AQI index number, category band (good through hazardous, color-coded per the EEA scale), and the four headline pollutants (PM2.5, PM10, O₃, NO₂). Data comes from the Copernicus Atmosphere Monitoring Service (CAMS) via wfy24.com. Pick it from the "Style variant" dropdown in settings, or set it inline with `[wfy24_weather variant="aqi"]`. * **Premium admin redesign.** The plugin's two separate admin screens — the onboarding wizard and the settings page — have been merged into a single unified screen at *Settings → WFY24 Weather Widget*. New 2-column layout with a sticky live preview on the right plus inline quick actions (create Weather page, add to sidebar) so you never need to leave the page to set up an embed. The old `wfy24-welcome` URL still works — it now redirects to the unified screen. * **Re-organized settings.** Essentials (city, language, theme, units, style) are upfront; visitor location, SEO JSON-LD, and the API key sit in a collapsible Advanced panel. * **Embed snippet card** with one-click copy-to-clipboard. * **Removed: multi-city (`cities="..."`).** The v1.7.x multi-city feature is removed in this major release — the implementation needed a dedicated admin picker UI to be discoverable, and the new unified layout focuses on the most common single-city flow. If you had multi-city enabled, your shortcodes without `cities=` now fall back to your Default City; explicit `[wfy24_weather cities="..."]` shortcodes will only render the first city. The `wfy24_default_cities` option is preserved on update so no data is lost in case the feature returns later. * `widget.js` is unchanged, so every existing shortcode and Gutenberg block in published posts continues to render exactly as before. = 1.6.0 = * **NEW: Schema.org JSON-LD output.** Each widget instance now emits a server-rendered `WebPageElement` block describing the city (as `Place`), language, units, and provider. Helps search engines and AI agents understand that the page contains a weather forecast for a specific location — useful for semantic search, AI overviews, and future rich-result eligibility. Toggle from the settings screen (on by default). * **Canonical URLs + localized names.** The JSON-LD looks each shortcode's city up with the wfy24.com search API on the server side; when the search finds the place, the JSON-LD adds its wfy24.com `url` (e.g. `https://www.wfy24.com/el/weather/thessaloniki-gr57554537`) and a `Place` with its name in the widget's language (`İstanbul` for `tr`, `Θεσσαλονίκη` for `el`, etc.). Answers are cached in a WP transient for 24h, misses for 5min. In 2.5.0 the search does not find a city given as a slug, which is what the settings store, so neither is added (see 2.5.0). * Filter hooks for third-party customization: `wfy24_jsonld_enabled` (per-widget on/off) and `wfy24_jsonld_data` (modify the payload before emission). * No change to the visual widget — `widget.js` is unchanged. Existing shortcodes and blocks render exactly as before with the new JSON-LD appended. = 1.5.6 = * **Language combobox: clicking the field now shows all 50 languages, not just the saved selection.** Previously, focusing the field with "English" already saved would self-match the filter and the dropdown would only show the single English entry — useless for switching language. Now the picker detects when the input value equals an existing language's native or English name (i.e. the saved selection) and shows the full list so you can browse. * Both city and language inputs now select-all on focus, so typing immediately replaces the saved value instead of appending to it. * Removed the 12-item / 20-item slicing on the language list — the dropdown is scrollable, all 50 are now reachable. = 1.5.5 = * **Fixed: city and language suggestion dropdowns never opened.** The combobox stylesheet sets `display: none` as the default state for the suggestion list; the JavaScript was clearing the inline override (`element.style.display = ''`) which fell back to that CSS default — so the dropdown was always hidden, even though the REST proxy was returning matches and no console errors were thrown. Now sets `display: block` explicitly. Affects both the Default City picker and the Language combobox on the settings and onboarding screens. = 1.5.4 = * **City picker UX matches the public wfy24.com search.** The Default City dropdown now renders each result as a two-line item — country flag, bold place name, and a grey secondary line with region + country (e.g. "Athens" / "Attica, Greece") — instead of a single concatenated label. The picker also forwards the admin's locale to the upstream search so localized place names are returned. * **Keyboard navigation in the city picker.** ↑ / ↓ to move through results, Enter to select, Escape to close — same shortcuts as the public site's search dialog. Hovered and keyboard-active items share a single highlight state. * Internal: `/wp-json/wfy24/v1/cities` now returns structured fields (`slug`, `name`, `country_code`, `country_name`, `flag`, `region`) instead of a single pre-formatted `label`. Cache key includes the locale so per-language responses don't collide. = 1.5.3 = * **Onboarding overhaul.** Step 1 is now a complete configuration form — admin email (editable inline; no need to leave the wizard for Settings → General), default city (autocomplete search backed by wfy24.com places API), language (searchable combobox with all 50 supported languages shown in their native script and English name), theme, units, and a visitor-geolocation toggle — all set in one place before activation. Click Activate and the widget is live with your exact configuration. * **Visitor geolocation is now off by default.** Previously the widget would call `navigator.geolocation` whenever no default city was set, which triggered a browser permission prompt on every visitor and silently broke when declined. Auto-detect is now an explicit opt-in checkbox; the default is to honour the admin-set city (e.g. a tourism site for Crete shouldn't show a Swedish visitor's local weather). * **City picker.** Type a city name and pick from results (slug + flag + country) instead of needing to know the wfy24.com slug format. Powered by a server-side proxy (`/wp-json/wfy24/v1/cities`) so the admin's IP is never exposed cross-origin. * **Language combobox.** All 50 supported languages now appear in a searchable dropdown with native + English names; type-ahead filters by either. The free-text 2-letter code input is gone. * **Stronger Pro pitch.** The free-version notice now lists the full Pro feature set inline (no attribution, higher rate limits, priority support, custom CSS via theme tokens, historical data + analytics) instead of just "removes the link." * **Sticky settings access.** A "Open plugin settings" button is now pinned on the onboarding screen, and a "Skip onboarding" link routes admins straight to Settings if they prefer to configure manually. * **CORP header on widget.js + /api/widget/.** The hosted bundle now ships `Cross-Origin-Resource-Policy: cross-origin`, which makes the widget work in cross-origin-isolated environments (e.g. playground.wordpress.net) that ship `Cross-Origin-Embedder-Policy: require-corp`. = 1.5.2 = * **Activation transparency.** The onboarding wizard now displays a dynamic disclosure of the activation values sent to wfy24.com on click — the site domain, the administrator email currently configured in Settings → General (rendered live so the admin sees their own email before consenting), the site name, the WordPress version, the plugin version, and the locale. Admins who want to register with a different email are pointed to Settings → General and asked to change it before clicking Activate. * Documented multisite behaviour explicitly: per-subsite onboarding, no automatic phone-home on Network Activation, domain-bound API key per subsite. See the new "Multisite Support" section. = 1.5.1 = * Plugin Check compliance — replaced two `wp_redirect()` calls in the Pro flow (Stripe Checkout and Billing Portal) with `wp_safe_redirect()` plus a scoped `allowed_redirect_hosts` filter that whitelists `checkout.stripe.com`, `billing.stripe.com`, and `pay.stripe.com`. The redirect helper validates the target host against this list before issuing the redirect, falling back to a safe admin URL on mismatch. * Tightened the readme upgrade notice for 1.5.0 to fit the 300-character limit. * Cleaned up readme: the "External service" section and FAQ no longer reference the daily telemetry ping (removed in 1.4.0) — the plugin schedules no WP-Cron events. = 1.5.0 = * **WP.org compliance: replaced inline `