SearchCue
Menu
Back to the WordPress search plugin

SearchCue WordPress plugin source code

The SearchCue plugin adds fast site search and cited answers to WordPress. Install it from the WordPress plugin directory, and inspect every line of source code below.

Designed to keep WordPress setup small.

Install the plugin

In WordPress admin, open Plugins → Add New Plugin, search for "SearchCue", install it, and activate it.

Connect your site

Sign in to SearchCue, copy your site settings, and let the hosted crawler index your public content.

Keep WordPress light

SearchCue runs search and answers from our hosted index instead of adding a heavy search engine to your database.

Everything SearchCue can do on WordPress.

The plugin includes every SearchCue feature. If your site uses WooCommerce, it also adds rich product search.

Real-time search

Instant, typo-resistant results across every page, with matching terms highlighted.

AI answers from your content

Direct answers grounded in your content, with citations visitors can inspect.

See what people search for

See popular queries, clicks, dead ends, content gaps, and changes over time.

Matches your site

Place a search bar or button anywhere, then match its colours and style to your site.

You control the results

Exclude landing pages, SEO filler, or anything else you do not want to surface.

Document search

Index supported PDFs and Office documents alongside your pages.

Image recognition

Make images searchable with OCR and image understanding.

WooCommerce product search

Search published products and variations with prices, sale and stock status, images, attributes, and faceted filters.

Source you can inspect.

The browser below is generated from the plugin files during the site build. Pick a file to read it without downloading anything.

Download source zip
searchcue SearchCue WordPress plugin source code
README.md 100 lines
# SearchCue - WordPress Plugin

SearchCue is a hosted site search service with results that appear as visitors type, typo-tolerant matching, semantic search, and optional cited AI answers grounded in indexed content from your site.

The SearchCue WordPress plugin connects supported public pages, WooCommerce products, documents, and image content to that hosted search service. It can also notify SearchCue when public content changes, helping the hosted index stay current without building a search index in the WordPress database.

