WP functions in .js

To access server-side functions you’ll need to trigger a server event from JS using AJAX, JSON API, XML/RPC, custom endpoints, or even template_redirect hooks. Just be sure to liberally sprinkle nonces when performing major functions.


The simple and proven technique is the AJAX call. Setup a couple handlers when AJAX receives an action while the user is either logged-in or out (nopriv).

add_action( 'wp_ajax_add_foobar', 'prefix_ajax_add_foobar' );
add_action( 'wp_ajax_nopriv_add_foobar', 'prefix_ajax_add_foobar' );

function prefix_ajax_add_foobar() {
    // Handle request then generate response using WP_Ajax_Response
}

Then trigger the action via JS. The response is whatever you output in the handler but usually wp_send_json_success will work fine.

jQuery.post(
    ajaxurl, 
    {
        'action': 'add_foobar',
        'data':   'foobarid'
    }, 
    function(response){
        alert('The server responded: ' + response);
    }
);

If the JS needs access to server variables at runtime consider using wp_localize_script for more than text translations. It’s really your opportunity to pass inline JS before a script loads. Thus ensuring JS has access to proper URLS, settings and states required for your app. ajaxurl may exist for some people but localizing that onto a variable will assure you that it’s the correct url.

// Register the script
wp_register_script( 'some_handle', 'path/to/myscript.js' );

// Localize the script with new data
$translation_array = array(
    'some_string' => __( 'Some string to translate', 'plugin-domain' ),
    'a_value' => '10'
);
wp_localize_script( 'some_handle', 'object_name', $translation_array );

// Enqueued script with localized data.
wp_enqueue_script( 'some_handle' );

The JSON API is also a good choice and very easy to setup. The major drawback is that it’s only a few weeks old in core (since 4.4) and not fully established (full by 4.5). If you don’t mind living on the edge you can be up and running in a short time with custom endpoints.

function my_awesome_func( $data ) {
    $posts = get_posts( array(
        'author' => $data['id'],
    ) );

    if ( empty( $posts ) ) {
        return null;
    }

    return $posts[0]->post_title;
}

add_action( 'rest_api_init', function () {
    register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array(
        'methods' => 'GET',
        'callback' => 'my_awesome_func',
    ) );
} );

XML RPC was cool enough that everyone is switching to the JSON API if they can help it. It’s a proven solution but who wants XML these days?

add_filter('xmlrpc_methods', function ($methods) {
    $methods['myNamespace.getTotalImageCount'] = 'rpc_myNamespace_getTotalImageCount';
    return $methods;
});

function rpc_myNamespace_getTotalImageCount($args)
{
    return array_sum((array)wp_count_attachments('image'));
}

add_action('parse_request', function () {

    // PULL USER CREDS FROM CURRENT USER
    global $current_user;

    $user = $current_user->user_login;
    $password = $user->data->user_pass;

    include_once(ABSPATH . WPINC . '/class-IXR.php');
    include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php');
    $xmlrpc_url = home_url('xmlrpc.php');
    $client = new WP_HTTP_IXR_CLIENT($xmlrpc_url);

    // CALL OUR CUSTOM METHOD
    $response = $client->query('myNamespace.getTotalImageCount', array(0, $user, $password));

    echo 'Response:<pre>';
    $count = $client->message->params[0];
    print_r("{$count} total images");
    echo '</pre>';

    wp_die('FIN');
});

If you’re curious about how much AJAX you should use then look no further than the future of WordPress.com’s pet project Calypso where they redefine the admin back-end using as much JS as possible.


All these options are great unless someone turns off JS so keep that in mind when you construct your site.


There are also a few tools to help out along the way.

Postman – REST Client extension for Chrome can test GET and POST requests – DEMO.

Monkeyman Rewrite Analyzer WP plugin can double check your custom rewrite endpoints are working correctly.