How to Add Conditional Hooks (Run Code Only When Needed)
WordPress makes it easy to add actions and filters everywhere, but that convenience can turn into performance and
maintenance problems: heavy logic runs on every request, admin-only code runs on the front end, and expensive queries
run even when the feature isn’t used.
This article shows a practical, production-safe way to add conditional hooks so your code runs
only when needed—without breaking core behavior or creating hard-to-debug edge cases.
Why Conditional Hooks Matter
- Reduce unnecessary work on every request (especially on high-traffic sites)
- Prevent admin-only logic from affecting front-end requests
- Keep integrations scoped (WooCommerce/ACF/etc.)
- Make code easier to reason about (feature boundaries are clear)
Core Rule: Conditionals Must Run at the Right Time
Many WordPress conditional tags (is_page(), is_singular(), is_category(), etc.)
depend on the main query. They do not work reliably before WordPress has parsed the request.
Practical guidance:
- Use
is_admin()early (safe) - Use plugin/class checks early (safe)
- Use template/query conditionals after
wpor insidetemplate_redirect,wp_enqueue_scripts, etc.
1) Conditional Hooks by Request Context (Admin vs Front End)
Load Admin-Only Hooks
<?php
if ( is_admin() ) {
add_action( 'admin_init', 'wpct_admin_init' );
add_action( 'admin_menu', 'wpct_admin_menu' );
}
function wpct_admin_init(): void {
// Admin-only logic here.
}
function wpct_admin_menu(): void {
// Admin menus here.
}
This prevents admin hooks from ever registering on the front end.
Skip Hooks During AJAX Requests
Some hooks run in admin-ajax.php where you don’t want UI logic.
<?php
add_action( 'admin_init', function () {
if ( wp_doing_ajax() ) {
return;
}
// Normal admin request logic.
} );
2) Conditional Hooks by Plugin Availability
Never register WooCommerce/ACF logic unguarded.
If the plugin is disabled, you risk fatals or wasted hooks.
WooCommerce Conditional Hooks
<?php
if ( class_exists( 'WooCommerce' ) ) {
add_filter( 'woocommerce_product_add_to_cart_text', 'wpct_wc_button_text', 10, 2 );
}
function wpct_wc_button_text( $text, $product ) {
return $text;
}
ACF Conditional Hooks
<?php
if ( defined( 'ACF_VERSION' ) ) {
add_filter( 'acf/format_value/type=text', 'wpct_acf_format_text', 10, 3 );
}
function wpct_acf_format_text( $value, $post_id, $field ) {
return $value;
}
3) Conditional Hooks by Screen (Admin Screen Targeting)
If your code is only needed on specific admin screens (post editor, taxonomy screens),
gate it using current_screen.
<?php
add_action( 'current_screen', function ( $screen ) {
if ( ! $screen ) {
return;
}
// Only on post editor screens.
$targets = array( 'post', 'page' );
if ( ! in_array( (string) $screen->id, $targets, true ) ) {
return;
}
add_action( 'admin_enqueue_scripts', 'wpct_enqueue_editor_assets' );
} );
function wpct_enqueue_editor_assets(): void {
// Load editor-only scripts/styles.
}
This keeps editor assets from loading on unrelated admin screens.
4) Conditional Hooks by Page Template / Route
Front-end conditionals should run after WordPress knows what the request is.
A safe place is wp_enqueue_scripts or template_redirect.
Load Scripts Only on a Specific Template
<?php
add_action( 'wp_enqueue_scripts', function () {
if ( ! is_page_template( 'templates/landing.php' ) ) {
return;
}
wp_enqueue_script( 'landing', get_template_directory_uri() . '/assets/js/landing.js', array(), '1.0.0', true );
}, 20 );
Run Redirect Logic Only on a Specific Page
<?php
add_action( 'template_redirect', function () {
if ( ! is_page( 123 ) ) {
return;
}
if ( ! is_user_logged_in() ) {
wp_safe_redirect( wp_login_url( get_permalink() ) );
exit;
}
} );
5) Conditional Filters: Add Them Only When Needed
Some filters can be expensive (e.g., manipulating SQL, rewriting content).
Instead of always applying them, attach them only when required.
Attach a Filter Only on Search Requests
<?php
add_action( 'pre_get_posts', function ( $query ) {
if ( is_admin() ) {
return;
}
if ( ! $query->is_main_query() ) {
return;
}
if ( ! $query->is_search() ) {
return;
}
add_filter( 'posts_where', 'wpct_search_posts_where', 10, 2 );
} );
function wpct_search_posts_where( $where, $query ) {
// Modify WHERE only for search main query.
return $where;
}
Important: if you add filters dynamically like this, consider removing them after use
when there’s a risk they affect other queries.
Attach and Remove a Filter for One Query Only
<?php
function wpct_run_query_with_temp_filter(): array {
add_filter( 'posts_orderby', 'wpct_custom_orderby', 10, 2 );
$q = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 10,
) );
remove_filter( 'posts_orderby', 'wpct_custom_orderby', 10 );
return $q->posts;
}
function wpct_custom_orderby( $orderby, $query ) {
return $orderby;
}
6) Conditional Hooks by Block Presence (Only When a Block Exists)
If you only need assets when a block exists on the page, detect it and enqueue conditionally.
<?php
add_action( 'wp_enqueue_scripts', function () {
if ( ! is_singular() ) {
return;
}
$post_id = get_queried_object_id();
if ( ! $post_id ) {
return;
}
$content = get_post_field( 'post_content', $post_id );
if ( ! is_string( $content ) || $content === '' ) {
return;
}
if ( has_block( 'core/gallery', $content ) ) {
wp_enqueue_script( 'gallery-enhancements', get_template_directory_uri() . '/assets/js/gallery.js', array(), '1.0.0', true );
}
}, 20 );
This avoids loading feature scripts on pages that don’t use them.
7) Conditional Hooks by Environment (Local/Staging/Production)
Debug hooks should never run in production unless explicitly enabled.
Gate them by environment.
<?php
function wpct_is_staging(): bool {
$host = isset( $_SERVER['HTTP_HOST'] ) ? (string) $_SERVER['HTTP_HOST'] : '';
return $host !== '' && strpos( $host, 'stg.' ) === 0;
}
if ( wpct_is_staging() ) {
add_action( 'wp_footer', function () {
echo '<p>STAGING</p>';
} );
}
Common Mistakes to Avoid
- Using
is_page()before WordPress resolves the main query (too early) - Registering heavy filters globally when only a few routes need them
- Forgetting to remove temporary filters after a specific query
- Not guarding plugin-specific hooks
- Loading assets everywhere “just in case”
Summary
- Use early-safe conditions (
is_admin(), plugin checks) to register only relevant hooks - Use query/template-aware hooks (
wp_enqueue_scripts,template_redirect,current_screen) for conditional tags - Attach expensive filters only on the requests that need them
- Remove temporary filters when scoping to a single query
- Gate debug code by environment
Conditional hooks are one of the simplest ways to keep WordPress codebases fast and maintainable:
register less, run less, and keep feature logic scoped to where it actually matters.
🎨 Want to learn more? Visit our WordPress Customization Hub for tips and advanced techniques.