
Ahh, your favorite local coffee shop. You walk in and they greet you by name and start making your usual. You feel like a VIP, and better yet, you save a few minutes in your already busy day. Wouldn’t it be nice if your website could offer that same experience to returning visitors, even if they never log in?
That’s exactly what a good returning user experience (RUX) is all about. It’s the art of making your site or app feel more welcoming and just a little bit magical every time a user comes back. When it’s done right it reduces friction, saves users time, and adds those personal touches that keep them engaged. And customers take notice — 81% of people prefer companies that offer an experience that is personalized to them.
Whether it’s customizing content, picking up where users left off, or reducing friction, a solid return user experience makes every visit feel great — logged in or not. In this article, you’ll learn how to optimize RUX and create a seamless journey for all your users.
Key components of RUX
You might be thinking, “Isn’t RUX just personalization?” Close, but not quite. The key difference is the return visit. Personalization doesn’t necessarily rely on remembering past interactions.
Take a flight search site, for example. If it pre-fills your outbound airport based on your detected location, that’s personalization. Great! But RUX takes it a step further. Maybe last time you searched, you picked a larger airport a little farther away because it had better flights. A good RUX remembers the choice you made and pre-fills it for you next time.
So while RUX includes personalization, not all personalization is RUX. RUX makes your users’ return visits smoother by remembering what actually matters to them. Some of the main components of RUX include:
Recognition
Identifying returning users is the foundation of any RUX strategy. Without recognition, every visit feels like the first, forcing users to start from scratch. Even without an account, good visitor recognition allows you to deliver a familiar, engaging experience that makes returning users feel like regulars. And on the flip side, it helps identify returning fraudsters or abusive visitors, allowing you to block or restrict them.
Personalized content
Personalization with RUX tailors your site and the content you show based on your users’ past interactions. This could mean surfacing frequently used features, adjusting content recommendations, or even changing the UI to match their behavior. Instead of pushing random bestsellers, you’re showing products related to what the user viewed in the past. RUX remembers what users have done before and uses that knowledge to make their experience smoother, smarter, and less annoying.
State persistence
A great RUX makes sure users don’t have to start over if they leave and come back. Whether it’s remembering what was in their cart, restoring a half-finished form, or picking up exactly where they left off in a multi-step process, state persistence makes interactions feel effortless. This is especially important for high-friction tasks like checkout flows, onboarding, or applications, where having to re-enter information can lead to frustration and abandonment. Even something as simple as retaining a user’s last-used settings, like preferred filters, dark mode preferences, or language choices can make an impact.
Reduced friction
Removing unnecessary steps can make any interaction faster and smoother. Autofilling usernames, skipping repetitive onboarding pop-ups, and enabling one-click checkouts all help cut down on friction. Even something as simple as automatically applying a returning customer’s preferred shipping method at checkout can speed things up without requiring extra effort. Friction isn’t always about major roadblocks; often, it’s the tiny, repetitive annoyances that slow users down, and RUX helps eliminate them.
Trust & security
Even when thinking about your site’s security, RUX can play a part. Recognized users can log in or recover passwords without unnecessary MFA prompts, while new or unusual login attempts trigger extra verification. But trust and security go beyond authentication. Recognizing returning devices helps detect fraud, prevent unauthorized access, and flag suspicious behavior. RUX balances ease of access with security, ensuring users feel both safe and valued.
Engagement awareness
RUX can also adapt to how often and in what context a user comes back. Daily visitors don’t need the same experience as those returning after months away. A news site might show frequent readers the latest articles since their last visit, while a productivity tool could highlight new features if the user hasn’t logged in for a while. Perhaps users are incentivized to return frequently with loyalty perks. By recognizing return patterns, engagement awareness keeps the experience relevant, proactive, and rewarding.
Example RUX user journeys
Now that you’ve got an idea of what RUX encompasses, let’s take a quick look at a few examples of how RUX can be applied to real-world scenarios across different use cases.
A seamless shopping experience
Sarah is browsing an online store for running shoes but isn’t sure if she wants them and leaves without purchasing. A few days later, she returns, hoping to pick up where she left off.
- Her cart is still full with any shoes she added, and a banner reminds her of the items she left behind.
- The search bar offers up her previous searches with one-click suggestions and applies her last-used filters, like her shoe size.
- At checkout, the type of payment method (e.g., PayPal, Google Pay, credit card) she used in previous purchases is highlighted or prioritized.
- Since she didn’t buy on her last visit, she’s offered a personalized discount to encourage her purchase.
Sarah checks out in seconds, with a smooth experience that makes her more likely to return.
A frictionless workday
Aaron, a product manager, logs into his project management tool to check his team’s progress.
- His device is recognized, so his usual authentication method appears first in the list of options. His username is pre-filled, and he skips unnecessary MFA prompts.
- The app opens directly to his last-viewed project, so he can dive in without navigating menus.
- His personalized dashboard prioritizes the tasks and projects he interacts with most.
- When he returns to the site a few days later, he’s still logged in, reducing repeated logins.
Aaron gets straight to work without login hassles or unnecessary friction.
A personal content journey
Jordan loves reading articles, watching videos, and discovering new content on her favorite news and entertainment site.
- When she returns, the homepage highlights new content since her last visit.
- Her reading and playback settings, like dark mode and captions, are already applied.
- If she didn’t finish a video, playback resumes where she left off.
- The site suggests new content based on her interests and past activity.
Jordan’s experience feels smooth and personalized, keeping her engaged without extra effort.
How to recognize returning visitors
At the core of all these RUX use cases is one simple truth: You can’t roll out the red carpet for returning users if you don’t recognize them when they come back. Without some way to do this, every visit is a fresh start — and not in a good way.
If your site or app has user accounts, you’ve got a head start! Just save preferences and activity history to the account, and boom — instant ability for return visit personalization. If you have accounts, you can also recognize users across devices. But here’s the catch: this only works after the user logs in. Anything they do before that? They might as well be strangers. And good luck remembering anything if they don’t want to create an account at all.
So what can you do to recognize anonymous visitors? One option is using cookies or local storage to save preferences and identify users. But cookies are fragile. Users can clear them, some browsers wipe them automatically after short time periods, and they don’t work across devices. You could try identifying visitors by their IP address, but that’s a mess too. IPs change constantly, and multiple users can share the same one, making it incredibly unreliable and inaccurate.
A more reliable way to recognize returning visitors, without relying on logging in or fragile cookies, is browser and device fingerprinting. Instead of looking at a single piece of data like an IP address, fingerprinting combines multiple signals from a user’s browser and device to create a unique identifier. This includes things like screen resolution, installed fonts, browser settings, and hardware details.
Even if a user clears their cookies or switches networks, their fingerprint persists and is highly stable, making it possible to recognize the same device over time. Since fingerprinting is device-specific, it doesn’t identify users across multiple devices — but that’s where pairing it with user account data becomes a powerful combination. Together, they give you the best of both worlds: a seamless returning user experience whether users are logged in or not. And if you don’t use accounts? Fingerprinting has your back, filling in the gaps so anonymous visitors don’t feel like strangers every time they return.
Industry-leading visitor recognition with Fingerprint
If you want to recognize returning users with industry-leading accuracy, then look no further than Fingerprint. Our device intelligence platform analyzes over 100 browser and device signals to deliver reliable, long-term visitor identification. But we don’t just use fingerprint hashes; we go further, incorporating server-side techniques and machine learning to give you a deeper, more resilient way to recognize your user’s browsers and devices. Our visitor identifiers remain stable for months, unaffected by cleared cookies, VPN usage, or incognito browsing.
With just a lightweight client agent and simple APIs, you can start recognizing returning visitors on your site or mobile app in minutes. Fingerprint easily integrates with your existing stack, and we have SDKs for your favorite frameworks and languages for easy implementation.
And to be clear, Fingerprint is privacy-first. We don’t collect personally sensitive data or attempt to identify the individual behind the device. Instead, we focus on recognizing browsers and devices, allowing you to enhance the return user experience while maintaining your users privacy.
In addition to providing highly accurate visitor recognition with the visitor identifier, Fingerprint also offers actionable insights like browser tampering, VPN usage, and bot detection through Smart Signals. With this extra data, you can further refine a curated experience while also identifying and mitigating suspicious activity.
How to improve RUX with Fingerprint
Now that you’ve got a good handle on what goes into a great RUX, we’ll pick a few examples from the above use cases to show how you can use Fingerprint’s device intelligence to improve it. This example will be for a Node-based website, but Fingerprint works with mobile app development as well.
Once you have a Fingerprint account (sign up for a free trial!) and your API keys, the first thing you’ll need to do is add the JavaScript client agent in your front end. This is a generic step that you’ll need to do for any use case but we’ll start with an authentication example first.
When integrating Fingerprint into your site, make sure to load it as soon as possible and then request identification when you need it. In this example, the identification request happens when the user clicks “Log in.”
// Initialize the Fingerprint client agent as soon as possible
const fpPromise = import("https://fpjscdn.net/v3/YOUR_PUBLIC_API_KEY").then(
(FingerprintJS) => FingerprintJS.load()
);
async function handleLogin(credentials) {
// Request identification data when the user attempts to log in
const fp = await fpPromise;
const result = await fp.get();
const { requestId, sealedResult } = result;
// Include the requestId and/or sealedResult with the login request
const loginPayload = {
...credentials,
requestId,
sealedResult
};
const requestOptions = {
method: "POST",
body: JSON.stringify(loginPayload),
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
};
// Send the login payload to your authentication server
const response = await fetch("/api/login", requestOptions);
if (!response.ok) {
throw new Error("Login failed");
}
const data = await response.json();
return data;
}
When you call the get()
method, Fingerprint returns a JSON object with details about the visitor, including their unique visitorId
. However, instead of using the returned visitorId
directly, we recommend using the requestId
or sealedResult
. This is because information from the front end cannot be trusted and you’ll need to assess the visitor ID on the server side. Note that the requestId
is unique to each identification request and the visitorID
is unique to the user’s browser or device and remains the same.
There are three ways to do this:
- Send the
requestId
to the Fingerprint Server API to retrieve the full identification details. - Set up webhooks to send identification event results directly to your server, linking them using the
requestId
from the client side. - Retrieve the full details directly on the client side in encrypted form as a
sealedResult
, then pass it to your server for decryption.
We’ll be using the third option. To enable this, you first need to set up an encryption key in the Fingerprint dashboard.
The following steps should be done securely on your server. Since we already received the full details of the visitor identification, we don’t need to make any second API calls and can just use our encryption key to decrypt the sealedResult
data.
Begin by installing the relevant version of the Fingerprint Server API library — here, we’re using the Node SDK.
npm install @fingerprintjs/fingerprintjs-pro-server-api
Then, retrieve and decrypt the sealedResult
to access the full and untampered identification event details.
const {
unsealEventsResponse,
} = require("@fingerprintjs/fingerprintjs-pro-server-api");
const { sealedResult } = request.body;
const decryptionKey = "YOUR_ENCRYPTION_KEY";
// Decrypt the identification event
const unsealedData = await unsealEventsResponse(
Buffer.from(sealedResult, "base64"),
[
{
key: Buffer.from(decryptionKey, "base64"),
algorithm: "aes-256-gcm",
},
]
);
// Extract the true visitor identifier
const visitorId = unsealedData.products.identification.data.visitorId
To see all of the data Fingerprint provides in the identification event, take a look at our demo playground and see the details for your own device.
Adaptive authentication
Now that we have the visitor identifier, let’s see how it applies to some of the previous use cases. First, we’ll continue with authentication and use the visitor ID to check if a user is logging in from a recognized device. This requires storing the visitor ID whenever someone logs in so you have a list of devices associated with the account. Then, it’s simply a matter of querying that list and comparing it to the device being used for the login attempt.
// Query known visitor IDs for the given username
const [rows] = await db.execute(
"SELECT visitor_id FROM user_devices WHERE username = ?",
[username]
);
const knownVisitorIds = rows.map((row) => row.visitor_id);
if (knownVisitorIds.includes(visitorId)) {
// Recognized device, proceed with login
return authenticateUser(username, password);
} else {
// New device detected, require additional verification
const otp = generateOTP();
await sendOTP(username, otp);
return {
status: "MFA_REQUIRED",
message: "New device detected. Please verify with the OTP sent to your phone.",
};
}
Frictionless e-commerce for anonymous users
When an anonymous visitor browses products or adds items to their cart, we can associate that activity with their visitorId
. This allows us to restore their shopping session when they return, even if they never created an account. If they’ve visited before, we can retrieve their saved cart and previous searches to help them pick up where they left off. If they’re new, we simply start fresh. Again, this requires first saving the user’s activity, such as search requests and cart additions, along with their visitorId
.
// Retrieve cart items for the returning visitor
const [cartRows] = await db.execute(
"SELECT cart_items FROM user_carts WHERE visitor_id = ?",
[visitorId]
);
// Retrieve the most recent search terms for the returning visitor
const [searchRows] = await db.execute(
"SELECT search_term FROM user_searches WHERE visitor_id = ? ORDER BY searched_at DESC LIMIT 5",
[visitorId]
);
const cartItems = cartRows.length > 0 && cartRows[0].cart_items ? JSON.parse(cartRows[0].cart_items) : [];
const searches = searchRows.map((row) => row.search_term);
if (cartItems.length > 0 || searchSuggestions.length > 0) {
return {
cart: cartItems,
searchSuggestions: searches,
message: "Welcome back! Here's where you left off.",
};
} else {
return {
cart: [],
searchSuggestions: [],
message: "Welcome! Start browsing, and we’ll save your preferences for next time.",
};
}
Engaging content
When users return to a content platform, they don’t want to dig through menus to find what’s new or where they left off. Each time the visitor watches an episode or favorites a tv series, save their activity with their visitorId
. By linking their visitorId
to their watch history and new content updates, we can surface a personalized “Continue Watching” section along with new episodes of their favorite shows.
// Retrieve unfinished content and new episodes for the returning visitor
const [continueRows] = await db.execute(
"SELECT content_id, playback_position FROM user_content_progress WHERE visitor_id = ? AND completed = FALSE ORDER BY updated_at DESC LIMIT 5",
[visitorId]
);
const [newEpisodesRows] = await db.execute(
`SELECT show_id, episode_id
FROM new_episodes
WHERE show_id IN (SELECT show_id FROM user_subscriptions WHERE visitor_id = ?)
AND release_date > COALESCE(
(SELECT last_visited_at FROM user_visits WHERE visitor_id = ?),
'1970-01-01'
)
ORDER BY release_date DESC
LIMIT 5`,
[visitorId, visitorId]
);
return {
continueWatching: continueRows.length > 0 ? continueRows : null,
newEpisodes: newEpisodesRows.length > 0 ? newEpisodesRows : null,
message: "Welcome back! Here’s what’s new and what you were last watching.",
};
You’ll notice a common theme in these examples: the key is storing data with a stable identifier (like Fingerprint’s visitorId
!) to recall information later. Whether you are storing just the visitorId
or also have access to account data and are combining it together, being able to recognize your returning users means you have a way to craft experiences just for them.
However, when designing your RUX strategy, do keep in mind that personalization shouldn’t carry over between incognito and regular browsing. While Fingerprint can recognize the same browser or device in private mode (which is great for fraud prevention), applying personalization in that context can feel intrusive and create a bad user experience.
Treat all your returning users like regulars
Creating a great return user experience isn’t just about convenience. It’s about reducing friction, building trust, and keeping users engaged every time they come back.
Whether it’s skipping MFA because you just logged in yesterday, seeing the perfect pair of shoes based on your past activity, or hitting play without having to scrub a 2-hour movie to find where you left off, these small touches make a big difference. And the best part? You don’t need to be invasive to do it. Fingerprint lets you remember without tracking, giving you the power to recognize returning visitors while respecting their privacy.
Want to see how implementing RUX strategies with Fingerprint can reduce friction and improve user satisfaction? Read our case study on how we helped a fast-growing fintech startup reduce redundant MFA requests by 70%. Or if you want to take a crack at it yourself, sign up for a free trial to get started!
FAQ
RUX refers to the experience a user has when they revisit a website or app. It uses visitor recognition to personalize content, reduce friction, and ensure continuity from their previous interactions. Great RUX boosts engagement, increases conversions, and can even fight fraud by identifying returning bad actors.
You can use methods like cookies, local storage, or device fingerprinting to identify returning visitors and tailor their experience, even if they never create an account. Fingerprinting lasts much longer than cookies and local storage which can be cleared at any time.
A smoother return experience reduces drop-off, encourages repeat visits, and boosts conversions by letting users pick up where they left off. When a site remembers their preferences and past activity, users feel valued, routine tasks become less frustrating, and the experience feels like it was built just for them.