Practical Guide to GDPR compliance for WordPress plugin & theme developers.

Last updated: 05/14/2018 4:00 am EST.

You are likely here because you have a WordPress plugin that manages user data in some way and your users are SCREAMING about GDPR Compliance (as they should be). This is currently the only guide to GDPR compliance for WordPress plugins until the WP Codex is updated.

This will help you get started with what support WordPress core is bringing in the near future. I will keep this updated as new features are offered.

There was a 3rd party GDPR standards plugin being developed but it got enough attention to get co-opted into the core at least in theory. It used class-based implementations in PHP, where core chose to go the more common WP way using hooks & filters.

The final details of how these functionalities will work for users and site owners are still in the works, but users will be able to request their data for export or removal, and site admins will be able to approve these requests in an automated fashion. Here is a quick rundown of what is known so far.

WP Core v4.9.6 will include several new Privacy functions functionalities including:

There are a few other items coming such as general cookie consent messages, GDPR optin fields on all core forms and a few other things to make site owners lives simpler when dealing with compliance. Below I will detail each of the v4.9.6 functionalities and how to use them for your plugin.


Privacy Settings

A new settings page available at Settings -> Privacy has been added to the admin & network admin areas.

This will offer the ability to create or assign a page to hold your site or networks Privacy Policy.


This page also introduces a new user capability manage_privacy_options which allows limiting which site administrators have access to change these settings apart from manage_options.

Multisite Note: By default, only network admins will be able to set these options. There will be an additional option to change it from Network Wide Policy to Per Site Policy. Only when the network admin sets it to Per Site will the extra Settings -> Privacy page for every single site appear. These pages will be hidden otherwise.


Privacy Policy Guide – GDPR Privacy Policy

With the latest copy of core v4.9.6-rc.1 the Privacy Policy Guide is now a dedicated page. Before it was located above the content editor of your selected privacy page, but this led to some confusion due to the overwhelming business of the interface as seen below.

Privacy policy generator in the admin.
 This is what it looks line in the admin.


Now when editing the Privacy Page a notice like this will be shown instead, linking to a (currently hidden) inner admin page. You can access it manually by visiting the /wp-admin/tools.php?wp-privacy-policy-guide=1 on your domain.


This new page is broken into multiple sections with a nice table of contents at the top. The number of sections will vary both with the number of plugins and with time as more plugins add their own information. Each section excluding the Introduction also includes a Copy button to quickly grab it for pasting into your privacy policy text.


Each plugin will them be able to add its own section or sections, near mimicking what WordPress core has done where needed to inform the user of what information they need to add or disclose in their privacy policy as well as what section it should go under.


As of now these are the processes I have noticed during testing.

  • When first installed a new page is generated for a privacy policy.
  • New options in the admin allow changing this assigned & mandatory page.
  • When you edit the privacy policy page at first it will have a basic template of sections & headings inserted into the editor. There will also be a notice with a link to the Privacy Policy Guide page.
  • Any time a plugin changes the suggested text, plugin or theme is activated or deactivated, it will notify the admins that the privacy policy may need to be updated.
  • Eventually (I believe) core will include agreeing to checkboxes and possibly a cookie notice that points to these policies.

Registering additional content for the Privacy Policy Generator in your WP plugin is pretty easy.

The example below shows how this would look.


Personal Data Exporter – GDPR Right of Access 

Data portability requirements mean that users will be able to request all data a site has stored about them and site admins will be able to approve and send them a zipped HTML file by email that includes all of their information.

This works by looping through a list of registered data exporters and rendering the info passed back. It is still in the early but very reliable stages of development, and already available in the WP nightly betas as of now.

Registering a custom Personal Data Exporter for your WordPress plugin is rather easy. The following is a basic example for a fictitious plugin that adds additional user profile information via user_meta. For a version that includes a pagination example such as how core handles comments, see here


Personal Data Eraser – GDPR Right to be Forgotten

The term “eraser” in this context refers to a process that will either anonymize or remove all data related to a user per their request. If the data cannot be removed for some reason an explanation should be given.

Erasers work in much the same way as the exporters. You first register a callback and label. Erasers do 2 things:

  • They attempt to anonymize or remove the user’s data.
  • When data cannot be removed, it returns a message indicating why that data could not be erased or anonymized.

As such an exporters return should always look like this.

return array(
    'items_removed' => false, // Boolean whether items were anonymized or removed.
    'items_retained' => false, // Boolean whether items were not able to be anonymized and were retained.
    'messages' => array(),
    'done' => true,
);

