When it comes to WordPress performance, we have a lot to say about plugins. Each plugin adds PHP code that has to be executed, usually includes scripts and styles, and may even execute additional queries against the database. This means that unnecessary plugins can affect page speed and may have a negative impact on the user experience and your page ranking.
As an example, consider a plugin that builds and displays custom forms on front pages, like Contact Form 7. Typically, you would only need one form on a single page, but ideally, you may want to embed a form on any page using the plugin’s shortcode. For this reason, Contact Form 7 loads scripts and styles on every page of your website.
But do you really want to run the plugin code and include scripts and styles on every page of your WordPress website?
In this post, I will show you how to prevent unnecessary plugins from loading on specific posts/pages, so that you can install additional plugins (don’t go crazy of course), and still have your WordPress website load fast. To accomplish this task, we’re going to disable WordPress plugins programmatically on specific posts and pages. This is a four-step process:
- Choose the most popular plugins that fit your needs, and compare their features and effects on page speed.
- Programmatically list and filter plugins before page loads.
- Programmatically filter and deactivate unnecessary plugins with a mu-plugin.
- Filter and deactivate unnecessary plugins using a plugin.
- Track the site performance.
Let’s dive deep.
Three General Rules to Follow When Choosing a Plugin
The following general rules can be helpful when choosing a plugin:
- Install only well-coded plugins from trusted developers: consider active installs, user rating, client support, update frequency, and any useful piece of information coming from the WordPress community.
- Prefer scalable plugins: compare similar plugins in terms of performance, making use of browser dev tools and/or online services like Google Pagespeed Insights, Pingdom, and GTmetrix to evaluate the impact of each plugin on page load time.
- Do not install unnecessary plugins: it should be obvious, but it’s worth mentioning that you should never install a plugin you don’t really need for security and performance reasons. Also, make sure you review your plugins from time to time and uninstall those you don’t need and use anymore.
A Real Life Example
Contact Form 7 is a great plugin that builds and displays forms in WordPress. It provides a perfect example for our purposes, because it includes the following files on every page, even if the page doesn’t contain a form:
- style.css
- scripts.js
A plugin can slow down your website, but we can force WordPress to selectively deactivate plugins depending on the request URL. If you’re a developer, read over the next section where we’ll learn how to programmatically manage plugins and build a mu-plugin that filters unnecessary plugins. If you are not a developer, feel free to hop over to the section dedicated to plugins that allow to filter and organize plugins.
How To Get a List of All Active Plugins Programmatically
First off, you can get a list of all active plugins on your WordPress website with a simple snippet of PHP code. You can add the following code either in a custom plugin, or in the editor of a free WordPress plugin like Code Snippets. If you’d decide to go with your custom plugin, just don’t forget to add the plugin header as seen below.
Each active plugin is stored in wp_options
table where options_name
is active_plugins
. So we can extract the list of those plugins with a simple get_option
call. Here is the code:
<?php
/**
* @package active-plugins
* @version 1.0
*
* Plugin Name: Active Plugins
* Plugin URI: http://wordpress.org/extend/plugins/#
* Description: This is a development plugin
* Author: Your Name
* Version: 1.0
* Author URI: https://example.com/
*/
add_shortcode( 'activeplugins', function(){
$active_plugins = get_option( 'active_plugins' );
$plugins = "";
if( count( $active_plugins ) > 0 ){
$plugins = "<ul>";
foreach ( $active_plugins as $plugin ) {
$plugins .= "<li>" . $plugin . "</li>";
}
$plugins .= "</ul>";
}
return $plugins;
});
Change the plugin details, then save the active-plugins.php
file and upload it onto your /wp-content/plugins/
folder. Create a new blog post and include the [activeplugins]
shortcode. It should now display a list of all active plugins.
With that being done, we can go a step further and add or remove plugins programmatically by taking advantage of the option_active_plugins
filter. This filter belongs to the option_$option_name group of filters, which allow to filter any option after it’s been retrieved from the database. Since all active plugins are stored in wp_options
table where option_value
is active_plugins
, the option_active_plugins
filter provides a way to programmatically activate or deactivate plugins.
So we can activate a plugin programmatically. Say, as an example, you want to activate the ACF plugin. Here is the code:
add_filter( 'option_active_plugins', function( $plugins ){
$myplugin = "advanced-custom-fields/acf.php";
if( !in_array( $myplugin, $plugins ) ){
$plugins[] = $myplugin;
}
return $plugins;
} );
In this example, we are assuming that the plugin has been installed and hasn’t been activated yet.
The code above simply adds the plugin to the list of active plugins on every page of our website. Not very useful, but you get the point.
Moreover, the plugin should load before any other plugin, otherwise, our code could not work as expected. In order to prioritize our plugin load, we have to add our script in a Must-use plugin.
How to Build a Must-use Plugin to Programmatically Deactivate Plugins
We are going to build a Must use plugin, which is a plugin residing in a specific /wp-content
sub-folder, and runs before any regular plugin.
Unfortunately, in this situation, we are not allowed to use conditional tags, because conditional query tags do not work before the query is run. Before then, they always return false. So we have to check our conditions otherwise, such as by parsing the request URI and checking the corresponding URL path.
Add the following code to the active-plugins.php
file, then move it to /wp-content/mu-plugins
:
$request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
$is_admin = strpos( $request_uri, '/wp-admin/' );
if( false === $is_admin ){
add_filter( 'option_active_plugins', function( $plugins ){
global $request_uri;
$is_contact_page = strpos( $request_uri, '/contact/' );
$myplugin = "contact-form-7/wp-contact-form-7.php";
$k = array_search( $myplugin, $plugins );
if( false !== $k && false === $is_contact_page ){
unset( $plugins[$k] );
}
return $plugins;
} );
}
Let’s dive into this code:
- parse_url returns the path of the requested URL.
- strpos finds the position of the first occurrence of
'/wp-admin/'
, and returnsfalse
if the string is not found.$is_admin
variable stores the returned value. - The condition prevents the filter to be run in the admin panel, so that we can safely access plugin settings pages. If the request URI does not contain
'/wp-admin/'
, then we invoke theoption_active_plugins
filter. - Finally, if the current plugin is not in the array of active plugins, and the current page’s URI does not contain
/contact/
, then we remove the plugin from$plugins
.
Now save your plugin and upload it to your /wp-content/mu-plugins/
folder. Clear the cache and add the [activeplugins]
shortcode to several pages. It should be shown in the list only on the /contact/
page.
We can then unset an array of plugins at once with just a bit of additional PHP.
$request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
$is_admin = strpos( $request_uri, '/wp-admin/' );
if( false === $is_admin ){
add_filter( 'option_active_plugins', function( $plugins ){
global $request_uri;
$is_contact_page = strpos( $request_uri, '/contact/' );
$myplugins = array(
"contact-form-7/wp-contact-form-7.php",
"code-snippets/code-snippets.php",
"query-monitor/query-monitor.php",
"autoptimize/autoptimize.php"
);
if( false === $is_contact_page ){
$plugins = array_diff( $plugins, $myplugins );
}
return $plugins;
} );
}
In this example, we’ve first defined an array of plugins to be removed, then we remove them with array_diff. This function “compares array1 against one or more other arrays and returns the values in array1 that are not present in any of the other arrays”.
You can download the full code of this plugin from Gist.
Now you can upload the plugin to the mu-plugins folder and inspect any page of your website. The mu-plugin can be highly customized adding more conditions and checking more URIs, but each condition has to be manually added to the code, and in the long run, this simple mu-plugin could be difficult and a hassle to maintain.
For this reason, you may want to check out the following plugins.
Plugins That Filter Plugins
As an alternative, we can look at a number of good plugins that allow us to add filters that can be managed from the WordPress admin panel.
Plugin Load Filter
Plugin Load Filter is a free option for WordPress users who need to filter plugins under several conditions.
Currently, it supports the following features:
- Post formats
- Custom post types
- Jetpack modules
- WP Embed content card
- URL Filter for Expert (REST API / Heartbeat / AJAX / AMP / etc)
Once a filter has been activated, the admin user can specify where in the site it has to be applied, as shown in the image below.
Plugin Organizer
Plugin Organizer is a popular plugin with over 10,000 active installs and an impressive 5 out of 5-star rating. It is a more comprehensive plugin allowing site admins to:
- Selectively deactivate plugins by post type and request URL
- Selectively deactivate plugins by user roles
- Create groups of plugins
- Change the plugin loading order
- Additional features
The Global Plugins options page provides a drag&drop facility that allows the admin user to globally disable plugins, preventing WordPress to run one or more plugins anywhere in the site, unless it’s differently specified for single posts or pages. The same feature is available for search page and post types.
The plugin adds a metabox in the post editing screen so that the admin is allowed to override global and post type settings. This feature can be activated for post types as well, by checking the corresponding item in the General Settings screen. A great feature is the Plugin Organizer Debug Message, which provides the site admin with useful information about plugins affecting every site page.
More information can be found in their documentation.
Perfmatters Plugin
A partially different approach comes from the Perfmatters plugin. It’s a premium alternative that allows the site admin to selectively load theme and plugin assets depending on URL or custom post type. It is a great tool for both plugin and theme optimization. In fact, it’s developed by a team member from Kinsta!
The plugin has a feature called the Script Manager, where everything is grouped together by the plugin or theme name. This makes it super easy to disable an entire plugin at once, or individual CSS and JavaScript files within it.
You can even disable scripts with regex. This is especially helpful for sites that have a more complex URL structure in place or dynamically generated pages.
This is very powerful and can drastically increase the speed on your WordPress sites (especially your homepage). A few examples of what this can be used for:
- Social media sharing plugins should only be loaded on your posts. You can easily disable it everywhere and load only on post types, or even custom post types.
- The popular Contact Form 7 plugin loads itself on every page and post. You can easily disable it everywhere with one click and enable only on your contact page.
- If you’ve upgraded to WordPress 5.0 but aren’t using the Gutenberg block editor, perhaps you’re still using the classic editor, there are two additional front-end scripts that are added site-wide which you can disable:
/wp-includes/css/dist/block-library/style.min.css
and/wp-includes/css/dist/block-library/theme.min.css
You can see from this review of perfmatters, it decreased their total load times by 20.2%. On their homepage alone they were able to reduce the number of HTTP requests from 46 down to 30! The page size also shrunk from 506.3 KB to 451.6 KB.
Saved 25% (and 500KB) off total page size using @_perfmatters – this is AFTER extensive optimization using Plugin Organizer. I was *shocked* at how much I was able to save by fine tuning js/css that is downloaded per page.
— Vanessa (@technologypoet) March 14, 2019
How to Track Performance: The Browser’s Dev Tools
A fundamental step on the highway to performance optimization is the load time measurement. We have a number of plugins and online tools we can use to track site performance, like Google Pagespeed Insights and Pingdom. But first and foremost, we can use the browser’s Dev Tools, which provide a lot of meaningful information.
Each browser inspector has a Network panel which displays a list of network requests and related information. Follow these links for detailed documentation:
In a WordPress install with eighteen active plugins, we’ve repeatedly inspected a post page with Firefox Dev Tools. We’ve first measured page speed and listed requested resources before installing any filtering plugin. The following image shows the output of the performance analysis tool available in the Firefox Network monitor.
The Network monitor provides the following results (empty cache):
- size: 255.19 Kb
- load time: 1.24 seconds
- requests: 12
Following, we have installed the Plugin Organizer to prevent WordPress from running the CF7 plugin. The pie chart changes a bit.
Now the page loads faster (empty cache):
- size: 104.21 Kb
- load time: 0.80 seconds
- requests: 8
Next, we’ve deactivated several unnecessary plugins, and the next image shows how much we’ve improved the page performance.
After disabling all unnecessary plugins, the empty browser cache of the Network monitor returns the following data:
- size: 101.98 Kb
- load time: 0.46 seconds
- requests: 8
We can compare the results of our tests. The resource size has been reduced by 60.04%, the load time was reduced from 1.24 seconds to 0.46 seconds, and the number of HTTP requests decreased from 12 to 8. This confirms that plugins can affect page performance, and that we can increase page speed by taking advantage of a plugin filter.
Summary
Whether you build your own scripts or install third-party tools, organizing and filtering plugins is something you should always consider when it comes to performance optimization. Remember, not all plugins are developed with performance in mind. Therefore, it can be wise to take some time and determine what plugin assets (CSS and JS) are loading and where.
But learning how to disable WordPress plugins is just one among many other techniques aimed to increase site speed. Here is a list of some other helpful guides and tutorials related to site performance:
- How to Speed up WordPress (Ultimate Guide)
- A Beginner’s Guide to Website Speed Optimization
- How to Reduce TTFB to Improve WordPress Page Load Times
- How to Diagnose High Admin-Ajax Usage on Your WordPress Site
- How to Clean up Your wp_options Table and Autoloaded Data
- How To Disable WordPress Plugins (No Access to WP-Admin)
It simply is too bizarre for words that a plugin such as Contact Form 7, to this day still loads all files on each and every page load.
I totally agree! But there are a ton of popular plugins that still do this. This ends up in the plugin developer responsible for harming performance on client’s sites who may not know how to fix it :(
I feel like WordPress shoult implement a system to disable/enable single plugins from single pages. And a control in the Plugin area of the dashboard.
That would definitely be nice :)
Great article! :) Could you also provide an example of code for loading certain plugins only in posts (is_single)?
Hi. The script should run before any regular plugin. This means that we need a must-use plugin. Unfortunately, mu-plugin load before any is_ variable has been defined, so we are not allowed to use conditional tags like is_single.
But you could try another way. 1) build a regular plugin that filters plugins, 2) build a must-use plugin that force WordPress to load your filtering plugin before any other active plugin.
You can read more about changin the plugin loading order here: https://wordpress.org/support/topic/how-to-change-plugins-load-order/
Thanks, I’ll check it out.
Hey Kinsta Bloggers, you are awesome!
That is really nice tutorial. Many plugins not needed on homepage and they just increase the size.
Glad you liked it Atul! Definitely agree… the homepage is one of the most important pages for a site as it is the entry way for a lot of traffic. Even just applying some methods above on just the homepage can make a big difference.
Thank you so much for the tutorial, super helpful!
What would be the most efficient way of matching with two or more different URIs? checking the two different strpos statements with ||? or another str method?
Thanks you Jeremy,
I’m in awe of WordPress. This post is a perfect example. Thanks ver much for discussing this. This is a speed improvement game changer in my book.
Hello,
I can’t know if the author Carlo, or indeed anyone from Kinsta itself, reads the comments here, but I felt I should leave this one nonetheless.
This article from Carlo, and so many more articles on Kinsta, are nothing but outstanding! Only since very recently Google is referring many of my searches to Kinsta blog (maybe you are a new company), and pretty much everytime I visit I feel excited to read your articles, SO GOOD they are. My compliments!
Even for non-techies easy to implement.
On a sidenote, some advice: If you stop loading the comments right away, but defer them to be loaded only later, your page speed would increase even further. ;-)
Particularly because you (gladly) use gravatars, like we do too. They cause an “insane” brake on page speed, obviously. Hence we no longer load any comments initially. If someone wants to read or write comments, they will let you know. ;-) Just my advice. Because you are excellent! (although way too pricey for most normal wordpress sites, if I may say that?)
Hey David,
Yes, we manually moderate all comments. Carlo will see them as well :) We’re glad you like the article and are seeing our content!
Yes, lazy loading comments can be very good optimization as posts with a lot of gravatars quickly add up.
As far as our pricing goes :) you might want to check out how we are different from other hosts: https://kinsta.com/why-us/
Thanks again for the comment!
Hi David, thanks a lot for your comment. I’m glad you like our content.
And for what concern pricing, believe me, as Brian wrote in his comment, Kinsta is different ;)
When I run your code it deactivates the plugin sitewide and not just on the requested page. Is it just me or is that what is supposed to happen? Great post by the way.
For the people whom the mu-plugin seems to do nothing:
I think it may be our php configuration (I don’t know), that php processes the slash “/” in the strpos() function as an escape sequence. So in order to make it work you should use double slash “//” in your function, like this: strpos( $request_uri, “//contact//” ). Thanks for the post Carlo this is a very convenient way of speeding up wordpress sites, it has made my project load critically faster.
Nevermind, it made the “if” statement true, but it doesn’t turn false when required… so the double slash may be wrong, in that case, why is when I write it as you did it doesn’t work?
What if you had a URI in your site which included “/contact/” as part of a page slug, or a category?
Hey Nev,
just change the needle passed to strpos accordingly with your URI. Check PHP docs for further information. Anyway, if you need a deeper control over your plugins, and/or you have a bigger website with a lot of posts, pages and plugins, you should consider one of the recommended plugins. Plugin Load Filter and Plugin Organizer allow you to filter plugins, while perfmatters gives you a more granular control over your install, allowing you to handle specific assets.
… and, what of the json requests made by, say, Contact Form 7 ?
great informative article…awesome but most of plugins that i already have used and i have found problem with W3 Total cache that page not refreshed after deleting all cache… please suggest some tips according to the your best experiences……
This is the most comprehensive acticle on this subject.
Unfortunately you forgot about one more useful plugin for this purpose – Plugin Logic. It has the same goal, but a slightly different logic than the other plugins (more basic).
And one more note… post based plugin loading logic doesn’t work properly on sites that use a multi language plugin (or maybe changing the order of loading the plugins could fix that…)
Thanks for this insightful article!
But, good lord! Please use array_diff()[1] instead of array_search() and all the other code in there. This operation is more or less a one-liner with built-in PHP functions.
As a “premium hosting provider” (quoting this website) you should know how the accumulation of these kind of mistakes results in slow and poorly performing web applications.
Thanks,
Daniel
[1] http://php.net/manual/en/function.array-diff.php
Thanks Daniel! We’ve actually done a slight rewrite of the post and we are using array_diff now.
Why not use the WP function is_admin()?
Hi Edward. We are not allowed to use conditional tags, because this plugin must be loaded before the WP_Query is executed. At this point of WP execution, conditional tags always return false. But we can check our conditions anyway by parsing the request URI as we have done here.
A nice premium-plugin to be added to the article is the Gonzales plugin.
We use it on several websites – works well so far :)
Thanks,
Sven
Hey Sven, thanks for adding that plugin to the list. Actually, Gonzales Plugin has a great reputation. Have you compared it with similar free plugins?
Asset Cleanup is a very solid plugin, for setting which plugin assets load on which specific posts and pages on a site.
Thanks for your comment, Luke. Actually, Asset Cleanup may not completely disable plugins, but it does a great job when WP admins need to selectively filter plugin assets. And it’s free! It absolutely worths a try
Is there a modification for the Must-use Plugin to Programmatically Deactivate Plugins based on an array of page slugs?
Is there any way to disable plugins based on a category?
The mu-plugin https://kinsta.com/blog/disable-wordpress-plugins-loading/#mu-plugins will break CF7.
It will Indeed exclude CF7 from all other page but contact page, but you wont be able to submit forms, it will spin for ever.
Regarding contact form would say one should check the contact form site where they have explained how to handle the loading issue.
All articles on your site are worth reading.
For faster websites one should convert it to an AMP website.
Thanks for the entry. I have tested your solution, but what it does is, it turns off the plugin for good during the visit on selected page. That means that when (in your example) a user enters the URI containing a string “/contact/” the code removes the plugin from the array of active plugins. As a result the plugin (CF7 in this case) is turned off on all of the sites of this wordpress instance. Unless you turn it back on it is off and during all the next visits of all users the plugin is off. I do not know if it was the goal. Am I right?
Worked like a charm to deactivate a plugin that was causing an extra 5+ seconds load time on my website (when I only need this plugin active on ONE PAGE)
I’m glad to hear that the issue has been resolved, Karen! Thanks for letting us know. Tom from Kinsta
Thanks for the article, I hadn’t realised disabling plugins like this was possible before.
I think the Documentation link for “Plugin Organizer” goes to the wrong place or has been hijacked. It should go here: https://www.sterupdesign.com/dev/wordpress/plugins/plugin-organizer/documentation/
Thanks for letting us know, Dan!
FYI, you should use wp_parse_url() instead of parse_url() because of inconsistencies in the way URLS are handled across different PHP versions.
In one of your first steps, when getting the list of active plugins, you forgot to add that the custom-coded plugin needs to be activated, before running the post that will print the list of the plugins.
Thanks for the article, but it’s not working for me. The shortcode works, but it doesn’t affect which plugins are enabled/disabled.
Ultimately looking to see if it’s possible to disable plugins only when editing a post or page, or in the Customizer, etc.
Great article! I was searching exactly something like this, because the Website I am building is a membership site with many plugins (which are needed…but not on every page) and the pagespeed was sooo slow with all the plugins active. I followed your instructions and added some more detailed code to disable plugins on specific sites and the pagespeed is waaay better now.
Big thanks!
Can you clarify how to include more URIs so that someone can keep a plugin working on multiple pages. Thanks
Hi Carlo, thanks so much for this. It’s been very helpful. One question, why do you prevent the filter from running in the /wp-admin/ area? Can we also disable plugins on admin pages? E.g. SEO only needs to run on the front end….
Great post, how do these plugins work with caching though, like WP Rocket?
I used a adapted variant of the mu-plugin. It broke contact form 7. I have a contact form on page …/?page_id=6496
The mu-plugin removed contact form 7 from any other page. It also removed contact form 7 from a page called
…/index.php?rest_route=/contact-form-7/v1/contact-forms/3939/feedback/schema
Hence, it was no longer possible to send messages.
To solve the problem, I adapted the mu-plugin to leave a page unchanged if the url includes the substring “rest-route”.