⚠️ Only the technical part is explained. If you care about legality, you're on your own. At the time of writing, this method works in Firefox and Chrome.

Browser Tracking with Fingerprints

Tracking users is a touchy topic. Should you rely on screen size? Favicon loading hacks (like this one)? Or something more exotic?

Honestly, it depends. What level of accuracy do you need? How much time are you willing to sink into it? There's a sea of FOSS libraries and SaaS platforms out there, but sometimes you don’t want the whole enterprise-grade circus—just a quick way to know if "User A" today is the same "User A" from last week. Ideally, it should also be low-maintenance and not break every time a browser sneezes.

So here's a dead-simple way to track users using browser fingerprinting. It’s not perfect, but it’s light, easy to implement, and does the job for a lot of use cases.

We're using Broprint.js — a tiny browser fingerprinting library that gives you a unique(ish) identifier based on a bunch of properties like canvas fingerprinting, user agent, timezone, etc.

🖥️ Client Side

Add this snippet to your frontend to grab a fingerprint and send it off somewhere. We’re using a CORS proxy and a GET request for simplicity—mostly because browsers these days don't like cross-origin POSTs.

const { getCurrentBrowserFingerPrint } = require('@rajesh896/broprint.js');


async function sendFingerprintToServer() {
    try {
        const fingerprint = await getCurrentBrowserFingerPrint();
        const userAgent = window.navigator.userAgent;
        const proxyUrl = 'https://corsproxy.io/?';
        const apiUrl = 'https://script.google.com/macros/s/CHANGE_ME/exec';

        const encodedUrl = encodeURIComponent(`${apiUrl}?id=${fingerprint}&userAgent=${userAgent}`);
        const fullUrl = `${proxyUrl}${encodedUrl}`;

        const xhr = new XMLHttpRequest();
        xhr.open('GET', fullUrl, true);
        xhr.send(null);
    } catch (error) {
        console.error('Error sending fingerprint to server:', error);
    }
}

You could expand this to send fingerprints on every click, scroll, or form submit if you're feeling fancy. Right now, we’re just capturing the browser fingerprint and user agent. If you start adding resolution, timezone, device memory, etc., you'll get better accuracy—especially if you later combine this with some ML to group behavior.

🗃️ Server Side (Google Sheets)

Google Sheets — the poor man’s database that actually works. Here’s how to catch that fingerprint data and dump it into a spreadsheet using Google Apps Script:

var ssID = 'CHANGE_ME';
var sheetLog = 'Log';

function doGet(e) {
  try {
    // Append the data to the spreadsheet
    SpreadsheetApp.openById(ssID).getSheetByName(sheetLog).appendRow([new Date(), e.parameter.id, e.parameter.userAgent]);
    // Return a simple response
    return ContentService.createTextOutput("Success");
  } catch (err) {
    // Log error details to the spreadsheet
    SpreadsheetApp.openById(ssID).getSheetByName(sheetLog).appendRow([new Date(), err.stack || 'No stack', err.message || 'No message']);
    // Return an error response
    return ContentService.createTextOutput("Error");
  }
}

When a browser visits your site, you’ll log the timestamp, fingerprint ID, and user agent. If something goes wrong, the error gets logged too. Good enough for debugging.

📈 Basic Analysis

Later we can analyze logs on all different way, one simple analysis can be number of visits per month.
For that we create another sheet and use following formula to map timestamps from Log sheet into here with only month and year.

=IF(Log!A1<>"";TEXT(Log!A1; "MM/YYYY"))

Visits per month

🤔 Final Thoughts

This isn’t foolproof tracking. If someone switches browsers, disables JavaScript, or uses a hardened privacy setup (Brave), they’ll slip through. But for casual, low-friction tracking, it’s surprisingly effective—and you can set it up in under an hour without deploying a single server.