Plugin installation techniques; activation, deactivation and uninstall

If you are building a complex plugin, or one which needs it’s own database tables, you’ll likely be installing all kinds of things during activation or first run. Uninstalling your data however may be an after thought.

In this post I’ll explain techniques you can use to install and remove your data to keep things tidy, should the user decide they no longer want your plugin.


During plugin activation you may need to setup your plugin’s initial data, and do things such as:

  1. Install some tables using dbdelta
  2. Setup some roles and capabilities using add_role and add_cap respectively.
  3. Create a cron job using wp_schedule_event
  4. Create some initial data i.e. pages, terms

Registering your activation function

To hook in your activation function, you’ll need to register it with the register_activation_hook function.

register_activation_hook( __FILE__, 'your_plugin_activation_function' );
function your_plugin_activation_function() {
// Do stuff here

view raw


hosted with ❤ by GitHub

It is important to note that:

  • activation hooks only run when the plugin is activated – not during plugin updates.
  • activation hooks need to be registered outside of other WP hooks such as init and plugins_loaded because your activation function is called prior to the plugin being loaded/activated.
  • If you are creating an install class, you can register your hook in its constructor, if its constructed right away.
  • If you are not registering your function in the main plugin file, __FILE__ won’t work. You may want to store __FILE__ in a constant for reference from other files.
  • File doesn’t work with symlinks (if you develop with these), but you can use (a little hacky): basename( dirname( __FILE__ ) ) . '/' . basename( __FILE__ ) instead.

Notes on custom post types

If you are installing some default terms or custom post types, you’ll need to ensure the post types are registered prior to running your code. A quick and easy way to do this would be to register multiple activation hooks in order, for example:

register_activation_hook( __FILE__, 'your_post_type_registration_function', 10 );
register_activation_hook( __FILE__, 'your_plugin_activation_function', 15 );
register_activation_hook( __FILE__, 'flush_rewrite_rules', 20 );

view raw


hosted with ❤ by GitHub

You can use the same technique to flush permalinks after installing a custom post type too which is also in that snippet, which calls flush_rewrite_rules after we’ve installed.


This occurs when the user deactivates your plugin from admin. At this point you shouldn’t delete data, because the plugin is still technically installed (its just inactive), but you can:

  1. Remove cron jobs
  2. Remove roles

Personally I tend to leave out a deactivation hook and run all removal logic during uninstall instead as this shouldn’t cause any major performance issues, but if you need to use it you can hook in your deactivation function just like the activation one (for examples see here).


when the user presses ‘delete’ on the admin plugins screen (if the plugin is already deactivated), WordPress runs a special file in your plugin called uninstall.php if it exists.

2013-12-09 at 09.56

At this point you’ll most commonly want to delete any stored data your plugin may have made so the DB is left clean. You may:

  1. Remove settings data using a wpdb query or delete_option.
  2. Remove post type data with a query
  3. Delete DB tables with a query

How to format your uninstall.php

Uninstall.php needs to be protected – you don’t want someone viewing that file directly and triggering an uninstall maliciously.

if( ! defined( 'WP_UNINSTALL_PLUGIN' ) )
// Uninstall code goes here

view raw


hosted with ❤ by GitHub

Checking for WP_UNINSTALL_PLUGIN is enough – WordPress defines this just prior to loading your file.

Multisite usage

Uninstall.php is still ran when using multisite. In this instance however you may have more data to remove (from each site on the network); in this case you can use switch_to_blog to loop through all blogs and delete what you need to.


Some users have been known to ‘delete’ a plugin to re-install it or update it – obviously this isn’t the ideal situation as it means they lose their data when uninstall is triggered.

One day I’d like to see a way for WP to ‘flag’ whether or not data should be removed so its user-optional, until then you need to handle this yourself. In WooCommerce we now do this from the status page:

2013-12-09 at 10.00

This prevents accidental loss of data/angry folk with pitchforks.

Final notes

  • When using any of these functions/hooks avoid echo’ing any data it may cause “headers already sent” errors as they hooks are ran early.
  • To debug your install/uninstall functions, you could use WP_DEBUG_LOG






3 responses to “Plugin installation techniques; activation, deactivation and uninstall”

  1. Patrick avatar

    So there isn’t a way to add some sort of pop up on plugin deletion that asks users if they want to delete their data? That would be very handy.

    Is it worth having a setting that controls the status of deleting ALL of the plugins data? Or just specific data like the WC custom post types?

    1. mikejolley avatar

      Nope, there isn’t a way. Selective deletion could be useful, but I guess only in cases where your post types etc could be re-used by other plugins? Post data could be useful to keep.

  2. Shawn Wernig avatar
    Shawn Wernig

    Hey I had a to do a really quick fix on my plugin today because the activate hooks weren’t firing on updates. This post helped me work through it, thank you! I did a blog post on how I solved this problem if anyone is interested

Leave a Reply

Your email address will not be published. Required fields are marked *

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

%d bloggers like this: