I've already added my scripts, but I wanted to know the preferred way.
I just put a <script> tag directly in the header.php of my template.

Is there a preferred method of inserting external or custom js files?
How would I bind a js file to a single page? (I have the home page in mind)


4 Answers 4


Use wp_enqueue_script() in your theme

The basic answer is to use wp_enqueue_script() in an wp_enqueue_scripts hook for front end admin_enqueue_scripts for admin. It might look something like this (which assumes you are calling from your theme's functions.php file; note how I reference the stylesheet directory):

add_action( 'wp_enqueue_scripts', 'mysite_enqueue' );

function mysite_enqueue() {
  $ss_url = get_stylesheet_directory_uri();
  wp_enqueue_script( 'mysite-scripts', "{$ss_url}/js/mysite-scripts.js" );

That's the basics.

Pre-defined and Multiple Dependent Scripts

But let's say you want to include both jQuery and jQuery UI Sortable from the list of default scripts included with WordPress and you want your script to depend on them? Easy, just include the first two scripts using the pre-defined handles defined in WordPress and for your script provide a 3rd parameter to wp_enqueue_script() which is an array of the script handles used by each script, like so:

add_action( 'wp_enqueue_scripts', 'mysite_enqueue' );

function mysite_enqueue() {
  $ss_url = get_stylesheet_directory_uri();
  wp_enqueue_script( 'mysite-scripts', "{$ss_url}/js/mysite-scripts.js", array( 'jquery', 'jquery-ui-sortable' ) );

Scripts in a Plugin

What if you want to do it in a plugin instead? Use the plugins_url() function to specify the URL of your Javascript file:

define( 'MY_PLUGIN_VERSION', '2.0.1' );
add_action( 'wp_enqueue_scripts', 'my_plugin_enqueue' );

function my_plugin_enqueue() {
  wp_enqueue_script( 'my-script', plugins_url('/js/my-script.js',__FILE__), array('jquery','jquery-ui-sortable'), MY_PLUGIN_VERSION );

Versioning your Scripts

Also note that above we gave our plugin a version number and passed it as a 4th parameter to wp_enqueue_script(). Version number is output in source as query argument in URL to script and serves to force browser to re-download possibly cached file if version changed.

Load Scripts only on pages where needed

The 1st rule of Web Performance says to Minimize HTTP Requests so whenever possible you should limit the scripts to load only where needed. For example if you only need your script in the admin limit it to admin pages using the admin_enqueue_scripts hook instead:

define( 'MY_PLUGIN_VERSION', '2.0.1' );
add_action( 'admin_enqueue_scripts', 'my_plugin_admin_enqueue' );

function my_plugin_admin_enqueue() {
  wp_enqueue_script( 'my-script', plugins_url( '/js/my-script.js', __FILE__ ), array( 'jquery', 'jquery-ui-sortable' ), MY_PLUGIN_VERSION );

Load Your Scripts in the Footer

If your scripts is one of those that need to be loaded into the footer there is a 5th parameter of wp_enqueue_script() that tells WordPress to delay it and place it in the footer (assuming your theme did not misbehaved and that it indeed calls the wp_footer hook like all good WordPress themes should):

define( 'MY_PLUGIN_VERSION', '2.0.1' );
add_action( 'admin_enqueue_scripts', 'my_plugin_admin_enqueue' );

function my_plugin_admin_enqueue() {
  wp_enqueue_script( 'my-script', plugins_url( '/js/my-script.js', __FILE__ ), array( 'jquery', 'jquery-ui-sortable' ), MY_PLUGIN_VERSION, true );

Finer Grained Control

If you need finer grained control than that Ozh has a great article entitled How To: Load Javascript With Your WordPress Plugin that details more.

Disabling Scripts to Gain Control

Justin Tadlock has a nice article entitled How to disable scripts and styles in case you want to:

  1. Combine multiple files into single files (mileage may vary with JavaScript here).
  2. Load the files only on the pages we’re using the script or style.
  3. Stop having to use !important in our style.css file to make simple CSS adjustments.

Passing Values from PHP to JS with wp_localize_script()

On his blog Vladimir Prelovac has a great article entitled Best practice for adding JavaScript code to WordPress plugins where he discusses using wp_localize_script() to allow you to set the value of variables in your server-side PHP to be later used in your client-side Javascript.

Really Fine Grained Control with wp_print_scripts()

And finally if you need really fine-grained control you can look into wp_print_scripts() as discussed on Beer Planet in a post entitled How To Include CSS and JavaScript Conditionally And Only When Needed By The Posts.


That's about it for Best Practices of including Javascript files with WordPress. If I missed something (which I probably have) be sure to let me know in the comments so I can add an update for future travelers.

  • 1
    That's an enormous article! Now I have a lot to choose ;)
    – naugtur
    Commented Aug 19, 2010 at 12:19
  • Ok, it worked. Now the second part of the question - how do I check if I'm on the homepage?
    – naugtur
    Commented Aug 19, 2010 at 13:39
  • Look for the answer here: wordpress.stackexchange.com/questions/575/…
    – naugtur
    Commented Aug 23, 2010 at 10:23
  • 3
    Hook into admin_init instead of asking for is_admin(). Remove the version parameter if you use the Google CDN, otherwise the browser cache will hold two versions: one without the query string from other sites and your's.
    – fuxia
    Commented Nov 9, 2010 at 23:02
  • @toscho - Good call, I'll update. Commented Nov 10, 2010 at 1:11

To compliment Mikes wonderful illustration of using enqueues i just wish to point out that scripts included as dependancies do not need to be enqueued...

I'll use the example under the Scripts in a Plugin heading in Mike's answer.


add_action( 'wp_enqueue_scripts', 'my_plugin_enqueue_scripts' );
function my_plugin_enqueue_scripts() {

This can be trimmed down to read..


add_action( 'wp_enqueue_scripts', 'my_plugin_enqueue_scripts' );
function my_plugin_enqueue_scripts() {
    wp_enqueue_script('my-script', plugins_url( '/js/my-script.js', __FILE__ ), array('jquery','jquery-ui-sortable'), MY_PLUGIN_VERSION);

When you set dependancies, WordPress will find and enqueue them ready for your script, so you don't need to make any independent calls for these scripts.

Additionally, some of you may be wondering if setting a multiple dependancies might cause scripts to output in the wrong order, here let me give an example

wp_enqueue_script( 'first-script', 'example/path/example_script_1.js', array('second-script','third-script') );

If script two were dependant on script three(ie. script three should load first), this wouldn't matter, WordPress will determine the enqueue priorities for those scripts and output them in the correct order, in short, it all gets worked out automagically for you by WordPress.

  • I think init is not the proper place to dispatch the enqueue.
    – brasofilo
    Commented Sep 21, 2013 at 23:14
  • Code was originally copied from Mike's answer, then adjusted to illustrate a point. You are correct however, so i've updated the answer to use a better and more correct hook.
    – t31os
    Commented Jan 28, 2014 at 14:42

For small pieces of scripts, which you may not want to include in a separate file, for instance because they are generated dynamically, WordPress 4.5 and further offers wp_add_inline_script. This function basically latches the script to another script.

Let's say, for instance, that you are developing a theme and want your customer to be able to insert his own scripts (like Google Analytics or AddThis) through the options page. You could then use wp_add_inline_script to latch that script to your main js-file (let's say mainjs) like this:

$custom_script = get_option('my-script')
if (!empty($custom_script)) wp_add_inline_script ('mainjs', $custom_script);

My preferred way is to achieve good performance, so rather than using wp_enqueue_script I use HEREDOC with the Fetch API to load everything asynchronously in parallel:

$jquery_script_path = '/wp-includes/js/jquery/jquery.js?ver=1.12.4';
$jquery_dependent_script_paths = [
  get_theme_file_uri( '/assets/js/global.js' ),
  get_theme_file_uri( '/assets/js/jquery.scrollTo.js' ),
  get_theme_file_uri( '/assets/js/skip-link-focus-fix.js' ),
  get_theme_file_uri( '/assets/js/navigation.js' )
$jquery_dependent_script_paths_json = json_encode($jquery_dependent_script_paths);
$inline_scripts = <<<EOD
(function () {
  'use strict';
  if (!window.fetch) return;
   * Fetch Inject v1.6.8
   * Copyright (c) 2017 Josh Habdas
   * @licence ISC
  var fetchInject=function(){"use strict";const e=function(e,t,n,r,o,i,c){i=t.createElement(n),c=t.getElementsByTagName(n)[0],i.type=r.blob.type,i.appendChild(t.createTextNode(r.text)),i.onload=o(r),c?c.parentNode.insertBefore(i,c):t.head.appendChild(i)},t=function(t,n){if(!t||!Array.isArray(t))return Promise.reject(new Error("`inputs` must be an array"));if(n&&!(n instanceof Promise))return Promise.reject(new Error("`promise` must be a promise"));const r=[],o=n?[].concat(n):[],i=[];return t.forEach(e=>o.push(window.fetch(e).then(e=>{return[e.clone().text(),e.blob()]}).then(e=>{return Promise.all(e).then(e=>{r.push({text:e[0],blob:e[1]})})}))),Promise.all(o).then(()=>{return r.forEach(t=>{i.push({then:n=>{"text/css"===t.blob.type?e(window,document,"style",t,n):e(window,document,"script",t,n)}})}),Promise.all(i)})};return t}();
  , fetchInject([

And then insert them into the head, sometimes along with styles like this:

function wc_inline_head() {
  global $inline_scripts;
  echo "{$inline_scripts}";
  global $inline_styles;
  echo "{$inline_styles}";

Resulting in waterfall that looks like this, loading everything at once but controlling the execution order:

enter image description here

Note: This requires use of the Fetch API, which is not available in all browsers.

Not the answer you're looking for? Browse other questions tagged or ask your own question.