Seekmodo Search

Description

Seekmodo Search replaces the built-in WordPress site search (and the
WooCommerce product search, when WooCommerce is active) with an AI-powered
search experience served by the Seekmodo platform at mcp.seekmodo.com.
One plugin, two activatable verticals:

  • Content vertical — WordPress core search via pre_get_posts +
    posts_pre_query. Auto-detects public Custom Post Types so blog posts,
    pages, docs, and your custom CPTs all participate in the same ranked
    result set.
  • Commerce vertical — WooCommerce product search via
    woocommerce_product_query + posts_search. Indexes products plus
    variations, stock state, price, SKU, and attributes. Auto-on when
    WooCommerce is detected; dormant otherwise.

What you get:

  • AI search out of the box — vector recall + commerce-aware reranking
    on top of Typesense, with no relevance tuning required to start.
  • Typo tolerance, partial-word matching, and prefix-matched typeahead
    via a single REST endpoint your theme can hit from any autocomplete
    widget.
  • Click-through telemetry feeds a self-tuning learn-to-rank pipeline.
    Relevance gets better as your shoppers interact.
  • Always-on safety net — every gateway-talking entry point falls
    through to native WP_Query (or WC_Query for products) inside the
    same request when the platform is unreachable. Visitors never see an
    empty results page. A per-tenant circuit breaker prevents repeated
    timeouts from compounding.
  • Multi-environment safe — Seekmodo locks each tenant to a canonical
    storefront host. Staging / dev clones are auto-detected and return
    no-op from every gateway entry, so your production index is never
    polluted by a non-production deploy.
  • Settings tunable remotely — flip search mode, adjust ranking knobs,
    and toggle the “Powered by Seekmodo” badge from
    https://admin.seekmodo.com; the connector picks the change up on
    the next 5-min cadence.

External service dependency. Seekmodo Search is the WordPress
connector for the Seekmodo AI search platform. The platform is a
hosted service operated by Numinix Technology Inc. at
https://mcp.seekmodo.com and https://admin.seekmodo.com. The
plugin connects your site to a Seekmodo tenant via an HMAC-signed
pairing flow; once paired, the plugin sends indexable post / product
data to mcp.seekmodo.com and queries it for search results, typeahead
suggestions, and click telemetry.

Free trial. Every Seekmodo plan ships with a 14-day free trial at
$0 — full features, unlimited searches, no card required upfront.
Cancel before day 14 and you pay nothing. After the trial, plans
start at $29/month. Pricing details, including how the plan auto-sizes
to your real traffic during the trial: https://seekmodo.com/pricing.

What happens if you stop paying. The plugin does not break your
site. If the gateway is unreachable, your subscription lapses, or
you simply uninstall the plugin, every search entry point falls back
to native WordPress / WooCommerce search inside the same request. No
white screens, no fatal errors, no broken search box.

Privacy + data handling.
https://seekmodo.com/legal/privacy lays out the full picture, but
in short: searchable post / product content you choose to index is
sent to mcp.seekmodo.com; visitor search queries and clicks are sent
to mcp.seekmodo.com as telemetry; no personal data about your
visitors leaves your site unless you opt in to additional
analytics integrations from the Seekmodo admin. The plugin
self-checks for stale indexes, configuration drift, and update
availability — all such phone-home requests are vanilla HTTPS GETs
that carry no tenant ID and no site-identifying data; they’re
static-cacheable from our perspective.

Screenshots

Blocks

This plugin provides 5 blocks.

  • Seekmodo Chat Conversational AI shopping assistant. Supports policy/shipping RAG when configured.
  • Seekmodo Ask AI Single-turn Ask AI Q&A over your indexed catalog and policies.
  • Seekmodo Search Box AI-powered search input that emits seekmodo:search events. Pairs with <seekmodo-results> on the same page or links to a search-results URL.
  • Seekmodo Recommendations Renders a horizontal strip of related/popular/similar products. Backed by the Seekmodo recommendation algorithms.
  • Seekmodo Quiz AI shopping quiz / product finder. Reads a quiz definition and surfaces a personalized result set.

Installation

Either:

  1. In WordPress admin, go to Plugins Add New and search for “Seekmodo”.
  2. Click Install Now on “Seekmodo Search”, then Activate.

Or upload manually:

  1. Download the latest zip from https://seekmodo.com/plugins/wordpress.
  2. Upload via Plugins Add New Upload Plugin choose the zip Install Now Activate.

Then in either case:

  1. Go to Settings Seekmodo Search Connect to Seekmodo.
  2. Click Start free trial / sign in and approve the pairing on seekmodo.com.
  3. (Optional) Run wp seekmodo index --full to seed your tenant immediately. (The plugin will otherwise reindex incrementally on its own.)
  4. Flip search mode from shadow to active in the connector settings once you’ve spot-checked a few searches.

Headless / CI install:

wp plugin install seekmodo --activate
wp seekmodo connect --tenant=<tenant_id> --secret=<shared_secret>
wp seekmodo index --full
wp option update seekmodo_wp_mode shadow

FAQ

Do I need a Seekmodo account?

