WordPress Privacy System Overview

WordPress includes a comprehensive privacy and GDPR compliance system introduced in version 4.9.6. This system enables sites to handle personal data requests from users, including data export and erasure (right to be forgotten).

Core Concepts

Personal Data Requests

WordPress handles two types of privacy-related requests:

Request TypeAction NameDescription
Export Personal Dataexport_personal_dataExports all personal data associated with an email address
Erase Personal Dataremove_personal_dataAnonymizes or deletes personal data associated with an email address

Request Workflow

  1. Request Creation – Admin or user initiates a request via the privacy tools
  2. Email Verification – A confirmation email is sent to the user’s email address
  3. User Confirmation – User clicks the confirmation link to verify ownership
  4. Admin Notification – Site admin receives notification of the confirmed request
  5. Request Processing – Admin processes the export or erasure
  6. User Notification – User receives notification when their request is fulfilled

Request Statuses

Requests are stored as a custom post type (user_request) with these statuses:

StatusDescription
request-pendingAwaiting user email confirmation
request-confirmedUser confirmed, awaiting admin processing
request-failedEmail sending failed
request-completedRequest has been fulfilled

Personal Data Exporters

The export system uses a plugin-based architecture. Exporters are registered via the wp_privacy_personal_data_exporters filter.

Built-in Exporters

Exporter IDFriendly NameSource
wordpress-userWordPress Useruser.php
wordpress-commentsWordPress Commentscomment.php
wordpress-mediaWordPress Mediamedia.php

Exporter Callback Format

php
function my_exporter_callback( $email_address, $page = 1 ) {
    return array(
        'data' => array(
            array(
                'group_id'          => 'my-group',
                'group_label'       => 'My Data Group',
                'group_description' => 'Description of this data group.',
                'item_id'           => 'item-123',
                'data'              => array(
                    array(
                        'name'  => 'Field Name',
                        'value' => 'Field Value',
                    ),
                ),
            ),
        ),
        'done' => true, // false if more pages exist
    );
}

Registering a Custom Exporter

php
add_filter( 'wp_privacy_personal_data_exporters', function( $exporters ) {
    $exporters['my-plugin'] = array(
        'exporter_friendly_name' => 'My Plugin Data',
        'callback'               => 'my_plugin_personal_data_exporter',
    );
    return $exporters;
} );

Personal Data Erasers

Erasers handle anonymization or deletion of personal data. Registered via wp_privacy_personal_data_erasers filter.

Built-in Erasers

Eraser IDFriendly NameSource
wordpress-commentsWordPress Commentscomment.php

Note: WordPress does not include an eraser for user accounts or media by default, as deletion may have wider implications.

Eraser Callback Format

php
function my_eraser_callback( $email_address, $page = 1 ) {
    return array(
        'items_removed'  => true,  // Were items actually removed?
        'items_retained' => false, // Were items retained (couldn't delete)?
        'messages'       => array(), // Messages to include in results
        'done'           => true,  // false if more pages exist
    );
}

Registering a Custom Eraser

php
add_filter( 'wp_privacy_personal_data_erasers', function( $erasers ) {
    $erasers['my-plugin'] = array(
        'eraser_friendly_name' => 'My Plugin Data',
        'callback'             => 'my_plugin_personal_data_eraser',
    );
    return $erasers;
} );

Data Anonymization

WordPress provides helper functions for consistent data anonymization:

php
// Anonymize different data types
wp_privacy_anonymize_data( 'email' );    // Returns: '[email protected]'
wp_privacy_anonymize_data( 'url' );      // Returns: 'https://site.invalid'
wp_privacy_anonymize_data( 'ip', $ip );  // Returns anonymized IP
wp_privacy_anonymize_data( 'date' );     // Returns: '0000-00-00 00:00:00'
wp_privacy_anonymize_data( 'text' );     // Returns: '[deleted]'
wp_privacy_anonymize_data( 'longtext' ); // Returns longer deletion message

Privacy Policy Page

WordPress supports designating a Privacy Policy page:

php
// Get the privacy policy URL
$url = get_privacy_policy_url();

// Display the privacy policy link
the_privacy_policy_link( 'Before text ', ' After text' );

// Get link markup
$link = get_the_privacy_policy_link( '<span>', '</span>' );

The privacy policy page ID is stored in the wp_page_for_privacy_policy option.

Export File Management

Personal data exports are stored as files in wp-content/uploads/wp-personal-data-exports/.

  • Files include a cryptographically secure random string in the filename
  • Files are automatically deleted after 3 days via cron job
  • The wp_privacy_export_expiration filter can modify the expiration time

Admin Screens

The privacy system adds two admin screens:

ScreenURLPurpose
Export Personal Data/wp-admin/export-personal-data.phpManage export requests
Erase Personal Data/wp-admin/erase-personal-data.phpManage erasure requests

GDPR Compliance Notes

While WordPress provides the technical infrastructure for GDPR compliance, site owners are responsible for:

  1. Privacy Policy – Creating and maintaining an appropriate privacy policy
  2. Data Inventory – Understanding what personal data is collected
  3. Consent – Obtaining proper consent for data collection
  4. Third Parties – Ensuring plugins and themes also comply
  5. Processing Requests – Responding to data requests within required timeframes
FileContents
wp-includes/class-wp-user-request.phpWP_User_Request class
wp-includes/user.phpRequest handling functions
wp-includes/functions.phpAnonymization and export utilities
wp-includes/comment.phpComment exporter/eraser
wp-includes/media.phpMedia exporter
wp-includes/link-template.phpPrivacy policy link functions
wp-includes/default-filters.phpHook registrations

Version History

VersionChanges
4.9.6Initial privacy system introduced
5.4.0Added Community Events Location and Session Tokens to user export
5.7.0Added $status parameter to wp_create_user_request()
5.8.0Deprecated some email content filters, added new ones
6.2.0Added privacy-policy rel attribute to policy links
6.8.0Confirmation keys now use wp_fast_hash() instead of phpass