Created
September 23, 2017 22:52
-
-
Save adamrneary/6e6d802de2f7f78e6be186b5ada14c91 to your computer and use it in GitHub Desktop.
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
import Tracking from 'airbnb-tracking'; | |
import { PerformanceAirbnbWebInteractiveEvent } from 'airbnb-jitney-schemas/logging_performance_airbnb_web_interactive_v1'; | |
import { UniversalPageImpressionEvent } from 'airbnb-jitney-schemas/logging_universal_page_impression_v1'; | |
import { PageRequestMethodType } from 'airbnb-jitney-schemas/logging_type_page_request_method_type_v1'; | |
import windowPerformance, { performanceNowFromEpoch } from '../../utils/windowPerformance'; | |
export const VALIDATED_AIRBNB_INTERACTIVE = 'validated-airbnb-interactive'; | |
export const NEVER_INTERACTIVE = 'never-interactive'; | |
function hasActiveServiceWorker() { | |
if (!('serviceWorker' in navigator)) return Promise.resolve(false); | |
if (!navigator.serviceWorker.getRegistration) return Promise.resolve(false); | |
return navigator.serviceWorker.getRegistration('/').then((registration) => { | |
if (registration) { | |
return true; | |
} | |
return false; | |
}); | |
} | |
function prepareWindowPerformanceForWebPerformance({ | |
navigationStart, | |
unloadEventStart, | |
unloadEventEnd, | |
redirectStart, | |
redirectEnd, | |
fetchStart, | |
domainLookupStart, | |
domainLookupEnd, | |
connectStart, | |
connectEnd, | |
secureConnectionStart, | |
requestStart, | |
responseStart, | |
responseEnd, | |
domLoading, | |
domInteractive, | |
domContentLoadedEventStart, | |
domContentLoadedEventEnd, | |
domComplete, | |
loadEventStart, | |
loadEventEnd, | |
}) { | |
return { | |
navigation_start_timestamp_in_ms: navigationStart, | |
time_to_unload_event_start_in_ms: unloadEventStart, | |
time_to_unload_event_end_in_ms: unloadEventEnd, | |
time_to_redirect_start_in_ms: redirectStart, | |
time_to_redirect_end_in_ms: redirectEnd, | |
time_to_fetch_start_in_ms: fetchStart, | |
time_to_domain_lookup_start_in_ms: domainLookupStart, | |
time_to_domain_lookup_end_in_ms: domainLookupEnd, | |
time_to_connect_start_in_ms: connectStart, | |
time_to_connect_end_in_ms: connectEnd, | |
time_to_secure_connection_start_in_ms: secureConnectionStart, | |
time_to_request_start_in_ms: requestStart, | |
time_to_response_start_in_ms: responseStart, | |
time_to_response_end_in_ms: responseEnd, | |
time_to_dom_loading_in_ms: domLoading, | |
time_to_dom_interactive_in_ms: domInteractive, | |
time_to_dom_content_loaded_event_start_in_ms: domContentLoadedEventStart, | |
time_to_dom_content_loaded_event_end_in_ms: domContentLoadedEventEnd, | |
time_to_dom_complete_in_ms: domComplete, | |
time_to_load_event_start_in_ms: loadEventStart, | |
time_to_load_event_end_in_ms: loadEventEnd, | |
}; | |
} | |
class AirbnbInteractiveLogger { | |
constructor() { | |
this.pageTransitionStart = undefined; | |
} | |
getPageRequestMethod() { | |
return hasActiveServiceWorker().then((serviceWorker) => { | |
let pageRequestMethod; | |
if (this.pageTransitionStart) { | |
pageRequestMethod = PageRequestMethodType.ClientRouteRequest; | |
} else if (serviceWorker) { | |
pageRequestMethod = PageRequestMethodType.ServiceWorkerFulfilledRequest; | |
} else { | |
pageRequestMethod = PageRequestMethodType.DirectRequest; | |
} | |
return pageRequestMethod; | |
}); | |
} | |
logImpression({ universalPageName, extraEventData }) { | |
if (typeof window !== 'undefined') { | |
this.getPageRequestMethod().then((pageRequestMethod) => { | |
const jitneyData = { | |
schema: UniversalPageImpressionEvent, | |
event_data: { | |
page_name: universalPageName, | |
referrer: document.referrer || 'unknown', | |
page_request_method: pageRequestMethod, | |
eventData: extraEventData, | |
}, | |
}; | |
Tracking.logJitneyEvent(jitneyData); | |
}); | |
} | |
} | |
logAirbnbInteractive({ methodology, extraEventData = {}, universalPageName }) { | |
const performance = global.window && windowPerformance(); | |
if (!performance || !performance.timing) { | |
return; | |
} | |
const endTime = performanceNowFromEpoch(); | |
let totalTime; | |
if (this.pageTransitionStart) { | |
totalTime = endTime - this.pageTransitionStart.startTime; | |
} else { | |
totalTime = endTime - performance.timing.requestStart; | |
} | |
performance.measure('Time to AirbnbInteractive'); | |
this.logTime({ methodology, tti: totalTime, extraEventData, universalPageName }); | |
} | |
logTime({ methodology, tti, extraEventData = {}, universalPageName }) { | |
const performance = global.window && windowPerformance(); | |
const path = global.location.pathname; | |
const domain = global.location.host; | |
const timing = prepareWindowPerformanceForWebPerformance(performance.timing || {}); | |
this.getPageRequestMethod().then((pageRequestMethod) => { | |
const information = { | |
methodology, | |
...extraEventData, | |
}; | |
Tracking.logJitneyEvent({ | |
schema: PerformanceAirbnbWebInteractiveEvent, | |
event_data: { | |
information, | |
domain_and_path: `${domain}${path}`, | |
page_request_method: pageRequestMethod, | |
time_to_airbnb_interactive_in_ms: tti, | |
web_performance_timing: timing, | |
universal_page_name: universalPageName, | |
}, | |
}); | |
}); | |
} | |
logStartPageTransition({ universalPageName, extraEventData }) { | |
if (!global.window) { | |
return; | |
} | |
this.pageTransitionStart = { | |
valid: true, | |
initialRoute: universalPageName, | |
extraEventData, | |
startTime: performanceNowFromEpoch(), | |
}; | |
} | |
} | |
export default new AirbnbInteractiveLogger(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment