Repository navigation
Releases: webhead-GmbH/searcio
Release list
1.3.1
Built and verified locally, since GitHub Actions is not running jobs for this account (billing). The package follows deploy.yml step for step.
After updating from 1.3.0, activate the plugin again
The plugin's main file is now searcio.php, the name wordpress.org gives it (searcio/searcio.php). WordPress finds a plugin by its main file, so after the update it shows Searcio as inactive under Plugins. Activate it there.
- The settings, the sync history and the connection stay.
- Nothing has to be synced again.
What changed
- The plugin calls itself Searcio everywhere. That covers the admin menu, the settings screen, "Connect to Searcio", the "Searcio Search" and "Searcio Products" blocks and Elementor widgets, the Elementor category, Site Health, the WP-CLI help, the readmes and all seven translations. Before, these still said webhead Search Cloud or Search Cloud.
- The slug, the text domain and searcio.com stay
searcio. - The options, the REST routes, the admin page, the block names and
wp webhead-search-cloudkeep their names.
- The slug, the text domain and searcio.com stay
- A post's excerpt on a search result ends at a whole word, with "…" when it was shortened. Before, it stopped in the middle of a word.
- The product finder counts only the questions on the visitor's own path. A quiz with branches no longer says "Question 1 of 3" when two questions are all there is.
- The camera button for search by photo lines up with the icons beside it.
- In the block editor, the size sliders of the search block's Styles tab have space between them.
- On the Search Config tab:
- the AI search index status lines up with its description;
- each type boost is named by its content type.
- The plugin's link in the plugin list goes to its page on wordpress.org, https://wordpress.org/plugins/searcio/.
- The repository is https://github.com/webhead-GmbH/searcio.
- The screenshots for wordpress.org show all of the above.
Merged in #32, #33, #34, #35 and #36.
Package: searcio-1.3.1.zip, built from the merge commit ca3392a with one composer install, npm ci and npm run build.
- Size and layout: 1.26 MB zipped, 5.15 MB installed, 304 files.
searcio/is the only root folder; LF line endings, no hidden file, novendor, nocomposer.json. - Its
public/is byte-identical to the build the end-to-end tests and the screenshots used.
Clean site: WordPress 7.1 with WooCommerce, Elementor and WP_DEBUG_LOG on, served on PHP 8.3.
- Update from 1.3.0. 1.3.0 was installed and activated and a setting saved; 1.3.1 then went over it. WordPress showed the plugin inactive and did not load it. Activating it again brought back the saved setting and both tables, and recorded 1.3.1 as the installed version.
- What it registers:
- header "Searcio - Fast AI Product Search for WooCommerce" with the wordpress.org Plugin URI;
- 15 REST routes, the 3 capabilities, both tables and the daily sync;
- both blocks, as "Searcio Search" and "Searcio Products", and both Elementor widgets under the same titles;
- Site Health checks labelled "Searcio …".
- Translations: all seven languages load from the installed folder, with 28 script translations.
- Front end: the search block renders over HTTP and loads its script and styles from
searcio/public. - Deactivate and uninstall: deactivating unschedules the daily sync. Uninstalling keeps the settings and tables (the default).
- Debug log: the only entries are WooCommerce's and Elementor's own notices.
- Plugin Check: no error in the plugin's own code, and the same known warnings as before: block
render.phplocals and the WPML hook names. The rest is in the bundled framework autoloader and League code.
Tests:
- Unit 159 and Jest 307, on the code of
ca3392a. - Integration 280 and multisite 280, on PHP 8.3 with WordPress 7.1, WooCommerce and Elementor, with the plugin in a
searcio/folder. They ran on #33; #34 to #36 changed no PHP. - End-to-end, desktop Chrome:
- In a browser, all eight languages on the demo shop, on the build of #33:
- no JavaScript error;
- no text running out of its button, tab or chip;
- no old or lower-case name on any screen;
- the only English left is WordPress, WooCommerce and shop data.
All passing.
1.3.0
Built and verified locally, since GitHub Actions is not running jobs for this account (billing); the package follows deploy.yml step for step.
Before you update a site that runs 1.2.2 or earlier
The plugin's folder is now searcio/, the name wordpress.org knows it by, and WordPress takes it for a different plugin than webhead-search-cloud/:
- Under Search Cloud > General, check that Delete plugin data on uninstall is off.
- Deactivate and delete the old copy.
- Install
searcio-1.3.0.zipand activate it.
The settings, the sync history and the connection stay; nothing has to be synced again. With that setting off, deleting the old copy removes nothing; with it on, it would delete the settings the new copy reads.
What changed
- The plugin is now "searcio - Fast AI Product Search for WooCommerce", and its slug and text domain are
searcio. Only the translations follow the new name: options, tables, hooks, the admin page, the REST routes andwp webhead-search-cloudkeep theirs. - New: Support Searcio. A small searcio logo, linked to searcio.com, ends the search window, faded until it is pointed at. It is always shown on the Free plan; on a paid plan it can be turned off under Search Cloud > General.
- New: French, Spanish, Italian and Polish, and the German translation is complete (it had 270 of 720 strings). German also ships for Austria (
de_AT) and Switzerland (de_CH), whose sites WordPress did not give the German of Germany. - The General tab of the settings screen is named in the language of the screen.
- The admin menu and the settings header show the searcio mark.
- The compare table marks a missing value with "-", and the price filter separates its two fields with "-".
- The readme describes the plugin for its page on wordpress.org.
Merged in #26, #27, #28, #29, #30 and #31.
Package: searcio-1.3.0.zip - 1.3 MB zipped, 5.2 MB installed, 304 files, built from the merge commit da78a64 with one composer install, npm ci and npm run build, with searcio/ as its only root folder, LF line endings and no hidden file, vendor or composer.json. Against 1.2.2: 36 files added (the new translations), 73 changed, 5 removed (the German files under their old name); its public/ is byte-identical to the build tested in the browser. Installed from the zip on a clean WordPress 7.1 (PHP 8.3) with WooCommerce 10.9.4, Elementor 4.1.4 and WP_DEBUG on: it installs as searcio/, activates with an empty debug log, and registers 15 REST routes and the verification route, both blocks, both Elementor widgets, 3 capabilities, both tables, the daily sync and 7 Site Health checks. It translates under searcio in all seven languages from the installed folder, and keeps the installed-version record under its earlier name. The search block renders and loads its script and styles from searcio/public. Deactivating unschedules the daily sync, and uninstalling keeps the settings and tables (the default); the log stays empty throughout. Plugin Check as wordpress.org runs it: nothing in the plugin's own code; 20 low-severity findings in the bundled framework autoloader and League code, as in 1.2.2.
Tests: unit 151 on the release branch; Jest 289, integration 280 and multisite 280 on 341f9f3 (the translations branch, the code of master before the version bump), on PHP 8.3 with WordPress 7.1, WooCommerce and Elementor, with the plugin in a searcio/ folder. In a browser on a WooCommerce demo shop, every shipped language against English: the search window (browse, results with filters, AI assistant, product finder), the five settings tabs and the block's settings in the editor showed no JavaScript error, no text running out of its button, tab or chip, and no string of the plugin left in English. All passing.
1.2.2
Built and verified locally, since GitHub Actions is not running jobs for this account (billing); the package follows deploy.yml step for step.
Prices in the search
- Simple products are shown with tax when the shop shows prices with tax, as variable products always were. A variable product's range came from WooCommerce's display prices, and a simple product's price, regular price and sale price were the amounts as entered. A shop that enters prices without tax and shows them with tax therefore had simple products in the search without tax and variable ones with it, and the price filter compared the two. The other way round (entered with tax, shown without) was wrong too. Every price in the search is now the price the shop displays, rounded to its decimals.
- Grouped products show the range of their published children's prices, each child with its own tax class, as the shop shows it. A child without tax, a voucher for example, keeps its price.
- The prices are the same whoever runs the sync. A sync run with WP-CLI priced variable products for the address and VAT exemption of the user it ran as.
After updating, run a sync: Start sync on the Sync tab, or wp webhead-search-cloud sync run. The daily scheduled sync does it as well. It sends only the products whose price changes; no forced sync is needed.
Merged in #25.
Package: webhead-search-cloud-1.2.2.zip - 1.0 MB zipped, 4.4 MB installed, 273 files, built from the merge commit with one composer install. Five files differ from 1.2.1: the plugin file, readme.txt, the two block.json and includes/Indexing/Woo.php. Its public/ is byte-identical to 1.2.1's. Installed from the zip on a clean WordPress 7.1 (PHP 8.3) with WooCommerce 10.9.4 and WP_DEBUG on: activates with an empty debug log, 16 REST routes, both blocks, 3 capabilities, both tables, the scheduled sync and 7 Site Health checks. In a German shop that enters prices without tax and shows them with tax (19%), the installed package indexes exactly what WooCommerce displays: a simple product 119.00 reduced to 95.20, a variable one 59.50 to 119.00, a grouped one 25.00 (an untaxed voucher) to 95.20. It gives the same numbers when the sync runs as an administrator whose address is in Austria. The uninstall routine runs clean. Plugin Check reports no errors in the plugin's own code, and nothing at all in it when run as wordpress.org runs it.
Tests: on the code of the release commit c26b238 (the merge 5c1b73f holds the same tree), on PHP 8.3 with WordPress 7.1, WooCommerce 10.9.4 and Elementor 4.1.4: unit 108; integration 260, with 3 skipped that need a network; multisite 260. That includes 20 new tests of indexed prices under every combination of the tax settings, grouped products, and syncs run with no customer, with a customer abroad and with a VAT-exempt one. Against 1.2.1's code they fail with the reported numbers (100 where the shop shows 119). The browser specs were not run again, since nothing they load changed. All passing. Run on the host with PHP 8.3 and MySQL 8, not in wp-env.
1.2.1
Built and verified locally, since GitHub Actions is not running jobs for this account (billing); the package follows deploy.yml step for step.
A release of corrections to the settings screen. The storefront is the one 1.2.0 shipped: its script, its styles and every PHP class are the same files.
Settings screen
- The words in the header no longer flicker as they appear. The title and the description fade in word by word, and a frame after a word had arrived it was gone for one frame and back.
- The confirmation before disconnecting says what disconnecting does. It said that only the saved credentials are removed and that nothing in the Search Cloud account changes. Disconnecting has Search Cloud remove the site and permanently delete its search index; the shop uses WordPress's own search until the site is connected and synced again, and nothing in WordPress is deleted. The button that goes ahead reads Disconnect and delete the index.
- Numbers and dates follow the language of the WordPress profile, not the language of the browser. An English screen in a Persian browser read "۲۷۰٬۰۰۰ of ۳۰۰٬۰۰۰", and a date in the sync history came out in the Persian calendar. A date in the sync history is now written in the site's date format and time zone.
- How connecting works names the link for another email address by its label, Not this email?.
- The Terms of Service, Privacy Policy and Data Processing Agreement links on the Connection tab lead to the documents at
searcio.comwhen Search Cloud cannot be reached. They led to an address that asks for a password.
Also
- The package holds no
vendorfolder and nocomposer.json. The plugin loads its own files throughincludes/autoload.php; it used to carry avendorthat held Composer's autoloader and nothing else. Nothing changes in how it works. - webhead plugin framework 1.5.0. The build gives a package the dependency npm installed for it, which is what ended the flicker: the settings script carried an older animation engine than the one it asks for.
- The readme says what connecting sends to Search Cloud, and what saving the Search Config tab sends.
The full list is in readme.txt and CHANGELOG.md. Merged in #19 to #24.
Package: webhead-search-cloud-1.2.1.zip - 0.99 MB zipped, 4.4 MB installed, 273 files, built from the merge commit with one composer install. Its public/ is byte-identical to the build the end-to-end specs ran against. Installed from the zip on a clean WordPress 7.1 (PHP 8.3) with WP_DEBUG on: activates with an empty debug log and without a vendor folder, 16 REST routes, both blocks, the admin menu, 3 capabilities, both tables, the scheduled sync and 7 Site Health checks registered; the framework's ten helper functions are there in the plugin's own namespace; the German translation loads; the uninstall routine runs clean. A package of the same tree, built one commit earlier: both Elementor widgets with Elementor and WooCommerce active; a page without a search block loads nothing of the plugin; in a browser, desktop and phone, the settings screen, the Sync tab, the Connection tab and the search modal pass 72 specs with the debug log empty; Plugin Check reports no errors in the plugin's own code, nothing at all in it when run as wordpress.org runs it, and no missing_composer_json_file.
Tests: on 8457938, the tree this release holds apart from two entries moved in CHANGELOG.md and readme.txt: unit 108, integration 240 with 3 skipped on PHP 8.3 with WooCommerce and Elementor loaded, multisite 240, JS 283, and the 72 browser specs above. On the tree of #22, which builds to the same public/: the seven admin specs, 77 passed and 1 skipped by its own rule on a narrow screen. The storefront specs were not run again, since no file they load changed since 1.2.0. All passing. Run on the host with PHP 8.3 and MySQL 8, not in wp-env.
This release replaces one published under the same number on 2026-10-07 from 07a5660, which had not been installed anywhere; that one carried vendor and composer.json and framework 1.4.1.
1.2.0
Built and verified locally, since GitHub Actions is not running jobs for this account (billing); the package follows deploy.yml step for step.
Requires WordPress 6.8, up from 6.0. A site on an older WordPress keeps the version it has.
Sync
- A sync that meets an error no longer stays paused until somebody resumes it. Until that click no scheduled sync ran and no change made in the shop was sent, so a price or a stock level could be wrong in the search for days. A sync that cannot reach Search Cloud now stays running, says when it tries again, and sends the same batch after 1, 2, 5, 10, 15 and 30 minutes. If that fails too it ends as failed, which lets the changes through again.
- The daily scheduled sync continues a paused sync. A sync an earlier version left paused comes back within a day of updating, or at once with Resume. A pause made by hand now lasts until the next scheduled sync at the latest, and the Sync tab says so.
- A batch that is sent again is counted once in a sync's Processed and Failed numbers.
wp webhead-search-cloud sync runwaits and tries again as the background sync does, and exits with an error when the sync did not complete. It used to report a failed sync as completed.
Storefront
- Cards designed in Search Cloud are drawn again. A placement set to the Search Cloud card design has shown an empty modal since 1.0.2. The cards come out as the panel draws them: without the plugin's own card frame round them, and without the site's styles for headings, links and images reaching into them.
- The search looks the same on a site that styles every element. A customized Elementor kit, or a theme's rules for buttons, fields, links and headings, no longer changes the modal's chips, filters, fields and cards. The site's own font, text size and text colour are still followed. Theming through the
--whsc-*properties is unchanged; a rule of your own that restyles a.whsc-*element directly now needs!importantto win. - The arrow keys move through the search suggestions, and Enter searches for the one they are on.
- A link in an AI assistant reply is shown as a link instead of as brackets and an address. Only an
http(s)address or a path on the site becomes one. - The results carousel works in right-to-left languages: its arrows, its page dots and the arrow keys.
- Keyboard focus rings are drawn whole on filter chips, carousel cards, the Compare switch and the compare table, and at the same width on every screen.
- The message shown when a search or a photo search fails matches the rest of the modal, and the search box's placeholder follows the colour of the box's text.
- A page without a search trigger no longer costs a database query and the loading of translations.
Admin
- The settings screen is redrawn with WordPress's current components: one title, a tab strip that scrolls on a phone, and the same cards, fields and notices throughout.
- A screen that could not load says why and offers to try again, and a save that fails is reported beside its button with the reason.
- Clearing the sync history, deleting a run from it and disconnecting from Search Cloud ask for confirmation first.
- The Elementor widgets are listed under webhead Search Cloud in the editor panel instead of General. Widgets already on a page are unaffected.
Also
- webhead plugin framework 1.4.0. The package no longer carries the framework's updater or its command runner.
- REST routes describe their parameters, so a value of the wrong shape is refused with a 400.
The full list is in readme.txt and CHANGELOG.md. Merged in #18.
Package: webhead-search-cloud-1.2.0.zip - 1.01 MB zipped, 4.5 MB installed; its public/ is byte-identical to the build the end-to-end suite ran against. Installed from the zip on a clean WordPress 7.1 (PHP 8.3) with WP_DEBUG on: activates without a notice, 16 REST routes, both blocks, both Elementor widgets, the admin menu, 3 capabilities, both tables, the scheduled sync and 7 Site Health checks registered; the German translation loads with the new sync messages; the search block renders, and a page without it loads nothing of the plugin. With every outbound request answered locally: a sync whose batch fails stays running and waits 1, 2, 5, 10, 15 and 30 minutes, carries on when the index answers, is continued by the scheduled sync when it is paused, and is given up at the seventh failure; a WooCommerce product reaches the index with its price, stock status and parent category, and a change of price and stock is sent by the incremental sync. The uninstall routine runs clean. Plugin Check reports no errors in the plugin's own code, and nothing at all in it when run as wordpress.org runs it.
Tests: on the release commit 5f1935a (the merge e040232 holds the same tree): unit 96, integration 240 with 3 skipped on PHP 8.3, multisite 240, JS 276, and a browser pass of 27 over the search modal, the settings screen and the Sync tab. On fae3fcb, one commit earlier - the release commit changes version strings only and builds to the same public/: end-to-end 255 on desktop and mobile with Elementor active, 7 skipped by project. All passing.
1.1.0
Built and verified locally, since GitHub Actions is not running jobs for this account (billing); the package follows deploy.yml step for step.
New
- Search by photo. Shoppers can upload a photo, or take one on a phone, instead of typing, and see the tags the vision model read. The button only appears when the site has the feature turned on.
- A guided quiz tab that turns a few questions into a filtered search. It appears once a quiz is published in the Search Cloud panel.
- Similar products - a "you may also like" row for product pages, driven by meaning rather than shared tags.
- Curated category listings - a block and Elementor widget that finally let merchandising rules for a category apply on that category's page: pinned products first, hidden ones gone, the rule's banner above.
- Search-term redirects - send a search straight to a page instead of showing results.
- Price (and any numeric facet) filtering with a minimum and a maximum, a Load more button past the first twenty results, and the plan's monthly usage on the Connection tab.
Indexing
- Products are indexed under their parent categories too, so filtering on "Shoes" - or a quiz answer or merchandising rule naming it - finds products filed under "Sneakers".
- Category, tag and attribute names no longer show HTML entities such as "&" in filters and the compare table.
- Renaming, moving or deleting a category now updates the products in it without a manual sync.
- WooCommerce products set to "Search results only" are indexed, and "Shop only" ones are not.
Existing documents pick up the parent categories and decoded names on the next sync, scheduled or started by hand. No forced re-sync is needed.
Elementor
- The widget can keep its search modal open while you edit it, optionally with a search already run, so style changes show as you make them.
- Its settings are regrouped by the part they style, with new ones for the overlay, the modal's font and content width, a centred floating dialog, card images, the sale badge, the carousel's card width and arrows, filter group names, title lines, the stock line and the trigger's alignment and width. Every existing setting is kept, so saved widgets lose nothing.
Storefront, accessibility and small screens
- A visible keyboard focus ring on every control in the modal, an accent colour that passes contrast wherever it is text, focus that follows the quiz and phone layouts, and the reduced-motion setting respected throughout.
- Better on phones: results above the recent and popular searches, scrolling mode tabs, larger carousel dots, and no iOS zoom on the assistant and price fields.
Sync
- A full sync removes every document the site put in the index that is no longer indexable, whichever sync pushed it.
- Removals that fail - from the incremental sync or from a full sync's clean-up - are kept and retried by every full sync until they succeed, so nothing stays searchable for good.
Security
- The domain-verification endpoint no longer returns the site's write key to unauthenticated callers.
- The write key and secret are no longer sent to the browser, even encrypted.
Also
- The search service moved to https://searcio.com. Nothing to do on your side; existing keys keep working.
- webhead plugin framework 1.3.1. No more "translation loading was triggered too early" notice on WordPress 6.7+.
- Tested up to WordPress 7.1.
The full list is in readme.txt and CHANGELOG.md. Merged in #17.
Package: webhead-search-cloud-1.1.0.zip - 0.84 MB zipped, 4.0 MB installed. Installed on a clean WordPress 7.1 with WP_DEBUG on: activates without a notice, 16 REST routes, both blocks, both Elementor widgets, the admin menu, 3 capabilities, both tables, the scheduled sync and 7 Site Health checks registered; the German translation loads; a WooCommerce product reaches the index with its parent category, decoded; the uninstall routine runs clean. Plugin Check reports no errors in the plugin's own code.
Tests: on the release commit, unit 93 and integration 209 on PHP 8.3 and 8.4, multisite 209. On the merged PR (the release commit after it changed no JavaScript, and the widget it touched prints the same markup): JS 230, and end-to-end 197 of 202 on desktop and mobile with Elementor active - the 5 skips are phone-only checks on the desktop run. All passing.
1.0.4
Front-end fixes to the AI assistant and the product comparison, found by testing against the real shop with real WooCommerce products.
- The assistant's answers now render properly. It is an LLM and replies in Markdown, so a reply literally read
**Price:** 19,99 €on the storefront. Answers now render as real text, lists and emphasis. The reply is third-party text, so it is turned into elements directly and never passed through as HTML. - The comparison table no longer shows indexing internals. WooCommerce attributes arrive prefixed, so a row read "Attr color"; the indexing timestamp appeared as if it were a product attribute; the same attribute could produce two identical rows; and values showed raw ("instock"). Prefixes are stripped, acronyms like SKU read correctly, internals are excluded, duplicates merge, values are humanized, and rows that actually differ between products sort to the top — a row where every product says the same thing helps nobody choose.
- Comparison columns keep a readable width on a phone instead of squeezing until titles truncate.
- Turning on the AI assistant no longer restyles the Search tab. The close button used to move out of the search input row into the tab bar; the search tab keeps its own again.
Also refreshed the npm version markers and the composer lock hash, which had drifted.
Tests: JS 143, PHP unit 87, integration 104. The built package was activated in a real WordPress: 16 REST routes, block registered, admin menu and capabilities in place.
Merged in #16.
Packaging: the JavaScript source is no longer bundled. wordpress.org needs the unminified source for the built files in public/, and the readme now links the repository and gives the build command instead — 130 KB off the download.
1.0.3
Built and verified locally, since GitHub Actions is over its monthly quota.
- Documented the external service the plugin talks to, as wordpress.org requires: what is sent when you sync, when a visitor searches, and when the AI assistant is used, with a link to the privacy policy.
- The package now carries the JavaScript sources alongside the built bundles, so the compiled assets can be checked against their source.
- Updated the webhead plugin framework to 1.2.0. The distributed package no longer carries development tooling:
symfony/console(~1.7 MB) and the framework's scaffolding CLI (~590 KB across 61 template files) were bundled but never loaded at runtime. The prefixed dependency bundle drops from 3.7 MB to 1.3 MB. - Front-end requests no longer scan the plugins directory. The framework resolved declared plugin dependencies on every request to build admin notices and a Site Health field, which outside wp-admin means globbing the plugins directory once per dependency; notices are now built only in wp-admin and the diagnostics field is deferred.
- Fixed the bundled WP-CLI commands (
cache,capabilities,jobs,upgrades) declaring--yesas a required flag, which made WP-CLI reject the very flag it told you to re-run with — leaving those commands impossible to run. - The AI assistant's message field now has its own border-radius control, in both the block editor and Elementor.
- The AI Assistant tab and its conversation can now be styled like every other part of the widget, in both the block editor and Elementor: tab colours (text, active, underline, divider), the assistant accent and reply text, and your-message bubble colours.
- The frontend filter list is capped in height and scrolls instead of stretching the modal when a field has many values; the cap is themeable per placement (default 132px).
- Fixed the storefront search and AI assistant showing English on a translated site. Every source file has to be listed in the script translation map for its strings to reach the browser, and the files added by recent features never were — so the whole assistant surface stayed English no matter how complete the translation was. All six missing files are mapped, the German translation is filled in for all 36 storefront strings, and a test now fails if a file with translatable strings is left out of the map.
- Reworked the assistant's waiting state. A bare spinner said only "something is loading"; it now says Thinking, with a shine travelling through the word and three dots rising in turn, so a wait of several seconds looks alive. Both stop for visitors who prefer reduced motion.
- The send button's arrow was sitting high and right of centre, and when disabled it was filled the same colour as the composer, so it vanished and left a grey arrow floating in the field. The glyph is redrawn centred and the disabled state is now a visible button.
- The conversation is anchored to the bottom of the pane, like every messenger, instead of clinging to the top with a large empty gap above the input.
- A failed answer now appears as a message from the assistant — same avatar, in a tinted bubble — with a Try again action that re-sends the question instead of making you retype it.
- Removed a group of orphaned options on upgrade. An earlier sync and onboarding flow kept its progress in standalone options — a discovery counter and status, initial-sync flags, several "last run" timestamps and a sync interval — which nothing has read since the current engine moved all of it into the sync-runs table. They lingered in the options table, where a value like a discovery status still reading "running" looks like live state. The opt-in "delete my data" uninstall path clears them too, for sites removed without ever reactivating.
- The Search Config tab now covers the whole of Search Cloud's search configuration. Merchandising rules (pin products to the top of a search, keep products out, show a banner) and the three site-level switches — AI search with its index status, AI visual tagging, and ranking by what visitors click — were only editable in the Search Cloud panel; the API exposes them now, so they are editable here too. A switch your plan does not include is shown but disabled, with the reason.
- Fixed click-through tracking never recording anything. The beacon sent a JSON body, which is not a CORS-safelisted content type, so the browser had to preflight it — and the API answers preflight requests without any CORS headers, so every click was blocked before it left the page. The beacon is now form-encoded, which needs no preflight and which the API reads identically.
- Fixed a sync that could stop dead with no way back: the follow-up worker tick was only scheduled at the very end of a tick, so a tick killed part-way through (a slow API against PHP's
max_execution_time, an out-of-memory, a restarted worker) left the run on "Running" with nothing left to advance it — and because a run in that state holds the single active slot, every later scheduled sync silently did nothing. A tick now arms its successor before it starts working, and the scheduled sync revives a run whose worker has died instead of skipping it. - Ticks are now time-boxed (20 seconds by default, filterable with
webhead_search_cloud/sync/tick_budget) rather than bounded only by a batch count. Removing stale documents costs one request each, so a large clean-up could previously run hundreds of blocking requests in a single tick and be killed part-way through. - Documents the index refuses to delete are now counted and reported on the sync run instead of being dropped from the queue in silence — a failing delete endpoint used to look exactly like a healthy clean-up, with "deleted 0" and no explanation.
- Incremental syncs now say why they failed. A failed incremental run was written to the history with no reason at all, and a rejected push that wasn't a plan-limit recorded nothing whatsoever, so the dashboard showed either an unexplained failure or no sign of a problem at all.
- Removed the leftover
webhead_search_cloud_site_idoption on upgrade. Nothing has read it since the connection moved to key-relative endpoints — the connection screen reads the id straight from the API — so all it did was go quietly stale and mislead anyone inspecting the options table (one site still held5while the API reported4). - Fixed sync history retention never deleting anything: the purge built a comparison query the database layer then rejected, so the runs table grew without bound however the retention setting was configured.
Package: webhead-search-cloud-1.0.3.zip - 0.8 MB zipped, 4.1 MB installed. Verified by activating it in a real WordPress: 16 REST routes registered, the block registered, capabilities granted.
Tests: unit 87, integration 104, JS 129 - all passing.
1.0.2
Security-hardening release from a pre-release audit of the plugin. No breaking changes.
Security
- Server card rendering — the server-designed result card renderer now fully escapes indexed field values (quotes included) and strips
javascript:/vbscript:/data:URL schemes from templatedhref/src, so a value from an indexed document can no longer break out of an HTML attribute or inject a script-bearing link. Affected sites using the "Search Cloud templates" card source. - Domain-ownership verify endpoint — the public
search-cloud/v1/verifyroute now requires the verification token the Search Cloud ping always sends, so a tokenless request can no longer read the write key. - Protected meta — WordPress protected meta (keys starting with
_) is no longer pushed to Search Cloud through ameta:field mapping by default, preventing accidental exposure of internal data in public search. Opt a specific key back in with the newwebhead_search_cloud/index/allow_protected_metafilter.
Build
- Excluded the local
.wp-env.override.jsondev file from the release package.
Full details in PR #2.
v1.0.1
- Fixed a sync that could stay stuck on "Running" when its background worker stopped (WP-Cron disabled, no site traffic, or a tick killed mid-run). Pause, resume, and cancel now detect a dead worker and act on the run directly instead of parking a control signal no live tick will ever read; cancelling also clears any stray scheduled tick and frees the active slot so a new sync can start.
- Added a wp-env integration test suite (activation, the sync REST endpoint, and the full start/tick/complete and dead-worker recovery workflows) alongside the existing unit tests.
What's Changed
- fix(sync): recover stuck Running syncs + add wp-env integration test suite by @mohammad425 in #1
New Contributors
- @mohammad425 made their first contribution in #1
Full Changelog: 1.0.0...1.0.1