Yes. Seekmodo Search is the WordPress connector for the Seekmodo
hosted AI search platform; the plugin itself is free and GPLv2, but
it needs a paired Seekmodo tenant to do its job. Every plan ships
with a 14-day free trial at $0 with full features and unlimited
searches. After the trial, plans start at $29/month. Pricing details:
https://seekmodo.com/pricing.

Do I need WooCommerce?

No. The content vertical works on any WordPress site (posts,
pages, public custom post types). The commerce vertical activates
automatically when WooCommerce is detected, and idles otherwise.

What happens if the gateway is down?

Every gateway-talking entry point falls through to native WP_Query
(or WC_Query for products) inside the same request. Visitors never
see an empty results page. A per-tenant circuit breaker prevents
repeated timeouts from compounding, and Seekmodo health metrics
auto-demote the connector back to native search if our gateway is
unhealthy.

What happens if I stop paying / cancel my subscription?

Same as the previous answer. The plugin stays installed, the
gateway-talking entry points start returning “no results” (since the
tenant is gated), and every entry point falls back to native search
in the same request. Your site keeps working; you just stop getting
AI relevance. Re-pairing with a paid tenant restores full
functionality.

Will this work on a staging clone?

Yes — Seekmodo locks each tenant to a canonical storefront host.
Staging / dev hosts are auto-detected and return no-op from every
gateway-talking entry point, so your production search index is never
overwritten by a non-production deploy.

Where are my credentials stored?

In wp_options (seekmodo_wp_tenant_id, seekmodo_wp_shared_secret).
wp seekmodo connect can be re-run any time to rotate the pair.

Where does the plugin send data?

Indexable post / product content goes to mcp.seekmodo.com (the
gateway). Visitor search queries and clicks go to mcp.seekmodo.com
as telemetry. The update check (12 h cadence) goes to
seekmodo.com/api/plugins/seekmodo. Configuration pull (5 min
cadence) goes to mcp.seekmodo.com/v1/tenant/snapshot. All
gateway-bound requests carry an HMAC signature derived from the
pairing secret. Full details in
https://seekmodo.com/legal/privacy.

Does the plugin support translations?

The admin UI is localised via the seekmodo text domain
and /languages/ directory. We ship English (en_US) as the source
locale; contributions for other locales are welcome.

How do I get help?

Where is the human-readable source for the Suggest JavaScript?

The production Suggest bundle
(assets/suggest/seekmodo-suggest.global.js) is a minified IIFE built
from @seekmodo/web-components. Readable TypeScript for that bundle
(and for the Ask IIFE / full web-components ESM) ships inside the
plugin at assets/suggest/src/. See assets/suggest/SOURCE.md for
the entry file map, rebuild steps (npm install + npm run build
in the web-components package), and notes on the inlined SDK copy
under assets/suggest/src/vendor/seekmodo-sdk/. Ask and full ESM
pointers: assets/ask/SOURCE.md, assets/web-components/README.md.

Reviews

September 15, 2026
Our on-site search is now actually useful. With well over 1k products SeekModo helps potential buyers find what they need quickly.
Read all 2 reviews

Contributors & Developers

“Seekmodo Search” is open source software. The following people have contributed to this plugin.

Contributors

Translate “Seekmodo Search” into your language.

Interested in development?

Browse the code, check out the SVN repository, or subscribe to the development log by RSS.

Changelog

0.11.62

  • Improvement: “Build index now” no longer runs the full rebuild inside the admin page load — it queues a resumable WP-Cron build that runs in bounded background slices, so large catalogs no longer hit proxy/Cloudflare timeout error pages while PHP keeps working. The settings panel shows live progress, and wp-cli wp seekmodo local_index build remains synchronous for operators.

0.11.61

  • New: wordpress.org review prompts — a dismissible admin banner shown 14 days after pairing, a “Rate it” link in the Plugins table row, and a footer line on the Seekmodo settings page. “No thanks” dismisses permanently; “Maybe later” snoozes for 14 days.
  • Chore: removed a stray internal debug file from the shipped package.

0.11.60

  • New: search-suggestions dropdown is now enabled by default on fresh installs and upgrades where the setting was never touched. Sites that previously turned it off keep it off; themes can still force-off via the seekmodo_enqueue_typeahead / seekmodo_enqueue_suggest filters.
  • Fix: bulk index pushes (/v1/index) now use a 30s timeout instead of the shopper-facing 250ms-2s search cap. Large batches no longer abort client-side and report phantom “failed” counts while still importing server-side.

0.11.59

  • Security: All $_SERVER inputs are properly sanitized through ServerInput helper class per WordPress.org Plugin Review requirements (DOCUMENT_ROOT, HTTP_REFERER, REQUEST_METHOD, etc.). uninstall.php cleanup uses only ABSPATH and no longer reads $_SERVER directly.
  • wordpress.org review: GET /seekmodo/v1/images is intentional public read-only image hydrate; remove mark_dirty (no unauthenticated post meta writes). Dirty reindex remains via product-save hooks and gateway pending_image_refresh_ids.

