Ever wanted to have some plugins active on your Live or Production site but automatically deactivated on your Staging or Test server? Oh yes you have! This makes it easy to do that. For example, I use it to make sure my analytics or caching or auto-social posting plugins are only active on the live site and never active on the staging sites. This script assumes that every site is Production unless the site’s domain contains one of the `$stagingKeywords` (which you can customize) and automatically deactivates the plugins you put in the `PLUGINS_TO_DEACTIVATE_ON_STAGING` list. And if you need the reverse functionality, then check out Deactivate_Plugins_On_Production.
Deactivate Specific Plugins on Staging & Non-Production Sites

See the code…
<?php
/**
* Deactivate Specific Plugins on Staging & Non-Production Sites [SnipSnip.pro] - https://snipsnip.pro/s/827
*/
if (!class_exists('Deactivate_Plugins_On_Staging')) {
/**
* Selectively deactivates plugins on staging and similar environments.
*/
class Deactivate_Plugins_On_Staging {
private $stagingKeywords = ['staging', 'dev', 'local', 'test', 'sandbox', 'demo'];
private $forceDeactivations = false; // Set to true to deactivate regardless of environment detection.
// List the slugs of plugins you want to deactivate
const PLUGINS_TO_DEACTIVATE_ON_STAGING = [
'query-monitor',
'create-block-theme',
'ai-engine*'
];
public function __construct() {
// Apply deactivations if forced or if the site is detected as a staging site.
if ($this->forceDeactivations || $this->isStagingSite()) {
add_filter('option_active_plugins', [$this, 'deactivatePluginsOnStaging']);
}
}
/**
* Checks if the current site URL matches any of the specified staging environment keywords.
*
* @return bool True if a matching keyword is found, indicating a staging environment.
*/
private function isStagingSite() {
$currentUrl = strtolower(get_option('siteurl'));
foreach ($this->stagingKeywords as $keyword) {
if (strpos($currentUrl, $keyword) !== false) {
return true;
}
}
return false;
}
/**
* Deactivates the specified plugins by filtering them out from the list of active plugins.
*
* This method is applied in staging environments only.
*
* @param array $activePlugins The list of currently active plugins' file paths.
* @return array The modified list with specific plugins deactivated.
*/
public function deactivatePluginsOnStaging($activePlugins) {
foreach (self::PLUGINS_TO_DEACTIVATE_ON_STAGING as $pluginPattern) {
$pattern = strtolower($pluginPattern);
if (strpos($pattern, '*') !== false) {
$pattern = str_replace('*', '.*', $pattern);
$activePlugins = array_filter($activePlugins, function($plugin) use ($pattern) {
// Extract plugin slug from the path for comparison
$pluginSlug = strtolower(substr($plugin, 0, strpos($plugin, '/')));
// Match against pattern (with wildcard support)
return !preg_match('/^' . $pattern . '$/', $pluginSlug);
});
} else {
// Handle direct plugin slug match (no wildcards)
$pluginPath = $pattern; // Direct matching of the plugin slug to path
$key = array_search("$pluginPath/$pluginPath.php", $activePlugins);
if ($key !== false) {
unset($activePlugins[$key]);
}
}
}
return array_values($activePlugins); // Ensure the array is correctly indexed after modifications
}
}
new Deactivate_Plugins_On_Staging();
}
See the code on github…