How to Conditionally Load JavaScript Only on WooCommerce Product Pages
When optimizing an e-commerce store for speed and performance, reducing unused JavaScript is one of the quickest ways to improve Core Web Vitals. If you have custom functionality meant solely for single product pages—such as custom gallery sliders, sizing calculators, or custom variation selectors—you want to ensure that code never runs on the shop archive, checkout, or homepage.
The Short Answer: Yes, You Are Doing It Right
Using is_product() inside the wp_enqueue_scripts action hook is the official, canonical WordPress and WooCommerce method to conditionally load assets on single product pages. Your approach is largely correct, but there are a few defensive coding practices and modern WordPress standards you should apply to make it bulletproof.
The Recommended Implementation
Here is an enhanced, production-ready version of your snippet:
function my_custom_enqueue_product_script() {
// 1. Safety check: ensure WooCommerce is active and function exists
if ( ! function_exists( 'is_product' ) ) {
return;
}
// 2. Check if we are viewing a single product page
if ( is_product() ) {
wp_enqueue_script(
'custom-product-script',
get_stylesheet_directory_uri() . '/js/product.js',
array( 'jquery' ),
'1.0.0',
array(
'in_footer' => true,
'strategy' => 'defer', // Available since WordPress 6.3
)
);
}
}
add_action( 'wp_enqueue_scripts', 'my_custom_enqueue_product_script' );Key Enhancements Explained
1. Guard Against Fatal Errors
Wrapping your conditional with function_exists( 'is_product' ) prevents fatal errors if WooCommerce is deactivated, updating, or running in an isolated environment. Without this check, WordPress could throw an uncaught Error: Call to undefined function is_product().
2. Modern Script Loading Strategies
Starting with WordPress 6.3, you can pass an array to the final parameter of wp_enqueue_script(). Specifying 'strategy' => 'defer' ensures the browser does not block DOM construction while downloading your script, directly improving your Largest Contentful Paint (LCP) and First Contentful Paint (FCP) metrics.
Common Conditional Tags in WooCommerce
It helps to know where is_product() stops and other WooCommerce conditionals begin:
is_product(): Returnstrueonly on single product detail pages.is_shop(): Returnstrueon the main shop archive page.is_product_category(): Returnstrueon category archive pages.is_woocommerce(): Returnstrueacross any WooCommerce-generated page (shop, product, category, tag).
Bonus: Target Specific Products Only
If your script is resource-heavy and only required for specific types of items (such as variable products or a single product ID), you can refine the condition even further:
if ( is_product() ) {
global $product;
// Only load for Variable Products
if ( $product && $product->is_type( 'variable' ) ) {
wp_enqueue_script( 'variable-product-helper', ... );
}
}Conclusion
Your original logic was spot-on. By adding a wrapper to confirm WooCommerce is active and leveraging deferred loading, you keep your site secure against PHP errors and ensure top-tier loading speeds for your shoppers.