0.11.58

  • wordpress.org review: GET /seekmodo/v1/images is intentional public read-only image hydrate; remove mark_dirty (no unauthenticated post meta writes). Dirty reindex remains via product-save hooks and gateway pending_image_refresh_ids.

0.11.57

  • Fix: commerce typeahead falls back to WooCommerce products (not blog posts) when cloud/Enhanced Native returns no rows; shared native-fallback filter keeps content rows for vertical=content.

0.11.56

  • wordpress.org review: remove remaining uninstall.php DOCUMENT_ROOT $_SERVER read (ABSPATH-only .well-known cleanup). Discovery/runtime already use ServerInput since 0.11.52; cited WellKnownWriter/ShopperContext/McpDiscovery snippets were pre-0.11.52.

0.11.55

  • Fix: EventsQueue::ensureTable() on boot and before push() so click beacons are not silently dropped; Options::bustOptionsCache() after pairing/mode so Redis alloptions cannot stay stale.

0.11.54

  • Broken suggest image heal: filesystem-aware ProductImage, REST /seekmodo/v1/images, Suggest images-hydrate-url, schedule commerce index cron, drain gateway pending_image_refresh_ids.

0.11.52

  • wordpress.org review: sanitize/validate $_SERVER (and related) inputs early via ServerInput helper; DOCUMENT_ROOT path guards; SearchSwap GET numeric casts sanitized.

0.11.51

  • wordpress.org review: Tested up to in readme.txt only; ship Suggest/Ask TS under assets/suggest/src/; remove static ABSPATH .well-known writes (PHP discovery only).
  • Fix: clear stale PreferLocal over_quota sticky while trial is still active.

0.11.50

  • wordpress.org review: exclude/remove .map files (no jsDelivr strings), JWKS fetch via wp_remote_get only, nonce on cloud-suggest-denied, JSON_HEX_* for Suggest inline config, wp_kses for recommendation placeholders.

0.11.49

  • Plugin Check i18n: SuggestLabels uses literal __() text/domain (no variables).

0.11.46

  • Fix: sticky unpaid/over-quota Suggest skips metered /v1/suggest (prefer-local) and still fills EN rows when img-ver is set.

0.11.45

  • Fix: unpaid/over-quota Suggest fallback keeps the Seekmodo-styled suggest box (EN via typeahead-fallback-url) instead of switching to the plain TypeaheadUI product list.

0.11.44

  • Fix: homepage suggestions when Suggest JS is delayed/blocked — autoboot on token-guard, typeahead skip while Suggest owns the input, watchdog flip to Enhanced Native typeahead.

0.11.41

  • Suggest: paint thumbnail_url for content posts; hide price_range on content vertical.

0.11.38

  • Fix: Multilingual Suggest sends serp_passthrough filter_by lang:=slug, over-fetches suggest limit to 48 for client i18n_filter, and keeps cloud products when typeahead returns only posts.

0.11.37

  • Fix: Polylang language-switch SERP no longer empties when gateway cache ignores lang (localize IDs + per-lang fetch buckets).

0.11.36

  • Fix: Suggest “View all” SERP href uses Polylang/WPML language path prefix (e.g. /fr/?s={q}&post_type=product).

0.11.35

  • Suggest chrome i18n: inject locale label packs into seekmodo-suggest (labels attr + SeekmodoSuggestLabels); vendor web-components 0.4.5 suggest bundle.

0.11.34

  • WordPress.org review follow-ups: enqueue Health/ModeBadge CSS and beacon seid via wp_add_inline_*; sanitize shopper UA/IP/referer and search keywords; rest_url() for pairing callback; shadow logs under uploads/seekmodo/; remove load_plugin_textdomain; static .well-known writes opt-in; exclude release-signing-keys from release zip.

0.11.33

  • Plugin Check: remove HEREDOC/NOWDOC from shipped PHP; Tested up to 7.1; release compliance gate.

0.11.22

  • Fix: Relevanssi-compat hydration re-applies post__in score order after get_posts so theme date sorting cannot reshuffle SERPs.

0.11.21

  • Improve: stronger ordered title-phrase boost so exact publication titles outrank long body TF matches.

0.11.20

  • Improve: Enhanced Native exact whole-word hits outrank prefix/partial matches; unquoted multi-word queries boost adjacent ordered title/excerpt phrases.

0.11.18

  • Fix: commerce-only tenants (enabled_verticals=commerce) now claim unscoped /?s= / post_type=any main searches so search_event_id reaches the click beacon.

0.11.17

  • Fix: content SERP (/?s= without post_type=product) now stamps search_event_id so click beacons are accepted; also supports Rank Math /search/{q}/ keyword detection.

0.11.16

  • Fix: WooCommerce add-to-cart and purchase events now register even when WooCommerce is not visible at plugins_loaded, flush in the same cron tick as clicks (instead of starving behind SERP click traffic), and no longer drop silent TypeErrors when quantity is a decimal.

