{"id":6409,"date":"2022-03-05T07:59:10","date_gmt":"2022-03-05T07:59:10","guid":{"rendered":"https:\/\/wp-tutorials.tech\/?p=6409"},"modified":"2023-08-12T21:09:03","modified_gmt":"2023-08-12T20:09:03","slug":"wordpress-ajax-login-form","status":"publish","type":"post","link":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/","title":{"rendered":"Ajax Login for WordPress Without a Plugin"},"content":{"rendered":"\n<p>Create a popup menu with an Ajax login form so users can sign-in to your WordPress site without leaving the current page. This is a nice little UX improvement, because your customers can log into their account without leaving the current page\/product\/article.<\/p>\n\n\n<figure class=\"menu-icon-demo-outer\"><div class=\"menu-ajax-login-demo-container\"><ul id=\"menu-ajax-login-demo\" class=\"menu-icon-demo\"><li id=\"menu-item-6414\" class=\"email-icon menu-item menu-item-type-post_type menu-item-object-post menu-item-6414\"><a href=\"https:\/\/wp-tutorials.tech\/refine-wordpress\/signup-to-sendinblue-from-the-checkout\/\">Sendinblue Checkout<\/a><\/li>\n<li id=\"menu-item-6415\" class=\"image-icon menu-item menu-item-type-post_type menu-item-object-post menu-item-6415\"><a href=\"https:\/\/wp-tutorials.tech\/refine-wordpress\/turn-any-wordpress-gallery-into-a-slide-show\/\">Slide Show<\/a><\/li>\n<li id=\"menu-item-6456\" class=\"demo-icon-3 menu-item menu-item-type-post_type menu-item-object-post menu-item-6456\"><a href=\"https:\/\/wp-tutorials.tech\/refine-wordpress\/add-nav-menu-icons-without-a-plugin\/\">Menu Icons<\/a><\/li>\n<li class=\"menu-item menu-item-has-children menu-item-login tutorial-higlight-downarrow\"><a href=\"javascript:void(0);\" class=\"menu-link\"><i class=\"fas fa-user\"><\/i>Login<\/a><ul class=\"sub-menu wptajl-container\"><p class=\"form-row\">\n\t<label for=\"wptajl-username\">User Name<\/label>\n\t<input id=\"wptajl-username\" name=\"username\" type=\"text\" placeholder=\"Username or email\" \/>\n<\/p>\n<p class=\"form-row\">\n\t<label for=\"wptajl-password\">Password<\/label>\n\t<input id=\"wptajl-password\" name=\"password\" type=\"password\" placeholder=\"Password\" \/>\n<\/p>\n<p class=\"form-row\">\n\t<button class=\"wptajl-login button\">Login<\/button>\n<\/p>\n<\/ul><\/li><\/ul><\/div><figcaption>An Ajax login form for WordPress<\/figcaption><\/figure>\n\n\n\n<p><span class=\"badge badge-warning\">important<\/span>Make sure you&#8217;re using a <a href=\"https:\/\/wp-tutorials.tech\/getting-started-with-wordpress\/create-a-wordpress-child-theme\/\">custom child theme<\/a>, because we&#8217;re going to create several code files and edit <strong>functions.php<\/strong>.<\/p>\n\n\n\n<p><span class=\"badge badge-warning\">important<\/span>You should never pass login credentials over an unsecured connection, so make sure your site is using <strong>HTTPS<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Project Requirements<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Automatically inject the login menu item into the site&#8217;s primary nav menu, but only if the user isn&#8217;t logged-in.<\/li>\n\n\n\n<li>Defend against brute force login attacks. We&#8217;ll do this by rate-limiting the login attempts per IP address to no more than one attempt every five seconds.<\/li>\n\n\n\n<li>We need a link to the site&#8217;s main login page (the front door).<\/li>\n\n\n\n<li>While a login is being attempted (and we&#8217;re waiting for a response from the server), show some visual feedback so the user knows something is happening.<\/li>\n\n\n\n<li>After a successful login, reload the current page.<\/li>\n\n\n\n<li>The mini HTML login form should be customisable, without having to change the project&#8217;s code.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Break it Down<\/h3>\n\n\n\n<p>This project needs to be part-PHP and part-JavaScript. We need to do the authentication stuff in the back-end, and handle the login form in the browser.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p>The <strong>back-end<\/strong> code has two main jobs:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create HTML that represents the login form as a sub menu.<\/li>\n\n\n\n<li>Respond to incoming Ajax calls from the login form and return the authentication cookie (if successful) or an error message (if failed).<\/li>\n<\/ol>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p>The <strong>front-end<\/strong> (browser) code needs to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Scan the DOM for the login form, connect an event listener for the login button&#8217;s &#8220;click&#8221; event.<\/li>\n\n\n\n<li>Post the login request to the server when the user clicks the login button, or presses <span class=\"keycap key-enter\"><span class=\"key-inner\">Enter<\/span><\/span> in the username\/password fields.<\/li>\n<\/ol>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Scaffold the Code<\/h2>\n\n\n\n<p>In your custom child theme&#8217;s main folder, create a folder called &#8220;wpt-ajax-login&#8221;. In this folder, create two empty files called &#8220;wpt-ajax-login.css&#8221; and &#8220;wpt-ajax-login.js&#8221;.<\/p>\n\n\n\n<p>Next up, create a file called &#8220;<strong>login-form.php<\/strong>&#8221; (in the same &#8220;wpt-ajax-login&#8221; folder) and paste the following into it:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\n\/**\n * Login form for the WP Tutorial AJAX Login tutorial for WordPress.\n * https:\/\/wp-tutorials.tech\/optimise-wordpress\/ajax-login-for-wordpress-without-a-plugin\/\n *\/\n\ndefined('WPINC') || die();\n\n?>&lt;p class=\"form-row\">\n\t&lt;label for=\"wptajl-username\">&lt;?php esc_html_e('User Name', 'wp-tutorials');?>&lt;\/label>\n\t&lt;input id=\"wptajl-username\" name=\"username\" type=\"text\" placeholder=\"Username or email\" \/>\n&lt;\/p>\n&lt;p class=\"form-row\">\n\t&lt;label for=\"wptajl-password\">&lt;?php esc_html_e('Password', 'wp-tutorials');?>&lt;\/label>\n\t&lt;input id=\"wptajl-password\" name=\"password\" type=\"password\" placeholder=\"Password\" \/>\n&lt;\/p>\n&lt;p class=\"form-row\">\n\t&lt;button class=\"wptajl-login button\">&lt;?php esc_html_e('Login', 'wp-tutorials');?>&lt;\/button>\n&lt;\/p><\/pre>\n\n\n\n<p>Find (or create) a nice animated loading spinner SVG and place it in the same folder. If you&#8217;re not sure where to start, try one of <a href=\"https:\/\/samherbert.net\/svg-loaders\/\">Sam Herber&#8217;s cool SVG Loaders<\/a> &#8211; I&#8217;m using &#8220;<strong>tail-spin.svg<\/strong>&#8221; in this tutorial.<\/p>\n\n\n\n<p>Next we need to create the main PHP file. In your custom child theme&#8217;s main folder, create a file called <strong>wpt-ajax-login.php<\/strong> and paste the following into it.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\n\/**\n * WP Tutorials : Ajax Login (WPTAJL)\n *\n * https:\/\/wp-tutorials.tech\/optimise-wordpress\/ajax-login-for-wordpress-without-a-plugin\/\n *\/\n\n\/\/ Prevent direct access to this file.\ndefined('WPINC') || die();\n\n\/\/ Consider changing these.\nconst WPTAJL_MENU_LOCATION = 'primary';\nconst WPTAJL_LOGIN_RETRY_PAUSE = 5; \/\/ secs\nconst WPTAJL_SPINNER_FILE_NAME = 'tail-spin.svg';\n\n\/\/ You probably don't need to change these.\nconst WPTAJL_LOGIN_ACTION = 'wptajl-login';\nconst WPTAJL_LOGIN_FORM_FILE_NAME = 'login-form.php';<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Add Some Style<\/h3>\n\n\n\n<p>Open <strong>wpt-ajax-login\/wpt-ajax-login.css<\/strong> and paste the following into it. This is just a starting point for your own login form.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/**\n * WP Tutorials : Ajax Login (WPTAJL)\n *\n * https:\/\/wp-tutorials.tech\/optimise-wordpress\/ajax-login-for-wordpress-without-a-plugin\/\n *\/\n.sub-menu.wptajl-container {\n\tpadding: 1em;\n\tbox-shadow: 0 0 3em #00000022;\n\tmin-width: 15em;\n\tposition: absolute;\n}\n\n.wptajl-container input,\n.wptajl-container button {\n\tdisplay: block;\n\twidth: 100%;\n\tposition: relative;\n\ttransition: 0.3s;\n}\n\n.wptajl-container button {\n\tfont-weight: bold;\n\tpadding: 0.75em 0;\n}\n\n.wptajl-container label {\n\tfont-size: 11pt;\n}\n\n.wptajl-container .form-row:not( :last-of-type) {\n\tmargin-bottom: 1em;\n}\n\n.wptajl-container .form-row:last-of-type {\n\tmargin-bottom: 0;\n}\n\n.wptajl-container button:disabled,\n.wptajl-container input:disabled {\n\topacity: 0.75;\n}\n\n.wptajl-container .login-spinner {\n\tdisplay: none;\n\twidth: 1.5em;\n\tposition: absolute;\n\tright: 0.5em;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n}\n\n.wptajl-container.working .login-spinner {\n\tdisplay: block;\n}<\/pre>\n\n\n\n<p><span class=\"badge badge-info\">tip<\/span>This has been tested with the <a href=\"https:\/\/en-gb.wordpress.org\/themes\/astra\/\">Astra theme<\/a> and it works well. If you&#8217;re using something else, you might need to tweak\/adjust\/hack the CSS a bit.<\/p>\n\n\n\n<p>The &#8220;<strong>wpt-ajax-login<\/strong>&#8221; folder in your custom child theme should look like this:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wpt-ajax-login-tutorial-file-list.png\"><img loading=\"lazy\" decoding=\"async\" width=\"671\" height=\"379\" src=\"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wpt-ajax-login-tutorial-file-list.png\" alt=\"Ajax Login Tutorial Files\" class=\"wp-image-6431\" srcset=\"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wpt-ajax-login-tutorial-file-list.png 671w, https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wpt-ajax-login-tutorial-file-list-300x169.png 300w\" sizes=\"auto, (max-width: 671px) 100vw, 671px\" \/><\/a><figcaption class=\"wp-element-caption\">Headwall WP Tutorials Ajax Login files<\/figcaption><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\">Reference the Code from functions.php<\/h3>\n\n\n\n<p>Finally, open your child theme&#8217;s <strong>functions.php<\/strong> and add the following lines to import our project:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ Ajax login\nrequire_once dirname(__FILE__) . '\/wpt-ajax-login.php';<\/pre>\n\n\n\n<p>Save everything and reload a page on your site to make sure we&#8217;ve not broken anything. If it all still works, we can start filling in the blanks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Back-end PHP Code<\/h2>\n\n\n\n<p>We&#8217;re going to use the following WordPress hooks to modify our primary nav menu and respond to the Ajax login requests:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/hooks\/init\/\">init<\/a> (action)<br>This is called by WordPress near the beginning of each page-load. This is where we connect our main login action listener.<\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/hooks\/wp_enqueue_scripts\/\">wp_enqueue_scripts<\/a> (action)<br>Triggered when WordPress wants to know which scripts and stylesheets to write into the page&#8217;s HTML <code data-enlighter-language=\"html\" class=\"EnlighterJSRAW\">head<\/code> element.<\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/hooks\/wp_nav_menu_items\/\">wp_nav_menu_items<\/a> (filter)<br>If WordPress is trying to render the primary nav menu, and the user is not logged-in, we want to append some HTML to include our menu item and mini login form.<\/li>\n<\/ul>\n\n\n\n<p>We&#8217;re also going to create some support\/utility functions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">wptajl_client_ip()<\/code> : Return the browser&#8217;s current IP address.<\/li>\n\n\n\n<li><code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">wptajl_is_login_menu_required()<\/code> : Return <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">true<\/code> or <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">false<\/code>, depending on whether the Ajax login form is required on this page-load.<\/li>\n\n\n\n<li><code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">wptajl_front_door_url()<\/code> : A fall-back login page URL. Usually this is <strong>wp-login.php<\/strong>, but we can use WooCommerce&#8217;s login page if it&#8217;s available.<\/li>\n<\/ul>\n\n\n\n<p>The core function will be called <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">wptajl_try_to_login()<\/code>. All it has to do is check a couple of <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">$_POST[]<\/code> items (user name &amp; password) and return success\/fail back to the browser.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Brute Force Login Protection<\/h3>\n\n\n\n<p>WordPress login forms are frequently attacked by armies of miscreant hack-bots, so we need to make sure we don&#8217;t add any security holes. We&#8217;re going to use <a href=\"https:\/\/developer.wordpress.org\/apis\/transients\/\">WordPress transients<\/a> to do this. A &#8220;transient&#8221; is just an object that exists for a finite amount of time &#8211; it can be seconds, years, or anything in between. Here&#8217;s the logic we&#8217;re going to implement:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If the incoming Ajax action contains a user name and a password, then&#8230;\n<ul class=\"wp-block-list\">\n<li>Create a transient &#8220;key&#8221; based on the client&#8217;s IP address. This is just a string, something like &#8216;login_attempt_123.123.123.123&#8243;<\/li>\n\n\n\n<li>If a transient with this key already exists, then&#8230;\n<ul class=\"wp-block-list\">\n<li>This client has tried to log in (and failed) within the last 5 seconds, so don&#8217;t try to authenticate now.<\/li>\n\n\n\n<li>Set response.errorMessage to &#8220;Slow down a bit&#8221;<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>else&#8230;\n<ul class=\"wp-block-list\">\n<li>Try to authenticate the user name and password<\/li>\n\n\n\n<li>If the user name and password are NOT valid, then&#8230;\n<ul class=\"wp-block-list\">\n<li>Create a new transient with the client&#8217;s key and set it to expire in five seconds time<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>else&#8230;\n<ul class=\"wp-block-list\">\n<li>The user has logged-in successfully<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>So&#8230; if a hack-bot tries to fire 100 login attempts at the server over a five second timespan, we&#8217;ll try to authenticate the first attempt, and we&#8217;ll return errors for the next 99 attempts.<\/p>\n\n\n\n<p><span class=\"badge badge-info\">tip<\/span>If your hosting provider has <a href=\"https:\/\/www.fail2ban.org\/wiki\/index.php\/Main_Page\">Fail2Ban<\/a>, you should look at installing a <a href=\"https:\/\/en-gb.wordpress.org\/plugins\/wp-fail2ban\/\">WordPress Fail2Ban plugin<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Actual PHP Code<\/h3>\n\n\n\n<p>In your custom child theme&#8217;s main folder, open <strong>wpt-ajax-login.php<\/strong> and paste the following into it (replacing what was already in there):<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\n\/**\n * WP Tutorials : Ajax Login (WPTAJL)\n *\n * https:\/\/wp-tutorials.tech\/optimise-wordpress\/ajax-login-for-wordpress-without-a-plugin\/\n *\/\n\n\/\/ Prevent direct access to this file.\ndefined('WPINC') || die();\n\n\/\/ Consider changing these.\nconst WPTAJL_MENU_LOCATION = 'primary';\nconst WPTAJL_LOGIN_RETRY_PAUSE = 5; \/\/ secs\nconst WPTAJL_SPINNER_FILE_NAME = 'tail-spin.svg';\n\n\/\/ You probably don't need to change these.\nconst WPTAJL_LOGIN_ACTION = 'wptajl-login';\nconst WPTAJL_LOGIN_FORM_FILE_NAME = 'login-form.php';\n\n\/**\n * Listen for incoming login requests from the Ajax form.\n *\/\nfunction wptajl_init() {\n\tadd_action('wp_ajax_nopriv_' . WPTAJL_LOGIN_ACTION, 'wptajl_try_to_login');\n}\nadd_action('init', 'wptajl_init');\n\n\/**\n * Get the IP address of the current browser.\n * *\/\nfunction wptajl_client_ip() {\n\tglobal $wptajl_client_ip;\n\n\tif (!is_null($wptajl_client_ip)) {\n\t\t\/\/ We've already discovered the browser's IP address.\n\t} elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) {\n\t\t$wptajl_client_ip = filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP);\n\t} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {\n\t\t$wptajl_client_ip = filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP);\n\t} else {\n\t\t$wptajl_client_ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP);\n\t}\n\n\treturn $wptajl_client_ip;\n}\n\n\/**\n * A convenience function that lets us disable the login menu item under\n * certain conditions.\n *\/\nfunction wptajl_is_login_menu_required() {\n\t$is_required = !is_user_logged_in();\n\n\t\/\/ You can put extra conditions in here.\n\t\/\/ if ($some_test == true) {\n\t\/\/    $is_required = false;\n\t\/\/ }\n\n\treturn $is_required;\n}\n\nfunction wptajl_front_door_url() {\n\t\/\/ Get the URL for the site's main login page, with the redirect\n\t\/\/ (after login) set to the page we're currently viewing.\n\t\/\/ This is useful for mobile devices where the Ajax login form might\n\t\/\/ not be available.\n\t$login_page_url = wp_login_url(home_url($_SERVER['REQUEST_URI']));\n\n\t\/\/ If WooCommerce is installed, use the my-account page as the frontdoor,\n\t\/\/ so we get a nice front-end login form.\n\tif (function_exists('wc_get_account_endpoint_url')) {\n\t\t$frontdoor_url = wc_get_account_endpoint_url('dashboard');\n\t}\n\n\treturn $frontdoor_url;\n}\n\n\/**\n * We add our assets to every page of the site, because the primay\n * nav menu is probably on every page.\n *\/\nfunction wptajl_enqueue_scripts() {\n\tif (wptajl_is_login_menu_required()) {\n\t\t$base_uri = get_stylesheet_directory_uri();\n\t\t$version = wp_get_theme()->get('Version');\n\n\t\t\/\/ Our login form stylesheet.\n\t\twp_enqueue_style(\n\t\t\t'wptajl',\n\t\t\t$base_uri . '\/wpt-ajax-login\/wpt-ajax-login.css',\n\t\t\tnull, \/\/ We don't have any style dependencies.\n\t\t\t$version\n\t\t);\n\n\t\t\/\/ Enqueue our main JavaScript file.\n\t\twp_enqueue_script(\n\t\t\t'wptajl',\n\t\t\t$base_uri . '\/wpt-ajax-login\/wpt-ajax-login.js',\n\t\t\tarray('jquery'), \/\/ Our code depends on jquery.\n\t\t\t$version\n\t\t);\n\n\t\t\/\/ Pass some settings and variables to the browser in a\n\t\t\/\/ JavaScript global variable called wptajlData.\n\t\twp_localize_script(\n\t\t\t'wptajl',\n\t\t\t'wptajlData',\n\t\t\tarray(\n\t\t\t\t'ajaxUrl' => admin_url('admin-ajax.php'),\n\t\t\t\t'action' => WPTAJL_LOGIN_ACTION,\n\t\t\t\t'frontDoor' => wptajl_front_door_url(),\n\t\t\t\t'spinnerUrl' => $base_uri . '\/wpt-ajax-login\/' . WPTAJL_SPINNER_FILE_NAME,\n\t\t\t)\n\t\t);\n\t}\n}\nadd_action('wp_enqueue_scripts', 'wptajl_enqueue_scripts');\n\n\/**\n * Render the login menu item and form. $items is a string that we're going\n * to append our HTML to.\n *\/\nfunction wptajl_wp_nav_menu_items($items, $args) {\n\t\/\/ The file name of the login form (PHP) we're going to \"include\".\n\t$file_name = dirname(__FILE__) . '\/wpt-ajax-login\/' . WPTAJL_LOGIN_FORM_FILE_NAME;\n\n\tif (!wptajl_is_login_menu_required()) {\n\t\t\/\/ We're already logged in so we don't need a login form.\n\t} elseif ($args->theme_location != WPTAJL_MENU_LOCATION) {\n\t\t\/\/ These aren't the menu item's you're looking for.\n\t} elseif (!is_file($file_name)) {\n\t\t$items .= sprintf(\n\t\t\t'&lt;li class=\"menu-item\">&lt;a class=\"menu-link\">&lt;strong>%s&lt;\/strong>&lt;\/a>&lt;\/li>',\n\t\t\tWPTAJL_LOGIN_FORM_FILE_NAME\n\t\t);\n\t} else {\n\t\t\/\/ Start rendering the HTML for the menu item.\n\t\t$outer_classes = array(\n\t\t\t'menu-item',\n\t\t\t'menu-item-has-children',\n\t\t\t'menu-item-login',\n\t\t);\n\t\t$items .= sprintf('&lt;li class=\"%s\">', esc_attr(implode(' ', $outer_classes)));\n\n\t\t\/\/ The login menu item. You can change the \"Login\" label here.\n\t\t$items .= sprintf(\n\t\t\t'&lt;a href=\"%s\">%s&lt;\/a>',\n\t\t\tesc_url(wptajl_front_door_url()),\n\t\t\tesc_html__('Login', 'wp-tutorials')\n\t\t);\n\n\t\t\/\/ Start rendering a sub menu to hold the login form.\n\t\t$sub_menu_classes = array(\n\t\t\t'sub-menu',\n\t\t\t'wptajl-container',\n\t\t);\n\t\t$items .= sprintf('&lt;ul class=\"%s\">', esc_attr(implode(' ', $sub_menu_classes)));\n\n\t\t\/\/ Include the login form PHP\/HTML file.\n\t\tob_start();\n\t\tinclude $file_name;\n\t\t$items .= ob_get_clean();\n\n\t\t$items .= '&lt;\/ul>'; \/\/ .sub-menu\n\n\t\t$items .= '&lt;\/li>'; \/\/ .menu-item\n\t}\n\n\treturn $items;\n}\nadd_filter('wp_nav_menu_items', 'wptajl_wp_nav_menu_items', 10, 2);\n\n\/**\n * The main function will try to log in to the site by sanitising and\n * authenticating $_POST['username'] and $_POST['password']\n *\/\nfunction wptajl_try_to_login() {\n\t\/\/ If we can't determine the client's IP address then something is very\n\t\/\/ wrong - possibly a hack attempt. Don't do anything.\n\tif (empty($client_ip_address = wptajl_client_ip())) {\n\t\tdie();\n\t}\n\n\t$client_key = 'login_attempt_' . $client_ip_address;\n\t$status_code = 200;\n\t$response = array(\n\t\t'isLoggedIn' => false,\n\t\t'errorMessage' => '',\n\t);\n\n\tif ((get_transient($client_key) !== false)) {\n\t\t$response['errorMessage'] = 'Slow down a bit';\n\t} elseif (empty($username = sanitize_text_field($_POST['username']))) {\n\t\t$response['errorMessage'] = 'No user name';\n\t} elseif (empty($password = sanitize_text_field($_POST['password']))) {\n\t\t$response['errorMessage'] = 'No password';\n\t} elseif (!is_a($user = wp_authenticate($username, $password), 'WP_User')) {\n\t\t$response['errorMessage'] = 'Invalid login';\n\t} else {\n\t\t\/\/ Logged in OK.\n\t\t$response['isLoggedIn'] = true;\n\n\t\t\/\/ We need to do this so wp_send_json() can return the cookie in\n\t\t\/\/ our response.\n\t\twp_set_auth_cookie(\n\t\t\t$user->ID,\n\t\t\tfalse\/\/ &lt;&lt; This is the \"remember me\" option.\n\t\t);\n\n\t\tdo_action('wp_login', $username, $user);\n\t}\n\n\tif (!empty($response['errorMessage'])) {\n\t\terror_log($response['errorMessage']);\n\t\tset_transient($client_key, '1', WPTAJL_LOGIN_RETRY_PAUSE);\n\t}\n\n\twp_send_json(\n\t\t$response,\n\t\t$status_code\n\t);\n}<\/pre>\n\n\n\n<p>It&#8217;s a bit of a lump, but it&#8217;s properly commented and it should read well. Notice how the project&#8217;s settings are declared at the top, as constants.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">WPTAJL_MENU_LOCATION<\/code> : Which menu location to inject. Default to &#8220;primary&#8221;.<\/li>\n\n\n\n<li><code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">WPTAJL_LOGIN_RETRY_PAUSE<\/code> : The minimum number of seconds between login attempts for a given IP address.<\/li>\n\n\n\n<li><code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">WPTAJL_SPINNER_FILE_NAME<\/code> : The name of the loader\/spinner file in the wpt-ajax-login folder.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">The JavaScript \/ Ajax Bit<\/h2>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:66.66%\">\n<p>Because we&#8217;re not using a standard HTML <code data-enlighter-language=\"html\" class=\"EnlighterJSRAW\">form<\/code>, we need to add some event-listeners to the text input controls and listen for <span class=\"keycap key-enter\"><span class=\"key-inner\">Enter<\/span><\/span> being pressed. When we detect it, we can trigger a login attempt by calling <code data-enlighter-language=\"js\" class=\"EnlighterJSRAW\">tryToLogin()<\/code>.<\/p>\n\n\n\n<p>We also need to hide and show a working\/loading &#8220;spinner&#8221;, which we&#8217;ll attach to the login button as an <code data-enlighter-language=\"html\" class=\"EnlighterJSRAW\">IMG<\/code>.<\/p>\n\n\n\n<p>To make it all work, we&#8217;ll use <a href=\"https:\/\/api.jquery.com\/jquery.post\/\">jQuery.post()<\/a> to send the login request to the server. While we&#8217;re waiting for a response, we&#8217;ll add the &#8220;working&#8221; CSS class to the sub-menu and disable the input\/button elements.<\/p>\n\n\n\n<p>Once the server has responded: If the attempt was successful, we\u2019ll reload the current page. If not, we\u2019ll put things back to how they were (remove &#8220;working&#8221; and re-enable the elements).<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:33.33%\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/example-ajax-login-form.png\"><img loading=\"lazy\" decoding=\"async\" width=\"320\" height=\"358\" src=\"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/example-ajax-login-form.png\" alt=\"Example WordPress Ajax Login Form\" class=\"wp-image-6438\" srcset=\"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/example-ajax-login-form.png 320w, https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/example-ajax-login-form-268x300.png 268w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><figcaption class=\"wp-element-caption\">Example Ajax login form<\/figcaption><\/figure>\n<\/div><\/div>\n<\/div>\n\n\n\n<p>Open <strong>wpt-ajax-login\/wpt-ajax-login.js<\/strong> and paste the following JavaScript code into it.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/**\n * WP Tutorials : Ajax Login (WPTAJL)\n *\n * https:\/\/wp-tutorials.tech\/optimise-wordpress\/ajax-login-for-wordpress-without-a-plugin\/\n *\/\n\n(function($) {\n\t'use strict';\n\t$(window).on('load', function() {\n\t\tconsole.log('WPT Ajax Login : load');\n\n\t\t\/**\n\t\t * If wptajlData hasn't been set using wp_localize_script() then don't do anything.\n\t\t *\/\n\t\tif (typeof wptajlData != 'undefined') {\n\t\t\t\/**\n\t\t\t * Create and attach an IMG to each login form button (there should\n\t\t\t * only be one).\n\t\t\t *\/\n\t\t\t$('.wptajl-login.button').each(function(index, el) {\n\t\t\t\tvar spinner = $(`&lt;img src=\"${wptajlData.spinnerUrl}\" class=\"login-spinner\" \/>`);\n\t\t\t\t$(this).append(spinner);\n\t\t\t});\n\n\t\t\t\/**\n\t\t\t * Listen for the \"click\" event on each login button.\n\t\t\t *\/\n\t\t\t$('.wptajl-login.button').click(function(event) {\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tvar container = $(this).closest('.wptajl-container');\n\t\t\t\ttryToLogin(container);\n\t\t\t});\n\n\t\t\t\/**\n\t\t\t * For every input text|password element in our login form, listen\n\t\t\t * for the Enter key (ASCII code 13).\n\t\t\t *\/\n\t\t\t$('.wptajl-container input[type=\"text\"], .wptajl-container input[type=\"password\"]').keypress(function(event) {\n\t\t\t\tif (event.which == 13) {\n\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\tvar container = $(this).closest('.wptajl-container');\n\t\t\t\t\ttryToLogin(container);\n\t\t\t\t};\n\t\t\t});\n\n\t\t\tfunction tryToLogin(container) {\n\t\t\t\t\/\/ This is our request object. Each of these keys (action,\n\t\t\t\t\/\/ username &amp; password) can be picked up in the PHP $_POST object.\n\t\t\t\tvar request = {\n\t\t\t\t\t'action': wptajlData.action,\n\t\t\t\t\t'username': $(container).find('#wptajl-username').val(),\n\t\t\t\t\t'password': $(container).find('#wptajl-password').val()\n\t\t\t\t};\n\n\t\t\t\tif (!request.username || !request.password) {\n\t\t\t\t\t\/\/ Missing user name or password.\n\t\t\t\t\t\/\/ console.log('Missing user name and\/or password.');\n\t\t\t\t} else if ($(container).hasClass('working')) {\n\t\t\t\t\t\/\/ We've been asked to login, even though the login box\n\t\t\t\t\t\/\/ already has the \"working\" class attached to it.\n\t\t\t\t\t\/\/ This should never happen.\n\t\t\t\t\t\/\/ console.log('Already trying to log in. Please wait.');\n\t\t\t\t} else {\n\t\t\t\t\t\/\/ console.log('Attempting to log in now.');\n\n\t\t\t\t\t$(container).addClass('working');\n\t\t\t\t\t$(container).find('input, button').prop('disabled', true);\n\n\t\t\t\t\t\/\/ Send our login request object to \/wp-admin\/admin-ajax.php\n\t\t\t\t\t$.post(wptajlData.ajaxUrl, request)\n\t\t\t\t\t\t.fail(function() {\n\t\t\t\t\t\t\t\/\/ There was an internal server error of some sort,\n\t\t\t\t\t\t\t\/\/ so direct the user to the main WP Login page.\n\t\t\t\t\t\t\tif (wptajlData.frontDoor) {\n\t\t\t\t\t\t\t\twindow.location.href = wptajlData.frontDoor;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.done(function(response) {\n\t\t\t\t\t\t\tif (response.errorMessage) {\n\t\t\t\t\t\t\t\talert(response.errorMessage);\n\t\t\t\t\t\t\t} else if (!response.isLoggedIn) {\n\t\t\t\t\t\t\t\t\/\/ Unknown error logging in.\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\/\/ We've successfully logged-in.\n\t\t\t\t\t\t\t\t\/\/ Reload the current page.\n\t\t\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.always(function(response) {\n\t\t\t\t\t\t\tif (!response.isLoggedIn) {\n\t\t\t\t\t\t\t\t$(container).find('input, button').prop('disabled', false);\n\t\t\t\t\t\t\t\t$(container).removeClass('working');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);<\/pre>\n\n\n\n<p>Notice the sections near the top that initialise the event listeners. Then there&#8217;s <code data-enlighter-language=\"js\" class=\"EnlighterJSRAW\">tryToLogin()<\/code> which does the main work. If you want to see the code in action, uncomment some of the <code data-enlighter-language=\"js\" class=\"EnlighterJSRAW\">console.log(...)<\/code> statements and check the JS Console in your browser.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>If you&#8217;ve got a password-reset page (from WooCommerce or somewhere else), you can add a &#8220;Forgot your password?&#8221; link by editing <strong>login-form.php<\/strong>. Nice and easy.<\/p>\n\n\n\n<p>To add a &#8220;Remember Me&#8221; checkbox, you could to do something like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add a checkbox into <strong>login-form.php<\/strong> and give it a sensible id.<\/li>\n\n\n\n<li>In <strong>wpt-ajax-login.js<\/strong>, detect if the checkbox is &#8220;checked&#8221; and add true|false to the request object, e.g.<br><code data-enlighter-language=\"js\" class=\"EnlighterJSRAW\">$(container).find('#wptajl-remember-me').prop('checked') \/\/ Returns true or false<\/code><\/li>\n\n\n\n<li>In <strong>wpt-ajax-login.php<\/strong>, pick up the checkbox from <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">$_POST<\/code>, in the same way we pick up the user name and password (except this is a bool field, not a text field).<\/li>\n\n\n\n<li>Pass this true|false value into <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">wp_set_auth_cookie()<\/code><\/li>\n<\/ul>\n\n\n\n<p>Try to keep the login form simple. This is an unobtrusive feature that should improve the User eXperience.<\/p>\n\n\n\n<p>That&#8217;s it. Happy logging-in! \ud83d\ude0e \ud83d\udc4d<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Create a popup menu with an Ajax login form so users can sign in to your WordPress site without leaving the current page. A neat little User Experience enhancement.<\/p>\n","protected":false},"author":1,"featured_media":6496,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"iawp_total_views":3242,"footnotes":""},"categories":[4],"tags":[31,10,122],"class_list":["post-6409","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-optimise-wordpress","tag-login","tag-security","tag-user-experience","masonry-post","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-33","no-featured-image-padding"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ajax Login for WordPress Without a Plugin - WP Tutorials<\/title>\n<meta name=\"description\" content=\"Create a popup menu with an Ajax login form so users can sign in to your WordPress site without leaving the current page.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ajax Login for WordPress Without a Plugin - WP Tutorials\" \/>\n<meta property=\"og:description\" content=\"Create a popup menu with an Ajax login form so users can sign in to your WordPress site without leaving the current page.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/\" \/>\n<meta property=\"og:site_name\" content=\"Headwall WP Tutorials\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/headwallhosting\/\" \/>\n<meta property=\"article:published_time\" content=\"2022-03-05T07:59:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-08-12T20:09:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wordpress-ajax-login-form-tutorial.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2456\" \/>\n\t<meta property=\"og:image:height\" content=\"1851\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"headwall\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@headwall\" \/>\n<meta name=\"twitter:site\" content=\"@HeadwallHosting\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"headwall\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/\"},\"author\":{\"name\":\"headwall\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#\\\/schema\\\/person\\\/567442e9250f58ba41a61bbfc1411622\"},\"headline\":\"Ajax Login for WordPress Without a Plugin\",\"datePublished\":\"2022-03-05T07:59:10+00:00\",\"dateModified\":\"2023-08-12T20:09:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/\"},\"wordCount\":1431,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wp-tutorials.tech\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/wordpress-ajax-login-form-tutorial.jpg\",\"keywords\":[\"Login\",\"Security\",\"User Experience\"],\"articleSection\":[\"Optimise WordPress\"],\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/\",\"url\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/\",\"name\":\"Ajax Login for WordPress Without a Plugin - WP Tutorials\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wp-tutorials.tech\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/wordpress-ajax-login-form-tutorial.jpg\",\"datePublished\":\"2022-03-05T07:59:10+00:00\",\"dateModified\":\"2023-08-12T20:09:03+00:00\",\"description\":\"Create a popup menu with an Ajax login form so users can sign in to your WordPress site without leaving the current page.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#primaryimage\",\"url\":\"https:\\\/\\\/wp-tutorials.tech\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/wordpress-ajax-login-form-tutorial.jpg\",\"contentUrl\":\"https:\\\/\\\/wp-tutorials.tech\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/wordpress-ajax-login-form-tutorial.jpg\",\"width\":2456,\"height\":1851,\"caption\":\"WordPress Ajax Login Form Tutorial\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/optimise-wordpress\\\/wordpress-ajax-login-form\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wp-tutorials.tech\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Optimise WordPress\",\"item\":\"https:\\\/\\\/wp-tutorials.tech\\\/category\\\/optimise-wordpress\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Ajax Login for WordPress Without a Plugin\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#website\",\"url\":\"https:\\\/\\\/wp-tutorials.tech\\\/\",\"name\":\"Headwall WP Tutorials\",\"description\":\"Practical WordPress Tutorials\",\"publisher\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wp-tutorials.tech\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#organization\",\"name\":\"Headwall WordPress Tutorials\",\"url\":\"https:\\\/\\\/wp-tutorials.tech\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/wp-tutorials.tech\\\/wp-content\\\/uploads\\\/2021\\\/12\\\/headwall-wp-tutorials-logo-retina.png\",\"contentUrl\":\"https:\\\/\\\/wp-tutorials.tech\\\/wp-content\\\/uploads\\\/2021\\\/12\\\/headwall-wp-tutorials-logo-retina.png\",\"width\":1640,\"height\":512,\"caption\":\"Headwall WordPress Tutorials\"},\"image\":{\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/headwallhosting\\\/\",\"https:\\\/\\\/x.com\\\/HeadwallHosting\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/wp-tutorials.tech\\\/#\\\/schema\\\/person\\\/567442e9250f58ba41a61bbfc1411622\",\"name\":\"headwall\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6106bc5e3abccd66f196d133fa692d0c6c53cc2cac1b58528c510ee8de9e791e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6106bc5e3abccd66f196d133fa692d0c6c53cc2cac1b58528c510ee8de9e791e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6106bc5e3abccd66f196d133fa692d0c6c53cc2cac1b58528c510ee8de9e791e?s=96&d=mm&r=g\",\"caption\":\"headwall\"},\"sameAs\":[\"https:\\\/\\\/headwall-hosting.com\\\/\",\"https:\\\/\\\/x.com\\\/headwall\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ajax Login for WordPress Without a Plugin - WP Tutorials","description":"Create a popup menu with an Ajax login form so users can sign in to your WordPress site without leaving the current page.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/","og_locale":"en_GB","og_type":"article","og_title":"Ajax Login for WordPress Without a Plugin - WP Tutorials","og_description":"Create a popup menu with an Ajax login form so users can sign in to your WordPress site without leaving the current page.","og_url":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/","og_site_name":"Headwall WP Tutorials","article_publisher":"https:\/\/www.facebook.com\/headwallhosting\/","article_published_time":"2022-03-05T07:59:10+00:00","article_modified_time":"2023-08-12T20:09:03+00:00","og_image":[{"width":2456,"height":1851,"url":"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wordpress-ajax-login-form-tutorial.jpg","type":"image\/jpeg"}],"author":"headwall","twitter_card":"summary_large_image","twitter_creator":"@headwall","twitter_site":"@HeadwallHosting","twitter_misc":{"Written by":"headwall","Estimated reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#article","isPartOf":{"@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/"},"author":{"name":"headwall","@id":"https:\/\/wp-tutorials.tech\/#\/schema\/person\/567442e9250f58ba41a61bbfc1411622"},"headline":"Ajax Login for WordPress Without a Plugin","datePublished":"2022-03-05T07:59:10+00:00","dateModified":"2023-08-12T20:09:03+00:00","mainEntityOfPage":{"@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/"},"wordCount":1431,"commentCount":0,"publisher":{"@id":"https:\/\/wp-tutorials.tech\/#organization"},"image":{"@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#primaryimage"},"thumbnailUrl":"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wordpress-ajax-login-form-tutorial.jpg","keywords":["Login","Security","User Experience"],"articleSection":["Optimise WordPress"],"inLanguage":"en-GB","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/","url":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/","name":"Ajax Login for WordPress Without a Plugin - WP Tutorials","isPartOf":{"@id":"https:\/\/wp-tutorials.tech\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#primaryimage"},"image":{"@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#primaryimage"},"thumbnailUrl":"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wordpress-ajax-login-form-tutorial.jpg","datePublished":"2022-03-05T07:59:10+00:00","dateModified":"2023-08-12T20:09:03+00:00","description":"Create a popup menu with an Ajax login form so users can sign in to your WordPress site without leaving the current page.","breadcrumb":{"@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#primaryimage","url":"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wordpress-ajax-login-form-tutorial.jpg","contentUrl":"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2022\/03\/wordpress-ajax-login-form-tutorial.jpg","width":2456,"height":1851,"caption":"WordPress Ajax Login Form Tutorial"},{"@type":"BreadcrumbList","@id":"https:\/\/wp-tutorials.tech\/optimise-wordpress\/wordpress-ajax-login-form\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wp-tutorials.tech\/"},{"@type":"ListItem","position":2,"name":"Optimise WordPress","item":"https:\/\/wp-tutorials.tech\/category\/optimise-wordpress\/"},{"@type":"ListItem","position":3,"name":"Ajax Login for WordPress Without a Plugin"}]},{"@type":"WebSite","@id":"https:\/\/wp-tutorials.tech\/#website","url":"https:\/\/wp-tutorials.tech\/","name":"Headwall WP Tutorials","description":"Practical WordPress Tutorials","publisher":{"@id":"https:\/\/wp-tutorials.tech\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wp-tutorials.tech\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/wp-tutorials.tech\/#organization","name":"Headwall WordPress Tutorials","url":"https:\/\/wp-tutorials.tech\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/wp-tutorials.tech\/#\/schema\/logo\/image\/","url":"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2021\/12\/headwall-wp-tutorials-logo-retina.png","contentUrl":"https:\/\/wp-tutorials.tech\/wp-content\/uploads\/2021\/12\/headwall-wp-tutorials-logo-retina.png","width":1640,"height":512,"caption":"Headwall WordPress Tutorials"},"image":{"@id":"https:\/\/wp-tutorials.tech\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/headwallhosting\/","https:\/\/x.com\/HeadwallHosting"]},{"@type":"Person","@id":"https:\/\/wp-tutorials.tech\/#\/schema\/person\/567442e9250f58ba41a61bbfc1411622","name":"headwall","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/6106bc5e3abccd66f196d133fa692d0c6c53cc2cac1b58528c510ee8de9e791e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/6106bc5e3abccd66f196d133fa692d0c6c53cc2cac1b58528c510ee8de9e791e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6106bc5e3abccd66f196d133fa692d0c6c53cc2cac1b58528c510ee8de9e791e?s=96&d=mm&r=g","caption":"headwall"},"sameAs":["https:\/\/headwall-hosting.com\/","https:\/\/x.com\/headwall"]}]}},"_links":{"self":[{"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/posts\/6409","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/comments?post=6409"}],"version-history":[{"count":0,"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/posts\/6409\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/media\/6496"}],"wp:attachment":[{"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/media?parent=6409"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/categories?post=6409"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp-tutorials.tech\/wp-json\/wp\/v2\/tags?post=6409"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}