Last active
December 27, 2015 09:19
-
-
Save th507/7302586 to your computer and use it in GitHub Desktop.
logging offline visits across sessions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# logging offline visits across sessions | |
# for in-house tracking and Google Analytics | |
# See my blog for more information (Chinese) | |
# http://ljw.me/2013/07/24/logging-offline-visits.html | |
# | |
# Usage: | |
# | |
# var tracker = new FTCTracker(beaconURLPrefix) | |
# tracker.push(url) | |
# | |
# A nice side-effect is that you could use | |
# `tracker.isAccessible()` to get the latest network status. | |
# This is more reliable than `navigator.onLine` | |
class FTCTracker | |
# just declare within ftcTracker scope | |
# array of untracked page visits | |
log = [] | |
# beacon image url prefix | |
prefix = "" | |
# is it in the process of sending report? | |
isBusy = false | |
# ballpark network status for a start | |
accessible = navigator.onLine | |
save = (key, value) -> | |
try | |
localStorage.setItem key, value | |
load = (key) -> | |
try | |
return localStorage.getItem key | |
catch e | |
return null | |
setAccessible = (_bool) -> | |
accessible = _bool | |
offlinePageView = "offlinePageView" | |
getOfflinePageView = -> load offlinePageView | |
saveOfflinePageView = -> | |
# reduce the number of localStorage writes | |
saved = getOfflinePageView() | |
unsaved = JSON.stringify log | |
# only save log when we change something | |
if unsaved isnt saved | |
save offlinePageView, unsaved | |
# part of a simple implementation of Deferred | |
isBusy = false | |
getTrackerURL = (url) -> | |
prefix + | |
'&url=' + encodeURIComponent(url) + | |
'&rnd=' + Math.random().toFixed(5) | |
sendToGA = (url) -> q.push(['_trackPageview', url]) if q = window._gaq | |
resolve = -> | |
return unless log | |
return unless log.length | |
return if isBusy | |
isBusy = true | |
url = log[0] | |
# strip invalid entries | |
while !url or url is "undefined" or url is "null" | |
log.shift() | |
url = log[0] | |
tracker = new Image() | |
tracker.onload = -> | |
setAccessible true | |
sendToGA url | |
log.shift() | |
saveOfflinePageView() # this also set isBusy to false | |
if log.length | |
resolve() | |
tracker.onerror = -> | |
setAccessible false | |
saveOfflinePageView() | |
tracker.src = getTrackerURL url | |
constructor: (beaconURLPrefix) -> | |
prefix = beaconURLPrefix | |
log = [].concat(JSON.parse(getOfflinePageView())) | |
# helper method, returns network status | |
isAccessible: -> accessible | |
# when user is in private/incognito mode, | |
# valueOf and toString yields different result | |
# toString would return null when localStorage is inaccessible | |
valueOf: -> log | |
toString: -> getOfflinePageView() | |
# sending page visit | |
push: (url) -> | |
return if !url | |
log.push url | |
resolve() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment