This recipe lets you use one public login page for multiple purposes, while showing different headlines, subheadlines, and background images depending on where the person is headed after logging in.

Think of it like this:

  • If they’re logging in to register for an event, they see “Let’s Get You Registered” with event-themed artwork.
  • If they’re joining a small group, the header might say “Welcome to Your New Community.”
  • If they’re giving, it could be “Let’s Make a Difference Together.”

All of this happens automatically, based on the page they’ll land on after login.

How it works

When someone clicks a link to a page that requires login, Rock sends them to the login page with a returnurl parameter in the URL. This recipe looks at that returnurl, figures out which Rock page it’s pointing to, and then pulls three attributes from that page:

  • Login Header – the big headline.
  • Login Subheader – a short explanation or encouragement.
  • Login Background Image – a background image to load behind the text.

If no image is set, the layout falls back to a logo + text.

What you’ll need

  • The ability to add Page attributes in Rock.
  • A Lava Shortcode to look up a page by its route.
  • The ability to add an HTML Content block on your login page.

Step 1: Add the three Page attributes

Go to Settings → System → Entity Attributes and create these attributes for the Page entity:

  • LoginHeader – Text field
  • LoginSubheader – Text field
  • LoginBackgroundImage – Image field

You only have to do this once, and any page in Rock can now have its own login header info.

Step 2: Create a “PageByRoute” Lava Shortcode

In Settings → CMS → Lava Shortcodes, create a new Inline shortcode named PageByRoute.

This shortcode takes a route (like connect/smallgroup/123) and returns the Page Id.

  • Name: PageByRoute
  • Tag Name: pagebyroute
  • Description: Intakes a page route and outputs the matching page id. 
  • Parameters
    • route (no default value set)
  • Enabled Lava Commands: Sql, Rock Entity

{% comment %} Short Code Markup {% endcomment%}
{% sql %}
DECLARE @path NVARCHAR(400) = '{{ route }}';         -- e.g. 'connect' or 'connect/davis'
IF LEFT(@path,1) = '/' SET @path = SUBSTRING(@path, 2, 400);

DECLARE @pathSegs INT = (SELECT COUNT(*) FROM STRING_SPLIT(@path, '/'));

;WITH pathSegments AS (
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS segNo, value AS segment
    FROM STRING_SPLIT(@path, '/')
),
routeSegments AS (
    SELECT
        pr.Id AS PageRouteId,
        pr.PageId,
        pr.Route,
        ROW_NUMBER() OVER (PARTITION BY pr.Id ORDER BY (SELECT NULL)) AS segNo,
        s.value                      AS segment,
        COUNT(*)     OVER (PARTITION BY pr.Id) AS RouteSegs
    FROM PageRoute pr
    CROSS APPLY STRING_SPLIT(pr.Route, '/') AS s
    -- OPTIONAL site scoping:
    -- JOIN [Page] p   ON p.Id = pr.PageId
    -- JOIN [Layout] l ON l.Id = p.LayoutId AND l.SiteId = @siteId
),
matched AS (
    SELECT
        rs.PageRouteId,
        rs.PageId,
        rs.Route,
        MAX(CASE WHEN rs.Route = @path THEN 1 ELSE 0 END) AS IsExact,
        SUM(CASE WHEN rs.segment LIKE '{' + '%' + '}' THEN 0 ELSE 1 END) AS LiteralCount
    FROM routeSegments rs
    JOIN pathSegments ps
      ON rs.segNo = ps.segNo
    WHERE (rs.segment = ps.segment OR rs.segment LIKE '{' + '%' + '}')
    GROUP BY rs.PageRouteId, rs.PageId, rs.Route, rs.RouteSegs
    HAVING COUNT(*) = @pathSegs           -- every path segment matched a route segment
       AND MAX(rs.RouteSegs) = @pathSegs  -- route has the SAME number of segments
)
SELECT TOP (1)
    PageRouteId, PageId, Route
