WP Shifty Documentation
Current Version: 1.1.4
Text Domain: wp-shifty
Getting Started
Activate WP Shifty
Activation doesn’t require a manual license key. Go to Tools → WP Shifty, click Activate your license, log in on musthaveplugins.com, select your subscription, then Connect.
Bought WP Shifty on wp-shifty.com before 2025? On the connect page click Connect with WP Shifty account and log in with your wp-shifty.com credentials. You don’t need a musthaveplugins.com account for this.
To move the license to another site or subscription, click the green active License status badge on the WP Shifty dashboard, confirm Would you like to disconnect license?, then connect again.
Creating and editing scenarios needs an active license, because scenarios are saved through the WP Shifty API.
Scenarios
What are scenarios?
Scenarios are collections of rules that apply when conditions are met. They can disable plugins, manage CSS/JS (disable, overwrite, lazy/async/defer), preload files, and inject HTML.
Apply and Exception conditions
Every condition has an Apply / Exception switch. The scenario card summarizes them as APPLY … IF … EXCEPT …:
- Location conditions (Page, Post Type, Archive, Author, Search, 404 Request, URL, Admin pages, AJAX, Shop Pages, Frontpage, Frontend, Everywhere, Cronjob, CLI): the scenario runs if any of them matches.
- Filter conditions (Query String, User, POST data, HTTP header, Cookie, User agent, Device): all of them must match too. They only narrow the locations, so always add at least one location condition, e.g. Everywhere or Frontend.
- Exceptions: if any condition switched to Exception matches, the scenario does not run for that request.
Example: Everywhere + Exception Shop Pages disables a plugin everywhere except the WooCommerce pages (shop, cart, checkout, etc.).
How to test rules (Live Preview)
The editor shows your site in a preview frame, so you can test changes without affecting visitors. Enter or pick a URL above the preview and choose a device. Under Advanced you can set the User role (default: User not logged in), Useragent, Custom headers, POST data and Cookies for the preview request.
- The Live tab lists the Plugins, CSS and JS loaded on the previewed page. The Editor tab holds the Disable, Inject, Preload and Load behavior rules.
- Turn off Refresh preview automatically to make several changes, then refresh the preview once.
- If the rule panel is greyed out and the preview shows Conditions are not matching with the preview, the previewed URL, device or user role does not meet the scenario’s conditions. Click Click here auto-configure preview, or set a matching URL, device or user role under Advanced.
Managing scenarios
All scenarios are listed on Tools → WP Shifty. Click Add new scenario to open the editor, give the scenario a name in the field at the top, then click Save & Activate or Save as draft. When you edit an existing scenario, the buttons are Save changes and Switch to draft.
- Each scenario card has Edit, Pause / Activate, Delete and Duplicate. A duplicate is created as a draft. Deleting a scenario also deletes its overwritten and injected files.
- Drag and drop the cards to change their order. Scenarios higher in the list are evaluated first.
- With more than one scenario, use the SEARCH box to filter them by condition or rule.
Toolbar shortcuts
When you have permission to manage options, WP Shifty adds an admin toolbar menu with quick actions:
- Edit matched scenarios for the current request.
- Add rule to current page/post type/URL directly from the toolbar.
Rules
Manage plugins (Disable plugins)
Toggle plugins off per scenario in the Plugins list of the editor’s Live tab. When conditions match, the plugin won’t execute at all (not just dequeued). Always verify functionality in Live Preview.
- Only plugins activated on the site itself can be disabled. Network-activated plugins on a multisite are not affected.
- A plugin is removed from the active plugin list only for the matching request. If another plugin saves the active plugin list during such a request (for example, to change the plugin load order), the temporarily disabled plugins are deactivated permanently. If this happens, re-activate them and find the plugin that rewrites the list (search its code for
active_plugins).
Disable resources
Disable any static resources, including inline CSS or JS. Reduces bloat by removing unneeded files. Be careful disabling JS that other scripts depend on; test interactions afterward.
Overwrite resources
Clone CSS/JS to a safe copy and edit it without touching the original. You can beautify minified sources and re-minify via WP Shifty API, and restore the original with one click.
Load behavior (async, defer, lazy)
- Lazy (CSS, JS and inline JS): held back until the first user interaction (
mousemove,click,touchstartorkeydown). If the page is already scrolled when the DOM is ready, the files load immediately. Scrolling alone does not trigger loading. - Async (external scripts): download asynchronously and execute as soon as loaded.
- Defer (external scripts): download asynchronously and execute after document parsing.
Preload resources
Preload critical assets like LCP images and above-the-fold CSS/JS to improve perceived performance. Pick the file or type its URL, set Preload as (style, script, font, image, video, audio, embed or document), and optionally add a Media query such as (min-width:768px) to preload it only on matching screens.
Inject HTML
Inject snippets at precise hooks: head beginning/after styles/end and footer beginning/end. Useful for critical CSS, inline scripts, or vendor tags.
Conditions
Page
Match specific page IDs.
Post type
Match the current post type.
Archive
Match archive contexts.
Author
Match author archives.
Search
Match search results pages.
404
Match 404 (not found) requests.
URL
Match by request path (no host, no query string) with exact, partial, or regex. Regex matching is case-insensitive.
Note: the regex itself is also read as a URL path, so everything from its first ? or # is cut off. Write ^/groups/{0,1}$ instead of ^/groups/?$, and avoid (?:…) and lazy quantifiers such as .*?. To match query arguments, add a Query string condition.
Admin pages
Match specific admin screens including query arguments.
AJAX
Match AJAX actions by exact/partial/regex.
Shop pages
Match WooCommerce core pages.
Frontpage
Match the site front page URL.
Frontend
Apply only on frontend requests.
Everywhere
Apply globally to all contexts.
Query string
Match GET keys/values by exact/partial/regex.
HTTP header
Match HTTP headers (keys normalized to HTTP_*).
Cookie
Match cookies by key/value with exact/partial/regex.
Post data
Match POST payload (supports regex), preserving plus signs.
User agent
Match UA by exact/partial/regex.
User
Target user roles (including Not logged in).
Device
Match desktop, phone, tablet, Android, iOS, or bots.
Cronjob
Apply for cron runs.
CLI
Apply for WP-CLI runs.
FAQ
Can I test WP Shifty before I buy?
Yes. There’s a 14-day money-back guarantee—buy risk-free and refund within 14 days if it’s not a fit.
Is WP Shifty suitable for beginners?
It’s designed to be easy, but it’s a pro tool. Basic WordPress and performance knowledge is recommended.
How can I know which resources or plugins should be disabled?
Click Lighthouse test in the editor’s Live tab, then Run mobile test or Run desktop test. It lists the render-blocking resources and the unused CSS/JS of the previewed page, which are good candidates for Disable or Load behavior rules. The test runs through the WP Shifty API, so it is not available on localhost. Then disable the candidates in Live Preview and verify the page and its interactive features.
Can I buy WP Shifty now?
Yes, purchase is available anytime; activation is a simple connect flow from the dashboard.
How is WP Shifty different from other optimization plugins?
Shifty focuses on conditional loading and selective disabling/rewiring of assets and plugins with a live, scenario-based editor.
Is WP Shifty a cache plugin?
No. It’s not a cache; it controls what loads and when. You can use it alongside caching plugins.
Developers
Actions
wp_shifty_match— Fired when at least one scenario should run.wpshifty_collect_resource(type, src, node) — Collected each matching CSS/JS (file or inline).wpshifty_disable_resource(type, src) — A resource was removed.wpshifty_overwrite_resource(type, original, new) — A resource was replaced.wpshifty_lazyload_resource(type, src) — A resource was marked for lazy loading.wpshifty_plugin_disabled(plugin) — A plugin was disabled by a scenario.
Filters
wp_shifty_dom(html) — Final HTML just before output buffering ends.wp_shifty_current_user_role(role) — The role the User condition checks for a logged-in visitor. WP Shifty reads it from the login cookie before WordPress loads the current user.
Note: WP Shifty evaluates scenarios while plugins are being loaded (its MU loader loads it early). wp_shifty_match, wpshifty_plugin_disabled and wp_shifty_current_user_role therefore run before regular plugins and the theme. Hook them from an MU plugin whose file name sorts before __wps-loader.php, e.g. wp-content/mu-plugins/__a-shifty-hooks.php.
DOM placeholders
WP Shifty uses HTML comment placeholders to inject content or scripts at render time:
<!--[if wpshifty]>WP_SHIFTY_HEAD_BEGINNING<![endif]--><!--[if wpshifty]>WP_SHIFTY_HEAD_AFTER_STYLES<![endif]--><!--[if wpshifty]>WP_SHIFTY_HEAD_END<![endif]--><!--[if wpshifty]>WP_SHIFTY_FOOTER_BEGINING<![endif]--><!--[if wpshifty]>WP_SHIFTY_FOOTER_END<![endif]--><!--[if wpshifty]>WP_SHIFTY_PRELOAD<![endif]-->— replaced by generated<link rel="preload">tags.<!--[if wpshifty]>WP_SHIFTY_LAZY<![endif]-->— replaced with the lazy helper script when needed.
Safeguards
Disable switch (?noshifty)
Append ?noshifty=1 to any URL to bypass WP Shifty entirely for that request. No scenarios are evaluated, no plugins are disabled, and no DOM/post-processing happens. This is ideal for troubleshooting or quick A/B checks.
https://example.com/shop?ref=ad
https://example.com/shop?ref=ad&noshifty=1
Note: The parameter is only used by Shifty; it does not affect WordPress routing.
JSON bypass
When a response is sent with a Content-Type: application/json header (REST API, wp_send_json() admin-ajax responses), WP Shifty returns the payload unchanged and skips all HTML DOM manipulation.
- Detection relies only on that header. A JSON response sent as
text/plainortext/htmlis processed like an HTML page and can be corrupted. Keep such endpoints out of the scenario with an Exception condition (Query string, AJAX or URL). - Plugin rules still apply. If a scenario matches a REST or AJAX request, the plugins it disables are not loaded for that request.
Per-resource skip
Add data-skip-shifty to a <script>, <style>, or <link rel="stylesheet"> tag to exclude it from Shifty’s HTML processing (disable/overwrite/lazy/async/defer).
<script src="/js/critical.js" data-skip-shifty></script>
<link rel="stylesheet" href="/css/critical.css" data-skip-shifty>
Note: a Disable rule also removes matching enqueued files (wp_enqueue_script / wp_enqueue_style) before their tags are printed, so the attribute cannot protect them. Make the rule more specific instead (Exact match or a tighter Regex).
MU Loader and plugin disabling
For plugin deactivation to work reliably, WP Shifty installs an MU loader file wp-content/mu-plugins/__wps-loader.php. If it cannot be created, an exception is raised and disabling plugins will not work. Ensure the MU plugins directory is writable.
Deactivation and uninstall
When you click Deactivate on the Plugins screen, WP Shifty asks Would you like to keep settings after uninstall WP Shifty?
- Yes: scenarios and settings stay in the database after you delete the plugin, ready for a reinstall.
- No: deleting the plugin drops the scenarios table and removes all
wp-shifty*options.
Deactivating alone never deletes anything. Deleting the plugin always removes the MU loader (__wps-loader.php). Overwritten and injected files in wp-content/uploads/wp-shifty/ stay in place.
Resource matching details
- Match modes: exact, partial, regex.
- Versioning: file URLs are normalized to include versions; matching respects
verargs. - Inline resources: Exact match uses a hash of the whole tag (whitespace ignored). If the inline code changes, for example because of nonces, per-user data or a plugin update, the hash changes and the rule stops matching. For dynamic inline CSS/JS, use Partial or Regex match on a distinctive part of the tag, such as its
idattribute. - Preload: disabled resources are skipped; if a source was overwritten, preload uses the overwritten URL.
- Skip processing: add
data-skip-shiftyattribute to a tag to exclude it from Shifty’s HTML processing. It does not stop a Disable rule from dequeuing an enqueued file (see Per-resource skip).
Examples:
// URL exact
/products/sale
// URL partial (matches /products/sale and /products/sale/summer)
/products/sale
// URL regex (matches any year under /archive/)
^/archive/20[0-9]{2}/$
// Inline resource matching
// Exact match: hash of the whole tag (whitespace ignored), changes with the inline code
// Partial / Regex: tested against the tag's full HTML, e.g. id="my-inline-css"
Evaluation & Priority
- Scenario order: active scenarios are loaded by
priority DESC, id ASC. - Preview: when editing, the preview scenario is applied in isolation and won’t be loaded with other actives; an empty preview shows a placeholder and a special CLI view is available via
?wpshifty-cli=1. - Execution flow: when any scenario matches, output buffering is started early and HTML is post-processed to apply rules; scripts/styles are dequeued via
wp_print_* / admin_print_*hooks. - Toolbar context: matched scenario IDs are exposed for quick edit links.
Changelog
1.2.0 – 2026-10-08
- [FIX] Overwriting a JS file removed the script from the page instead of loading the new file
- [FIX] Activating or deactivating any plugin (WP Shifty included) deactivated the plugins that a scenario disables on the Plugins screen
- [FIX] PHP 8 fatal error on the dashboard and in the editor when a scenario has a Search condition
- [FIX] Requests of logged-out visitors to admin-post.php (used by some front-end forms) were redirected to the WP Shifty settings page
- [FIX] Previewing with a user role other than Administrator left the Live panel of the editor empty
- [FIX] Preview: lazy loaded scripts are listed with their address and marked as lazy loaded
- [FIX] Preview test values of regex conditions now match character ranges (eg [a-z]) and longer repetitions (eg {10,20})
- [FIX] The dashboard no longer waits up to 30 seconds (or fails) when the license server can’t be reached: the license status shows “unreachable” and the scenarios stay available
- [FIX] Dashboard summary: partial and regex rules no longer cause a PHP warning, and load behavior (async, defer, lazy) rules are listed instead of “No rule set”
- [FIX] Condition summary now shows OR between conditions and between exceptions, matching how they are evaluated
- [FIX] Drag and drop ordering on the dashboard (jQuery UI Sortable was not loaded)
- [FIX] “Add rule to current post type” in the admin bar now creates the post type condition
- [FIX] Plugin icons in the dashboard summary
- [FIX] Duplicating a scenario without overwrite rules no longer causes PHP warnings, and duplicating a scenario that was deleted in the meantime no longer leaves a broken entry
- [FIX] Multisite uninstall now cleans up each site’s own table and options
- [FIX] Zero-byte resources now show “0 Bytes” instead of “unknown”
- [FIX] More reliable handling of unexpected responses from the API
- [FIX] Minor bugfixes
1.1.4 – 2026-07-02
- [IMPROVE] Updated device detection library for better recognition of newer devices and bots
- [IMPROVE] PHP 8.x compatibility (removed deprecation notices and undefined index/offset warnings)
- [FIX] URL condition matching for URLs containing encoded commas, colons and semicolons
- [FIX] Regex user agent condition was not evaluated correctly
- [FIX] More reliable parsing of custom request headers
- [SECURITY] Minor security improvement
1.1.3 – 2026-03-05
- [FIX] PHP warnings in WP-CLI/cron environment when URL conditions are evaluated
1.1.2 – 2025-04-08
- [FIX] Minor Bugfixes
1.1.1 – 2025-03-18
- [NEW] 404 Request condition
- [NEW] Edit matching rules from topbar
- [FIX] Minor Bugfixes
1.1 – 2024-11-06
- [IMPROVE] Must-Have Plugins license management added
- [FIX] Minor Bugfixes
1.0.14 – 2024-09-30
- [NEW] Rule order can be changed
- [NEW] Rules can be named
- [IMPROVE] Minor improvements
1.0.13 – 2024-04-29
- [FIX] Rule editor bug with Admin pages
1.0.12 – 2024-03-25
- [FIX] PHP Compatibility fix
1.0.11 – 2024-02-29
- [FIX] PHP Compatibility fix
1.0.10 – 2024-02-12
- [FIX] PHP Compatibility fix
1.0.9 – 2023-12-11
- [FIX] Minor bugfixes
- [IMPROVE] Regular Expression Support for Post Data Condition
1.0.8 – 2023-10-25
- [FIX] CPT category detection issues
1.0.7 – 2023-08-24
- [FIX] Minor code improvements
1.0.6 – 2023-01-30
- [FIX] Rank Math compatibility issue
1.0.5 – 2023-01-28
- [FIX] Post type mismatch
- [IMPROVE] Hide preview data for non-admin users
1.0.4 – 2023-01-27
- [FIX] Minor bugfixes
- [FIX] Custom Post Type issues
1.0.3 – 2022-07-30
- [FIX] Minor bugfixes
- [FIX] Not logged in user role issue in editor
1.0.2 – 2022-05-31
- [FIX] Minor bugfixes
- [IMPROVE] RTL compatibility
1.0.1 – 2022-04-19
- [FIX] Minor bugfixes
- [FIX] Firefox lazyload script issue
1.0 – 2022-03-21
- [FIX] Minor bugfixes
- [NEW] Duplicate scenario
0.1.14 – 2022-02-18
- [FIX] Elementor editor issue
0.1.13 – 2022-02-18
- [IMPROVE] Compatibility improvements
- [IMPROVE] Better error messages if network error occured in editor
- [FIX] Remove the unecessary lazyload option for inline styles
- [FIX] Minor fixes
0.1.12 – 2022-02-04
- [IMPROVE] Compatibility improvements
- [NEW] Add comment to source
0.1.11 – 2022-01-18
- [FIX] Minor fixes
- [IMPROVE] Add more devices/screen sizes
0.1.10 – 2022-01-14
- [IMPROVE] Minor improvements
- [NEW] Check preview in new tab
0.1.9 – 2022-01-08
- [FIX] Minor bugfixes
- [NEW] Cronjob condition
- [NEW] CLI condition
- [NEW] Apply wp_shifty_match action when conditions are met
0.1.8 – 2021-12-11
- [FIX] Fix relative URLs for overwrite CSS
- [FIX] Fix missing size badge
0.1.7 – 2021-12-06
- [NEW] Add Lighthouse testing
- [NEW] Add ?noshifty mode
0.1.5 – 2021-12-05
- [FIX] PHP warnings & errors
0.1.4 – 2021-12-04
Initial Release