0.11.15

  • Fix: the events-queue flush cron (clicks, add-to-cart / purchase conversions) never actually ran on any install. wp_schedule_event() was called with a recurrence name that was never registered via the cron_schedules filter, so WordPress silently refused to schedule it while searches kept working fine — the underlying cause of fleet monitoring flagging sites with real traffic but zero recorded clicks. Registering the plugin now also self-heals existing installs immediately (no need to deactivate/reactivate).

0.11.14

  • Daily unpaid-recovery: the existing 5-minute tenant.snapshot pull now clears a stuck trial_expired / paused / closed sticky as soon as the gateway reports the account active again, so a resubscribe or trial extension restores cloud suggest within one pull instead of waiting out the 1-hour sticky TTL. An over_quota sticky is left to clear on its own (TTL or next successful search) since an active subscription can still be over this period’s quota.

0.11.13

  • Search suggestions box now supports full CSS custom-property theming (accent color, header, CTA pill, row accent bar, rail background) so you can brand the dropdown to match your site without a child plugin. No visual changes if you don’t set any of the new properties.

0.11.10

  • Stamp search_event_id on add_to_cart / purchase for LTR last-touch linkage.

0.11.9

  • Shopper-context parity for typeahead + conversion events (session_id / ua / referer).

0.11.8

  • Document HMAC auth_fail / signature_mismatch contract: Gateway\Client returns null (native WP/Woo fallback) during secret drift; optional WP_DEBUG log.

0.11.7

  • Text domain seekmodo; removed Update URI / WporgUpdateClient for Directory updates.
  • Suggest branding defaults off; privacy guide mentions IP/UA/referer.
  • Plugin Check ERROR cleanups (escaping, SQL prepare, ABSPATH, packaging excludes).

0.11.6

  • WordPress.org submission readiness: vendored full
    @seekmodo/web-components ESM under assets/web-components/ (no
    default CDN load; override via seekmodo_web_components_src).
  • Complete uninstall cleanup (options, local-index tables, crons,
    transients).
  • Tested up to: 7.0. Health dashboard widget requires
    manage_options. Suggested privacy-policy guide text added.
  • Cart cascade ranks multi-line carts by support_count across up
    to 10 anchors.

0.11.5

  • PDP/cart recommendation cascades (pdp-cascade, cart) via
    /wp-json/seekmodo/v1/recommendations with cross-section de-dupe and
    in-cart exclude_doc_ids, matching the AKS cascade contract.
  • Auto-injects placeholders on WooCommerce PDP/cart templates and
    refreshes after cart fragments; enqueues @seekmodo/web-components
    on those templates even without Gutenberg blocks.

0.11.4

  • Stop requiring REQUEST fingerprints for add_to_cart mirrors (theme/custom AJAX was dropping all ATCs). Session-restore skip remains the spam guard.
  • Also emit purchases on woocommerce_payment_complete (deduped) when thankyou never renders.

0.11.3

  • Events flush uses an 8s timeout and smaller batches (clicks first) so ATC attribution no longer wedges the queue.
  • Skips cart-session restore add_to_cart mirrors; only intentional shopper adds are queued.
  • Persists sm_seid cookie for SERP click attribution when footer beacon localization races.

0.11.2

  • Stamps per-shopper session_id + visitor IP/UA on search and click events for bot-check and fleet linkage.
  • Drops unlinked SERP beacon clicks (missing search_event_id) that were polluting LTR / fleet health.

0.8.9

  • Shared thumbnail resolver for content typeahead and indexing (featured
    image, inline content image, seekmodo_thumbnail_url filter).

0.8.8

  • Content typeahead unions gateway hits with native WP rows and applies
    post-type priority so pages surface before posts (trek.ca parity with SERP).
  • Suggest widget always merges the REST typeahead fallback when configured.

0.8.7

  • Fixes WooCommerce SERP showing product categories instead of ranked
    gateway products after the search swap.
  • Suggest dropdown merges REST typeahead fallback when gateway suggest
    returns no product rows (content sites like trek.ca).

0.8.6

  • Fixes WooCommerce SERP titles showing Search results: "" after the
    gateway search swap clears the query s var.

0.8.4

  • Fixes mobile split-rail draggable divider (both panels resize again).
  • Refreshes the vendored @seekmodo/web-components suggest bundle.

0.8.3

  • Typeahead product-row clicks thread search_event_id from /v1/suggest
    meta for LTR click attribution.
  • Refreshes the vendored @seekmodo/web-components suggest bundle (split-rail
    mobile divider, native title tooltips, anchor performance fixes).

0.8.2

  • Fixes typeahead and search-swap click attribution (rank/surface metadata).
  • Refreshes suggest bundle with split-rail scroll and thumb scaling fixes.

0.8.1

  • CORS-block UX when gateway script loads or suggest fetches are blocked.
  • Refreshes suggest bundle to v0.2.2.

0.8.0

  • Enhanced Native search layer (Tier 1 + Tier 2) for unpaired installs.