FROM matched
ORDER BY
    IsExact DESC,          -- exact literal route (e.g., 'connect') wins
    LiteralCount DESC,     -- more literal segments beats more tokens
    PageRouteId ASC;       -- stable tie-breaker
{% endsql %}
{{ results[0].PageId }}

Step 3: Add Lava to the login page

On your public login page, add an HTML Content block (Header zone works well).

In the block’s settings, make sure the “Rock Entity” Command is enabled.

Paste in the code below. You'll need to modify styles based on your site's theme and existing page styles. The styles below likely do not apply to your page. We also have a default image logo set in this code that you'll want to replace the reference to.

    
{% comment %} HTML Content {% endcomment %}
<style>
    header{
        padding:0;
    }
    article{
        padding-top:0;
    }
    .logo{
        text-align:center;
        margin: 30px 0;
        width:100%;
    }
    .logo img{
        width: 80px;
        height: auto;
        user-drag: none;
        -webkit-user-drag: none;
    }
    .login-image-header{
        padding:10px;
    }
</style>

{% comment }MAIN LOGIC HERE{% endcomment %}
{% assign returnurl = 'Global' | PageParameter:'returnurl' | UrlDecode | RemoveFirst:'/' %}
{% if returnurl contains '?' %}
    {% assign urlsplit = returnurl | Split:'?' %}
    {% assign returnurl = urlsplit | First %}
{% endif %}
{% if returnurl contains '&' %}
    {% assign urlsplit = returnurl | Split:'&' %}
    {% assign returnurl = urlsplit | First %}
{% endif %}
{% assign route = returnurl %}
{% capture pageId %}{[ pagebyroute route:'{{ route }}' ]}{% endcapture %}
{% if pageId > 0 %}
    {% comment %}Can't enable security because this is the login page. Person isn't logged in yet.{% endcomment %}
    {% page id:'{{ pageId }}' securityenabled:'false' %}
        {% assign header = page | Attribute:'LoginHeader' %}
        {% assign subheader = page | Attribute:'LoginSubheader' %}
        {% assign image = page | Attribute:'LoginBackgroundImage','Url' %}
    {% endpage %}
{% endif %}

{% if image == '' or image == null %}
<style>
    #brand-bar{
        display:none;
    }
    header {
        padding: 0 15px;
    }
    .login-image-header{
        padding:0;
    }
</style>
{% endif %}

<div style="display:flex;justify-content:center;align-items:center;">
    <div class="login-image-header"
        style="
            display:flex;
            {% if image !='' and image != null %}
            background-image:url('{{ image }}');
            background-size:cover;
            background-position: center center;
            height:350px;
            {% endif %}
            width:100%;
            justify-content:center;
            "
        >
        <div class="header-cta-wrapper" style="width:100%;height:100%;justify-content:center;align-items:flex-start;text-align:left;max-width:400px;">
            {% if image == '' or image == null %}
            <div class="logo">
                <img src="/GetImage.ashx?id=93993" alt="Bayside Church"/>
            </div>
            {% endif %}
            <div class="cta-title">{{ header | Default:'Sign in to your account'  }}</div>
            <div class="cta-text">{{ subheader }}</div>
        </div>
    </div>
</div>
    

Step 4: Set the attributes on destination pages

For any page that requires login, go to Page → Basic Settings → Attribute Values and set:

Registration page sample.

  • Login Header – “Let’s Get You Registered”
  • Login Subheader – “We can’t wait to see you. Sign in below to complete your registration.”
  • Login Background Image – recommended 

Step 5: Test it

  • Visit a protected page while logged out.
  • Make sure the login page updates its header to match that page’s attributes.
  • Try it with different pages (events, small groups, giving) and see each one change.

Why This is Great

Instead of showing the same generic login page for everything, this recipe lets you greet people with a message that fits why they’re logging in. Whether it’s for an event, a small group, giving, or another purpose, they’ll see something that feels relevant and welcoming—without you having to manage multiple pages.