snowplow-javascript-tracker icon indicating copy to clipboard operation
snowplow-javascript-tracker copied to clipboard

Investigate localStorage in multiple tabs

Open fblundun opened this issue 9 years ago • 11 comments

localStorage is shared between tabs, but the localStorage lock is restricted to a single tab. Can trackers operating in different tabs send duplicate events?

Possible solution: save the lock in localStorage.

fblundun avatar Mar 20 '15 16:03 fblundun

Good thing to explore...

alexanderdean avatar Mar 20 '15 16:03 alexanderdean

The biggest problem with putting a lock in localStorage is that the page could unload before it has a chance to release the lock. The lock will still be there if the user returns to the page and it will prevent events from being sent.

fblundun avatar Mar 20 '15 17:03 fblundun

Hmm good point... I wonder if there is a way of identifying a tab uniquely which would be safer...

alexanderdean avatar Mar 20 '15 17:03 alexanderdean

We might be able to do something like this:

http://balpha.de/2012/03/javascript-concurrency-and-locking-the-html5-localstorage/

Every time we acquire the localStorage lock, we set its value to the current time.

If we want to acquire the lock but it already exists, we check whether it is more than 10 seconds old.

If it is, then we conclude that the last tracker was unloaded before it was able to release the lock, and we acquire the lock.

fblundun avatar Mar 20 '15 17:03 fblundun

Cool putting a TTL on the lock sounds like a good approach

alexanderdean avatar Mar 20 '15 18:03 alexanderdean

I can make this bug appear if I change the tracker by wrapping the code which empties localStorage in a setTimeout of about 20ms.

fblundun avatar Mar 23 '15 10:03 fblundun

This approach should prevent almost all duplicate events when multiple tabs are open simultaneously. But it could lead to lost events. Suppose a user opens an inbound link in a new tab, triggering a link click event in the current tab. If the link click isn't sent fast enough, the second tab won't be able to access localStorage, and will hold the page view event in memory. If the user leaves the second tab before triggering a second event there, the page view event will never make it to localStorage or the collector.

fblundun avatar Mar 23 '15 14:03 fblundun

Another possible approach would be to treat tabs asymetrically. For example, say that only the first tab opened gets to use localStorage.

fblundun avatar Mar 23 '15 14:03 fblundun

just passing through, but there's also sessionStorage which is per tab. might be helpful?

cmawhorter avatar Mar 26 '15 20:03 cmawhorter

I thought about using sessionStorage, but the problem is that it gets cleared when the page session ends. The only reason the tracker uses localStorage is so that if events fail to send and the user leaves the page, the events will still exist when they return.

fblundun avatar Mar 27 '15 09:03 fblundun

IndexedDB provides better concurrency primitives than localStorage. It isn't yet fully supported across all major browsers, but is worth investigating...

fblundun avatar Dec 16 '15 12:12 fblundun