0.6.0

  • SM-606 Universal Suggest Widget: when the operator-facing
    “Enable connector typeahead UI” toggle is on, v0.6.0 enqueues the
    new <seekmodo-suggest> custom element (~7 KB gzip, lives at
    assets/suggest/seekmodo-suggest.global.js) instead of the legacy
    flat-row dropdown. The web component renders the rich /v1/suggest
    envelope from the gateway (WS-2): recent + trending + keywords +
    products + categories + did-you-mean + “View all N results” CTA,
    all from one server round-trip. UX is shared 1:1 with the
    BigCommerce / Zen Cart / AKS / WordPress connectors so a tenant
    with multiple storefronts gets one suggestions UI everywhere.
  • Opt-out flag: new seekmodo_wp_suggest_legacy per-site option
    (Settings Seekmodo “Use legacy flat-row typeahead instead of the
    universal suggest widget”) flips back to the v0.5.x dropdown for one
    major-version cycle. The two surfaces are mutually exclusive —
    Frontend\TypeaheadUI::isEnabled() returns false when the flag is
    off, preventing double-attaching dropdowns to the same input.
  • Browser-token refresh: new public POST /wp-json/seekmodo/v1/browser-token
    route returns {token, expires_at, session_id} so the in-bundle SDK
    can refresh a 5-min JWT without a full page reload. Cached behind
    the existing per-tenant transient in Gateway\BrowserToken so a
    long-running tab amounts to ~one mint per ~4 min regardless of how
    many keystrokes the shopper triggers.
  • Customization surface (theme-side):
    • seekmodo_suggest_selectors — CSS-selector list the autoboot
      walks (default input[type="search"], input[name="s"],
      input[data-seekmodo-suggest], input[data-seekmodo-typeahead]).
    • seekmodo_suggest_blocks — CSV of blocks the widget should
      render in order (default recent,did_you_mean,keywords,trending,
      products,categories
      ). Drop any block by leaving it out.
    • seekmodo_suggest_view_all_href — URL template for the CTA.
      Default /?s={q} (or /?s={q}&post_type=product on Woo sites).
    • seekmodo_suggest_extra_attrs — assoc map of additional
      attributes (e.g. min-length, debounce-ms, limit,
      cache-size, lang) forwarded to every spawned element.
    • seekmodo_suggest_config — last-resort filter on the localized
      JS config.
    • Shadow-DOM CSS Custom Properties (--seekmodo-suggest-bg,
      –seekmodo-suggest-row-hover, --seekmodo-suggest-thumb-size,
      etc.) so child themes can theme the dropdown without forking
      its markup.
    • <slot name="recent|keywords|trending|products|categories|empty|
      header|footer">
      lets a theme drop bespoke HTML inside an
      element and override any one block’s rendering wholesale.
  • Performance: matches the AKS-3801e baseline (sub-300 ms p95
    cold cache, <16 ms warm-cache render) via the bundle’s built-in
    150 ms keystroke debounce, AbortController cancel-on-next-keystroke,
    32-entry LRU cache, and single rAF-batched render. Skeleton loader
    masks the first-render latency on a cold cache.

0.5.3

  • Operator UX: wp seekmodo index --full now reindexes every
    gateway-enabled vertical for the tenant (content + commerce, in
    series), and accepts a new --vertical=content|commerce|all flag
    for surgical per-vertical reindexes. Pre-0.5.3 the command only
    invoked Content/Indexer::reindexFull(); commerce-only operators
    (and dual-vertical operators chasing a stale product index) had to
    drop into wp eval '\Numinix\SeekmodoWordPress\Commerce\Indexer::reindexFull();'.
    Verticals the gateway hasn’t enabled for this tenant — or whose
    runtime dependency is missing (e.g. WooCommerce inactive) — are
    skipped silently with an info-level log line; the command reports
    the per-vertical totals separately so the operator can tell at a
    glance whether each vertical actually executed.
  • Safety: stricter write-side host-lock gate, exposed as
    DomainLock::canIndex() and surfaced in wp seekmodo health /
    wp seekmodo diagnose as a new can_index row. Used by every
    gateway-mutating helper (numinix_seekmodo_run_bulk_upsert,
    numinix_seekmodo_mirror_click) plus the cron-tick early-out in
    both Content/Indexer::tick() and Commerce/Indexer::tick().
    Failure modes the new gate catches that the looser
    DomainLock::matches() did NOT:

    • Self-referential lock on a non-prod host. dev.example.com
      seeds its seekmodo_wp_storefront_host to its own home_url() at
      activation; matches() returns true (current==locked); pre-0.5.3
      indexer cron would happily push every product save to the prod
      tenant’s Typesense collection, with dev.example.com URLs
      poisoning the customer-visible search results. Exact PM-303
      regression.
    • Unset lock on a non-prod host. A freshly-installed dev clone
      that hasn’t completed its first 5-min tenant.snapshot pull yet:
      pre-0.5.3 matches() returned true (no lock tentative allow).
      0.5.3 fails closed.
  • Safety: read paths (typeahead, search-swap, click-beacon
    enqueue) keep gating on numinix_seekmodo_enabled() so an
    operator smoke-testing search behavior on a staging clone still
    gets results — only writes are tightened.
  • Safety: two override filters, intentionally separated so a
    read-side bypass doesn’t accidentally also unlock writes:

    • seekmodo_disable_storefront_host_lock (existing, since v0.1.0)
      — read AND write; bypasses every check. Used by blue/green CDN
      setups where the request reaches WP under a different Host
      header than the visitor sees.
    • seekmodo_allow_nonprod_indexing (NEW, v0.5.3) — write only;
      consenting non-prod indexer for installs paired to a separate
      *-dev tenant. Defaults false.
  • Operator UX: wp seekmodo health now prints current_host,
    locked_host, host_lock_match, can_index, and
    looks_like_nonprod instead of the older single host_lock_match
    row, so an operator chasing “why isn’t dev indexing?” can see
    every input the gate consults at a glance.

