Platforms
WordPress
See who visits your WordPress site, where they come from, and when AI agents read it.
The Runlight plugin runs Runlight inside a WordPress site, with the dashboard at /runlight on the site and the numbers in its own database. It can also send to a Runlight you run elsewhere, either the standalone server or an app with Runlight mounted, so one dashboard covers many sites. It’s on WordPress.org.
What it does
- It adds Runlight’s script to every page. On a page WordPress answers with a 404, the script also records an event named 404 with the missing page’s path, so the properties of 404 in the Events box list the broken addresses people reached and how often.
- It leaves out administrators’ own visits unless you turn that off.
- It records AI agents such as ChatGPT and Claude when they fetch your pages. Agents run no JavaScript, so the script cannot see them, and the plugin records them on the server once the page has been sent. Runlight checks the agent’s IP address against its published list and then drops it.
- It adds a Runlight item to the admin menu that shows this site’s dashboard in wp-admin.
Set it up
Install the plugin and activate it, with wp plugin install runlight --activate, or under Plugins, Add New. The plugin opens its setup screen, and nothing is counted until you choose where Runlight runs. Press Run Runlight in this WordPress and it starts counting the site.
The Runlight item in the admin menu shows the numbers, and its Open in Runlight button opens the full dashboard at /runlight on your site. There you can add goals, funnels, short links, and email reports, and import history from Umami.
Anyone who can manage options, administrators by default, is an owner of this Runlight, and everyone else is asked to sign in to WordPress.
Running Runlight inside WordPress needs PHP 8.2 or later with the mbstring and openssl extensions. The settings page, under Settings, Runlight, says when something is missing.
Where the numbers are kept
When WordPress’s database is MySQL 8.0.20 or later, or MariaDB 11.4 or later, Runlight keeps its numbers there through WordPress’s own connection, so your database backups include them. Its tables are named after WordPress’s table prefix, such as wp_runlight_events, so another app or another WordPress sharing the database keeps its own.
If tables with those names are already there and are not Runlight’s, it uses a SQLite file. With any other database, the numbers go in a SQLite file in wp-content/uploads/runlight, under a name no one can guess, which needs PHP’s sqlite3 extension.
Each site in a network always gets a file of its own. The choice is made the first time Runlight runs and never changes, so the numbers never split across two places.
Deactivating the plugin keeps everything. Deleting it removes Runlight’s tables or its folder, along with the plugin’s settings, on every site of a network. It drops only Runlight’s own tables, each by name.
Locations
Visitors’ countries come from Cloudflare’s header when the request verifiably came through Cloudflare’s own addresses. Otherwise, turn on Show which countries visitors come from under Settings, Runlight, and the plugin downloads DB-IP’s free country database once a month and keeps it in the uploads folder. Addresses are looked up on your server and never sent anywhere.
Hourly upkeep
WordPress’s cron runs Runlight’s scheduled check every hour, which makes each day’s salt, sends email reports, deletes visits past the retention you set, and adds up finished days. WordPress’s cron runs when someone visits the site, so on a quiet site it can be late, which only delays reports.
Sites that turn off WordPress’s cron and call wp-cron.php from a real one get the check on that schedule. When the check has not run for over a day, the settings page says so.
Email reports
When an SMTP or mail plugin is active in WordPress, such as WP Mail SMTP, FluentSMTP, Post SMTP, or Easy WP SMTP, Runlight sends its email reports and test emails through WordPress, from the admin email address in the site’s name. Settings, Email service in the dashboard then says which plugin sends them.
WordPress on its own sends with PHP’s mail(), which often lands in spam or goes nowhere, so without such a plugin the dashboard asks you to set up a mail service there instead. You can also choose another service while a plugin is active, and go back to WordPress’s mailer later from the same place.
The dashboard offers no SMTP server in WordPress, since an SMTP plugin covers it and Runlight sends through that plugin.
Visitors’ addresses
Runlight counts visitors with a daily hash of their address, and limits how often one address can send. The plugin works out the address itself, so no visitor can choose one. It takes the address the request came from, unless that is the server itself or a private network, where a proxy on the same host passed the request on. Then it takes the nearest public address in X-Forwarded-For, which each proxy adds to.
When that address is one of Cloudflare’s, it takes the visitor’s address from Cloudflare’s CF-Connecting-IP header. A host that knows the real address can supply it with the runlight_client_ip filter.
php
add_filter( 'runlight_client_ip', function ( $ip, $server ) {
return $server['HTTP_X_REAL_IP'] ?? $ip;
}, 10, 2 );Plain permalinks
With plain permalinks, a server such as Apache sends only index.php to WordPress, so Runlight answers at /index.php/runlight, which works on every server, and the settings page shows that address. Choosing any other structure under Settings, Permalinks moves it to /runlight.
Send to a Runlight you run elsewhere
- On the plugin’s setup screen, under Connect to a Runlight you run elsewhere, enter the address that Runlight answers at, such as
https://stats.example.comfor the standalone server orhttps://example.com/runlightfor an app with Runlight mounted. Runlight shows it under Settings, Install, as Runlight address. - Press Connect. Your Runlight asks you to sign in if you have not, and then asks you to allow the connection for this domain’s site. If Runlight has no site for it yet, it offers to add one when its sites are managed in its dashboard, as on the standalone server.
- Press Allow. Runlight sends you back to WordPress with every setting filled in, and the Runlight item in the admin menu shows this site’s numbers.
Connecting gives the plugin two keys. The agents key reports AI agents reading your pages, and it can only report fetches for this one site, so it cannot read your stats or write into another site. The dashboard key shows this site’s dashboard in wp-admin, read only, so treat it as you would a password.
The dashboard key appears in Runlight under Settings, MCP & API, where deleting it stops the dashboard in wp-admin.
You can also revoke this site’s dashboard keys in Settings, Install, under Dashboard key.
Connect needs wp-admin on HTTPS, or on localhost while you try things out, since Runlight only sends people back to such addresses. In an app with Runlight mounted, the site has to be in hostnames already (see Configuration), because there the sites are set in code.
Enter the settings by hand
Each setting in the plugin has the same name in Runlight, under Settings, Install, in the WordPress, Drupal, and Craft section, with a button to copy it. Copy Runlight address, Agents key, and Dashboard key into the fields of the same names and save. Runlight shows the dashboard key only once, so make a new one if you lose it.
Site id is needed only when that Runlight cannot tell this site by its domain. When you save, the plugin checks that the address answers and tells you the result.
Counting
Under Counting, Count clicks on links to other sites records each click on a link to another site as an event named Outbound link, and Count file downloads records each click on a link to a file, such as a PDF or a zip, as an event named File download. Both are on until you turn them off.
The dashboard in wp-admin
With Runlight inside WordPress, the Runlight item in the admin menu shows the whole dashboard in wp-admin, the same one as at /runlight, with its settings, goals, and short links. Only pages on your own site may show it in a frame, so when wp-admin is served from a different address than the site, such as with www. on only one of them, the page opens the dashboard in a new tab.
With a Runlight elsewhere, the Runlight item shows this site’s dashboard in the same read-only view a share link shows, with its reports and date ranges and none of Runlight’s settings, short links, people, or other sites. The Open in Runlight button opens the full dashboard in your own Runlight.
With a Runlight elsewhere, the address wp-admin is served from must be among the site’s domains in Runlight, since only an admin page on one of them may show the dashboard. Connecting takes care of that, and a leading www. makes no difference.
The dashboard key never reaches the browser. Each time an admin opens the page, the plugin’s server sends the key and the admin’s origin to Runlight and gets back a ticket that opens the dashboard once, within five minutes. The page loads the dashboard from your Runlight in a frame that only this admin may show.
The frame keeps its session in the page for an hour, without cookies, so browsers that block cookies in frames still show it. Once the hour is up, the frame says so and reloads the page when asked.
Deleting the key in Runlight’s Settings, MCP & API stops it and every open session at once. Your Runlight must be served over HTTPS when wp-admin is, or the browser refuses the frame.
Page caches
Some caching plugins serve pages straight from the web server without running PHP, such as WP Super Cache in its expert mode. Those pages still include the script, so visits are counted.
WordPress never runs for those requests, so AI agent fetches of cached pages are not reported. Caches that run through PHP, such as WP Rocket and most host-level caches, report agent fetches as usual.