Determining whether it’s a AJAX call from front-end or from back-end

I am developing an admin-only plugin, which uses some ajax calls in its interface. The website itself also relies on ajax calls on its front-end, too.

I’d like to be able to identify when the WP is loaded due to “simple backend call”, “AJAX backend call” or “AJAX frontend call”. The use case, in its simplest form, could be to load my plugin only on admin pages or ajax calls from them. Besides, it helps not to break the front-end while developing on a live site 🙂

Read More

So far, I found the following:

  • is_admin() returns true on all AJAX calls (which is strange, imho)
  • as all my AJAX calls are done via jQuery, I can determine an AJAX call by HTTP variable HTTP_X_REQUESTED_WITH (see here).

But I still cannot figure out how to distinguish between admin-side AJAX and front-side AJAX. Any ideas?

Related posts

Leave a Reply

3 comments

  1. I understand the problem you are having, I was thinking of the same thing.

    It is not really a problem tho, it’s more a matter of good programming design and have a good separation of front-end and back-end.

    Now the way I have managed to solve this is doing the following:

    I hope you are calling your AJAX action with wp_localize_script. We are going to extend this is a little by implementing it this way:

    wp_localize_script(
        'my-site-script',
        'my_ajax_object',
        array(
            'my_ajax_url' => admin_url( 'admin-ajax.php' ),
            'my_frontend_call' => 'something-here',
            'my_nonce' => wp_create_nonce( 'my_nonce' )
    );
    

    This is ONLY added in the frontpage, I am sure you know how this works. Now as you know this will add a little piece of javascript. Note here the variable my_frontend_call, this is the important one we are going to use.

    More instructions on how to set up a good ajax call here: link

    Now we have this all set up, now we can easily implement the logic in the backend as this:

    <?php
    // Here we check that we are facing the backend.
    // This will also be true if we are facing the 
    // frontend but making an AJAX call. 
    // As you say bad, also IMO
    if( is_admin() )
    {
            //Now here we are going to put the magic
            if(isset($_POST['my_frontend_call'])){
                // Now these actions are loaded only when `my_frontend_call` is set
                // You can add everything here that only get's loaded on a call where
                // `my_frontend_call` is set
                add_action('wp_ajax_handle_frontend_ajax', 'handle_frontend_ajax_callback');
                add_action('wp_ajax_admin_only_ajax', 'admin_only_ajax_callback');
            }
    }
    

    Now you can mix this up a little with different variables from different locations.

    I don’t know why this isn’t a known recommendation. In my opinion it’s ugly when stuff get’s loaded when it is not even needed.

    NOTE I still am new to WordPress, so maybe this is not a good method, I hope some of the professionals here can comment on this.

  2. is_admin() returns true on all AJAX calls (which is strange, imho)

    This is not strange, because Ajax calls follow much more of admin load logic, than front-end. Essentially Ajax load is specialized version of admin load.

    The use case, in its simplest form, could be to load my plugin only on admin pages or ajax calls from them.

    Not sure what you mean here. Script queueing does not depend on Ajax. If you don’t want script on front end – don’t load it there.

    Modern WordPress does not rely on referrers and such for detection where call came from, instead nonces should be used for source and intent verification.

    Since it is your own code than simplest way to distinguish request is to have request carry explicit argument with information is it from front or back.

  3. is_admin() returns always true whether it is from back or front ajax request.
    

    My idea is very simple.
    Just define two different names for the nonce field. (So, other than the developer, no one will know which name for which purpose.) Example:

    add_action('wp_ajax_{my_ajax_hook}', 'my_ajax_function');
    function my_ajax_function() {
    
        if( isset($_REQUEST['f_nonce']) ){
            $fromFront = true;
            $nonceField = 'f_nonce';
        }else{
            //by default from backend or you can alter;
            $fromFront = false;
            $nonceField = 'b_nonce';
        }
    
        if ( ! wp_verify_nonce( $_REQUEST[$nonceField], 'my-nonce-pass' ) ) {
            die( 'Security check' ); 
    
        } else {
            // Do stuff here according to the value of $fromFront;
    
        }
        exit();
    }
    

    The nonce data should be with each ajax call to secure your script according to http://codex.wordpress.org/AJAX_in_Plugins .