0.5.1

  • Reliability: deploy-channel-agnostic version-bump detector. The
    connector now compares the on-disk SEEKMODO_WP_VERSION constant
    to the last-seen value stored in wp_options on every request,
    and on a mismatch fans out cache invalidations to every page-cache
    / minify / object-cache / OPCache plugin we know about. Closes the
    “I rsync’d v0.5.0 onto the server but visitors still load v0.4.0”
    regression that surfaced on POCO after the v0.5.0 push: WP Rocket
    was serving the cached v0.4.0 minified JS for 1 year because it
    only invalidates on upgrader_process_complete (which rsync
    deploys never fire).
  • Reliability: explicit OPCache reset on version bump. Hosts
    with opcache.validate_timestamps=0 (typical on shared hosting
    for performance) silently kept executing the old PHP class
    bytecode after rsync. The reset is wrapped in a function-exists
    guard so PHP builds without OPCache compiled in stay safe.
  • Reliability: browser-token transient explicitly invalidated
    on version bump so the next typeahead keystroke re-mints a token
    signed against whatever the new gateway expects, instead of
    inheriting a payload-shape from the prior connector version.
  • Maintenance: fan-out is gated behind a one-shot atomic option
    write so two concurrent first-bump requests don’t double-fire the
    cache flush. Hosts running bespoke cache infra can suppress the
    fan-out entirely with the new seekmodo_skip_upgrade_flush
    filter, or extend it with extra do_action keys via
    seekmodo_upgrade_flush_actions.
  • No new operator-facing settings; mass-deployable as a no-op
    update on every connector site.

0.5.0

  • Performance: typeahead now POSTs mcp.seekmodo.com/v1/typeahead
    directly from the storefront browser using a short-lived browser
    token minted server-side at page render. Skips the WordPress REST
    hop (and the ~1.5–2 s WordPress full-stack boot it pays on a heavy
    WooCommerce + Wordfence install) on every keystroke.
    Per-keystroke latency on POCO observed dropping from ~2,250 ms to
    ~80–150 ms.
  • Performance: 32-entry client-side LRU cache keyed on the
    normalized (vertical, max, q) prefix. Backspace + retype on a
    previously-fetched prefix renders synchronously from in-memory
    cache, no network round-trip. Cache size is operator-tunable via
    the seekmodo_typeahead_config filter.
  • Performance: server-side Cache-Control: public, s-maxage=30,
    must-revalidate
    + Vary: X-Seekmodo-Tenant on gateway typeahead
    responses lets Cloudflare / Varnish absorb keystroke storms on
    hot prefixes without leaking rows across tenants.
  • Performance: per-FPM-process APCu micro-cache (10 s TTL) on
    the gateway side defends Typesense from a hot prefix when the
    edge cache is cold.
  • Added: seekmodo_typeahead_gateway_direct filter. Defaults
    true. Site can __return_false to force every typeahead call
    back to the WordPress REST endpoint — useful for incident-response
    / debugging without a connector update.
  • Added: Gateway/BrowserToken.php — caches the per-tenant
    browser-token mint in a WordPress transient (refresh window
    honored, hard-cap 240 s). The mint failure mode silently falls
    back to the REST hop, so the typeahead never breaks regardless
    of token availability.
  • Fixed: pre-existing regression where Client::typeahead()
    POSTed /v1/typeahead against the gateway, the gateway returned
    404 tool_not_found, and the connector fell back to a native
    WP_Query LIKE search on every keystroke (~2.3 s on POCO,
    ~1.1 s on Trek.ca). The new gateway-side TypeaheadTool (SM-602
    on the platform side) is what makes the gateway-direct path
    return real Typesense rows in ~80 ms.

