Track Live Website Visitors Without Subscriptions
A client wanted to see who was on their website in real time.
They liked the Tidio widget but did not want to pay for a subscription.
The challenge had two parts:
- The site used WordPress on different hosting.
- I could not add Firebase directly to the WordPress setup.
I built an external tracker using Firebase. Here is how it works.
The Solution
I used a single script tag in the WordPress header. This script connects to an independent Firebase project.
• Live Presence: I used Firebase Realtime Database with the onDisconnect() function. This automatically removes a user from the "online" list when they close their tab or lose connection. • Visitor History: I used a Netlify Function to write data to Firestore. This allows for server-side IP geolocation. • Security: I used anonymous authentication. Visitors can only write to their own session node. Only the admin can read the full list.
The Tricky Bugs
Building this was not smooth. I ran into three major technical hurdles.
- The Caching Trap The history showed zero sessions. I found out the tracker script had a one-year cache policy. Visitors were stuck using an old version of the script.
- Fix: I set a five-minute cache policy for the tracker script.
- The Fake CORS Error The browser reported a CORS error. I thought I had a domain whitelist issue. A simple curl test showed the server worked fine. The truth was different. The server was actually crashing. In Node.js, if you use a 204 status code, you cannot use an empty string as a body. You must use null. The empty string caused a crash before the CORS headers could be sent. The browser saw no headers and assumed it was a CORS problem.
- Fix: Changed the response body from '' to null.
- The Missing Data Gap Filters for "Today" or "Last 7 Days" returned nothing. Some users showed "Unknown" locations. This happened because I only calculated the timestamp and location on the very first page load. If a user had an old session in their browser, the server missed the "start" event.
- Fix: I made the calculation idempotent. Now the script recomputes these values on every event.
Key Takeaways
• A CORS error in the browser is not always a configuration issue. It can hide a server crash. Always check your server logs. • A curl POST test does not test a browser. Browsers send an OPTIONS preflight request first. Your test must include this to be valid. • Use null for "no content" HTTP statuses like 204. Do not use empty strings.
