Cookie-Based Redirects for the Elementor Pro Login Widget
Elementor, Websites

Cookie-Based Redirects for the Elementor Pro Login Widget

Cookie-Based Redirects for the Elementor Pro Login Widget
Elementor Pro Login Widget

Cookie-Based Redirects for the Elementor Pro Login Widget

What to do when "Redirect After Login" only accepts one fixed URL, and your site has more than one page worth protecting.

Elementor Pro's native login form looks like every other WordPress login widget until you try to make it behave like one. Under the hood it submits via AJAX, not a standard page POST, and that single architectural choice quietly breaks the pattern most developers reach for first.

The instinct is to append a redirect_to parameter to the login URL, the way wp_login_form() or a classic wp-login.php flow would handle it. With the Elementor widget, that parameter goes nowhere. The form's Redirect After Login field in the widget settings takes exactly one static URL, set once, applied to everyone, regardless of which page sent them there.

The scenario that exposes the problem

I ran into this on a restaurant site with a bookings page restricted to staff — administrators and contributors only. A visitor without the right role hits the page, gets bounced to login, logs in successfully, and lands... on the homepage. Not on the bookings page. Every time. The login worked. The experience didn't.

Multiply that by every protected page on the site and you get a login form that technically authenticates but functionally loses the user's original intent on every single visit.

Why the fix has to route through a cookie

Since the widget won't carry a dynamic redirect target through its AJAX submission, the destination has to survive somewhere else — a place the login process doesn't need to know about at all. A cookie does exactly that. Set it before the redirect to login, read it after the login completes, and the widget's fixed redirect URL becomes a waypoint rather than a destination.

Two hooks, both on template_redirect, do the whole job.

Step one: catching the unauthorized visit

This runs on every protected page. If the visitor isn't logged in, or is logged in but lacks the right role, it stores the current URL in a cookie and sends them to the login page — in this case, an /account/ page carrying the Elementor login widget.

add_action( 'template_redirect', function() {
    $pagine_protette = array( 827, 4929 );

    if ( is_page( $pagine_protette ) ) {
        if ( ! is_user_logged_in() || ! ( current_user_can( 'administrator' ) || current_user_can( 'contributor' ) ) ) {
            setcookie( 'naos_redirect_to', get_permalink(), time() + 300, ( COOKIEPATH ?: '/' ), COOKIE_DOMAIN );
            wp_redirect( home_url( '/account/' ) );
            exit;
        }
    }
}, 5 );

The array of page IDs is deliberately simple — no custom post type registration, no settings screen, just numbers you can find in the WordPress admin URL when editing a page. For two or three protected pages, that's the right amount of engineering. For twenty, you'd want a meta field instead, but I'd cross that bridge when a client actually asks for it.

The 300-second cookie expiry is worth a note. Five minutes. Long enough to cover a login with a fumbled password on the second attempt, short enough that the cookie doesn't linger as dead weight in the browser for a visitor who abandoned the flow entirely.

Step two: closing the loop after login

The widget's own redirect setting sends every successful login to the homepage — that's the fixed URL Elementor's interface allows. This second hook intercepts right there, checks for the cookie, and — if the now-authenticated user actually has permission — sends them on to where they originally wanted to go.

add_action( 'template_redirect', function() {
    if ( is_front_page() && is_user_logged_in() && isset( $_COOKIE['naos_redirect_to'] ) ) {
        if ( current_user_can( 'administrator' ) || current_user_can( 'contributor' ) ) {
            $redirect_to = esc_url_raw( $_COOKIE['naos_redirect_to'] );
            setcookie( 'naos_redirect_to', '', time() - 3600, ( COOKIEPATH ?: '/' ), COOKIE_DOMAIN );
            wp_redirect( $redirect_to );
            exit;
        }
    }
}, 5 );

Notice the role check happens twice — once before the redirect to login, once again after. That's not redundancy for its own sake. A user could theoretically log in as a role that doesn't qualify, and without the second check, the cookie would still fire and grant access to a page it shouldn't. The cookie carries a destination, not a permission.

The cookie clears itself immediately after use, via a negative expiry timestamp — the standard trick for deleting a cookie without a dedicated deletion function. esc_url_raw() on the way out matters too; the cookie value is user-influenced data, even if only indirectly, and it's going straight into a redirect.

Configuring the widget itself

In the Elementor editor, the login widget's Redirect After Login field points to the homepage — nothing clever there, it's meant to be boring. All the actual routing intelligence lives in the two PHP hooks, not in the widget configuration. That separation is deliberate: it means the redirect logic survives even if someone later swaps out the login widget for a different one, as long as it still lands users on the homepage after authentication.

Where this quietly breaks: caching

Here's the part nobody warns you about. On a related project — a staff-only link, not a full page, shown conditionally via a shortcode — the exact same logic worked perfectly in a logged-in session and then kept showing the link to logged-out visitors anyway. Not as broken shortcode text, mind you. As a clean, clickable link. Which meant the PHP was executing correctly.

The actual cause was full-page caching, combined with Elementor's own Element Caching feature introduced in version 3.22. The page had been cached once, while a logged-in admin was viewing it, and that cached HTML — link included — was then served to everyone afterward regardless of role. The fix wasn't in the PHP at all. It was excluding the affected pages from full-page cache at the hosting level.

I mention it here because the same failure mode applies to this redirect system. If your host or a plugin caches the protected page itself, the template_redirect hook may never even fire for subsequent visitors — they get served a cached copy before WordPress gets the chance to check who they are. Any page carrying this logic needs a permanent cache exclusion, not an occasional one.

Scope and requirements

This approach assumes cookies are enabled in the visitor's browser — not a controversial assumption in 2026, but worth stating, since a cookie-blocked session degrades gracefully to "always lands on homepage" rather than failing outright, which is an acceptable fallback. It also assumes a single login destination; multi-step or multi-role redirect trees would need a slightly more elaborate cookie payload than a single URL string.

Whether this pattern is worth generalizing into a small reusable plugin, versus keeping it as a page-specific WPCode snippet, really depends on how many client sites end up needing the same fix — for a one-off restricted page, the snippet is the right amount of code.

Need help with this solution or looking for custom development?

Visit my Stay In Touch page to connect and discuss your project. Discover a range of web development services and specialized WordPress solutions tailored to your needs. Let's work together to enhance your digital presence.