March 18, 2025

Tutorial: Reducing cart abandonment & improving the guest experience

Image for preventing checkout abandonment tutorial

Guest checkouts are a critical sales tool — and requiring customers to create an account is the second largest reason for cart abandonment

Since avoiding abandonment is the primary motivator for offering guest checkouts, it’s crucial to also offer a streamlined experience designed to decrease abandonment rates. Optimizing your guest checkout will improve conversion rates, increase repeat business, and help convert guest shoppers into full accounts.

Pros and cons of a guest checkout 

Being able to check out as a guest allows users to have a fast, pleasant buying experience. The advantages for the customer are:

  • Quick checkout experience: The user can quickly complete their purchase in one go without needing to switch tabs or devices to verify emails.
  • No passwords: Since they do not have to create an account, this is one less password to remember.
  • Feels more anonymous: While the seller will need certain information to complete the transaction, a guest checkout can feel like it asks for less information compared to creating an account.
  • Fewer emails: With a guest checkout, you tend to just get the necessary emails confirming your purchase.

However, there are downsides to guest checkouts, too:

  • Repeat form filling: Returning customers need to enter the same information each time they check out.
  • Typing mistakes: Errors such as the wrong postcode or card number are more likely if the user needs to fill in forms every single time.
  • Security checks: Puzzle-based security checks like ReCAPTCHAv2 may be used to deter bots. These can cause significant friction and frustration for users, leading them to abandon the transaction.
  • Harder to track orders: Without an account, you will only have the original emails sent at the time of the transaction. There is no account where you can track past orders, request refunds, or download invoices.

Additionally, the anonymity and low friction of guest checkouts can make them attractive for fraudsters who use bots to attempt payments with stolen credit cards. So how can businesses ensure a smooth guest checkout without compromising on security? 

How to improve guest checkout abandonment rate

First, let’s go through the main ways you can improve the guest checkout experience and increase your conversion rates.

Minimize required form fields

Try to minimize the amount of required information the customer needs to provide. Each required field is friction. For a digital product or service, you can keep it minimal and ask only for an email address and payment details. 

If you need to ship the product, provide an address search while ensuring the customer can manually enter an address. This way, there is an escape hatch for customers whose addresses are not listed.

You should avoid asking for marketing information during the checkout process, such as “how did you hear about us” and demographic information. You could ask for that politely after the transaction is complete. By doing this, you have avoided friction that could cost a sale while still being able to collect the feedback from those who are keen to provide it.

Use browser autocomplete

Guest checkouts that require a lot of typing and thinking are a source of friction. This may seem unavoidable since there is essential information to gather for the purchase — and because the customer is anonymous, we have to ask for it all. 

However, when the browser fills those fields, it reduces the time and energy customers need to expend to buy from you; for example, they won’t need to get their wallet to pull out their credit card, then manually type in their card number. It also reduces the chances of an error being made, like the customer mistyping their card number.

To ensure autocomplete is offered to your customers, use the HTML autocomplete attributes in your checkout pages. The customer will automatically be asked by their browser which details they want autofilled, giving them control and security over the process. In the tutorial, we will use autocomplete attributes.

Support commonly used payment providers

In addition to the usual credit card payment options, offering alternative online payment options is a good idea. An example is PayPal, which 429 million people use globally. 

With PayPal’s checkout, you add a button to take the customer to PayPal’s site to complete their transaction, where their details will be filled from their PayPal preferences. 

Similarly, supporting Google Pay, Apple Pay, or Shop Pay will simplify guest checkout for your customers who use these services. On Apple Pay, for example, a mobile customer can just click the pay button and then verify with Touch ID, Face ID, or their passcode. On Shop Pay, customers can choose to have their details autofilled from their previous purchases after completing SMS verification.

Adding alternative payment methods will reduce abandonment, as almost 1 in 10 customers abandon shopping carts because of a lack of payment methods.

Save previously entered information without account creation

