UNPKG

gaf-mobile

Version:

GAF mobile Web site

133 lines (117 loc) 4.07 kB
/** * This script will be imported in our service worker which would add a `fetch` * event handler for intercepting tracking-related requests. For the tracking * libraries (GTM, QTS, TTREF), the handler will observe the network-first * strategy, falling back to the previously cached copy. For QTS tracking * requests, this should handle network failures such as being offline. * Failed requests are stored in IndexedDB. Every time the service worker * starts up, this would try to replay the failed requests. */ // TODO: Implement some kind of garbage collection for failed requests stored // in IndexedDB /* global self */ 'use strict'; var IDB = { NAME: 'offline-qts', STORE: 'requests', VERSION: 1 }; var CACHE_NAME = 'offline-tracking-gaf-mobile'; var QTS_HOSTNAME = 't.freelancer.com'; var QTS_LIB_HOSTNAME = 'd2werhn82xczly.cloudfront.net'; var QTS_LIB_PATHNAME = '/20140328/main.min.js'; var GTM_HOSTNAME = 'www.googletagmanager.com'; var GTM_PATHNAME = '/gtm.js'; var TTREF_PATHNAME = '/build/js/ttref.js'; var idb = (self.IDBHelper)(IDB.NAME, IDB.VERSION, function(db) { // upgrade callback return db.createObjectStore(IDB.STORE); }); /** * Upserts the failed tracking requests to IndexedDB. We will do the following * manipulations to the QTS request: * 1. Push back the original event name to `real_event_name` param * 2. Change event name to `mobile_offline_event` * 3. Add a `real_timestamp` param */ var enqueueOfflineQts = function(url) { var now = Math.round(Date.now() / 1000); var newUrl = url; var search = newUrl.search; var searchMap = {}; if (search.charAt(0) === '?') { search = search.slice(1); } // TODO: Use URLSearchParams when widely supported (Chrome 49+ and FF 29+) var pairs = (search || '').split('&'); pairs.forEach(function(pair) { var index = pair.indexOf('='); if (index > -1) { var key = pair.slice(0, index); var value = decodeURIComponent(pair.slice(index + 1)); searchMap[key] = value; } }); searchMap.real_event_name = searchMap.en; searchMap.en = 'mobile_offline_event'; searchMap.real_timestamp = now.toString(); var newPairs = [], key, value; for (key in searchMap) { value = encodeURIComponent(searchMap[key]); newPairs.push(key + '=' + value); } newUrl.search = ('?' + newPairs.join('&')); return idb.put(IDB.STORE, newUrl.toString(), now); }; /** * Resends requests stored in IndexedDB. If the request was successfully sent, * the entry is deleted from the store. */ var resendOfflineQts = function() { if (self.fetch) { return idb.getAllKeys(IDB.STORE).then(function(urls) { return Promise.all(urls.map(function(url) { return self.fetch(url, { method: 'GET', mode: 'no-cors' }) .then(function() { return idb.delete(IDB.STORE, url); }); })); }); } }; /** * Handles requests to either the tracking libraries or QTS requests. */ self.addEventListener('fetch', function(event) { if (!self.fetch || !self.caches) { // Fetch or Cache API is not supported return; } var request = event.request; var url = new URL(request.url); if (request.method === 'GET') { if (url.hostname === QTS_HOSTNAME) { event.respondWith( self.fetch(request).catch(function() { enqueueOfflineQts(url); }) ); } else if ((url.pathname === TTREF_PATHNAME) || (url.hostname === GTM_HOSTNAME && url.pathname === GTM_PATHNAME) || (url.hostname === QTS_LIB_HOSTNAME && url.pathname === QTS_LIB_PATHNAME) ) { event.respondWith( self.caches.open(CACHE_NAME).then(function(cache) { return self.fetch(request).then(function(response) { return cache.put(request, response.clone()).then(function() { return response; }); }).catch(function() { return cache.match(request); }); }) ); } } }); // Resend locally stored offline QTS requests every time SW starts up resendOfflineQts();