Note: items_retained refers to data that couldn’t be erased, for instance, a WooCommerce order that has not shipped yet.

Registering a custom Personal Data Eraser for your WordPress plugin is just as simple as the exporter. Here is an example based on our social profiles example above. Example of how core anonymizes comments found here


Helper functions to make it easier.

Function to anonymize any data type. Types include email, url, ip, date, text, longtext.

Since there is a new Privacy Policy page there are new helper functions to get that pages URL. I imagine there will shortly be conditionals such as is_privacy_policy_page() or similar.

get_privacy_policy_url();
the_privacy_policy_link( $before, $after );

There are also a couple functions to help anonymize data when possible rather than removing it.

/**
 * Helper to anonymize data.
 * 
 * @param $type string accepts email, url, ip, date, text, & longtext.
 * @param $value string value to be anonymized.
 *
 * @return string
 */
wp_privacy_anonymize_data( $type, $value );
/**
 * Helper to anonymize IP addresses.
 *
 * @param $ip_address string IP adddress to be anonymized.
 *
 * @return string
 */
wp_privacy_anonymize_ip( $ip_address )

WooCommerce

If you develop products that extend WooCommerce check out this guide for some tips on doing that quickly.

How to add GDPR support on your custom WooCommerce plugin

Changelog

The purpose of this log is to keep track of changes after publishing in case you want to know exactly what has changed since you began implementation.

  • 05/29/2018 – Added link to WooCommerce specific developer information.
  • 05/12/2018 – Added section for Privacy Settings page, new user capability & network admin options.
  • 05/14/2018 – Updated section on Privacy Policy Guide to match v4.9.6-rc.1. Reorganized sections to be more logically ordered.

Daniel Iser is a professional WordPress plugin developer, and the author of plugins such as Easy Modal & Popup Maker. Founder of Wizard Internet Solutions he has been working with WordPress for over 7 years creating websites and tools for clients & blog authors.

Follow on:

14 Comments

  1. Pat on May 11, 2018 at 6:26 pm

    Very nice overview!
    Hope many developers will see the opportunities with this!

    • danieliser on May 11, 2018 at 10:36 pm

      Thanks, Be sure to bookmark it. Until core gets docs out on wordpress.org I will try to keep it up to date.

  2. Collins Agbonghama on May 12, 2018 at 6:34 am

    Great overview Daniel. Currently running the beta version of 4.9.6 but no privacy page was created when I upgraded. *confused*

    • danieliser on May 12, 2018 at 6:41 am

      To my knowlege it doesn’t auto create it. There will be a notice, but in case you have one already they didn’t want to break that.

      In which case go to Settings -> Privacy and check out the settings there.

      Hope that helps.

  3. HDS on May 13, 2018 at 8:44 pm

    Ausgezeichnetes Konzept mit wertvollen Entwicklungen zu diesem WordPress-Plugin.
    Freue mich auf die Umsetzung.

    • danieliser on May 14, 2018 at 7:17 am

      Ich denke, es kommt gut voran. Einige Orte, die ich sehe, könnten verbessert werden, aber die Community wird diese Entscheidungen auf lange Sicht treffen.

  4. Sean Davis on May 16, 2018 at 5:58 pm

    Thanks, Daniel. You da man.

  5. Jack Torrance on May 17, 2018 at 12:03 am

    Awesome. Works great.

    Just the function plugin_register_exporters add_filter( ‘wp_privacy_personal_data_exporters’, ‘plugin_register_exporter’ );

    Need to fix the typo and remove the “s” from function name.

    Thanks

    • danieliser on May 17, 2018 at 3:43 am

      Fixed, thanks. Though I would expect anyone reading this would name those functions themselves. Corrected for good measure though.

  6. Jack Torrance on May 17, 2018 at 1:00 am

    What is the point of using wp_privacy_anonymize_data ?

    Can that anonymized data be used in any way? Can it be “decrypted” ?

    Looking at the function definition, it seems pretty pointless if it returns the same data for email/url ?

    • danieliser on May 17, 2018 at 3:45 am

      Email returns something like d********r@w**********s.com I think, but its randomized. It still returns a valid email address though as to not break functions expecting such a format.

      others simply return ”.

    • danieliser on May 17, 2018 at 3:47 am

      And to my knowledge, there is no decryption because it simply overwrites the old string with an empty one or **** one. If there was an algorithm doing it then you could go backward, but they are simply returning blank or blanked strings.

Leave a Comment





This site uses Akismet to reduce spam. Learn how your comment data is processed.