4

On the internet there are thousand of articles on how to insert external scripts using wp_enqueue_script().

Anyway i didn't find anything explanatory on how to add inline, <script> enclosed, scripts.

I use to add them in the middle of the page code but i suppose it's not the most elegant way and there should be a better way, so that the script code is automatically moved in the head or the footer.

Any ideas?

Edit: I forgot the ' around <script> so it got cancelled. Now my question should be clearer

0

You can add inline js by using the wp_add_inline_script function.

function prince_scripts() {

    wp_enqueue_script( 'prince-script', get_template_directory_uri(). 'main.js');

    $hide_on_mobile = apply_filters( 'prince_hide_on_mobile', true );

    $data = 'var hideOnMobile = ' . ( $hide_on_mobile ? 'true': 'false' ) . ';';

    wp_add_inline_script( 'prince-script', $data, 'before' );

}

add_action( 'wp_enqueue_scripts', 'prince_scripts');
4

I'm looking at the Twenty Seventeen functions.php source code right now and they left a pattern in there for inlining script (or anything for that matter) into the document with priority, shown here generalized using a named function:

function add_inline_script() {
  echo "<script>/* do awesome things */</script>\n";
}
add_action( 'wp_head', 'add_inline_script', 0 );

You might want to do this, for example, if you are loading an async script like the alternative Google Analytics async tracking snippet, enabling you to kick off non-blocking script requests as soon as the document starts getting parsed (if placed above blocking requests).

Besides async, modern browsers also allow us to manage async dependencies leveraging the Fetch API, affording one the ability to load external dependencies asynchronously in parallel without risking a race condition.

The following image and example illustrate using this technique to reduce page load time by loading scripts without blocking in the Twenty Eleven theme using Fetch Inject:

Loading Twenty Seventeen with Fetch Injection Figure 1: Twenty Seventeen theme scripts plus lazysizes loading asynchronously in parallel.

Piggybacking on a question about string interpolation. Use it while dropping arbitrary blocks of content into the page with echo using NOWDOC or HEREDOC and global assignments and string interpolation with Fetch Inject, as shown here:

/**
 * Load scripts using Fetch Inject instead of wp_enqueue_script
 * for for faster page loads and lower perceived latency.
 *
 * @since WordCamp Ubud 2017
 * @link https://wordpress.stackexchange.com/a/263733/117731
 * @link https://github.com/jhabdas/fetch-inject
 *
 */
function add_inline_script() {
  $twentyseventeen_l10n = array(
    'quote' => twentyseventeen_get_svg( array( 'icon' => 'quote-right' ) ),
    'expand' => __( 'Expand child menu', 'twentyseventeen' ),
    'collapse' => __( 'Collapse child menu', 'twentyseventeen' ),
    'icon' => twentyseventeen_get_svg( array( 'icon' => 'angle-down', 'fallback' => true ) )
  );
  $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' )
  ];
  $lazysizes_path = get_theme_file_uri( '/assets/js/lazysizes.min.js' );
  $screen_reader_text_object_name = 'twentyseventeenScreenReaderText';
  $twentyseventeen_l10n_data_json = json_encode($twentyseventeen_l10n);
  $jquery_dependent_script_paths_json = json_encode($jquery_dependent_script_paths);
  $inline_script = <<<EOD
window.{$screen_reader_text_object_name} = $twentyseventeen_l10n_data_json;
(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(
    $jquery_dependent_script_paths_json
  , fetchInject([
    "{$jquery_script_path}"
  ]));
    fetchInject(["{$lazysizes_path}"])
})();
EOD;
  echo "<script>{$inline_script}</script>";
}
add_action('wp_head', 'add_inline_script', 0);

Reduces perceived latency on a stock Twenty Seventeen theme by ~50 percent. Can be applied to any theme.

How does it work?

  • Replaces all of the scripts enqueued with wp_enqueue_script so they output faster by using Fetch Injection. (Note: See Fetch Inject docs for backwards browser compatibility with older browsers.)
  • Uses HEREDOC to output everything in a script tag in the head.
  • Defines a window Global the theme wants.
  • Loads all of the scripts asynchronously in parallel as shown in the above image, but waits for jQuery to finish loading before executing the dependencies (already downloaded).
  • Does all the work in an IIFE to prevent any free variables from leaking into the window scope.

HEREDOC is ideal for controlling output when you need to maintain copyright notices or other formatting via mixed templates. It also helps increase script debugging speed when you don't have the minified code handy or just want to lob something into the document for testing purposes.

If you want to ensure items are only added one time, see this answer: https://wordpress.stackexchange.com/a/131640/117731

Finally, if you wanted to add to the footer instead of the head, you can replace wp_head in the add_action call with wp_footer.

EDIT: After some more digging I found this post on David Walsh's blog, suggesting at least simple inlining has been available since at least 2012. Have fun!

2

wp_enqueue_script() is the only way that javascript should ever be added to your site. It allows you and other plugins to declare dependencies and even deregister scripts if needed. As mentioned on a different thread today, caching plugins can't gzip or minify your scripts if you don't use the proper WordPress technique.

If you look at the codex page, you'll see that you can control whether the script is in the header or footer.

  • i noticed that the <script> was cancelled by stackoverflow security system. Now my question should be more clear. I'm speaking about inline scripts that needs to know what's inside the page. – Bakaburg May 9 '12 at 0:35
  • Doesn't answer OP or consider real world use cases for things like admin_enqueue_scripts, login_enqueue_scripts or scripts as part of shortcodes which need to wait for the wp_footer. Or enqueue_embed_scripts, which are intended for use by plugins. – Josh Habdas Jun 19 '17 at 13:58
2

Even though mrwweb is correct and that technique should be used, in reality nothing is perfect and there are times when inline scripts and styles are used. You can use wp script is to check for a script and output them in the header or footer using wp_head or wp_footer.

You can refer to scribu's answer in this post, wp enqueue inline script due to dependancies

  • So basically Scribu suggest to just print it in the footer via the wp_footer action? – Bakaburg May 9 '12 at 0:41
  • 2
    also the wp_localize_script is to be considered – Bakaburg May 9 '12 at 0:44
  • If needed, yes. – Wyck May 9 '12 at 0:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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