Retention Enforcement
Define retention policies, schedule automated deletion, and maintain a tamper-evident audit log.
Retention Enforcement
DPOKit's retention module automates the lifecycle of personal data — from initial collection through to deletion or anonymisation — and keeps an immutable audit log of every action.

Configuring retention policies
Go to DPOKit → Retention → Policies to define periods per data category:
| Data category | Default period | Configurable? |
|---|---|---|
| WooCommerce orders | 7 years | Yes |
| Form submissions | 2 years | Yes |
| WordPress user accounts | Until account deleted | Yes |
| WordPress comments | 3 years | Yes |
| Consent records | 3 years | Yes |
| Audit log | 3 years | Yes |
Legal hold rules
Legal holds override standard retention periods. Example:
- Tax retention hold: retain orders for 7 years regardless of any shorter policy
- Litigation hold: retain specified records indefinitely until the hold is lifted
Holds are configured at Retention → Legal Holds and require Administrator capability to create or modify.

Registering a custom retention policy
Plugin authors can register their own data categories and retention periods:
add_filter( 'pv_retention_policies', function( $policies ) {
$policies['my_plugin_submissions'] = [
'label' => 'My Plugin Submissions',
'default_days' => 365, // 1 year
'min_days' => 30,
'max_days' => 2555, // 7 years
'action' => 'anonymise', // 'delete' | 'anonymise' | 'flag'
'query_callback' => 'my_plugin_get_expired_records',
'action_callback'=> 'my_plugin_anonymise_records',
];
return $policies;
} );
/**
* Return IDs of records older than $before_date.
*
* @param string $before_date ISO 8601 date string.
* @return int[]
*/
function my_plugin_get_expired_records( string $before_date ): array {
global $wpdb;
return $wpdb->get_col(
$wpdb->prepare(
"SELECT id FROM {$wpdb->prefix}my_submissions WHERE created_at < %s",
$before_date
)
);
}
/**
* Anonymise a batch of records by ID.
*
* @param int[] $ids
* @return int Number of records affected.
*/
function my_plugin_anonymise_records( array $ids ): int {
global $wpdb;
$placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) );
return $wpdb->query(
$wpdb->prepare(
"UPDATE {$wpdb->prefix}my_submissions
SET email = 'anonymised@example.com', name = 'Anonymised', ip = ''
WHERE id IN ({$placeholders})",
...$ids
)
);
}Hooking into enforcement events
// Fired after each enforcement batch completes
add_action( 'pv_retention_batch_complete', function( $policy_id, $action, $count ) {
error_log( "Retention: {$action} {$count} records for policy '{$policy_id}'" );
}, 10, 3 );
// Fired when a record is skipped due to a legal hold
add_action( 'pv_retention_legal_hold_applied', function( $policy_id, $record_id, $hold_id ) {
// Custom notification or logging
}, 10, 3 );Automated enforcement
DPOKit runs a retention enforcement job via WP-Cron on a configurable schedule (default: daily at 02:00).
For each data category, the job:
- Queries records older than the configured retention period
- Checks for legal hold overrides
- Applies the configured action: delete, anonymise, or flag for manual review
- Writes an entry to the immutable audit log
Dry-run mode
Before running enforcement, you can preview what would be affected without making any changes:
- Go to Retention → Run Enforcement.
- Enable Dry-run mode.
- Click Preview — a report shows the record counts and actions that would be taken.

Rate limiting
Large-scale enforcement jobs are chunked to avoid PHP timeouts and database overload. The default chunk size is 500 records per batch, with a configurable delay between batches.
// Adjust batch size and delay for large databases
add_filter( 'pv_retention_batch_size', fn() => 200 );
add_filter( 'pv_retention_batch_delay_ms', fn() => 500 ); // milliseconds between batchesAudit log
Every deletion and anonymisation is recorded in the audit log at Retention → Audit Log:
| Field | Description |
|---|---|
| Timestamp | When the action was taken |
| Data category | e.g. woocommerce_orders |
| Record count | How many records were affected |
| Action | deleted / anonymised / flagged |
| Job ID | Links related log entries for one enforcement run |
| Hash | SHA-256 of the previous entry — tamper-evident chain |

Exporting the audit log
Export the log as CSV or PDF from the Audit Log screen. Reports are timestamped and archived for the configured log retention period (default: 3 years).
WP-CLI
Run retention enforcement from the command line:
# Dry run
wp dpo-kit retention run --dry-run
# Live run
wp dpo-kit retention run
# Run for a specific data category
wp dpo-kit retention run --category=woocommerce_orders