Documentation Index
Fetch the complete documentation index at: https://docs.fingerprint.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This tutorial walks through implementing Fingerprint to personalize the experience for anonymous visitors, without requiring them to create an account or log in. You’ll begin with a starter app that includes a mock vacation rental site with a list of properties and basic filtering. From there, you’ll add the JavaScript agent to identify each visitor and use server-side logic with Fingerprint data to show rentals closest to the visitor’s location on their first visit, and restore their viewing history and saved filters when they return. By the end, you’ll have a sample app that delivers a tailored experience to every visitor from the moment they land, and remembers their preferences across sessions. This tutorial uses just plain JavaScript and a Node server with SQLite on the backend. For language- or framework-specific setups, see the quickstarts.Estimated time: < 15 minutes
Using Fingerprint for personalization may require visitor consent depending on your local
regulations, similar to the requirements around cookies. The incognito mode behavior demonstrated
in this tutorial is intended to make it easy to simulate a returning visitor during development.
We do not recommend using Fingerprint to persist personalization specifically in incognito mode in
production because it conflicts with the users’ expectations and may lead to a bad experience.
Prerequisites
Before you begin, make sure you have the following:- A copy of the starter repository (clone with Git or download as a ZIP)
- Node.js (v20 or later) and npm installed
- Your favorite code editor
- Basic knowledge of JavaScript
1. Create a Fingerprint account and get your API keys
- Sign up for a free Fingerprint trial, or log in if you already have an account.
- After signing in, go to the API keys page in the dashboard.
- Save your public API key, which you’ll use to initialize the JavaScript agent.
- Create and securely store a secret API key for your server. Never expose it on the client side. You’ll use this key on the backend to retrieve full visitor information through the Fingerprint Server API.
2. Set up your project
- Clone or download the starter repository and open it in your editor:
Terminal
- This tutorial will be using the
personalizationfolder. The project is organized as follows:
public
index.html - Vacation rental browsing page
index.js - Frontend logic for rental listings and filters
server
server.js - Serves static files and rental listing endpoint
db.js - SQLite database connection
rentals.js - Rental listing and personalization logic
data
rentals.json - Mock rental listing data with coordinates
.env.example - Example environment variables
- Install dependencies:
Terminal
- Copy or rename
.env.exampleto.env, then add your Fingerprint API keys:
Terminal
- Start the server:
Terminal
- Visit http://localhost:3000 to view the mock vacation rental site from the starter app. You’ll see a “Hot Rentals” section showing three randomly selected properties, followed by the full listing grid with filters for property type, guests, bedrooms, amenities, and price. Click any card to open a detail view with the full description and amenity list. Try adjusting the filters, then open the page in a new tab and you’ll see that your selections are gone. By default, the hot rentals are random and the app has no memory of previous visits.
3. Add Fingerprint to the frontend
In this step, you’ll load the JavaScript agent when the page loads and trigger identification when fetching rental listings. The JavaScript agent returns both avisitor_id and an event_id. You’ll send the event_id to your server along with the request for rentals. The server will then call the Fingerprint Events API to securely retrieve the full identification details, including geolocation data.
- At the top of
public/index.js, load the JavaScript agent:
public/index.js
-
Make sure to change
regionto match your workspace region (e.g.,eufor Europe,apfor Asia,usfor Global (default)). -
In
public/index.js, the page already callsinit()on startup to fetch and render listings. AddvisitorIdto the state variables at the top of the file so it can be reused for saving preferences later:
public/index.js
- Inside
init(), request visitor identification from Fingerprint using theget()method. Store the visitor ID for later use and include the event ID when fetching rentals so the server can find rentals closest to the visitor’s location:
public/index.js
get() method sends signals collected from the browser to Fingerprint servers, where they are analyzed to identify the visitor. The returned event_id acts as a reference to this specific identification event, which your server can later use to fetch the full visitor details, including geolocation data.
This personalization use case demo is using the
visitor_id from fp.get() directly. For fraud
or security-sensitive use cases, never trust the visitor_id from the client, always retrieve it
server-side using getEvent() so it can’t be tampered with.get() method.
4. Sort rentals by proximity
Next, pass theeventId through to your rental listing logic, initialize the Fingerprint Node Server SDK, and fetch the full visitor identification event. You’ll use the visitor’s geolocation data to sort listings so that before they’ve interacted with anything, the listings are already arranged to be nearest to them.
- In the backend, the
server/server.jsfile defines the API routes for the app. Update the/api/rentalsroute to accept a POST request, extracteventIdfrom the request body, and pass it into thegetRentalsfunction:
server/server.js
- The
server/rentals.jsfile contains the logic for fetching and personalizing rental listings. Start by importing and initializing the Fingerprint Node Server SDK there, and load your environment variables withdotenv:
server/rentals.js
-
Make sure to change
regionto match your workspace region (e.g.,EUfor Europe,APfor Asia,Globalfor Global (default)). -
Update the
getRentalsfunction to callgetEvent(), extract the visitor’s coordinates, and sort the listings by distance. Every rental inrentals.jsonincludes alatandlngfor its city and you can sort by squared Euclidean distance:
server/rentals.js
eventId, the getEvent method retrieves the full data for the visitor identification event, including geolocation, device and browser details, and Smart Signals like bot detection, VPN detection, and more. You can see a full example of the event structure in the demo playground.
Now every visitor sees listings sorted with the closest cities at the top. Visitors in London will see London and European properties first; visitors in San Francisco will see West Coast rentals at the top.
For checks to ensure the validity of the data coming from your frontend, view how to protect from client-side tampering and replay attacks.
5. Persist visitor filters across sessions
Next, use thevisitorId from fp.get() to remember each visitor’s filter choices. When they return their filters will be restored automatically.
Unlike fraud prevention use cases where every request should be verified server-side via getEvent(), personalization carries much lower risk. Since you already receive the visitor ID in the frontend, you can send it directly with preference saves rather than making a new getEvent() call each time. This keeps things simple and avoids unnecessary API calls.
The starter app includes a SQLite database with the following table already created for you:
SQLite database table
- Add helper functions to
server/rentals.jsto read and write filter preferences:
server/rentals.js
- Update
getRentalsto return saved filters alongside the listings:
server/rentals.js
- Add a
saveFiltersexport to handle filter updates from the frontend:
server/rentals.js
- Add the corresponding route to
server/server.js:
server/server.js
- Back in
public/index.js, add anapplyFiltersfunction that restores saved filter state and syncs the UI, asaveFiltersfunction that posts the current state, and adebouncedSavewrapper so rapid filter changes are batched into a single request. AddsaveTimerto the state variables at the top of the file:
public/index.js
public/index.js
- In
init(), callapplyFiltersif saved filters are returned:
public/index.js
- Call
debouncedSave()afterrender()in the filter pill click handler and the price slider handler:
public/index.js
6. Show recently viewed rentals
When a visitor clicks to view a rental’s details, save the rental ID. On their next visit, the “Hot Rentals” section will show those properties instead of a random selection.- Add a
getRecentlyViewedForhelper and anaddRecentlyViewedexport toserver/rentals.js:
server/rentals.js
- Update
getRentalsto use recently viewed IDs for thehotRentalsresponse, falling back to the 3 random rentals if the visitor hasn’t viewed anything yet:
server/rentals.js
- Add the
/api/viewedroute toserver/server.js:
server/server.js
- In
public/index.js, add asaveViewedfunction and call it fromopenModal:
public/index.js
public/index.js
This is a minimal example to show how to implement Fingerprint. In a real application, make sure
to implement proper security practices, error checking, and data handling that align with your
production standards and local regulations.
7. Test your implementation
Now that everything is wired up, you can test the full personalized experience.- Start your server if it isn’t already running and open http://localhost:3000:
Terminal
- Notice that the listings are already sorted with cities closest to your location at the top with no interaction required.
- Apply some filters and click a few rental cards to view their details.
- Open the page in a private or incognito browser window. Your filters will be restored, the listings will again be sorted by proximity, and the Hot Rentals section will show the properties you just viewed.