Wordpress - 400 bad request on admin-ajax.php only using wp_enqueue_scripts action hook

I think the only thing missing here is that you need to move add_action('wp_ajax_nopriv_ajaxlogin','ajax_login'); outside ajax_login_init.

That code registers your Ajax handler, but when you only run it on wp_enqueue_scripts, it's already too late and wp_ajax_nopriv_ hooks are already run.

So, have you tried something like this:

function ajax_login_init(){
  if ( ! is_user_logged_in() || ! is_page( 'page-test' ) ) {

  wp_localize_script('ajax-login-script','ajax_login_object',array('ajaxurl' => admin_url('admin-ajax.php'),'redirecturl' => 'REDIRECT_URL_HERE','loadingmessage' => __('Sending user info, please wait...')));

add_action( 'wp_enqueue_scripts','ajax_login_init' );

add_action( 'wp_ajax_nopriv_ajaxlogin','ajax_login' );

function ajax_login(){
  //nonce-field is created on page


Now it's more clear that you only want to load the JavaScript on that particular page. This means you need to put your is_page() inside ajax_login_init(). I've updated the code accordingly.

Now, why didn't your solution work?

The is_page() check meant that your functions file was only loaded on that specific page. ajax_login_init() gets called and your scripts enqueued. So far so good.

Now your script makes the ajax call. As mentioned in the comments, ajax calls are not aware of the current page you're on. There's a reason the file sits at wp-admin/admin-ajax.php. There's no WP_Query and thus is_page() does not work during an ajax request.

Since that does not work, sw18_page_specific_functions() won't do anything in an ajax context. This means your functions file is not loaded and your ajax handler does not exist.

That's why you need to always include that functions file and move that is_page() check inside ajax_login_init().

So instead of sw18_page_specific_functions() { … } just run include_once dirname(__FILE__).'/includes/my-page-test-functions.php'; directly. Without any add_action( 'parse_query' ) call.