One of the challenges you will run into, when developing for WordPress, is finding a way to make your data (which is accessed via PHP) available to your scripts. For example, you might have a popup notification that is displayed when someone clicks a button. The message in this popup, in order to be translatable, should be defined via PHP. The question then, is how do you get it into your jQuery? The answer is with the truly awesome wp_localize_script() function.
The wp_localize_script() was one that eluded me for my first two years of WordPress development. I would see references to it, but I couldn’t ever figure out exactly what it did, or how it worked. It wasn’t until I read Michael Martin’s tutorial titled Load Next WordPress Posts With AJAX. He was the first person I had come across that really explained, and demonstrated how the function worked, and what it did.
The gist of the function is that it allows you to take data from PHP and make it available to your Javascript.
Let’s take the example I mentioned a moment ago, with the popup alert, and see how we can use wp_localize_script().
Since we are loading our scripts correctly, we are using wp_enqueue_script() to load our jQuery:
1 2 3 4 5 6 7 | <?php function pw_load_scripts() { wp_enqueue_script('pw-script', plugin_dir_url( __FILE__ ) . 'js/pw-script.js'); } add_action('wp_enqueue_scripts', 'pw_load_scripts'); |
The use of wp_enqueue_script() or wp_register_script() is required for wp_localize_script() to work.
Our example jQuery file looks like this:
1 2 3 4 5 | jQuery(document).read(function($) { $('#pw_button').on('click', function() { alert('Hey! You have clicked the button!'); }); }); |
These two code snippets assume that we have an HTML button somewhere on our page with an ID of “pw_button”. When that button is clicked, a javascript alert is displayed, like the one below:
The problem that we have here is that our text, “Hey! You have clicked the button!”, is hard coded into our jQuery. Why is this bad? It’s bad because it cannot be translated, but we can get around this by using wp_localize_script().
Usage of the function is actually quite simple. Here is our PHP:
1 2 3 4 5 6 7 8 9 10 11 | <?php function pw_load_scripts() { wp_enqueue_script('pw-script', plugin_dir_url( __FILE__ ) . 'js/pw-script.js'); wp_localize_script('pw-script', 'pw_script_vars', array( 'alert' => __('Hey! You have clicked the button!', 'pippin') ) ); } add_action('wp_enqueue_scripts', 'pw_load_scripts'); |
The first function parameter is the handle of our Javascript file, which is the same as the first parameter in our wp_enqueue_script() function.
The function is going to create an object that is accessible from our Javascript The name of this object is the second parameter, pw_script_vars
The third function parameter, is an array of variables to pass to our script. Each key in the array will be setup as an item in our Javascript object. In this case, I have only passed one array key, so we will have just one option, but you can have as many as you want. Each variable will be accessible like this:
pw_script_vars.VARIABLE_NAME
Our alert text is accessible like this:
pw_script_vars.alert
If this doesn’t make sense, read just a little further and it will.
Previously, in our jQuery, we hard coded the alert message, but now we can just pass our localized variable, like so:
1 2 3 4 5 | jQuery(document).read(function($) { $('#pw_button').on('click', function() { alert( pw_script_vars.alert ); }); }); |
That is really, really cool, if you ask me.
Now what about multiple variables? let’s say, for a moment, that our jQuery contains two alerts, one for each button that is pressed. Because we have two buttons, we want to have two messages, and wp_localize_script() makes this very easy:
1 2 3 4 5 6 7 8 9 10 11 12 | <?php function pw_load_scripts() { wp_enqueue_script('pw-script', plugin_dir_url( __FILE__ ) . 'js/pw-script.js'); wp_localize_script('pw-script', 'pw_script_vars', array( 'alert' => __('Hey! You have clicked the button!', 'pippin'), 'message' => __('You have clicked the other button. Good job!', 'pippin') ) ); } add_action('wp_enqueue_scripts', 'pw_load_scripts'); |
Our updated jQuery now looks like this:
1 2 3 4 5 6 7 8 9 10 11 | jQuery(document).read(function($) { $('#pw_button').on('click', function() { alert( pw_script_vars.alert ); }); $('#pw_button_2').on('click', function() { alert( pw_script_vars.message ); }); }); |
Is this the first time you’ve seen wp_localize_script()? Do you have questions? Just let me know below in the comments.
yeah, it’s a great technique. I’m using it heavily on a plugin I’m working on. I use it with json_encode, and then jQuery parseJSON to use WordPress settings as objects..
didn’t know about the array for passing multiple variables though. that’s a nice tip
Oh, that’s a great idea for passing plugin settings.
I use it most commonly for passing the admin ajax URL to my JS.
Great post Pippin. It’s really good to see this technique explained fully. It’s not something you come across easily, but once you’ve tried it out, you start to wonder how you ever did without it before.
And thank you for the post link! π
I can’t imagine not using this function in just about every plugin I write.
Thanks for stopping by π
wp_localize_script() is a powerful little thing. We usually use it to pass parameters from our options panel to jQuery sliders mostly located on homepages.
What a nice tip!!! Thanks for that, you rock!
Glad you wrote about it π
Thanks!! it’s simple to understand:-)
Whether you have the data hard coded in jQuery script, or hard coded in php, it is the same difference – it is bad. The data should come from the database and be changeable via a post or a custom post type or some means such as that.
You can access data from the database via AJAX – but that is probably over kill for most requirements.
An easier way to do it is with the action ‘wp_head’. In the function tied to this action, get the data from the database, and output a simple script with a function that returns the data, Then in your jQuery you can call the function in the simple script to retrieve the data,
This way there is nothing hard coded in either php or jQuery.
Greg, there are very, very few scenarios where you should attach an action to “wp_head” for making data available to your Javascript.
Saying that you should always store data in the database is not really a good way to put it. There is absolutely nothing wrong with have data stored in a variable (not in the database at all), as long as you provide a way to modify / manipulate that data. Most of the time this will be done through add_filter() and apply_filter().
Pippin – Due to my 30+ years as a programmer and software engineer, working on some extremely complex web applications, I disagree with everything you wrote. So I guess we shall have to agree to disagree. Although I will allow for data to be stored in a variable, but that is not how your post put it.
I have no problem with you disagreeing with me π However, if you disagree with my post here, then you in general disagree with the ways WordPress does things, as the methods described above are used all throughout WordPress, which is also fine to disagree with.
Yes, I do disagree with bugs that are in WordPress, as well as disagreeing with several design decisions that were made in the creation of WordPress, as well as disagreeing with poor coding styles that are sometimes used. WordPress is far, far from perfect.
I would never claim that WP is perfect.
One thing I would point out further about wp_localize_script() is that one of the best uses for it is for performing Ajax functions on the front end. Using the included admin-ajax.php for processing Ajax functions is by far one of the best ways to do it in WordPress, and in order to do that, you have to make the URL to admin-ajax.php available to your JS file, which is what wp_localize_script is for.
Greg, if you’d rather store string translations in the database rather than using gettext, you clearly have not translated much in your 30+ years of programming.
You really shouldn’t be dumping scripts or styles in
wp_head
– the proper way is to register or directly enqueue it using the provided functions. And you could always retrieve the values you pass towp_localize_script
from the database – it’s just that is is not needed in this situation as we are just translating an internal plugin message.Besides, it’s just a tutorial – the focus is on whatwp_localize_script
does and how to use it – not on where the data comes from.much smarter people than me have been recommending this approach, ( people like Otto who is one of the core developers, and Justin Tadlock ). Here’s a post from 2010 about using wp_localize_script
http://ottopress.com/2010/passing-parameters-from-php-to-javascripts-in-plugins/
It is also recommended in the highly acclaimed Professional WordPress development book.
It also has a performance benefit in that the javascript files being static, they can be cached, whereas dynamically generated scripts cannot
Thanks for the support, Paul π
Just implementing my js the correct way in the Sermon Manager plugin. This helped – thanks!
Great little tutorial pippin, thanks for that, I’ve seen a couple tuts on using wp_localize_script() which went straight over my head, yours just made getting this right, and more importantly properly understanding it, so easy.
Cheers.
@pippin What is in the file js/pw-script.js ?
Can if be an included js file that I’d plan on using for other things, like a jquery.ajax call and other jquery ui stuff?
Thanks, Ron
I’m not sure I understand the question, sorry.
Thank you ! You’ve just made my day.
Great Tip. Before I was passing php variables to javascript by doing something like this:
<?php echo ' var product ='.'"'.$product.'"'.''; ?>
Thanks!
echo ‘ var product =’.'”‘.$product.'”‘.”;
script tags not posting… duh… of course not!
If you wrap the code in PRE tags, it will work π
Waoh, this tut is straight to the point, this is gonna help me alot in my theme developement…thanks!!
Mr. Pippin, just tell me how do I thank you!
I looked at the Codex page for this function a while back and I couldn’t figure it out. Recently I had to implement this and came across your tut here and in less than 5 min… BOOM! everything works! π
Or if you want to use a more object oriented JS approach:
( function( $, data ) {
$( ‘#’ + data.buttonID ).on( ‘click’, function() {
alert( data.alertText );
} );
} )( jQuery, pw_script_vars );
Hopefully the
pre
tags don’t get deleted in this comment.I like this approach. Itβs much cleaner, has advantages such as optimization when minifying scripts, and it doesnβt throw a warning in JSHint.
Very nice and well explained. thanks man !
I just spent a lot of time with a problem with wp_localize_script that turned out to be a silly misconception of how the thing works.
Hope it helps someone else -> http://blog.wpdevils.com/problems-wp_localize_script/
Thanks Pippin.
This really helped for a upcoming theme that I am launching soon. All the best.
Can I use wp_localize_script to load script at particular event in my plugin.
Can you elaborate?
I want to use wp_localize_script to draw pie chart of google api only on particular action call in my plugin.
No, I would not use it for that.
Hey Pippin,
I’ve been going a bit crazy and Twitter isn’t the best venue to hit up on my question. Here’s the lowdown:
I was hoping to pass an instance value within a widget class to the JavaScript in order to show/hide *administrative* sections based on true/false checkbox values (e.g. “Show Map”). Front end is easy, admin? Much harder aparently.
When I drop wp_localize_script() into the widget constructor, it works but I can’t retrieve any instance values. Obviously, if I add the function within function form( $instance ), I get yelled at because the same function is defined in the inactive + all active widget admins.
Where and how, within the widget class, would I define this in order to pass instance values like a checkbox status to the JavaScript for processing?
I know it can be done, but for the life of me I can’t figure out how. I’m at my wit’s end here.
Are you trying to pass the values to javascript used in the Widget admin or on the frontend of the site when the widget is displayed?
Admin. Front end was a breeze, admin not so much.
I’ve got two conditional sections in a widget that don’t need all their options shown. If I can’t pass the exact widget instance ID, I can’t target the conditional area with a JavaScript.
For the life of me, I can’t get the scope right. Either the function works but can’t access the instance values or the function errors because it gets called in all instances on the page (inactive + active).
I suppose if I had two of the same widget on the front end, I’d run into the same multi-instance issue. Best learn how to solve it now if possible. π
Why not just inject the values into the admin_head?
Thanks for this mate – very helpful!
spelling mistake, $(document).read
Sorry if it’s an outdatet post, but I don’t find a solution to my problem related to wp_localize_script, maybe someone has a solution. The problem is when I try to put more than one in the same page, for now I implemented it this way:
PHP
$example_arr = array( ‘example_id’ => ‘123’ );
wp_localize_script( ‘example_handle’, ‘example_obj’, $example_arr );
JS
var id = example_obj.example_id;
this works well, for example I can use it in a shortcode like this:
[example id=”123″]
but if I try to put more than one in the same page:
[example id=”123″]
[example id=”456″]
only the last id is rendered, this is because ‘example_obj’ gets the last value of example_id
I tried to add an ID to ‘example_obj’ something like this: ‘example_obj’.$id
but I don’t know how to get it in JS, for example if I created 2 objects:
‘example_obj123’ and ‘example_obj456’, how can I get these in my JS?
thanks in advance π
It’s getting overwritten because the “example_obj” has to be unique. It can only be used once.
Are you calling wp_localize_script() from a short code?
Hi Pippin, thanks for reply,
finally I don’t use wp_localize_script(), I’m using HTML data-attributes and get these in JS, something like this:
HTML
<div class="my_class" data-id="123" …
JS
var my_class = document.querySelectorAll(".my_class");
for( var i = 0; i < my_class.length; i++ ) {
var id = my_class[i].dataset.id;
…
Best
This is not the first time I’ve seen the wp_localize_script function, but certainly is the first time it’s been explained so clearly to me. Thanks so much!
Thanks for your post but in my case, I need to call twice or more times my ShortCode. It’s for display a countdown.
But with wp_enqueue_script and localize, If I make 2 calls, only the last is running π
Example :
/* <![CDATA[ */
var plugin_vars = {"rdm":"722656","aa":"2018","mm":"11","jj":"14","hh":"-1","skin":"{dn}{dl} : {hn}h : {mn}m : {sn}s”};
/* ]]> */
/* <![CDATA[ */
var plugin_vars = {"rdm":"814727","aa":"2014","mm":"9","jj":"14","hh":"24","skin":"{dn}{dl} : {hn}h : {mn}m : {sn}s”};
/* ]]> */
Any ideas?
Why do you need to do it twice?
You seem very fluent with WordPress API! respect!
really great tool. I have ever seen much clear, what i see here. really explained very clearly.. Thank you