Hack a WordPress plugin AJAX action

This post is more than 9 years old.

Customising the AJAX output of WordPress plugins can often be a breeze, when the authors oblige other developers by peppering their code with action and filter hooks. But if they don’t, you can always fall back on hacking the plugin’s AJAX action.

I’ve just completed a job customising an advertising portal built with WordPress. Thanks to WordPress’ many action and filter hooks, I managed to achieve the vast majority of the customisations demanded for the website. Of course there’s always something that conspires to trip you up, and one such thing was adding a custom field to a form that a plugin only presented via AJAX.

Thanks to the magic of WordPress action hook priorities and PHP’s fantastic output buffering capabilities, I discovered that it isn’t really all that hard to change the output of an AJAX action in WordPress. All you need to do is step in front of the AJAX handler, buffer the output, catch the buffer when it’s done, and hit it with the search-and-replace stick.

So, the first step: get in before the AJAX handler gets called. Now, your typical AJAX handler in WordPress is a PHP function that is registered with a call that looks something like this:

add_action('wp_ajax_example', 'example_ajax_handler');

Notice that it’s calling the add_action() function with the default priority, which is 10. If you want to step in front of that AJAX handler and do something before it starts, all you need to do is register a handler with a higher priority (i.e. number smaller than 10). Like this:

add_action('wp_ajax_example', 'before_example_ajax_handler', 5);

Of course, if the handler was registered with a different priority, just make sure you pick a smaller priority number. NB: even if the priority of the handler is 0, you can always go one better — -1 is a smaller number than 0!

Having stepped in front, now we want to start capturing the real AJAX handler’s output. Happily, PHP has a really handy mechanism for that. You can start an output buffer by calling ob_start(), and specify a function to process the buffered output. That function will be called when the PHP script terminates, i.e. even when the real AJAX handler calls exit your function will be called to process the output buffer!

function before_example_ajax_handler() {
    ob_start('after_example_ajax_handler');
}

All that’s left now is to grab that AJAX output and modify it to suit your needs. You can even do fun stuff like modify JSON-encoded data, like this:

function after_example_ajax_handler($buffer) {
    $json = json_decode($buffer);

    $search = '<p class="submit">';
    $inject = '<p>Example: <input name="example" /></p>';
    $json->html = str_replace($search, $inject . $search, $json->html);

    $buffer = json_encode($json);

    return $buffer;
}

And there it is. Job is done to another plugin’s AJAX handler, whether they wanted that to happen or not.