Start with the browser console, not the code
Open devtools (F12 or Cmd+Option+I) and reload the page with the Console tab open. WordPress-related JS failures nearly always throw a specific, readable error: "$ is not defined," "jQuery is not defined," a 404 for a script file, or a Content Security Policy violation message. Each of these points to a different fix, so read the exact wording before changing anything.
"$ is not defined" or "jQuery is not defined"
This means your script is trying to use jQuery's $ shorthand, but jQuery either did not load or loaded after your script ran. WordPress ships its own bundled jQuery and, since version 5.5, loads jQuery in noConflict mode, meaning the global $ alias is not automatically available; only jQuery is guaranteed as the global name unless you explicitly wrap your code.
- In functions.php, enqueue your script with jQuery as a declared dependency: wp_enqueue_script('my-script', get_template_directory_uri() . '/js/main.js', array('jquery'), '1.0.0', true).
- In main.js, wrap your code in (function($){ ... })(jQuery); to safely use $ inside that closure.
- Alternatively, replace every $ with jQuery directly throughout the script if you prefer not to use the wrapper.
Scripts not loading at all: missing wp_footer()
If wp_enqueue_script() correctly loads a script with $in_footer set to true, but nothing happens on the page and the script does not even appear in the page source, check that footer.php contains a wp_footer() call. Plugins and core hook their footer scripts into this action, and if it is missing from the theme's template, none of those scripts print to the page, silently, with no console error at all since the browser never even sees the script tag.
Scripts appear in source but still don't run: load order and defer/async
As of WordPress 6.3, wp_enqueue_script() supports a strategy argument to explicitly mark a script as defer or async: wp_enqueue_script('my-script', $src, $deps, $ver, array('strategy' => 'defer', 'in_footer' => true)). If your script references DOM elements without waiting for DOMContentLoaded, deferring incorrectly or loading in the head without defer can cause it to run before the elements it targets exist, producing errors like "Cannot read properties of null."
Wrap any code that queries the DOM in document.addEventListener('DOMContentLoaded', function() { ... }); as a safe default regardless of load position, since it guarantees the DOM is parsed before your code runs.
Content Security Policy blocking inline or external scripts
If the console shows a message like "Refused to execute inline script because it violates the following Content Security Policy directive," a security plugin or server header is enforcing a CSP that blocks inline <script> tags or scripts from external domains not in its allowlist. This is common after importing a site into a managed WordPress host with strict default security headers.
Move inline scripts into properly enqueued external files where possible, since CSPs are more commonly configured to allow same-origin script-src than inline script-src. If the script must load from a third-party CDN, add that domain explicitly to the CSP configuration in the security plugin or server config.
Mixed content blocking on HTTPS sites
If a script was hardcoded with an http:// URL from the original site and the WordPress install runs on https://, browsers block that request as mixed content, logged in the console as "Mixed Content: The page was loaded over HTTPS, but requested an insecure script." Update any hardcoded http:// references to https:// or, better, to protocol-relative or WordPress-generated URLs via get_template_directory_uri(), which automatically matches the site's current protocol.
Frequently asked questions
- Why does WordPress say jQuery is not defined even though I included jquery.js?
- WordPress loads jQuery in noConflict mode, so the shorthand $ is not globally available by default; wrap your code in (function($){...})(jQuery) or use jQuery directly.
- How do I know if a script failed to enqueue versus failed to run?
- Check the page source (view-source or the Elements tab): if the script tag is not there at all, it is an enqueue or wp_footer() problem; if it is there but errors in the console, it is a runtime issue.
- What does a Content Security Policy error in the console mean?
- It means a security header or plugin is blocking that specific script from executing, usually because it is inline or loaded from a domain not in the site's allowed sources list.
- Can mixed content errors break JavaScript silently with no visible message?
- No, browsers always log a Mixed Content warning or error in the console when this happens, though it is easy to miss if you are not actively checking the console after import.
