@speechkit/speechkit-audio-player
Version:
A web player component that can play audio from https://speechkit.io
246 lines (212 loc) • 6.8 kB
JavaScript
import MobileDetect from 'mobile-detect'
import { defaults } from 'lodash'
import uuidv4 from 'uuid/v4'
import EventTracker from '../SKSDK/EventTracker'
import { getCookieValue, setCookieValue } from '../utils/Cookie'
import MEDIA_TYPES from '../constants/mediaTypes'
class Analytics {
constructor({ options, podcast, media, mediaType, mediaAds, ads, player }) {
this.options = options
this.media = media
this.podcast = podcast
this.player = player
this.mediaType = mediaType
this.mediaAds = mediaAds
this.ads = ads
this.userId = this.getUserId()
this.deviceType = this.getDeviceType()
// So we can track one play and group it for progress stuff
this.listenSessionId = uuidv4()
this.percentPlayed = 0
if (!this.options.isDemo) {
this.eventTracker = new EventTracker({
skBackend: options.skBackend,
projectId: options.projectId,
publisherId: options.publisherId,
projectCampaignId: options.projectCampaignId,
mediaType: this.mediaType,
podcastId: this.podcast.id
})
}
}
getUserId() {
let userId = getCookieValue('userId')
if (!userId) {
userId = uuidv4()
setCookieValue('userId', userId)
}
return userId
}
getDeviceType() {
const md = new MobileDetect(window.navigator.userAgent)
if (md.phone()) {
return 'phone'
} else if (md.tablet()) {
return 'tablet'
} else {
return 'desktop'
}
}
getDefaultTrackOptions() {
return {
listen_session_id: this.listenSessionId,
media_id: this.mediaType === MEDIA_TYPES.PODCAST ? this.media.id : this.mediaAds.id,
referrer: document.referrer,
location: document.location.href,
user_id: this.userId,
device_type: this.deviceType
}
}
setMediaType(mediaType) {
if (!this.options.isDemo) {
this.mediaType = mediaType
this.eventTracker.setMediaType(this.mediaType)
}
}
startProgressTimer() {
// Track progress every 10 sec
this.intervalTimer = setInterval(this.trackProgress.bind(this), 10 * 1000)
}
// Ad Timer Code - so ad can be displayed for right time
startPercentTimer() {
const nSegment = this.player.getDuration() / 100 * 1000;
// may need remainingTime to double check progress.
// this.remainingTime = this.player.getDuration() - this.player.getCurrentTime();
if (this.percentPlayed <= 100){
this.percentPlayed += 1;
this.onProgress(this.percentPlayed);
this.progressTimer = setTimeout(this.startPercentTimer.bind(this), nSegment)
}
}
// track url using image beacon
addImageBeacon(sPath){
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => resolve('ok')
img.onerror = () => resolve('error')
img.src = sPath
})
}
// send tracking to google tag if present in page
sendGaEvent(eventName){
const sPreText = this.mediaType === MEDIA_TYPES.PREROLL ? 'Ad ' : '';
if(typeof gtag === 'function') {
const gaEventName = eventName === 'Load' ? eventName : (sPreText + eventName);
// console.log('event: ',gaEventName)
gtag('event', gaEventName, {
event_category: 'SpeechKit Player',
event_label: this.podcast.url
});
}
}
// take array for urls and fire each one
trackUrls(sEventName){
// exit here if we do not have any ads present
if(!this.mediaAds || !this.mediaAds.trackingUrls) return;
// now get the array of tracking URLs and fire them off
const oTracking = this.mediaAds.trackingUrls;
const aUrls = oTracking[sEventName];
if(aUrls) {
for(let i = aUrls.length -1; i >= 0; i--){
const sTrackingUrl = aUrls[i].trim()
aUrls.splice(i, 1);
this.addImageBeacon(sTrackingUrl)
}
}
}
// using the percent timer, track each of the events at the
// correct time whilst content plays, including quartiles
onProgress(nPercent){
switch (nPercent) {
case 1:
this.trackUrls('impression');
this.trackUrls('start');
break;
case 25:
this.trackUrls('firstQuartile');
this.sendGaEvent('25% Listened');
break;
case 50:
this.trackUrls('midpoint');
this.sendGaEvent('50% Listened');
break;
case 75:
this.trackUrls('thirdQuartile');
this.sendGaEvent('75% Listened');
break;
default:
break;
}
}
stopTimer() {
clearInterval(this.intervalTimer)
clearInterval(this.progressTimer)
}
trackEvent(event, params) {
if (!this.options.isDemo) {
params = defaults(params, { event_type: event }, this.getDefaultTrackOptions())
if (this.mediaAds) {
params = {
...params,
duration: this.mediaAds.duration,
campaign_id: this.ads.campaign_id
}
}
this.eventTracker.trackEvent(params)
}
}
trackDidLoad(params = {}) {
this.trackEvent('load', params)
// Google Analytics - record audio load event (but only first call)
if(params.media_type) {
this.sendGaEvent('Load')
}
}
trackDidPlay() {
this.startProgressTimer()
this.trackEvent('play')
// start percent timer to trigger quartile events for ads and Google Analytics
this.startPercentTimer()
// Google Analytics - send click event if currentTime=0 (first-play)
const currentTime = this.player.getCurrentTime()
if(currentTime < 0.1) {
this.sendGaEvent('Play')
}
}
trackProgress() {
this.trackEvent('progress', {
listen_length_seconds: this.player.getCurrentTime(),
listen_length_percent: this.player.getCurrentPercentage()
})
}
trackDidResume() {
this.trackEvent('resume')
}
trackDidPause(listenLengthSeconds, listenLengthPercent) {
this.stopTimer()
this.trackEvent('pause', {
ui_location: 'button',
listen_length_seconds: listenLengthSeconds,
listen_length_percent: listenLengthPercent
})
}
trackDidListenToEnd() {
this.stopTimer()
this.trackEvent('listenToEnd')
this.sendGaEvent('Complete')
this.trackUrls('complete');
this.percentPlayed = 0;
}
trackDidChangeSpeed(speed) {
this.trackEvent('speed', { speed })
}
trackAdLogoClick() {
this.trackEvent('ad_logo_click')
this.sendGaEvent('Ad Logo Click')
}
trackAdLinkClick() {
this.trackEvent('ad_link_click')
this.sendGaEvent('Ad Link Click')
}
}
export default Analytics