Title: Beziworld &#8211; Activity Log
Author: beziworld
Published: <strong>June 15, 2026</strong>
Last modified: October 15, 2026

---

Search plugins

![](https://ps.w.org/beziworld-activity-log/assets/banner-772x250.png?rev=3739441)

![](https://ps.w.org/beziworld-activity-log/assets/icon.svg?rev=3739441)

# Beziworld – Activity Log

 By [beziworld](https://profiles.wordpress.org/beziworld/)

[Download](https://downloads.wordpress.org/plugin/beziworld-activity-log.1.2.0.zip)

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

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

## Description

Beziworld – Activity Log records what users do on your WordPress site: who logged
in, who failed to log in, who changed a role, who edited their profile, who created
or edited content, and more. The focus is user activity, and the goal is to make
the capabilities competing plugins reserve for paid upgrades available for free.

**Designed for performance.** Events are stored in a dedicated, indexed custom table(
never in wp_posts), written in batches to keep request overhead low, while security-
relevant events are persisted immediately. Retention pruning keeps the table lean
automatically.

**Designed for trust.** Each event is signed with a per-site HMAC and sealed into
a hash-chained sequence of checkpoints, making after-the-fact tampering, including
row insertion or deletion, detectable. Because an attacker with full server access
could recompute local signatures, the latest checkpoint signature can be anchored
off-host (emailed or sent to a webhook) so the integrity proof leaves the machine.

**Designed for privacy.** IP logging is optional and can be anonymised at capture
time. The log takes part in Tools > Export Personal Data and Tools > Erase Personal
Data, and the plugin suggests a privacy policy paragraph. It never phones home and
never loads code from external servers.

**Designed for your security stack.** New events can be streamed as signed JSON 
Lines or syslog-compatible JSON to any HTTPS endpoint that accepts newline-delimited
JSON, typically a collector such as Vector, Fluent Bit or Logstash that forwards
to Elastic, Splunk, Loki or Datadog, with retries that never lose an event.

#### Highlights

 * Authentication and account activity: logins, logouts, failed logins (rate-limited
   to prevent log flooding), registration, role changes, profile and user-metadata
   changes, password resets, application passwords, user deletion.
 * Content activity: posts, pages and custom post types created, updated (with a
   field-level diff), status changes, trashing, restoring and permanent deletion;
   comments, media and taxonomy terms.
 * Clean, readable event viewer with severity badges, expandable detail rows, sorting,
   filtering and full-text search.
 * Granular configuration: enable or disable whole event groups or individual events.
 * Exclusion rules by IP/CIDR, user login, user ID, role and request path.
 * Plugin/theme and settings changes, navigation menus, and the GDPR personal-data
   request lifecycle.
 * Optional integrations: WooCommerce (orders, status changes, stock) and Yoast 
   SEO (metadata and settings).
 * Real-time notifications, Slack, Discord, Telegram, email and generic webhook,
   by urgency or chosen event codes, delivered immediately or as an hourly digest.
   Free.
 * Optional login geolocation (via a provider you wire) with an automatic alert 
   on a login from a new country.
 * Scheduled HTML summary reports emailed to the administrator (daily or weekly).
 * Statistics screen with daily-volume chart and category, user and event breakdowns.
 * Active session management: see who is logged in and terminate sessions. Free.
 * Tamper-evident integrity: per-row HMAC plus a hash-chained checkpoint sequence
   with optional off-host anchoring (email/webhook), verifiable with WP-CLI (`wp
   bzal verify-integrity`).
 * Real-time notifications also fire on a chosen set of event codes, regardless 
   of urgency.
 * Configurable severity per event code, driving notifications and the security 
   badge.
 * Optional anomaly detection: flags a rapid bulk-delete burst by one user and off-
   hours admin logins as high-severity alerts.
 * Admin-bar quick view: the latest events and a 24-hour security badge on every
   screen.
 * “Users online” view: who currently holds a session, with their most recent action,
   time and IP.
 * CSV, JSON and JSON Lines export of the filtered log, streamed page by page so
   large logs export quickly, with spreadsheet-formula-injection protection.
 * Log stream (SIEM export): new events are sent to your HTTPS endpoint (for example
   a Vector, Fluent Bit or Logstash HTTP input) in batches signed with HMAC-SHA256,
   with exponential backoff, a delivery status screen, a “Test connection” button
   and an alert event when delivery keeps failing.
 * GDPR tools: the person’s log entries are included in personal data exports; erasure
   requests either keep entries for the retention period (with an explanation for
   the requester) or anonymise them while the integrity chain stays verifiable.
 * Self-audit: changes to the plugin’s own settings, retention runs, anonymisation
   and stream failures are always recorded and cannot be switched off or excluded.
 * WooCommerce: refunds, trashed and deleted orders (HPOS and legacy storage), price,
   sale date, SKU and visibility changes with old and new values, and changes made
   on the WooCommerce settings screens (secrets are never logged).
 * Role capability changes (a capability granted to or revoked from a role) are 
   recorded as security events.
 * Read access via the REST API (offset and cursor pagination, plus an integrity-
   anchor endpoint) and optionally GraphQL, gated by capability.
 * Granular configuration: enable/disable whole event groups or individual events;
   exclusion rules by IP/CIDR, user, role and path.
 * Configurable retention with on-demand cleanup that keeps integrity verification
   intact; UTC storage with display in your chosen timezone.
 * Multisite ready: one shared, indexed table for the whole network, partitioned
   per site, with per-site settings, retention and integrity chain.
 * Fully translatable, with bundled Polish, German and Czech translations.

### External services

This plugin works fully offline. It does not connect to any external service on 
its own. The following optional integrations are disabled by default and only ever
contact a destination that you enter in the settings; each transmits a short summary
of a logged event (such as the event description, the acting user’s login, the time,
and, when IP logging is enabled, the IP address) at the moment the event occurs 
or, in digest mode, once per hour.

 * **Slack**: when you enter a Slack Incoming Webhook URL, matching events are POSTed
   to that webhook. See the Slack Terms of Service (https://slack.com/terms-of-service)
   and Privacy Policy (https://slack.com/trust/privacy/privacy-policy).
 * **Discord**: when you enter a Discord webhook URL, matching events are POSTed
   to that webhook. See the Discord Terms (https://discord.com/terms) and Privacy
   Policy (https://discord.com/privacy).
 * **Telegram**: when you enter a Telegram bot token and chat ID, matching events
   are sent through the Telegram Bot API at api.telegram.org. See the Telegram Terms(
   https://telegram.org/tos) and Privacy Policy (https://telegram.org/privacy).
 * **Generic webhook**: when you enter a custom webhook URL (for notifications or
   for off-host integrity anchoring), the corresponding payload is POSTed to that
   URL. The destination is yours; review its provider’s terms and privacy policy.
 * **Log stream (SIEM export)**: when you enable the log stream and enter an HTTPS
   endpoint, every new event (including the acting user’s login and, when IP logging
   is enabled, the IP address and browser identification) is POSTed to that endpoint
   in batches every fifteen minutes. The destination is a system you choose and 
   operate or subscribe to; review its provider’s terms and privacy policy.
 * **Login geolocation**: disabled unless you both enable it and wire a provider
   through the `bzal_geolocate_country` filter. The plugin bundles no geolocation
   provider and makes no geolocation request by itself; any lookup is performed 
   by the provider you supply, under that provider’s terms.

Summary reports and notification emails are delivered through your site’s own WordPress
mail system to the recipients you configure; they are not sent to any third party
by this plugin.

## Screenshots

[⌊The activity log viewer: filters, search and expandable detail rows with the full
event payload and request correlation.⌉⌊The activity log viewer: filters, search
and expandable detail rows with the full event payload and request correlation.⌉[

The activity log viewer: filters, search and expandable detail rows with the full
event payload and request correlation.

[⌊Statistics: headline figures, a daily-volume chart and a per-category breakdown.⌉⌊
Statistics: headline figures, a daily-volume chart and a per-category breakdown.⌉[

Statistics: headline figures, a daily-volume chart and a per-category breakdown.

[⌊Settings: enable or disable whole groups or individual events and override their
severity.⌉⌊Settings: enable or disable whole groups or individual events and override
their severity.⌉[

Settings: enable or disable whole groups or individual events and override their
severity.

[⌊Notifications, scheduled reports, integrity anchoring and anomaly detection.⌉⌊
Notifications, scheduled reports, integrity anchoring and anomaly detection.⌉[

Notifications, scheduled reports, integrity anchoring and anomaly detection.

[⌊Log stream: send every new event to a SIEM or log collector, with signing secret
and delivery status.⌉⌊Log stream: send every new event to a SIEM or log collector,
with signing secret and delivery status.⌉[

Log stream: send every new event to a SIEM or log collector, with signing secret
and delivery status.

[⌊Users online: who currently holds a session, with their most recent action, time
and IP.⌉⌊Users online: who currently holds a session, with their most recent action,
time and IP.⌉[

Users online: who currently holds a session, with their most recent action, time
and IP.

## Installation

 1. Upload the `beziworld-activity-log` folder to `/wp-content/plugins/`.
 2. Activate the plugin through the _Plugins_ screen in WordPress.
 3. Open _Activity Log_ in the admin menu to review events, and _Activity Log  Settings_
    to configure retention, events and exclusions.

## FAQ

### Where are events stored?

In dedicated custom database tables created on activation, not in the WordPress 
posts table, so your content queries are never affected.

### Will it slow down my site?

Non-critical events are buffered and written in a single batched query on shutdown;
security events are written immediately. Indexed columns keep the viewer responsive
even on large logs.

### Does the plugin detect changes made directly in the database?

No. Like every hook-based activity logger, it records actions that flow through 
WordPress. Direct SQL modifications bypass WordPress hooks and cannot be observed.

### Does it send my data anywhere?

No. There is no tracking or telemetry, and the plugin never loads code from external
servers. The only outbound requests are the optional integrations described under“
External services” below: every one is off by default and is sent only to an endpoint
you configure yourself.

### How do I verify the signature of streamed events?

Every request carries `X-Bzal-Timestamp` (Unix time) and `X-Bzal-Signature: sha256
=<hex>`, where the hex value is HMAC-SHA256 of the timestamp, a dot and the raw 
request body, keyed with the signing secret shown on the Log stream tab. Recompute
it, compare in constant time and reject requests older than a few minutes. Each 
event line also carries the row’s own integrity signature (`hmac`).

### What happens to the log when someone asks to be forgotten?

By default the entries are kept for the retention period as security records, which
is usually covered by legitimate interest, and the erasure request reports this 
to the requester. If you choose to anonymise instead, the user name, IP address,
browser details and identifying values are removed from that person’s entries. The
rows are re-signed and their original signatures kept, so `wp bzal verify-integrity`
still passes, and the anonymisation itself is recorded.

### Does retention break integrity verification?

No. Before removing old events the plugin seals them into a checkpoint and records
where the chain was cut, so verification covers everything that remains and still
detects any other change or deletion.

### Does it provide WP-CLI commands?

Yes:

 * `wp bzal verify-integrity`: verify the per-row signatures and the checkpoint 
   chain, reporting any detected tampering.
 * `wp bzal checkpoint`: seal a new integrity checkpoint immediately.
 * `wp bzal purge`: apply the retention policy now.
 * `wp bzal stats`: print the number of recorded events for the current site.
 * `wp bzal stream status|flush|reset [--from=<id>]`: inspect the log stream, deliver
   pending events now, or move the delivery cursor (`--from=0` replays the whole
   log).

### Can developers extend it?

Yes. The plugin exposes hooks for integration:

 * `do_action( 'bzal_event_logged', array $columns )`: fires after each event is
   stored; receives the event’s column map, for forwarding to your own systems.
 * `apply_filters( 'bzal_geolocate_country', string $country, string $ip )`, return
   an ISO country code for an IP to power optional login geolocation (no provider
   is bundled).
 * `apply_filters( 'bzal_user_meta_denied', bool $denied, string $meta_key )`, return
   true to keep a specific user-meta key out of the log.
 * `do_action( 'bzal_plugin_booted' )`: fires once the plugin has finished booting,
   for registering your own extensions.
 * `apply_filters( 'bzal_export_max_rows', int $max_rows )`: the maximum number 
   of rows in one CSV, JSON or JSON Lines export (default 100000).
 * `do_action( 'bzal_schema_upgraded', string $from )`: fires after the plugin’s
   database schema was installed or upgraded on a site.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

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

Contributors

 *   [ beziworld ](https://profiles.wordpress.org/beziworld/)

“Beziworld – Activity Log” has been translated into 1 locale. Thank you to [the translators](https://translate.wordpress.org/projects/wp-plugins/beziworld-activity-log/contributors)
for their contributions.

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

### Interested in development?

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

## Changelog

#### 1.2.0

 * New: quick date ranges on the Events screen (Today, Yesterday, Last 7 days, Last
   30 days) in your timezone.
 * New: the user filter suggests accounts as you type (login or display name) and
   accepts a login or an ID.
 * New events: plugin and theme files edited in the built-in file editor (only when
   the file really changed), Customizer changes published, Tools > Export run, plugin
   and theme auto-updates switched on or off.
 * New: anomaly rule “Administrator login from a new IP address” (off by default),
   with a configurable history length; with IP anonymisation it stores only keyed
   hashes, and the history is removed with the account and by personal data erasure.
 * Tested up to WordPress 7.1.

#### 1.1.0

 * New: a redesigned admin interface shared by all Beziworld plugins: a header with
   the plugin version and a dark, light or automatic theme, tabs between the Events,
   Settings, Sessions, Online, Statistics and About screens, and the settings sections
   in a vertical menu next to their content. The sidebar keeps a single “Activity
   Log” entry; every screen stays at its address.
 * New: “Send test notification” and a delivery status table (last attempt, HTTP
   code, error) for every notification channel.
 * New: Screen Options for the number of events per page, an IP address filter, 
   events grouped by category in the filter, and a “Clear filters” link when the
   filters match nothing.
 * New: exporting the log is recorded as an event (format, filters, whether IP addresses
   were included). The event cannot be disabled.
 * Fixed: date filters, exports and the daily chart compared local dates with UTC
   times, which added or dropped events at the edges of a day. Dates now follow 
   the configured timezone, including daylight saving changes.
 * Fixed: the hourly digest only reached email; it is now delivered to every enabled
   channel, and events queued for it by simultaneous requests are no longer lost.
 * Fixed: IP addresses follow one rule everywhere (list, Online screen, search, 
   exports, REST and GraphQL): only users who manage the log see them. Filter bzal_can_see_ip.
 * Fixed: sorting by user sorts by login name.
 * Improved: notifications are sent with wp_safe_remote_post; saved webhook URLs
   and the Telegram token are masked in the settings form and kept until a new value
   is entered.
 * Improved: the Sessions screen is paginated, asks for confirmation before ending
   all sessions (with a clear warning for your own account) and shows dates in the
   configured timezone.
 * Improved: event details are readable without JavaScript, and the details toggle
   has an accessible name and aria-controls.
 * Tested up to WordPress 7.1.

#### 1.0.0

 * New: Log stream (SIEM export). New events are delivered to an HTTPS endpoint 
   as JSON Lines or syslog-compatible JSON, in batches signed with HMAC-SHA256 (
   timestamp plus body), every fifteen minutes through WP-Cron. Delivery is cursor
   based: nothing is lost when the endpoint is down, failed batches are retried 
   with exponential backoff, and repeated failures are recorded as an event. Includes
   a delivery status screen, a “Test connection” button and `wp bzal stream`.
 * New: JSON Lines export of the filtered log. All exports now page by id instead
   of by offset, so the cost of each page stays constant and large exports no longer
   slow down as they progress (in testing, an export that took 32 seconds over 100,000
   events by offset runs in under a second).
 * New: personal data exporter and eraser for Tools > Export / Erase Personal Data,
   a choice between keeping entries for the retention period or anonymising them,
   and a suggested privacy policy paragraph.
 * New: the plugin records changes to its own settings, retention runs, anonymisation
   and stream failures. These events cannot be disabled or excluded.
 * New: role capability changes, WooCommerce refunds, trashed and deleted orders(
   HPOS and legacy), product price, sale date, SKU, tax and visibility changes, 
   and WooCommerce settings changes (secret values redacted).
 * Fixed: retention made integrity verification report tampering once old events
   were removed. Retention now seals and records the cut; installs pruned by earlier
   versions are reconciled once on upgrade.
 * Fixed: on multisite, sites other than the main site wrote to tables that did 
   not exist until an administrator visited that site, the network-wide storage 
   was split per site, and site administrators did not receive the log capabilities.
   All sites now share one network table (existing per-site tables are kept) and
   capabilities are granted per site.
 * Fixed: full-text search matched any of the words instead of all of them, and 
   every search also scanned the unindexed IP column. Searches now require every
   word and only look at IP addresses when the term can be part of one.
 * Fixed: search failed on databases that accept a FULLTEXT index but cannot run
   MATCH (such as the SQLite integration used by WordPress Playground); the plugin
   now checks MATCH works before using it.
 * Fixed: HPOS placeholder posts were logged as created content and WooCommerce 
   order notes as comments; WooCommerce housekeeping user meta and role meta under
   a custom table prefix were logged as user metadata changes.
 * Hardening: notification and anchoring webhooks use the request-time safe HTTP
   API, which refuses hostnames resolving to internal addresses; CSV cells starting
   with a tab or carriage return are neutralised.
 * Developer: automated PHPUnit integration tests and a GitHub Actions workflow (
   coding standards, PHP 7.4+ compatibility, tests on PHP 7.4 to 8.4, Plugin Check).
 * Tested up to WordPress 7.1.

#### 0.6.0

 * New: an “About the author” screen under Activity Log with the author’s details,
   a link to the plugin page and an optional, voluntary way to support development.
   It is also linked from the plugin’s row on the Plugins screen. Nothing is shown
   unless you open it.
 * Changed: the plugin is now named “Beziworld – Activity Log” and links to its 
   page on beziworld.eu. The plugin folder, slug, text domain, settings and data
   are unchanged.
 * Improved: plugin texts and translations use plain punctuation instead of typographic
   dashes.
 * Tested up to WordPress 7.1.

#### 0.5.1

 * Hardening: settings inputs are now unslashed and sanitised at the point of access
   rather than across helper boundaries, satisfying Plugin Check static analysis.
 * Removed the redundant `load_plugin_textdomain()` call; bundled Polish, German
   and Czech translations load through WordPress just-in-time loading (the `Text
   Domain` and `Domain Path` headers are declared).

#### 0.5.0

 * Content, comment, media, taxonomy, menu, plugin/theme, settings, GDPR-request
   and user-metadata sensors.
 * WooCommerce and Yoast SEO integrations (loaded only when active).
 * Real-time notifications: Slack, Discord, Telegram, email, generic webhook, by
   urgency or per chosen event codes; immediate or hourly digest.
 * Optional login geolocation with a login-from-new-country alert.
 * Scheduled HTML summary reports; statistics screen with charts; admin-bar quick
   view with a security badge.
 * Active session management; CSV/JSON export with formula-injection protection.
 * Hash-chained integrity checkpoints with optional off-host anchoring and `wp bzal
   verify-integrity`; per-site partitioned on multisite networks.
 * REST (offset + cursor pagination + integrity-anchor endpoint) and optional GraphQL
   read access; advanced filters; dashboard widget; same-request event correlation.
 * Per-site partitioned integrity chain on multisite; optional full-text indexing
   of the event-data payload.
 * Configurable per-event severity and optional behavioural anomaly detection (bulk-
   delete burst, off-hours admin login).
 * Fast full-text search (MySQL FULLTEXT) across event object, user and message 
   columns, with a LIKE fallback and an optional mode that also indexes the event-
   data payload.

#### 0.1.0

 * Initial release: custom-table storage, per-row HMAC integrity, authentication/
   account sensor, event viewer, configurable retention with on-demand cleanup, 
   event toggles and exclusion rules.

## Meta

 *  Version **1.2.0**
 *  Last updated **1 day ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.4 or higher **
 *  Tested up to **7.1.3**
 *  PHP version ** 7.4 or higher **
 *  Languages
 * [Czech](https://cs.wordpress.org/plugins/beziworld-activity-log/) and [English (US)](https://wordpress.org/plugins/beziworld-activity-log/).
 *  [Translate into your language](https://translate.wordpress.org/projects/wp-plugins/beziworld-activity-log)
 * Tags
 * [Activity Log](https://sna.wordpress.org/plugins/tags/activity-log/)[audit log](https://sna.wordpress.org/plugins/tags/audit-log/)
   [GDPR](https://sna.wordpress.org/plugins/tags/gdpr/)[security](https://sna.wordpress.org/plugins/tags/security/)
   [siem](https://sna.wordpress.org/plugins/tags/siem/)
 *  [Advanced View](https://sna.wordpress.org/plugins/beziworld-activity-log/advanced/)

## Ratings

No reviews have been submitted yet.

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

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

## Contributors

 *   [ beziworld ](https://profiles.wordpress.org/beziworld/)

## Support

Got something to say? Need help?

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