It may be possible to save information from the previous time the customer used the guest checkout. Here are a few ways to implement this:

  • Local token, server storage: The information is stored on the server, with a secret key stored on in the browser’s local storage, or a cookie. Like the local storage option, this also relies on the customer using the same browser.
  • Email verification: You could offer to retrieve details from their last order if they click a verification link in the same email they used before. This has the advantage of being available if another device is used.
  • Recognize the device: Device fingerprinting provides a unique identifier for every device that visits your site and can be used to detect if a customer is a returning one — even if they don’t have an account.

One advantage of all these methods is that they can store information that autofill won’t store, such as delivery instructions. 

Bear in mind that any storage of credit card information on the server would likely mean you need to comply with PCI-DSS, a data security standard enforced by the major credit card networks, including Visa and Mastercard.

Convert the guest shopper into an account holder

By the time the purchase is complete, the customer has given enough information to create an account. Consider offering to create an account with just a click. This can be done in a couple of ways:

  • Ask for a password: Provide a button to create an account that just asks for a password. Once that’s provided, send a confirmation email. 
  • Provide a magic link: Add a checkbox option for the customer to save their information for next time. When they need to access their account in the future, send them a link by email or SMS that logs them in without a password.

Offering to create an account after checkout doesn’t add friction to the payment process, plus it gives the customer a way to reduce the friction next time they shop, too.

Streamline the experience for return visitors

If you recognize a returning visitor, you can provide the guest user a streamlined experience by:

  • Selecting the correct country-specific version of the site
  • Deciding what to show based on previous browsing or purchasing
  • Offering the customer the option to log in using their previous email address at checkout
  • Eliminating “are you human” type checks in the process

Relying on IP addresses or cookies to identify returning visitors isn’t enough; for example,  users can easily delete cookies, and IP addresses are not unique and can be changed using VPNs. 

Using Fingerprint’s device intelligence to recognize return customers

In contrast, Fingerprint’s device intelligence provides a unique identifier for every device that visits your site and can be used to detect if a customer is a returning one — even if they don’t have an account. This visitor ID can persist for months or even years, even when cookies are deleted or VPNs or incognito mode is used.

With this identifier, you can recognize and engage with this returning customer to simplify their checkout process. You can store the visitor ID, along with the actions taken on your site, to provide personalized, faster experiences for return visitors.

For example, you can show a greeting such as  “Hello! It looks like you’ve ordered from us before,” and then offer them the option to create an account or offer to fill in their preferences during the guest checkout process.

Fingerprint also offers Smart Signals, which allows you to determine whether visitors are bots or exhibiting other suspicious behavior.

Tutorial: Optimize your guest checkout experience with Fingerprint

This tutorial focuses on detecting returning guest visitors with Fingerprint and filling out their details so they spend less time in the checkout process. We will also see how to reduce humanity checks, such as ReCAPTCHAv2 for trusted visitors.

The example app will be a single guest checkout page for a physical shipment. It will ask for your name, address, email, phone number, and card details. We will use Fingerprint’s device intelligence in conjunction with a database to store checkout information against the device that was used.

The code is written in JavaScript, running in Node.js. If you are using another platform, Fingerprint provides libraries for all the popular frameworks and languages, so you can still follow along.

Here is the code for a checkout form within the index.html page and the Node.js app to serve and process the form. Note that we use HTML autocomplete here to make the form quicker to fill for visitors who have their browser configured for it.

index.html

