Every event shows the same IP address
Almost always a reverse proxy. If your site is behind Cloudflare, a load balancer, a CDN or a host-level proxy, REMOTE_ADDR is the proxy's address, and the plugin trusts only REMOTE_ADDR by default — deliberately, because forwarded headers can be forged by the client on a site that is not proxied.
Map your proxy's header with the whochita_client_ip filter; there is a Cloudflare example in hooks and filters. Do this only if traffic genuinely reaches your server through that proxy, or you are handing attackers control of the IP field.
This is worth fixing early: the new-IP and brute-force heuristics both key on the address, so until it is right, those escalations are meaningless.
Alert emails are not arriving
Alerts are automatic for dangerous events — there is no setting to switch on, so if none arrive, work through this in order:
- Was anything actually dangerous? Alerts fire only for dangerous events, not for strange or normal ones. Filter the log by severity to check. If nothing is dangerous, the system is working — it is just quiet.
- Throttling. One email per event type per 15 minutes. A burst of the same event type produces one message by design.
- The From address. The default is who-changed-it@yourdomain.com, which may not exist as a real mailbox. Strict SPF/DKIM setups and many hosts reject or silently drop such mail. Setting a custom From address to a real mailbox on your domain fixes most of these cases.
- WordPress email in general. Test with any "send a test email" tool. If WordPress cannot send mail at all — common on hosts without a configured mail transport — install an SMTP plugin. This is not specific to Who Changed It.
- The recipient. Defaults to the admin email under Settings → General, which on many sites is an address nobody reads. Redirect it with whochita_alert_recipient.
The chain reports altered or missing records
Verification is reported on the log and settings screens. What the counts mean:
- Authorised gaps are normal — retention purges, manual purges and GDPR erasures record the span they removed, and the chain still verifies across them.
- Missing records mean rows disappeared without a recorded gap. The usual innocent causes are a database restore from an older backup, a migration that copied only part of the table, or a developer clearing rows by hand.
- Altered records mean a row's contents no longer match its payload hash — something edited the table directly.
- Broken links mean a record's prev_hash does not match the record before it.
If you cannot account for a discrepancy on a production site, treat it as an incident rather than a bug. And note the limitation honestly: unless you have set WHOCHITA_CHAIN_KEY in wp-config.php, an attacker who could read your database could also recompute a consistent chain — see integrity and evidence.
Treating it as an incident means the same thing here as anywhere: preserve the evidence before you change anything, export the surrounding window while it is still intact, and work out how the database was reached rather than only repairing the chain. If that is not work you want to do alone, the plugin's author does it professionally as WP Server Guard — malware removal and hardening for a live compromise, or a WordPress security audit once the fire is out.
An event I expected is missing
- Is it muted? Check the event list on the settings screen. Muted events are never written.
- Did it happen before activation? The log starts at activation and cannot be backfilled.
- Is it a watched option? option_changed fires for a curated list of sensitive options, not for everything in wp_options. Add yours with whochita_watched_options.
- Did it go through WordPress? Direct database writes, files changed over SFTP, and anything done outside WordPress entirely are invisible to any plugin. A plugin that writes with raw SQL rather than the WordPress APIs will also bypass the hooks.
- Was it pruned? Check the retention window for that event's family — per-family overrides mean different parts of the log can expire at different times.
The log table is getting large
- Shorten the window for the noisy family rather than globally. Authentication is usually the culprit; commerce and settings are cheap to keep.
- Mute the noisiest event types. On sites with automated publishing or bulk imports, post_updated and attachment_uploaded are usually the top two.
- Look at what is actually filling it. Sustained login_failed volume means you are under continuous credential attack; the log is a symptom there, and the fix is a firewall or login rate limiter in front of it. This plugin deliberately does not block — it records.
- Export before pruning if you need the history for compliance. See exporting the log.
I cannot see the Activity Log menu
The menu only appears for users who may view the log. Check which viewer mode is set: in capability only mode, being an administrator is not enough — the user needs whochita_view_log or a listing in the viewers field. That mode exists precisely so administrators can be excluded, so this may be working as configured.
If you can see the log but not Settings, the plugin's access setting is probably pinned to only me under another administrator's account. If that account still exists, they can change it; if it has been deleted, management automatically falls back to all administrators.
WooCommerce events are not appearing
WooCommerce support activates automatically when WooCommerce is active — there is nothing to switch on. If store events are missing, confirm WooCommerce is actually active, and note that the plugin records price, coupon, order-status, refund, store-settings and payment-gateway changes specifically. Product edits that change neither price nor those fields are recorded as ordinary content events.
Still stuck
The support forum on the plugin's WordPress.org page is the best place for plugin problems — answers there help the next person with the same question. For anything that does not belong in public, see the contact page.