0.4.0

  • Added: front-end typeahead dropdown UI. The connector now ships
    assets/typeahead/seekmodo-typeahead.{js,css} plus
    src/Frontend/TypeaheadUI.php — a vanilla-JS dropdown that
    auto-binds to common search inputs (input[type="search"],
    input[name=”s”], input[data-seekmodo-typeahead]), debounces
    input at 150ms, and renders rows from the existing
    /wp-json/seekmodo/v1/typeahead REST endpoint. Two row shapes:
    content rows (title + post-type meta + excerpt + thumbnail) and
    commerce rows (product card with price / sale / stock badges).
  • Added: optional “Powered by Seekmodo” footer in the dropdown,
    driven by the existing seekmodo_show_branding filter +
    OPT_SHOW_BRANDING option. Default OFF — partner sites flip it on
    via the Settings page or have it pushed down by the gateway’s
    tenant-snapshot config pull. White-label by default.
  • Added: per-site “Enable typeahead” + “Show branding” toggles
    on Settings Seekmodo Search Typeahead dropdown. The enable
    toggle defaults OFF so an upgrade on a site that already has its
    own theme-level typeahead (e.g. trek.ca’s
    inc/seekmodo-search.php) doesn’t double-render.
  • Added: seekmodo_enqueue_typeahead,
    seekmodo_typeahead_selectors, and seekmodo_typeahead_config
    filters so themes can suppress or customise the connector UI
    without forking the JS.
  • Compat: existing assets/typeahead/seekmodo-beacon.js click
    attribution picks up data-seekmodo-id / data-seekmodo-pos /
    data-seekmodo-surface=”typeahead” attributes the new dropdown
    emits — no second beacon, no separate REST endpoint, click-through
    data flows through the same EventsQueue pipeline.

0.3.4

  • Added: editorial post-type ranking priority. After the gateway
    scores results by textual relevance, hits whose post type appears
    earlier in the configured priority list are bucket-sorted to the
    top. Within each tier the gateway’s relevance order is preserved
    — we don’t re-score textual relevance, just bucket-sort by post
    type. Configurable via the new Search ranking priority field on
    Settings Seekmodo Search, or by setting the
    seekmodo_wp_post_type_priority option directly. The
    seekmodo_post_type_priority filter overrides for site-specific
    mu-plugins. Default is empty — no re-rank, gateway order flows
    through untouched. Fixes the trek.ca complaint where blog posts
    dominated ?s=PPC while the high-intent /services/ pages got
    buried below the fold.

0.3.3

  • Fixed: the v0.3.2 pair-callback REST route at
    /wp-json/seekmodo/v1/connect/callback was registered behind
    Bootstrap::boot()’s is_admin() gate, so the route never
    appeared on the server-to-server POST from seekmodo.com (REST API
    requests are not “admin” in WordPress’s classification). The
    admin-side Connect button worked, but the JWT callback POST
    silently 404’d and pairing died at the last step. v0.3.3 lifts
    ConnectFlow::register() out of the is_admin() block so the
    rest_api_init hook always runs. The
    admin_post_seekmodo_wp_connect hook stays registered globally
    too (harmless — it only fires on admin-post.php hits).

0.3.2

  • Fixed: the “Connect to Seekmodo” pairing flow has been
    rebuilt on the canonical install_token + signed-JWT protocol
    (the same protocol Seekmodo for Zen Cart has used since v1.0.x).
    v0.3.0 and v0.3.1 sent legacy nonce + return_to query params
    that seekmodo.com rejects with “This link is incomplete” — the
    redirect-back side of that protocol was an aspirational design
    that was never implemented on the seekmodo.com side. Pairing
    through the browser was impossible until this release.

    • Admin\ConnectFlow::initiate() now mints a 32-hex
      install_token (10-min TTL) and sends
      ?install_token=&callback= to seekmodo.com/connect.
    • The new Admin\ConnectFlow::handleCallback() is registered as a
      public REST endpoint at
      wp-json/seekmodo/v1/connect/callback. seekmodo.com POSTs
      {token, install_token} to that URL with the
      X-Seekmodo-Install-Token header.
    • The new Connect\Pairing class verifies the EdDSA-signed JWT
      against https://seekmodo.com/.well-known/jwks.json, validates
      the standard claims (iss/aud/exp/install_token), and persists
      tenant_id + shared_secret + mcp_url.
  • Removed: Gateway\Client::verifyClaimToken() and the matching
    wp seekmodo connect –token=<…> CLI flag. They both round-tripped
    through a /v1/connect/verify endpoint that the gateway never
    implemented; users hitting that path were getting silent failures.
    The CLI pair still works via --tenant= --secret= for
    headless / CI installs.

  • Required: PHP sodium extension (ext-sodium) — needed for the
    JWT signature verify. It’s part of core PHP since 7.2 and shipped
    on default cPanel/EasyApache builds, but if it’s not loaded the
    pair-callback surfaces a cPanel-specific install hint
    (yum install -y ea-php82-php-sodium).

