How to run an activation function when plugin is network activated on multisite?

I’m trying to make my plugin multisite compatible. I’m using the register_activation_hook() function to register my my_activate() function to run when the plugin is activated. This works well on a single-site install.

function my_activate() {
    // Do some things.
}
register_activation_hook( __FILE__, 'my_activate' );

The problem is, my_activate() doesn’t run for each site when my plugin is ‘network activated’. Also, it doesn’t run when new sites are created on the network.

How can I get my activation routine to a) run when my plugin is network activated for all sites in the network and b) run when a new site is created on the multisite network?

Solutions Collecting From Web of "How to run an activation function when plugin is network activated on multisite?"

Your callback function should run when your plugin is network activated or activated for a single site. Either way, it should be working.

However, if you intend for the code contained within your callback to be ran for each blog in your network, then be aware that this will not happen out of the box, instead, the code within your callback will in the primary blog context.

If your code needs to run on each blog upon Network Activation:

function my_plugin_activate($network_wide) {

    if ( is_multisite() && $network_wide ) { 

        global $wpdb;

        foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
            switch_to_blog($blog_id);
            //do your specific thing here...
            restore_current_blog();
        } 

    } else {
        //run in single site context
    }

}

register_activation_hook( __FILE__, 'my_plugin_activate' );

If your code needs to run when a new blog is created:

function my_plugin_new_blog($blog_id, $user_id, $domain, $path, $site_id, $meta) {

    //replace with your base plugin path E.g. dirname/filename.php
    if ( is_plugin_active_for_network( 'my-plugin-name-dir/my-plugin-name.php' ) ) {
        switch_to_blog($blog_id);
        //do your specific thing here...
        restore_current_blog();
    } 

}

add_action('wpmu_new_blog', 'my_plugin_new_blog', 10, 6 );

Additionally:

For those reading who want similar functionality but for all plugins that get network activated (not just the one you control, if at all applicable), then you may wish to look at: https://wordpress.org/plugins/proper-network-activation/ which will ensure that each plugin in your multisite network in which is network activated, has both its register_activation_hook and register_deactivation_hook run in each blog context.