Description
Records security-relevant site events into the site’s own database: logins, logouts and failed logins, post and page changes, plugin and theme installs, updates and activation, WordPress core updates, file editor saves, user and role changes, changes to the General, Writing, Reading, Discussion and Permalinks settings, menus, widgets, media, and content and personal-data exports and erasures. With WooCommerce active it also records order status and product price and stock changes. With Gravity Forms, WPForms, Contact Form 7, Yoast SEO, Rank Math, ACF, LearnDash, LifterLMS, MemberPress, Paid Memberships Pro or Elementor active, it records their form, submission, SEO, custom field, course, membership and page-builder changes (never what was typed into a form, a custom field’s value or a payment).
Each event stores its time, the acting user (or guest), the IP address (truncated by default), device and browser, event type, the object affected and a summary. An admin screen lists events newest first, with filters, search, pagination and CSV export. Retention is 90 days by default; choose a finite period or keep events indefinitely. The daily purge follows that setting. A daily summary email digest is included.
Features:
- Logs logins, failed logins and logouts, and profile, email, password and application-password changes. Passwords and password hashes are never stored.
- Logs post and page create, edit, trash, restore and delete, plugin and theme changes, WordPress core updates, and file editor saves (the file and its size, never its content).
- Logs user create, delete and role changes, and what a role may do.
- Logs popular form, SEO, custom field, LMS, membership and page-builder plugins, each only while it is active.
- Filterable log viewer with free-text search, pagination and CSV export.
- Read-only REST route and WP-CLI commands for administrators.
- Exclude chosen users or roles from the log, and import history from Simple History, WP Activity Log or Stream.
- IP addresses are truncated by default. Country and city come from a MaxMind database you supply, looked up on your own server.
- Works with WordPress’s personal-data export and erasure tools.
- Choose a finite retention period of up to a hundred years, or keep events indefinitely. The same setting applies to imported history and multisite event cleanup.
How it works
- A WordPress event, or a change in a supported active plugin, triggers a log entry.
- Activity Log stores the event in your site’s database. IP addresses are truncated by default; passwords and password hashes are never recorded.
- An administrator reviews and filters the log or exports matching events as CSV. The daily email digest goes to the site’s admin address. AI summaries require Activity Log’s AI opt-in and a compatible provider configured through WordPress Connectors.
Screenshot 5 diagrams this flow, and screenshot 6 shows the local log, email digest and optional data destinations. Screenshots 1–4 show the free plugin’s admin screens.
Pro
404ops Activity Log Pro is a separate, paid add-on plugin. It is not required, it is not bundled here, and none of it is present in this download: the free plugin above is complete on its own and behaves identically whether the add-on is installed or not. Buy it at https://404ops.com/plugins/404ops-activity-log and activate the licence on the plugin’s own Licence tab.
Three things it adds:
- External forwarding. Copy each event as it is recorded to a Slack channel, to your own HTTPS webhook (JSON, optionally signed with a shared secret), or to this server’s syslog. Every destination is off until you switch it on, and you choose which.
- Monthly archives. On the first of each month, the previous month is written to a CSV file under uploads and — if you ask for it — those rows are then removed from the database. The archives are protected from the web and downloaded through a capability- and nonce-checked admin action, never a direct link.
- Saved reports. Filter the Activity Log tab the way you want, then « Save this view » to keep it as a named report on the add-on’s own Reports tab. Turn on a daily or weekly schedule and Pro emails it automatically — a short plain-text summary (counts by event type and the busiest actors) with the matching rows attached as a CSV — to up to ten recipients you choose. A saved report’s schedule and recipients are the add-on’s own settings; the event data it draws on is the same log the free plugin already keeps.
External services
The free plugin contacts an external service only when you start or switch on one of these optional features:
-
WordPress.org checksums (file integrity scan). When you run a file integrity scan, or the daily scan is switched on, this site asks api.wordpress.org for the checksums of its WordPress version and downloads.wordpress.org for the checksums of each plugin version it compares. Each request carries only a version number, a locale or a plugin’s public slug. Nothing about your visitors or your content is sent. WordPress.org handles these requests under its privacy policy (https://wordpress.org/about/privacy/).
-
MaxMind (optional, off by default). If you turn on « Download and install weekly » under Settings Location and device and enter your own MaxMind account ID and licence key, this site downloads the GeoLite2 Country or City database from download.maxmind.com once a week (and when you press « Save and download now »). The request carries your account ID and licence key in an HTTP Authorization header and nothing about your site’s visitors or events; MaxMind then redirects the download to its storage provider, which receives no credentials. The database is installed on your own server and every lookup happens there. Data sent this way is handled under MaxMind’s terms of use (https://www.maxmind.com/en/terms-of-use), GeoLite2 end user licence (https://www.maxmind.com/en/geolite2/eula) and privacy policy (https://www.maxmind.com/en/privacy-policy). Uploading a database file yourself, or pointing at one already on the server, contacts nothing.
-
AI provider (optional, off by default). When you enable AI in Activity Log settings and configure a compatible provider in WordPress Settings Connectors, the daily digest gets a short AI-written summary. WordPress chooses a compatible provider from those configured, and that choice can change as providers change. The WordPress AI Client sends that provider the day’s event counts by type and anomaly descriptions. The provider’s terms apply. The separate Pro weekly summary, if enabled for AI, sends redacted figures, flags and change summaries. Without Activity Log’s opt-in or a compatible provider, the digest uses a local overview and sends no data to AI. Existing 404ops AI Connection credentials are not migrated: configure WordPress Connectors and enable AI for Activity Log again.
Policy references for commonly available WordPress AI providers (check the provider you configure):
- OpenAI: API services agreement and privacy policy.
- Anthropic: commercial terms and privacy policy.
- Gemini: API terms and Google privacy policy.
For any other provider available through WordPress, review that provider’s terms and privacy policy before enabling the feature.
The Pro add-on contacts only the services you configure yourself, and only the ones you switch on:
- Your own webhook endpoint. If you enable webhook forwarding and supply an HTTPS URL, each recorded event is sent to that URL as a JSON request containing this site’s URL and the event’s time, user, IP address as stored, event type, object type and summary. The address is yours; where it goes, what it is used for, and its privacy terms are entirely under your control.
- Slack. If you enable Slack forwarding and supply a Slack incoming-webhook URL, the same events are posted to the channel that webhook belongs to as short text lines, batched into one message per page request. Data sent this way is handled under Slack’s terms of service (https://slack.com/terms-of-service) and privacy policy (https://slack.com/trust/privacy/privacy-policy).
- 404ops licensing. The Pro add-on checks its licence against 404ops’s licensing service once a day, and when you activate or deactivate a key. It sends the key, this site’s address, and the add-on’s version. For a licence that includes installed-use coverage it also asks that service which published release and download match the installed version.
Syslog forwarding is local to your own server and contacts nothing over the network.
Captures d’écrans






Installation
- Upload the plugin files to
/wp-content/plugins/404ops-activity-log, or install through the WordPress Plugins screen directly. - Activate the plugin through the « Plugins » screen in WordPress.
- Open « Activity Log » in the admin menu to view events, and its Settings tab to set retention.
FAQ
-
Does this plugin make any external requests?
-
Not unless you start or switch one on. Out of the box this plugin makes no HTTP requests, and every event stays in your own site’s database. The requests it can make are the WordPress.org checksum requests of a file integrity scan (only when you run one, or switch the daily scan on), and the optional weekly GeoLite2 download from MaxMind, with your own MaxMind account, which is off until you turn it on (see External services); geolocation itself is a lookup in a file on your own server. The daily summary email, which WordPress sends through its own
wp_mail()to your site’s admin email address, is the only thing that leaves the site on its own. If you connect an AI provider, the same digest also sends that provider the day’s event counts and anomaly flags to write its summary (see External services). The separate Pro add-on can forward events to a destination you configure yourself, and can email a scheduled report to recipients you choose; see the External services section above. Nothing in this download does that, and installing the add-on does not switch any destination or schedule on. -
Where is the data stored?
-
In a single custom table in your site’s database. Uninstalling the plugin removes it.
-
How long are events kept?
-
By default 90 days. Change the retention period on the plugin’s Settings tab, or enable « Keep events indefinitely ». A daily cron purges anything older than the chosen finite period; it leaves events in place while indefinite retention is enabled. This setting also applies to imported history and each site’s events on multisite.
-
Are IP addresses stored in full?
-
Not by default. IPv4 addresses are truncated to their first three octets (last octet zeroed) and IPv6 addresses to their first 48 bits (last 80 bits zeroed) before being stored — the same anonymization convention used by common analytics tools. Enable « Store full IP addresses » on the Settings tab to store them unmodified instead.
-
How do location and device work, and what do they store?
-
Device context is on by default: each event records whether the request came from a desktop, mobile, tablet or bot, plus the browser and operating system (for example « Mobile · Safari 18 · iOS 18 »), parsed from the browser’s user agent when the event happens. Only that result is stored — never the user-agent text itself. Turn it off under Settings Location and device.
Location needs a MaxMind-format database (.mmdb) that you provide: GeoLite2 is free with a MaxMind account, GeoIP2 is MaxMind’s paid edition, and DB-IP’s lite databases use the same format. Upload it on the Settings tab, enter the path of a copy already on the server (best on nginx, where an uploaded file’s .htaccess guard does nothing), or let the plugin download GeoLite2 weekly with your own licence key. Each event then stores the country, and with a City database the city. The lookup happens on your own server; no address is sent anywhere.
When IP addresses are stored truncated (the default), the location is looked up from the full address first — a truncated address can belong to a different network — and only the location and the truncated address are stored. The full address is never written.
The personal-data export includes an entry’s location and device alongside its IP address, and erasure clears them together.
-
Which IP address is recorded?
-
The address of the connection to your server (REMOTE_ADDR). Headers such as X-Forwarded-For can be sent by any visitor, so they are ignored unless you choose one under « IP address source » on the Settings tab. Do that only if a proxy or CDN in front of your site sets it (X-Forwarded-For, X-Real-IP, or Cloudflare’s CF-Connecting-IP). Behind such a proxy with the default setting, the log records the proxy’s address.
-
What does the « Details » toggle show, and does editing a post leak its content into the log?
-
Each row with extra information has a « Details » toggle on the log screen, expanding it into an escaped key/value view (nested data is shown up to 3 levels and 50 entries deep, with the rest summarised). For a post or page edit specifically, only the fields that actually changed are listed — title, status, slug, author, excerpt, menu order and parent, each as its value before and after — plus, when the content itself changed, how many characters it was before and after and, if WordPress created one, a link to the revision it made for that edit. The post content itself is never recorded, before or after, only that character count; an administrator who can edit the post can follow the revision link to see the actual before/after text there, the same way they could without this plugin.
-
Can I honour a GDPR data request against the log?
-
Yes. The plugin registers with WordPress’s own Tools Export Personal Data and Tools Erase Personal Data screens. An export includes every log entry about that person: what they did, whether logged under that email address or under their account with an earlier one, and what was done to their account, such as someone else changing its role — including that entry’s own recorded details, when it has any. On an entry someone else performed, that other person’s IP address is left out. An erasure request changes exactly the entries an export shows. It anonymizes matching entries rather than deleting them outright, so the security audit trail — the fact that an event of a given type happened, when, to what — is preserved. Anonymization removes every identifying field: the account ID, email address, and IP address, plus the username itself where it would otherwise appear in a log entry’s summary (for example a login/logout record, or an entry about a role change someone else performed on that account), and, for a post edit performed by the erased account, the author and excerpt values its details may hold. This also covers the one case where an edit’s details name someone who is not that entry’s actor: when an administrator reassigns a post’s author, the previous and/or new author’s own id inside that entry is found and cleared for their own erasure request, whether or not they made the edit themselves.
-
Can I read the log from a script or another system?
-
Yes, two ways, both read-only and both limited to administrators.
Over the REST API,
GET /wp-json/activity-log/v1/eventsreturns one page of events, newest first, as JSON, with the total in theX-WP-TotalandX-WP-TotalPagesheaders. The filters are the screen’s:user_id,user_email,event_type,object_type,object_id,date_from,date_to,search,country(a two-letter code),device_class(desktop, mobile, tablet or bot) andmarker(a login marked new_country, new_device, impossible_travel, dormant_days or anonymous_network), plusper_page(1 to 100, default 20) andpage. Each event carries its country, city, device, browser, operating system and login markers. On a network with the plugin network-activated, super admins can read the network log atGET /wp-json/activity-log/v1/network-events, with asitefilter. A date can be a day (2026-09-01) or a phrase such as-7 days. A filter the plugin cannot read is refused with a 400 response rather than ignored. Another system authenticates with an administrator’s application password (Users Profile Application Passwords), which WordPress accepts over HTTPS only; the plugin issues no tokens or keys of its own.From the command line,
wp activity-log listprints the same events as a table, or as CSV, JSON, YAML or a list of IDs with--format, taking the same filters as flags, for examplewp activity-log list --event_type=login_failed --date_from="-1 day" --format=csv.wp activity-log countprints how many events match; both take--network(and--site) for the network log.wp activity-log integrity scan,statusandacceptrun and review the file integrity scan.wp help activity-log listdescribes every option. -
Is the CSV export safe to open in a spreadsheet?
-
The export guards against CSV/formula injection: rows can contain user-controlled text (a post title, a username, a browser’s user agent string, a URL) submitted by anyone the site lets post, register, or simply visit, so an anonymous or low-privileged visitor could otherwise plant a spreadsheet formula that runs when an administrator later opens the file. Before a cell is written, any leading run of whitespace or control characters is skipped; if the next character is then
=,+,-,@,|,%, or a full-width equivalent of=,+,-or@, or if the cell’s raw first character is a tab or carriage return, the cell is prefixed with a leading apostrophe so spreadsheet software treats it as plain text rather than a formula. This also means an ordinary negative number (-5) exports as text rather than as a number a spreadsheet can compute on — a deliberate trade-off, since the same leading-is a recognized formula trigger.This is defense in depth, not a guarantee for every spreadsheet application, locale, or import setting: it neutralizes the known trigger characters at write time, but how a specific version of Excel, LibreOffice, Google Sheets, or another importer parses a re-opened or re-imported file is still governed by that application’s own settings.
-
Does a Pro scheduled report contain personal data?
-
Yes. A saved report’s summary and CSV attachment are drawn from the same log the free plugin already keeps, which includes user logins and IP addresses, so anyone who receives a scheduled report sees the same personal data an administrator sees on the Activity Log tab. Choose recipients accordingly — the recipient list itself is a Pro setting, not something the personal-data export or erasure tools cover. Running the existing « Erase Personal Data » tool against an account still anonymizes that account’s own log entries in every future report; it does not, and cannot, reach a copy already delivered by email.
-
Where can I get help?
-
Visit https://supportminer.404ops.com to open a support request.
Avis
Il n’y a aucun avis pour cette extension.
Contributeurs/contributrices & développeurs/développeuses
« 404ops Activity Log » est un logiciel libre. Les personnes suivantes ont contribué à cette extension.
ContributeursTraduisez « 404ops Activity Log » dans votre langue.
Le développement vous intéresse ?
Parcourir le code, consulter le SVN dépôt, ou s’inscrire au journal de développement par RSS.
Journal des modifications
0.21.0
- AI summaries use the WordPress AI Client and WordPress Connectors. Enable AI again in Activity Log settings after configuring a compatible provider; existing 404ops AI credentials are not copied.
0.20.1
- Maintenance: bundles ai-client 0.4.3, which normalizes the AI Connection nonce before verification and rejects malformed inputs.
- Fixed: Free sites can select the full finite retention range of 1 to 36,500 days, with the existing 90-day default and indefinite-retention choice unchanged.
- Fixed (Pro): nonce values in five settings helpers are normalized before verification, and malformed values are rejected.
0.20.0
- New: Free sites can keep events indefinitely. The setting also applies to imported history and multisite cleanup; existing Pro indefinite-retention choices migrate automatically.
0.19.1
- Updated the licence client (0.3.5): Pro keeps working after a licence expires.
0.19.0
- New: popular plugins are logged. With Gravity Forms, WPForms or Contact Form 7, form changes and submissions (the form and entry, never what was typed); with Yoast SEO or Rank Math, a post’s SEO fields and the SEO settings; with ACF, field group changes and which custom fields changed (never their values); with LearnDash or LifterLMS, enrolments, completions, quizzes and groups; with MemberPress or Paid Memberships Pro, membership changes (never amounts); with Elementor, one entry per editor save. Each works only while its plugin is active.
- New (Pro): saved views. Saved reports appear as one-click views under the log’s filters, keep the country and device filters, can keep a relative date range, and can be opened or sent now from the Reports tab.
- New (Pro): weekly « what changed » summary. An optional weekly email compares the week with the one before, flags anomalies, lists the most serious changes and, with your own AI provider connected, adds a short summary written from figures with names, addresses and secrets removed. The free daily digest is unchanged.
0.18.2
- Updated the bundled licence client to 0.3.4.
0.18.1
- Listing: real WordPress.org screenshots, with one matching caption each in the Screenshots section. No code change.
0.18.0
- Pro: a licence that includes installed-use coverage now keeps the version you installed working after the licence expires. Updates still need an active licence. Existing licence keys behave exactly as before.
0.17.8
- Updated the licence client and refreshed wording.
0.17.7
- Admin menu labels and headings drop the 404ops prefix.
0.17.6
- Changed: the MMDB geo reader is now built in, in place of the maxmind-db/reader library; Composer’s generated loader is hardened for Plugin Check.
0.17.5
- Plugin URI points to the 404ops.com plugins page.
0.17.4
- Changed: listing text corrected for WordPress.org review. The contributor, description and changelog text now fit their limits, and the external services disclosure names the WordPress.org checksum requests that a file integrity scan makes.
0.17.3
- Changed: Bundled libraries updated; translatable strings now use this plugin’s text domain.
0.17.2
- Changed: requires WordPress 7.0 or newer (it was 6.9); tested up to WordPress 7.1.
0.17.1
- Changed: the plugin now requires WordPress 6.9 or newer and is tested up to WordPress 7.1.
0.17.0
- New (Pro): log tampering alerts. A new Log alerts tab can email the site’s administration address when the daily verification finds the log altered or can no longer be verified, and can record the log’s head after each clean verification so the Forwarding tab sends that fingerprint off the site. Both are off by default.
0.16.0
- New: a tamper-evident log. Every event is sealed into a keyed chain when it is logged, and the log verifies itself every day. Editing an entry, or removing, inserting or reordering entries, shows up on the new Log integrity tab, in
wp activity-log chain verify(which exits non-zero when the log has been altered) and at/wp-json/activity-log/v1/chain. Retention and privacy erasures are expected and are not reported. Add unique keys and salts to wp-config.php for the strongest protection; the tab tells you if they are missing.