Please note that SearchCue is a paid service. You can try it for free for 15 days, and there are no bad feelings if you decide it isn't for you. We won't try to upsell you or trick you to become a customer. If you want more information about what the service costs before getting started, please check our [website here](https://searchcue.com).

## Plugin features

- Adds the shared inline SearchCue loader into the `<head>` of every public page and excludes it from WP Rocket minification
- Adds a **SearchCue** admin menu page to configure SearchCue
- Optional automatic pings to SearchCue when content changes in order to keep the search index up to date
- Exposes the published, visible WooCommerce catalog to the connected SearchCue backend through an authenticated endpoint
- Exposes published posts' categories and tags, with identities and parent relationships, to the connected SearchCue backend through an authenticated endpoint
- No third-party PHP dependencies
- The search index is hosted by SearchCue rather than built or queried in the WordPress database

## SearchCue features

- Typeahead keyword search
- AI answers and conversational search
- Design editor making it easy to adapt the search interface to the design of your site
- Search analytics
- Advanced tuning controls
- The ability to upload additional custom data you want to make searchable
- Rich WooCommerce product and variation results with prices, images, attributes, and faceted filters

## Installation

### From ZIP (for production use)

1. Download the plugin ZIP
2. In WordPress admin, go to **Plugins > Add New > Upload Plugin**
3. Upload the ZIP and activate

## Configuration

1. Open **SearchCue** from the WordPress admin menu
2. Enter your email and follow the sign-in link to connect the site
3. Keep **Automatic updates** checked if you want SearchCue to re-index changed pages automatically
4. Optionally set a different Site ID under **Advanced settings**
5. Save changes

Connections use WordPress's configured site address, not the current language's URL. Language changes retain the Site ID and API key. Existing language-path bindings and recognised WPML language-domain bindings migrate automatically, including hostname-only language settings. Setup returns to the configured origin and preserves the WordPress admin path. A canonically bound connection requires reconnection after moving to an unrelated origin.

If the site is already connected through another SearchCue account, SearchCue verifies site control before emailing you a masked account hint and recovery instructions. Sign out of your current SearchCue account, return to WordPress **SearchCue**, and request a fresh sign-in link using the original email address. Confirm the connection to reuse the existing site. Reply to the recovery email if you cannot identify or access that account.

The embed script will appear in the `<head>` of all public pages that call `wp_head()`.

The loader downloads the embed without delaying the page's load event. If the site's Content Security Policy prevents fetch or local execution, a native script request starts only after the page has loaded. It preserves nonce, integrity, and referrer-policy restrictions. Harmless URL transformations, such as changed cache-busting parameters, protocol-relative URLs, hostname case, and default ports, are normalised to the configured SearchCue bundle URL. Ordinary HTTP forms of the HTTPS endpoint are upgraded, not fetched over HTTP.

WP Rocket must load the embed from SearchCue's CDN rather than retain its own minified copy. After updating an existing installation, purge any previously generated WP Rocket minified scripts and affected page caches.

Recognised WP Rocket delayed script tags are rebuilt as inert inline loaders. WP Rocket still decides when they execute. Deliberately removed tags, consent-blocked types, unexpected hosts or paths, and ambiguous markup are not forced to run. Rejected output contains a fixed diagnostic comment, not the filtered markup or credentials.

The WordPress settings page shows **Search on your website** only for a current rendering failure after setup. The section uses SearchCue's semantic error colours with the existing typography, actions, and disclosure styles. It explains the problem in plain language and offers a link to open the site. First-run setup uses the existing connection form, without a separate error card.

**Details for support** contains a selectable, copyable report with the SearchCue version, effective public Site ID, credential-free canonical site address, fixed reason, and check limitations. It lists other installed plugins with versions and active, inactive, network-active, or must-use status. Installed drop-ins are listed without claiming they are active. These are diagnostic candidates, not proof of fault. The inventory is collected when the settings page is loaded, not stored with the rendering result. **Copy diagnostics** uses the browser clipboard API, falls back to native text selection and copying, and leaves the text selected for manual copying if clipboard access fails. The report excludes API keys, connection tokens, private configuration, and absolute file paths.

The local rendering record is bound to the Site ID, plugin version, and configured site address; unchanged results do not trigger repeated database writes. Successful rendering clears the warning without adding a success notice. Unobserved or stale results stay silent. This records PHP output only, not cached pages, later HTML transformations, or browser execution.

After correcting a problem, clear page caches, open a public page, and refresh SearchCue settings to check the new result.

Automatic updates send affected public page and product URLs when an image changes, rather than the image file URL. The plugin resolves upload parents, featured images, WooCommerce galleries, saved content, gallery shortcodes, and synced blocks, including encoded image filenames and bulk changes. Parentless images trigger updates when referenced or when they have an enabled public HTML attachment page. Public document attachments retain their direct URLs. Draft, private, and password-protected pages are excluded. References generated exclusively by themes, CSS, options, or plugin-specific fields cannot be inferred from WordPress's standard image metadata.

Changed URLs are stored in a local delivery queue, separately from the hosted search index. WP-Cron combines and deduplicates complete queued batches every minute while Automatic updates is enabled, authenticates delivery using the current stored API key, and retains them until SearchCue acknowledges receipt. Normal deliveries contain at most 1,000 URLs and 1 MiB of URL text. Authentication failures, throttling, and temporary failures pause delivery rather than attempting every remaining batch. Ordinary post saves do not wait for remote HTTP. Delivery depends on WordPress cron running; configure an external cron runner if WP-Cron is disabled or site traffic is infrequent.

Image edits persist their old and new reference information instead of scanning the site during a save. The same cron job combines up to 100 immutable change batches per pass and processes multiple 50-post chunks within a shared 20-second scanning and delivery budget, resuming where it stopped. Each invocation examines at most 5,000 stored post IDs across at most five passes. Generated URLs are deduplicated and delivered in the same run when time permits. New changes arriving during a scan receive a complete pass in a later cron request, preserving updates behind the current cursor without reusing stale post caches. Large sites may still need several cron runs; existing URL notifications continue during that work.

Unchanged core post saves ignore modification timestamps and editor locks. Custom-field changes made alongside a save, changed categories or tags, WooCommerce product update events, and media changes still notify SearchCue. Unrelated frontend metadata writes, such as view counters, do not trigger crawling.

Ordinary WooCommerce exports contain 10 parent products per page, ordered by ID, with each parent's visible variations kept together. Incremental exports select a known parent or resolve a public product URL locally, returning an explicit selection acknowledgement so a removal cannot be confused with an unsupported selector. The existing 1,000-variation safety ceiling per parent remains. GTranslate fetches one parent family per request. Stock and price changes update every cached language while reusing valid translated text.

Stock metadata includes the source quantity only when WooCommerce stock management is enabled globally and for the product or its parent. Unknown quantities remain unknown, zero and negative quantities are retained, and backorder policy is separate from physical stock. Variation records retain the stock-owning product ID, so shared parent quantities are not added together or presented as a quantity for every variant. SearchCue records when each source response was fetched; partial refreshes retain the previous observation time for untouched products. Indexed stock is a snapshot, not a live checkout availability or reservation check.

Direct WooCommerce stock-change hooks use the same queued automatic updates as product saves. Freshness still depends on Automatic updates, WP-Cron, successful notification delivery, and the hosted crawl completing; the one-minute delivery schedule is not a one-minute inventory guarantee. Existing installations need a plugin release containing the export change and a subsequent product recrawl before quantities become available. Rebuilding an old index alone cannot recover quantities that were never exported.

Plain `?product=...` URLs also resolve when WordPress uses a static homepage. Database query failures return HTTP 503 without acknowledging a removal, so the previously indexed product family can be retained.

Blog taxonomy lookups accept only selected public posts, not a whole-blog enumeration. Term edits capture old and new affected permalinks for up to 100 posts in a hierarchy containing at most 100 terms; larger taxonomies or affected post sets request broad reconciliation without loading the full hierarchy. Partial crawls skip screenshots.

Normal visitor and post-save hooks do not make synchronous SearchCue HTTP calls. Passive capability and Password Protected metadata checks run through coalesced cron jobs, not while rendering settings. Analytics, capability reporting, and IP-list requests have two-second transport timeouts; initial connection and explicit setup actions still wait for their results. WordPress cron normally uses a separate loopback request, but still consumes a PHP worker, CPU, and database capacity. Older WordPress versions can also pay the spawn cost before sending the page; alternate cron can continue on the originating worker after flushing output. Output buffering and a saturated worker pool can still delay visitors. A low request rate is not a guarantee of low server load. See the [shared-hosting development requirements](development.md#shared-hosting-request-cost).

## External Service and Privacy

The plugin requires the hosted SearchCue service; it has no third-party PHP dependencies. A SearchCue account is required, and continued service after the free trial requires a paid subscription.

Once connected, the plugin loads SearchCue's executable browser embed, sends public content updates when enabled, and exchanges setup and analytics data with SearchCue. SearchCue also pulls the WooCommerce catalog through an authenticated endpoint, including product names, descriptions, public URLs, product and variation IDs, SKUs, prices and currency, sale and stock status, managed stock quantities and their owning product IDs, backorder policy, categories and tags with their identities and parent relationships, attributes, images, and timestamps. Only published, visible catalog data is shared. The plugin does not share drafts, hidden or password-protected products, orders, customers, or download files. SearchCue also pulls blog taxonomy through an authenticated endpoint, including public post URLs, post IDs, and the identities, names, and parent relationships of the categories and tags assigned to published posts, including ancestor categories. Only published, public posts are shared, never post content, drafts, private posts, password-protected posts, or user data. Automatic updates sends the parent product URL after product or variation changes, the public URL of a post or product after its category or tag assignments change, and the home page URL after a category or tag is edited or deleted. The embed processes visitor searches and interaction metrics. The settings page uses locally bundled SearchCue font files under the SIL Open Font License 1.1.

See the complete data-flow disclosure in [`readme.txt`](readme.txt), the [SearchCue terms and conditions](https://searchcue.com/terms/), and the [SearchCue privacy policy](https://donoharm.world/privacy-policy/searchcue/).

## Uninstalling

Disabling Automatic updates or deactivating the plugin pauses delivery and preserves pending notifications. Deleting the plugin through WordPress runs `uninstall.php`, which removes stored options, queued notifications, and scheduled plugin jobs.

## License

This plugin is licensed under the [GNU General Public License v2.0 or later](https://www.gnu.org/licenses/gpl-2.0.html) (GPLv2+), which is the same license as WordPress itself. This is required for plugins published in the [WordPress.org Plugin Directory](https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/#1-plugins-must-be-compatible-with-the-gnu-general-public-license).