WordPress login link with a popup form

This post is more than 6 years old.

I’m a big fan of the Login with Ajax plugin. It makes it really easy to add a nice popup login form to a website. Here’s how to make the most of it, with a little custom code.

NB: developers only! If you’re not comfortable writing custom PHP and JavaScript code for your WordPress theme, you probably want to stick with what the plugin already does for you. It’s pretty good as-is, I just like to squeeze everything I can out of it 🙂

One thing about LWA is that it doesn’t like being called more than once on a page, due to some necessary IDs in its form fields. That’s OK, we’ll set it up to add the form to the page only once, and then we can call it from one or more login links on the page.

Templates

The plugin uses templates for its login forms, which makes it easy to override the HTML in its login forms. Each named template (default, divs-only, modal) can actually have two template files: one for when visitors are logged in, and another for logged out (anonymous) visitors.

Login with Ajax templates in the plugin
Login with Ajax templates in the plugin

The easy way to set up a custom template is to copy an existing template pair from the plugin’s widgets folder into your theme. We’ll set up a new named template called “login”, which means we need a new folder in our theme:

wp-contents/themes/example-theme/plugins/login-with-ajax/login

We need a simple template for visitors that are already logged in; they only need a logout link. Create a file called widget_in.php in that folder, and add this content:

<?php
/*
* minimal, so only displays as a link
*/
?>
<div class="lwa lwa-template-modal">
	<a id="wp-logout" href="<?php echo wp_logout_url() ?>">Logout</a>
</div>

Now we can copy the widget_out.php file from the plugin’s modal template. It is almost perfect how it is; there’s just two things we need to change:

  • with the div wrapping it all, add a class that we can target from JavaScript, like “example-lwa-modal”
  • remove the login link (A tag) just inside that div; we’ll be providing our own login links

Put Login with Ajax in a menu

Wouldn’t it be nice to have a login / logout link in the menu? When visitors are logged in, they get a logout link, but otherwise the link pops up a Login with Ajax form. Easy! Copy a link to your website’s login page (wp-login.php) and create a Custom menu item using the menu admin in WordPress.

Adding a custom login link to a menu
Adding a custom login link to a menu

OK, so it’s a link to the login page. Now to make it use Login with Ajax, and change to a logout link when visitors are logged in. Add this code to your functions.php file. Note that we only want to mess with the menu on the front of the website, not in the admin!

if (!is_admin()) {

    /**
    * filter menu items to replace login link with logout link when user is logged in
    * if Login with Ajax is installed, use it for the login link
    * @param string $item_output
    * @param WP_Post $item
    * @return string
    */
    add_filter('walker_nav_menu_start_el', function($item_output, $item) {
        if ($item->type === 'custom' && strpos($item->url, 'wp-login.php') !== false) {
            if (is_user_logged_in()) {
                $item_output = sprintf('<a href="%s">Logout</a>', wp_logout_url(get_permalink()));
            }
            else {
                if (class_exists('LoginWithAjax')) {
                    $item_output = sprintf('<a class="example-login-link" href="%s">%s</a>', esc_url(wp_login_url(get_permalink())), esc_html($item->title));
                    add_action('wp_print_footer_scripts', 'example_load_lwa_login_template');
                }
                else {
                    $item_output = sprintf('<a href="%s">%s</a>', wp_login_url(get_permalink()), esc_html($item->title));
                }
            }
        }

        return $item_output;
    }, 10, 2);

}

/**
* load the Login with Ajax modal script for the menu link
* called from wp_print_footer_scripts
*/
function example_load_lwa_login_template() {
    $script = \LoginWithAjax::shortcode([
        'template'		=> 'login',
        'profile_link'	=> false,
        'registration'	=> false,
    ]);

    // strip extraneous whitespace to reduce size
    $script = preg_replace('#^\s*#m', '', $script);

    echo $script;
}

That sets up the HTML for the login link, and loads the HTML for the login form in the footer. Because we’re using a copy of the modal template, LWA will hide the form until we’re ready for it. What we want now is a way to trigger LWA when a visitor clicks on our login link, and for that we need some JavaScript. Normally, LWA handles that for us, but because we’re modifying things to run the login form from links we can add anywhere, we need to handle that ourselves.

Add this to the script you load on every page (or add it to a new file and enqueue it).

/**
* hook any login links to show the Login With AJAX form
*/
jQuery("a.example-login-link").on("click", function(e) {
    var target = jQuery("div.example-lwa-modal").data("modal");

    if (target && target.length > 0) {
        e.preventDefault();
        target.reveal({
            modalbgclass: "lwa-modal-bg",
            dismissmodalclass: "lwa-modal-close"
        });
    }
});

And we’re set! That should give us a menu link that brings up the LWA modal login form. But what about a link in the middle of the page?

From a shortcode

Let’s create a simple shortcode so that we can add [example_login_link] on any page to let visitors know they need to login. Back to the functions.php file to add this snippet:

/**
* shortcode to show a login link for anonymous visitors only
* @param array $attrs
* @param string $content
* @return string
*/
add_shortcode('example_login_link', function($attrs, $content) {
    if (is_user_logged_in()) {
        return '';
    }

    if (empty($content)) {
        $content = 'Already a member? Login';
    }

    add_action('wp_print_footer_scripts', 'example_load_lwa_login_template');

    return sprintf('<a class="example-login-link" href="%s">%s</a>', esc_url(wp_login_url(get_permalink())), strip_tags($content));
});

Note that it handles the shortcode’s content parameter, so we can get a little fancy with it:

[example_login_link]Missing some members only pages? Login to see them![/example_login_link]

Login with Ajax from Gravity Forms

Now how about a login link in Gravity Forms? Sure, we can do that too. Add a new HTML field to the top of your form, or we can use the first Section field if you have one of those. Now add this snippet to the HTML field content, or Section description. Notice that we’re using that class on the link again.

Are you a member?

<p id="example-current-login">Currently logged in as: <strong>{{example_current_user}}</strong>. <strong><a class="example-login-link" href="{{example_login_url}}">Log in as a different member</a></strong>.</p>

<p id="example-not-logged-in">Already a member? <strong><a class="example-login-link" href="{{example_login_url}}">Log in to continue</a></strong>.</p>

Now the trick here is to show the first paragraph to logged in visitors, and the second one to anonymous visitors. Why do it this way? So that the website admins who can edit Gravity Forms can change the text as they please, just like any other part of the form.

We can do the required magic with a Gravity Forms content filter called gform_field_content. We’ll target just that form field knowing the form ID and field ID (you can see these in the form editor); in this example, the form ID is 3 and the field ID is 1.

/**
* replace some template values in the login prompt text
* @param string $field_content
* @param GF_Field $field
* @return mixed
*/
add_filter('gform_field_content_3_1', function($field_content, $field) {
    $field_content = str_replace('{{example_login_url}}', esc_url(wp_login_url(get_permalink())), $field_content);

    if (is_user_logged_in()) {
        $user = wp_get_current_user();
        $field_content = str_replace('{{example_current_user}}', esc_html($user->display_name), $field_content);
        $field_content = preg_replace('#<p id="example-not-logged-in">.*?</p>#', '', $field_content);
    }
    else {
        $field_content = preg_replace('#<p id="example-current-login">.*?</p>#', '', $field_content);
    }

    return $field_content;
}, 10, 2);

As you can imagine, there’s lots of ways we can use this because it’s all hanging off a simple link with a class. Login with Ajax is providing all the magic, but we’re pushing it a little further.