0.3.1

  • Fixed: Admin\ConnectFlow::initiate() called
    wp_safe_redirect(‘https://seekmodo.com/connect?…’) without
    whitelisting the connect host. WP’s redirect validator silently
    rewrote the destination back to the site root, landing the
    operator on the WP admin homepage instead of the connect page —
    pairing was impossible via the browser flow. The wp seekmodo
    connect
    CLI path was unaffected. Now registers a one-shot
    allowed_redirect_hosts filter for the connect host (overridable
    via the existing seekmodo_connect_base_url filter) for the
    duration of the redirect call only.

0.3.0

  • Changed: Commerce vertical doc shape realigned to the gateway
    Typesense schema. Commerce\ProductFields::buildDoc() now emits
    gateway-canonical field names — name, url, in_stock (bool),
    category_id[], category_breadcrumbs[], image_url,
    description (combined excerpt + content_plain, HTML-stripped, 4
    KB cap), last_indexed_at, plus optional on_sale, sale_price,
    currency. Removes pre-v0.3.0 WP-shaped names (title,
    permalink, stock_status string, regular_price, excerpt,
    content_plain, attributes, variations[], categories,
    post_type, extra) that the gateway’s strict-schema Typesense
    was rejecting on every upsert.
  • Changed: Commerce schema version split out from the content
    schema version so a commerce-only realignment doesn’t trigger an
    unnecessary content-side full reindex. New
    Options::OPT_COMMERCE_SCHEMA_VERSION (commerce_schema_version
    in wp_options) is consulted by Commerce\Indexer::tick() and
    triggers a one-shot full reindex on upgrade — same trick as the
    v0.1.1 content-side bump.
  • Added: Self-service “Promote dev production” card on the
    Seekmodo Search settings page. Surfaces when the connector’s
    current host looks like a non-prod environment
    (dev|staging|stage|test|qa|preview|sandbox) and the canonical
    lock matches that host. One-click POST to the gateway’s new
    tenant.domain.promote MCP tool flips locked_domain to the
    selected production host. Within 5 min the dev plugin’s next
    tenant.snapshot pull sees the new lock and goes silent
    (DomainLock mismatch), so dev / staging mirrors stop polluting
    production search analytics automatically. Closes the operator
    round-trip the v0.2.x flow required.
  • Added: Gateway\Client::promoteCanonicalDomain() thin HTTP
    helper for the new tool. Same HMAC envelope as every other
    gateway call.
  • Added: Admin-app mirror — tenant-settings-form.tsx now shows
    a “Promote dev to production” hint band + one-click action when
    the tenant is locked to a non-prod host and a prod-looking
    connector has authenticated. Pre-fills the locked-domain field
    with the most-recently-seen prod host; operator clicks Save to
    apply.

0.1.4

  • Added: WordPress.org Plugin Directory submission readiness.
    Plugin header Update URI: https://seekmodo.com/plugins/seekmodo
    (WP 5.8+) routes update checks to our marketing-site endpoint, so
    the plugin lists at https://wordpress.org/plugins/seekmodo/ for
    initial install + searchability while all subsequent
    version-checks and zip downloads happen against seekmodo.com.
  • Added: Numinix\SeekmodoWordPress\Updates\WporgUpdateClient
    hooks update_plugins_seekmodo.com (the filter key WP core
    synthesises from our Update URI header) and the
    plugins_api plugin_information “View details” modal. Reads
    from https://seekmodo.com/api/plugins/seekmodo, cached 12 h on
    success and 5 min on failure. Endpoint is filterable via
    seekmodo_wporg_update_endpoint for staging.
  • Changed: Plugin name shortened from “Seekmodo Search for
    WordPress” to “Seekmodo Search” (w.org plugin-review guideline:
    the “for WordPress” suffix is discouraged when the plugin is
    listed there).
  • Changed: Plugin description rewritten for w.org’s plugin-card
    preview, with explicit SaaS-dependency disclosure and free-trial
    note matching the Mailchimp / Algolia / Akismet pattern.
  • Changed: Tested up to: 6.6 added to plugin header + readme so
    the WP-admin compatibility filter and the w.org directory listing
    reflect the latest tested WordPress release.
  • Fixed: tools/build_release.py --auto-pr now writes a manifest
    entry whose schema matches the live platforms.zen_cart entry
    exactly (sha256 / sig / sig_kid / signed_at / signed_with
    / released_at / release_notes_url) instead of the orphan
    sha256_url / signature_url / released_at_utc shape it
    produced before. Also replaces a Unix-only
    subprocess.check_output([“date”, …]) with portable
    datetime.now(timezone.utc).

0.1.3

  • Add: per-tenant “Powered by Seekmodo” branding toggle. Off by default;
    operators turn it on from the admin.seekmodo.com tenant settings page
    for partner / specific-deal sites. New helpers
    numinix_seekmodo_show_branding() and numinix_seekmodo_brand_url()
    for themes, with seekmodo_show_branding and seekmodo_brand_url
    filters.

0.1.2

  • Fix: AutoPromoter substate FSM is now actually wired up. Previous
    versions never advanced the active+shadow → active+enforce
    substate, and the SearchSwaps consulted the headline mode instead
    of the effective mode, so auto_promote=true was decorative.
    MODE=active now correctly bakes into enforce on healthy metrics
    and demotes back to shadow on a breach.
  • Fix: MODE=active + auto_promote=false now correctly collapses
    to a hard enforce (operator opt-out of the safety hop).

0.1.1

  • Fix: Content indexer doc shape aligned with the gateway’s strict
    Typesense content collection schema. Previous releases would
    have 400’d on every index.upsert.
  • Bumped Options::SCHEMA_VERSION to force a full reindex on
    upgrade.

0.1.0

  • Initial release. Sprints 0-5 shipped: content + commerce verticals,
    mode FSM with auto-promoter, shadow-mode diff logger, typeahead,
    click beacon, events queue, health widget, signed-zip release
    pipeline.