<form class="grid" method="post" action="/order">
  <div>
    <label for="name">Full Name</label>
    <input type="text" id="name" name="name" autocomplete="name" required />
    <label for="email">Email</label>
    <input type="email" id="email" name="email" autocomplete="email" required />
    <label for="address">Address</label>
    <input type="text" id="address" name="address" autocomplete="street-address" required />
    <label for="city">City</label>
    <input type="text" id="city" name="city" autocomplete="address-level2" required />
    <label for="state">State</label>
    <input type="text" id="state" name="state" autocomplete="address-level1" required />
    <label for="zip">Zip</label>
    <input type="text" id="zip" name="zip" autocomplete="postal-code" required />
    <label for="deliverypref">Delivery Preference</label>
    <select id="deliverypref" name="deliverypref">
      <option value="leave">Don't leave</option>
      <option value="front">Leave at front door</option>
      <option value="back">Leave at back door</option>
    </select>
    </div>
    <div>
    <label for="phone">Phone</label>
    <input type="tel" id="phone" name="phone" autocomplete="tel" required />
    <label for="paymethod">Payment Method</label>
    <select id="paymethod" name="paymethod">
      <option value="cc">Credit Card</option>
      <option value="paypal">Paypal</option>
      <option value="google">Google Pay</option>
    </select>      
    <label for="cardnumber">Card Number</label>
    <input type="number" id="cardnumber" name="cardnumber" autocomplete="cc-number" required />
    <label for="expmonth">Exp Month</label>
    <input type="number" id="expmonth" name="expmonth" autocomplete="cc-exp-month" required />
    <label for="expyear">Exp Year</label>
    <input type="number" id="expyear" name="expyear" autocomplete="cc-exp-year" required />
    <label for="cvc">CVC</label>
    <input type="number" id="cvc" name="cvc" autocomplete="cc-csc" required />
  
    <button type="submit">Order</button>
  </div>
</form>

app.js

const express = require('express');
const { Pool } = require('pg');


const app = express();
const port = 3000;


const pool = new Pool({
  user: 'guestcheckoutexample_user',
  host: 'localhost',
  database: 'guestcheckoutexample',
  password: 'guestcheckoutexample',
  port: 5432,
});


// Middleware to parse form data
app.use(express.urlencoded({ extended: true }));
app.use(express.json());


app.get('/success', (req, res) => {
  res.sendFile(__dirname + '/success.html');
});


app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});


app.post('/order', async (req, res) => {


  const { name, email, address, city, state, zip, phone, paymethod, deliverypref, cardnumber, expmonth, expyear, cvc } = req.body;


  try {
   const query = `
      INSERT INTO orders (name, email, address, city, state, zip, phone, paymethod, deliverypref, cardnumber, expmonth, expyear, cvc, visitorId)
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)`;
    await pool.query(query, [name, email, address, city, state, zip, phone, paymethod, deliverypref, cardnumber, expmonth, expyear, cvc, visitorId]);


    res.redirect('/success');


  } catch (err) {
    console.error(err);
    res.status(500).send('Error saving data');
  }


});


app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

We will now add the Fingerprint server-side library and use it to get the visitor ID so we can identify guest shoppers when they return.

To do this, first install the Fingerprint library.

npm install @fingerprintjs/fingerprintjs-pro-server-api

Now, sign up for a free trial and create a secret API key. Then, add the following code to the top of app.js, setting the apiKey value with your key. Change the region to match your workspace region:

app.js

const {
  FingerprintJsServerApiClient,
  Region,
} = require('@fingerprintjs/fingerprintjs-pro-server-api')

const client = new FingerprintJsServerApiClient({
  apiKey: '<<Private Api Key>>',
  region: Region.Global
})

Using the visitor ID from Fingerprint and store it in the database with the order:

// Use the request ID, which represents a specific user request to get the
  // Fingerprint event, that contains the device intelligence data:
  const event = await client.getEvent(req.body.requestId);


  // From the data, extract the visitor ID - a unique identifier for the device
  const visitorId = event.products.identification.data.visitorId;


  // Replace the DB query with these two lines to add the additional field:


    const query = `
      INSERT INTO orders (name, email, address, city, state, zip, phone, cardnumber, expmonth, expyear, cvc, visitorId)
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`;
    await pool.query(query, [name, email, address, city, state, zip, phone, cardnumber, expmonth, expyear, cvc, visitorId]);

The back end is now set up to receive the visitor identification details from the front end. Next, we’ll make the identification request on the front end to identify the visitor. Fingerprint will send back a request ID for this event and we will send the request ID to the back end when the form is submitted. To do this, add the following script to index.html, after the body:

