Use WordPress’s front-end enqueue hook and return early unless WooCommerce reports a single product page. This keeps the script off the shop archive, product categories, cart, checkout, and ordinary posts.
Last updated: October 20, 2026.
<?php
add_action('wp_enqueue_scripts', function (): void {
if (!function_exists('is_product') || !is_product()) {
return;
}
wp_enqueue_script(
'product-gallery',
get_theme_file_uri('/assets/js/product-gallery.js'),
[],
wp_get_theme()->get('Version'),
true
);
});Place this in a child theme or a small site plugin, and change the handle and file path to match the asset. The final true loads the script near the closing body tag.
Use the correct hook and condition
WordPress documents wp_enqueue_scripts as the proper hook for front-end scripts and styles. Calling wp_enqueue_script() through this hook also lets WordPress resolve dependencies, avoid duplicate handles, and print the correct URL.
WooCommerce documents that is_product() is true on a single product page. It differs from is_shop(), which targets the product archive, and is_product_category(), which targets category archives. The function_exists() guard prevents a fatal error when WooCommerce is inactive.
Declare dependencies and a useful version
If the file requires another registered script, list its handle in the dependency array rather than assuming load order. Use a theme or plugin version for stable releases, or filemtime() during active development when automatic cache busting is worth the filesystem check.
Do not place a raw <script> tag in a product template. That bypasses dependency management and can load the same file twice when another extension uses it. After deployment, inspect the product page source and the Network panel, then confirm that the asset is absent from shop and category pages.
If the script needs product data, pass only the values required by the browser and escape them appropriately. Keep prices, permissions, inventory decisions, and other authoritative checks on the server; conditionally loading JavaScript is a performance choice, not an access-control boundary.
Continue with running JavaScript after DOM readiness, tracing script errors, and fixing local asset 404 errors.