Title: 404ops Activity Log
Author: Steve White
Published: <strong>November 6, 2026</strong>
Last modified: November 7, 2026

---

Search plugins

![](https://s.w.org/plugins/geopattern-icon/404ops-activity-log.svg)

# 404ops Activity Log

 By [Steve White](https://profiles.wordpress.org/spwhite/)

[Download](https://downloads.wordpress.org/plugin/404ops-activity-log.0.21.0.zip)

 * [Details](https://wordpress.org/plugins/404ops-activity-log/#description)
 * [Reviews](https://wordpress.org/plugins/404ops-activity-log/#reviews)
 *  [Installation](https://wordpress.org/plugins/404ops-activity-log/#installation)
 * [Development](https://wordpress.org/plugins/404ops-activity-log/#developers)

 [Support](https://wordpress.org/support/plugin/404ops-activity-log/)

## 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

 1. A WordPress event, or a change in a supported active plugin, triggers a log entry.
 2. Activity Log stores the event in your site’s database. IP addresses are truncated
    by default; passwords and password hashes are never recorded.
 3. 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](https://openai.com/policies/services-agreement/)
   and [privacy policy](https://openai.com/policies/privacy-policy/).
 * Anthropic: [commercial terms](https://www.anthropic.com/legal/commercial-terms)
   and [privacy policy](https://www.anthropic.com/legal/privacy).
 * Gemini: [API terms](https://ai.google.dev/gemini-api/terms) and [Google privacy policy](https://policies.google.com/privacy).
   
   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.

## Screenshots

[⌊The activity log with search, user, event type, country, device and date filters,
and CSV export.⌉⌊The activity log with search, user, event type, country, device
and date filters, and CSV export.⌉[

The activity log with search, user, event type, country, device and date filters,
and CSV export.

[⌊File integrity: compare core and plugin files against wordpress.org checksums 
and a recorded baseline.⌉⌊File integrity: compare core and plugin files against 
wordpress.org checksums and a recorded baseline.⌉[

File integrity: compare core and plugin files against wordpress.org checksums and
a recorded baseline.

[⌊Settings: retention period, IP address truncation, high-risk event email alerts
and roles never logged.⌉⌊Settings: retention period, IP address truncation, high-
risk event email alerts and roles never logged.⌉[

Settings: retention period, IP address truncation, high-risk event email alerts 
and roles never logged.

[⌊Import history from Simple History, WP Activity Log or Stream.⌉⌊Import history
from Simple History, WP Activity Log or Stream.⌉[

Import history from Simple History, WP Activity Log or Stream.

[⌊How it works: site events become a local activity log for review, CSV export and
the daily email digest.⌉⌊How it works: site events become a local activity log for
review, CSV export and the daily email digest.⌉[

How it works: site events become a local activity log for review, CSV export and
the daily email digest.

[⌊Data paths: the local log, the daily digest and optional AI and Pro destinations.⌉⌊
Data paths: the local log, the daily digest and optional AI and Pro destinations
.⌉[

Data paths: the local log, the daily digest and optional AI and Pro destinations.

## Installation

 1. Upload the plugin files to `/wp-content/plugins/404ops-activity-log`, or install
    through the WordPress Plugins screen directly.
 2. Activate the plugin through the “Plugins” screen in WordPress.
 3. 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/events` returns one page of events,
newest first, as JSON, with the total in the `X-WP-Total` and `X-WP-TotalPages` 
headers. 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) and `marker` (a login marked new_country, new_device,
impossible_travel, dormant_days or anonymous_network), plus `per_page` (1 to 100,
default 20) and `page`. 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 at `GET /wp-json/activity-log/v1/network-events`,
with a `site` filter. 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 list` prints 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 example `wp activity-log list --event_type=login_failed --date_from
="-1 day" --format=csv`. `wp activity-log count` prints how many events match; both
take `--network` (and `--site`) for the network log. `wp activity-log integrity 
scan`, `status` and `accept` run and review the file integrity scan. `wp help activity-
log list` describes 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.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“404ops Activity Log” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ Steve White ](https://profiles.wordpress.org/spwhite/)

[Translate “404ops Activity Log” into your language.](https://translate.wordpress.org/projects/wp-plugins/404ops-activity-log)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/404ops-activity-log/),
check out the [SVN repository](https://plugins.svn.wordpress.org/404ops-activity-log/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/404ops-activity-log/)
by [RSS](https://plugins.trac.wordpress.org/log/404ops-activity-log/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 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.

## Meta

 *  Version **0.21.0**
 *  Last updated **2 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 7.0 or higher **
 *  Tested up to **7.1.4**
 *  PHP version ** 8.0 or higher **
 * Tags
 * [Activity Log](https://wordpress.org/plugins/tags/activity-log/)[audit log](https://wordpress.org/plugins/tags/audit-log/)
   [logging](https://wordpress.org/plugins/tags/logging/)[security](https://wordpress.org/plugins/tags/security/)
   [user tracking](https://wordpress.org/plugins/tags/user-tracking/)
 *  [Advanced View](https://wordpress.org/plugins/404ops-activity-log/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/404ops-activity-log/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/404ops-activity-log/reviews/)

## Contributors

 *   [ Steve White ](https://profiles.wordpress.org/spwhite/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/404ops-activity-log/)