<script>
    const fpPromise = import('https://fpjscdn.net/v3/<<Public Api Key>>')
      .then(FingerprintJS => FingerprintJS.load())


    const form = document.querySelector("form");
    form.addEventListener("submit", async (e) => {
      e.preventDefault();
      const fp = await fpPromise;
      const result = await fp.get();
      const requestId = result.requestId;
      const hiddenField = document.createElement("input");
      hiddenField.type = "hidden";
      hiddenField.name = "requestId";
      hiddenField.value = requestId;
      form.appendChild(hiddenField);
      form.submit();
    });


  </script>

Note: Replace <> with your public API key.

We now have a checkout that stores the visitor ID whenever a purchase is made. This is the groundwork for adding features to improve the experience. Let’s start with prefilling their order form.

In app.js, add an API endpoint to get that information for the previous order:

app.post('/prefill', async (req, res) => {
  
  const event = await client.getEvent(req.body.requestId);
  const visitorId = event.products.identification.data.visitorId;
  try {
    const query = 'SELECT * FROM orders WHERE visitorId = $1 ORDER BY id DESC LIMIT 1';
    const result = await pool.query(query, [visitorId]);
    if (result.rows.length > 0) {
      const { paymethod, deliverypref } = result.rows[0];
      res.send({ paymethod, deliverypref });
    } else {
      res.send({});
    }
  } catch (err) {
    console.error(err);
    res.status(500).send('Error getting data');
  }
});

Add this to index.html to populate some of the fields on the client side when previous order information is available:

 <script>
    // ...


    window.addEventListener("load", async () => {
      const fp = await fpPromise;
      const result = await fp.get();
      const requestId = result.requestId;
      
      const response = await fetch("/prefill", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ requestId }),
      });
      const data = await response.json();
      document.getElementById("paymethod").value = data.paymethod || "";
      document.getElementById("deliverypref").value = data.deliverypref || "";


    });


    // ...

Now, we have a guest checkout page that saves customers from typing out their information again if they have ordered from us before.

Skip bot checks for trusted customers

Fingerprint offers a wide range of signals that you can use to understand your visitor, including bot detection. Bot detection classifies the signal into “Good Bot” (e.g., the Google web crawler), “Bad Bot” (e.g., a tool used by people scraping data or spamming), or “No Bot Detected.”

The bot-detection result can be retrieved from the event data:

 const botDetection = event.products.botd.data.bot.result;

You can then use this value to replace ReCAPTCHAv2 or other humanity checks, for a smoother checkout experience. To do this, return a needsVerification value along in the existing API call if a bot is detected, otherwise continue:

if (result.rows.length > 0) {
      const { name, email, address, city, state, zip, phone } = result.rows[0];
      result = { name, email, address, city, state, zip, phone };
    } else {
      result = { };
    }


    if (botDetection != "notDetected") { 
      result.needsVerification = true;       
    }
    
    res.send(result);

Key takeaways

Optimizing guest checkouts helps reduce checkout abandonment and lost sales. There are many ways to make buying easy without requiring an account, such as using browser autofill features, and integrating payment providers like PayPal.

In addition, device intelligence enables you to recognize returning customers without an account and reduce the work they need to do to buy from you by prefilling forms and avoiding security checks for trusted visitors. Fingerprint provides a comprehensive suite of device intelligence tools to help achieve these goals.

Learn more about how Fingerprint works in our Getting Started Guide or contact our team to see how you can keep guest checkouts smooth and secure.

FAQ

What is a good checkout abandonment rate?

A good checkout abandonment rate is below 40%, based on industry benchmarks. Top-performing e-commerce sites manage to achieve rates around 20%, though completely eliminating abandonment is unrealistic due to natural shopping behaviors.

Why do people abandon their carts and the checkout process?

Visitors often abandon their carts when they encounter unexpected extra costs, forced to create an account, or the checkout process is complicated. Mobile users are particularly sensitive to lengthy forms and complex navigation during checkout.

How can I encourage guest shoppers to create accounts after completing a purchase?

Offer post-purchase incentives like a discount on their next order or highlight benefits such as order tracking and faster checkout for future purchases. Make the account creation process extremely simple by pre-filling information they've already provided during guest checkout.

Share this post