I'm using ajax in a plugin for a front-end form. But it only works if I place the add_action("wp_ajax_..." in the plugin loader. I would like to register the call in another file.

I have tried:

function my_plugin_init() {

    if ( ! is_admin() ) {

        require( dirname( __FILE__ ) . '/inc/my-plugin-functions.php' );


//add_action( 'wp_loaded', 'my_plugin_init' );
add_action( 'init', 'my_plugin_init' );

But neither add_action hook seems to work. Ajax fails because it cannot find the ajax function in inc/my-plugin-functions.php.

If I place the ajax function in the plugin loader, everything works as expected:

function my_plugin_etc() {

    $title = sanitize_text_field( $_POST['title'] );

    $meta = update_post_meta(1234, 'test_key', $title);

    if ( $meta != false ) 
        echo json_encode(array('status' => 'success', 'message' => 'Title added as postmeta.') );
        echo json_encode(array('status' => 'error', 'message' => 'There was a problem.' ) );


add_action("wp_ajax_my_plugin_etc", "my_plugin_etc");

I'd rather not put the ajax function in the plugin loader.

What is the proper hook to use to include a file so that the ajax function in that file is registered?

  • Is the function my_plugint_init() a typo? – Nathan Johnson Mar 26 '17 at 20:01
  • Yes, just an exaple. – shanebp Mar 26 '17 at 20:38

Any action that fires before the AJAX call is made will work. Generally speaking, init is good choice.

You mention that the ajax call is made from a "front-end form". If that form is available to end-users who are not logged in, then you need to use:

add_action ('wp_ajax_nopriv_my_plugin_etc', 'my_plugin_etc') ;

See wp_ajax_nopriv_{$_REQUEST[‘action’]}.


Must be my lack of sleep, because I should have seen this earlier.

is_admin() returns false during an invocation of admin-ajax.php. Thus, change your my_plugin_init() to be:

function my_plugin_init() {

    if ( ! is_admin() || wp_doing_ajax ()) {

        require( dirname( __FILE__ ) . '/inc/my-plugin-functions.php' );


add_action( 'init', 'my_plugin_init' );

wp_doing_ajax() was introduced in WP 4.7.

If your plugin needs to work in version of WP before that, then change it to:

function my_plugin_init() {

    if ( ! is_admin() || (defined( 'DOING_AJAX' ) && DOING_AJAX)) {

        require( dirname( __FILE__ ) . '/inc/my-plugin-functions.php' );


add_action( 'init', 'my_plugin_init' );

The advantage of wp_doing_ajax() over the pre-4.7 test (if you can get away with only supporting 4.7+) is that applies the wp_doing_ajax filter to the value of defined( 'DOING_AJAX' ) && DOING_AJAX which can give you finer control over whether you want to consider yourself within an ajax context. However, this extra control is probably not necessary in your case.

Finally, if inc/my-plugin-functions.php only contains code related to AJAX, then you remove ! is_admin() || from the if condition.

  • Only logged in users can access the form, but thanks. So if I'm using init as a hook, any thoughts on why the ajax add_action only works in the plugin loader and not in a required file? – shanebp Mar 26 '17 at 22:47
  • @shanebp see my edited answer – Paul 'Sparrow Hawk' Biron Mar 26 '17 at 23:45

Have you enqueued your script and then added wp_localize_script in the file you wish to use ajax?

// your javascript with ajax calls must be enqueued before wp_localize_script.     
wp_enqueue_script( 'ajax-script', plugins_url( 'file_location.js', __FILE__ ), array('jquery') );
            // Wordpress localize script
            wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'we_value' => 1234 ) );

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.