What this is
A small must-use plugin that runs inside WordPress, inspects the user agent of every request that reaches PHP, and forwards the ones that match Searchable’s canonical AI-crawler list to LLM Analytics. It feeds the same server-side pipeline as the Vercel, Cloudflare, and Netlify connectors — same classifier, same dashboards. The difference is where it runs: in your application, not at a CDN edge.Must-use plugins load automatically and can’t be deactivated from the admin UI, so the forwarder
survives plugin and theme updates.
First, check this is the right path
Use the WordPress plugin when your site isn’t behind a CDN we support natively, or when you specifically want the forwarder in the application layer. The same caveat applies to any full-page cache. See Troubleshooting below.Before you start
Self-hosted WordPress (this does not work on WordPress.com’s hosted plans, which don’t allow
mu-plugins or wp-config.php edits)SFTP, SSH, or a file manager that can write to
wp-content/ and wp-config.phpYour project’s domain confirmed in LLM Analytics → Setup → Confirm your domain
Step 1: Open the WordPress connector
1
Go to the Setup tab
In Searchable, open LLM Analytics (left nav, under Analytics) → Setup, then pick WordPress under “Connect your crawler source”.
2
Generate a tracker API key
Click Generate key. Searchable mints a key with the
log_events permission, scoped to this project, and shows it once — copy it now. Keys start with sk_live_….3
Copy the wp-config snippet
The panel shows a
define() block with your project’s site token already filled in. Copy it verbatim — you’ll paste it in Step 3.Step 2: Install the plugin
1
Download the plugin file
Click Download plugin in the WordPress panel. It downloads
searchable-ai-traffic.php, served from your project’s tracker host.2
Upload it to wp-content/mu-plugins/
Create
wp-content/mu-plugins/ if it doesn’t already exist, then copy searchable-ai-traffic.php directly into it.Step 3: Add your credentials
Openwp-config.php and paste the snippet from Step 1 above the line that reads /* That's all, stop editing! Happy publishing. */.
wp-config.php
sk_live_YOUR_API_KEY with the key you generated. The site token is already filled in for you in the in-app snippet.
Projects on a dedicated tracker hostname see two extra
define() lines in the in-app snippet
(SEARCHABLE_API_URL and SEARCHABLE_BOTS_URL). Don’t drop them — without them the plugin falls
back to the shared host, and you’d end up downloading the plugin from one endpoint while posting
events to another. Most projects use the shared host and won’t see these lines.Why wp-config.php and not the plugin file
wp-config.php sits outside the plugin directory, is excluded from most deployment pipelines by default, and won’t leak the key if mu-plugins/ is ever served as plain text.
Optional constants
Step 4: Verify
Send a request to your site with a known crawler user agent:- Check the Logs tab first — it shows individual bot requests as they land.
- On the Setup tab, the WordPress card flips from Waiting for the first event from your WordPress site… to Connected — the plugin is sending events.
How it works
- Bot list. The plugin fetches Searchable’s canonical bot list from
/v1/bots.json, validates each pattern, and caches the compiled list in a transient for one hour. If the fetch fails it falls back to the last good list persisted inwp_options, so a network blip doesn’t silently disarm the filter. Failures are cached for five minutes, so an outage never adds a fetch attempt to every request. - Matching. On the
shutdownhook the plugin matches the request’s user agent against that list. Non-matching requests do nothing — no outbound call, no work beyond the regex pass. WP-CLI, cron, and CLI requests are skipped entirely. - Latency. On PHP-FPM the response is flushed to the crawler via
fastcgi_finish_request()before the outbound POST, so forwarding adds no latency. On other SAPIs the POST is blocking with a 2-second timeout, and only ever fires for matched crawler requests. - IP handling. The client IP is resolved proxy-aware (
CF-Connecting-IP→ left-mostX-Forwarded-For→X-Real-IP→REMOTE_ADDR, each validated) and anonymized on your server before sending — the last IPv4 octet or IPv6 group is zeroed, so the full IP never leaves the site.
What gets sent
Only requests from user agents matching Searchable’s canonical AI-crawler list are forwarded. Human traffic is never sent. Each matched request sends:- HTTP method, path, and full URL (query strings are stripped server-side before storage)
- Response status code and server response time
- User agent and referrer
- An anonymized client IP — last octet zeroed, or omitted entirely with
SEARCHABLE_SEND_IP - A
sourcetag ofwordpress, so these events are distinguishable from Middleware SDK or edge-connector events
Optional: enhance the data
The plugin is a crawler-log source. It powers the Overview, Pages, AI Crawlers and Logs tabs. To populate the Visitors tab — humans arriving on your site from AI answers — connect Google Analytics 4, Search Console, or Bing in step 3 of the Setup wizard. These are additive; they don’t replace the crawler-log source.Troubleshooting
Nothing appears in the dashboard
Nothing appears in the dashboard
Work through these in order:
- Placeholders still in place. The plugin no-ops while
SEARCHABLE_API_KEYorSEARCHABLE_SITE_TOKENcontainsYOUR_. Confirm both were replaced with real values. - Wrong directory. The file must be directly in
wp-content/mu-plugins/— notplugins/, and not a subdirectory. Confirm it appears under the Must-Use filter on the admin Plugins screen. If that filter isn’t shown at all, WordPress isn’t seeing any mu-plugin — check the path over SFTP. - Constant names. They’re case-sensitive and must be spelled exactly as in the snippet.
- Outbound HTTP blocked. Some managed hosts restrict
wp_remote_postto an allowlist. Ask your host to allowtracker.searchableanalytics.com(or your dedicated tracker hostname).
A page cache sits in front of WordPress
A page cache sits in front of WordPress
Full-page caches — WP Rocket, WP Super Cache, W3 Total Cache, Varnish, Cloudflare APO, or host-level caches on WP Engine and Kinsta — serve cached HTML without booting PHP. When that happens the
shutdown hook never fires and the crawler visit is never recorded.Two options:- Exclude known crawler user agents from the cache, so their requests always reach PHP.
- Move to an edge-level integration — the Cloudflare Worker is the usual answer, since it runs in front of the cache.
The crawler views are empty but Visitors has data
The crawler views are empty but Visitors has data
You’ve connected Google Analytics or Search Console but no crawler-log source. The Overview,
Pages, AI Crawlers and Logs tabs need this plugin (or a Cloudflare, Vercel, or other edge source)
working.
Only some crawlers are captured
Only some crawlers are captured
Searchable’s canonical bot list is regenerated once daily at 03:00 UTC, and the plugin caches its own copy for up to another hour. A newly added crawler can therefore take up to ~25 hours to start being captured.Deleting the
searchable_bot_patterns transient forces a refetch, but that only helps once the daily upstream publish has picked the new bot up. To see what the plugin is working from, fetch the list yourself:Requests are slower after installing
Requests are slower after installing
On PHP-FPM they shouldn’t be — the response is flushed before the POST. If your host runs mod_php or another non-FPM SAPI, matched crawler requests carry a blocking POST bounded at 2 seconds. Human traffic is unaffected either way, since non-matching requests never make an outbound call.
Next steps
See the data
Open LLM Analytics to see which assistants are crawling your site.
Connect Search Console
Layer in keyword data so you can correlate AI crawls with search demand.