var customIma = function() { this.adsManager; this.adsLoader; this.adDisplayContainer; this.videoContent; this.videoInfo; this.nvIma; } /* @description - this method initializes the videoContent object to be used by the ad handler. It further calls the IMA setup handler method. */ customIma.prototype.init = function() { if(appConfig.disableAds == true) return false; this.resetIma(); if(typeof this.adsLoader == 'undefined' || this.adsLoader == null) { logger.printLog('adlog', 'customIma.init setting up adsLoader now', ''); this.videoContent = document.getElementById('videoHls'); this.setUpIMA(); this.nvIma = new nonVmapIma(); return true; } } /* @description - this method initializes the container for displaying ads and sets up required event listeners. For eg, ad loaded, ad error etc. */ customIma.prototype.setUpIMA = function() { // Create the ad display container. this.createAdDisplayContainer(); // Create ads loader. this.adsLoader = new google.ima.AdsLoader(this.adDisplayContainer); // Listen and respond to ads loaded and error events. this.adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, this.onAdsManagerLoaded, false); this.adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, this.onAdError, false); } customIma.prototype.resetIma = function() { if(this.adsManager) { this.adsManager.destroy(); this.adsManager = null; } } /* @description - this method creates a new object for Google IMA Ad Request class, and makes a call to fetch ads using the global variable adObj.adUrl only. Other settings can be configured using the adsRequest object properties. */ customIma.prototype.requestAds = function(videoInfo, adType = 'all') { logger.printLog('data', 'requestAds called - videoInfo, appConfig.useVmap, adType', [videoInfo, appConfig.useVmap, adType]); // this.resetIma(); // normal if(appConfig.useVmap == false) { if(appState.player.pausedTime == 0) { adType = 'preroll'; } else { adType = 'midroll'; } adPlayObj.nvIma.initRequestAds(videoInfo, adType); } else { //vmap case, process further and then send request to IMA this.createVmapJs(videoInfo); } } customIma.prototype.cancelAdsRequest = function() { appState.ads.preRollRequestMade = false; } /* @description - this method initializes the add playback. We set the ad player height and width after container is initialized. As ads are played in a separate player, other than the main video player. We need to set its view mode settings. If the adsManager fails, it will resume playback @param - none @returnValue - none */ customIma.prototype.playAds = function() { // Initialize the container. Must be done via a user action on mobile devices. this.adDisplayContainer.initialize(); try { // Initialize the ads manager. Ad rules playlist will start at this time. this.adsManager.init(appUIConfig.winW, appUIConfig.winH, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. this.adsManager.start(); logger.printLog('adlog', 'playAds() starting ad playback'); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. logger.printLog('error', 'playAds() received an ad error: ', adError); // if(appState.playlistPlayMode == false) { // customIma.onContentResumeRequested(); // } } } /* @description - this method creates simply creates a new ad display container based on the element id we pass. In our case its "adContainer". */ customIma.prototype.createAdDisplayContainer = function() { // We assume the adContainer is the DOM id of the element that will house the ads. this.adDisplayContainer = new google.ima.AdDisplayContainer(document.getElementById('adContainer'), this.videoContent); } /* @description - Its a listener method, this method handles what should be done after the adsManager is loaded. We can set rendering settings, preloading etc. from here. Here, we also initialize various event listeners for different ad events and errors. @param - "loaded" event from the adsManager @returnValue - none */ customIma.prototype.onAdsManagerLoaded = function(adsManagerLoadedEvent) { logger.printLog('adlog', 'onAdsManagerLoaded', adsManagerLoadedEvent); // Get the ads manager. var adsRenderingSettings = new google.ima.AdsRenderingSettings(); if(appConfig.enableMidrolls == true) { adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; } // videoContent should be set to the content video element. adPlayObj.adsManager = adsManagerLoadedEvent.getAdsManager(adPlayObj.videoContent, adsRenderingSettings); // Add listeners to the required events. adPlayObj.adsManager.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, adPlayObj.onAdError); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, adPlayObj.onContentPauseRequested); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, adPlayObj.onContentResumeRequested); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, adPlayObj.onAdEvent); // Listen to any additional events, if necessary. adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.LOADED, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.STARTED, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.COMPLETE, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.AD_BREAK_READY, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.PAUSED, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.RESUMED, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.AD_BUFFERING, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.IMPRESSION, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.FIRST_QUARTILE, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.MIDPOINT, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.THIRD_QUARTILE, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.LOG, adPlayObj.onAdEvent); adPlayObj.adsManager.addEventListener( google.ima.AdEvent.Type.AD_PROGRESS, adPlayObj.onAdEvent); adPlayObj.playAds(); } /* @description - Its a listener method, this method handles what should be done whenever an ad event occurs like loaded, started, complete etc. Here, we also make the logging call for ad complete scenario. @param - "adEvent" @returnValue - none */ customIma.prototype.onAdEvent = function(adEvent) { // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) // don't have ad object associated. if(adEvent.type !== google.ima.AdEvent.Type.AD_PROGRESS) { logger.printLog('adlog', 'onAdEvent: ', adEvent.type); logger.printLog('adlog', 'onAdEvent details: ', adEvent); logger.printLog('adlog', 'onAdEvent appState.player.rwdFwdStatus: ', appState.player.rwdFwdStatus); } var ad = adEvent.getAd(); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if(appState.player.rwdFwdStatus == true) { adPlayObj.stopAdPlay(); } else { if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoObj.videoPlay(); } else { adPlayObj.onAdLoaded(); } } break; case google.ima.AdEvent.Type.AD_BREAK_READY: break; case google.ima.AdEvent.Type.STARTED: // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. // ad type using time offset adPlayObj.onAdStarted(); break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. adPlayObj.onAdComplete(); break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: adPlayObj.resetIma(); adPlayObj.nvIma.missingLogsSent = false; break; case google.ima.AdEvent.Type.PAUSED: appState.ads.adPaused = true; appState.eventInProgress = false; // customIma.deInitAdHangTimer(); break; case google.ima.AdEvent.Type.RESUMED: appState.ads.adPaused = false; appState.eventInProgress = false; // customIma.initAdHangTimer(); break; case google.ima.AdEvent.Type.FIRST_QUARTILE: case google.ima.AdEvent.Type.MIDPOINT: case google.ima.AdEvent.Type.THIRD_QUARTILE: // customIma.initAdHangTimer(); break; case google.ima.AdEvent.Type.AD_PROGRESS: // appState.ads.adHangProgress ++; if(adPlayObj.adsManager.getRemainingTime() < 1) { appState.eventInProgress = true; } else if((adPlayObj.adsManager.getCurrentAd().getDuration() - adPlayObj.adsManager.getRemainingTime()) < 1) { appState.eventInProgress = false; } if(adPlayObj.adsManager.getRemainingTime() < 0.5 && adPlayObj.adsManager.getRemainingTime() > 0.2) { helper.preloaderDisplay('show'); } break; case google.ima.AdEvent.Type.LOG: appState.player.pausedTime = videoObj.getPlayerCurrentTime(); let adData = adEvent.getAdData(); if (adData['adError']) { logger.printLog('adlog', 'Non-fatal error occurred: ' + adData['adError'].getMessage()); logger.processUserAction('AdError_NonFatal_' + adData.adError.getErrorCode() + '_' + adData['adError'].getMessage()); var errorCode = adData.adError.getErrorCode(); if(errorCode == 402 || errorCode == 400) { adPlayObj.stopAdPlay(); // adPlayObj.onContentResumeRequested(); } if(videoObj.isPaused() == true) { // adPlayObj.onContentResumeRequested(); } adPlayObj.adsManager.discardAdBreak(); this.currentAd.adTitle = 'AdError_' + adData.adError.getErrorCode() + '_' + adData['adError'].getMessage(); adPlayObj.nvIma.initAdLog(adPlayObj.nvIma.currentAd.type, false, false); adPlayObj.onContentResumeRequested(); } break; } } /* @description - Its a listener method, this method handles what should be done whenever an ad error occurs like failed ad, empty VAST response etc. Here, we also make the logging call for null ad scenario. @param - "adErrorEvent" @returnValue - none */ customIma.prototype.onAdError = function(adErrorEvent) { // Handle the error logging. logger.printLog('adlog', 'AD ERROR DETAILS - ', adErrorEvent); currentAdError = adErrorEvent; try { if(adErrorEvent !== undefined && adErrorEvent.getError() !== undefined) { currentAdError.type = currentAdError.getError().getType(); currentAdError.code = currentAdError.getError().getErrorCode(); currentAdError.message = currentAdError.getError().getMessage(); currentAdError.vastCode = currentAdError.getError().getVastErrorCode(); logger.printLog('adlog', 'AD ERROR DETAILS - ', 'Type - ' + currentAdError.type + ' | Code - ' + currentAdError.code + ' | Message - ' + currentAdError.message); appState.player.pausedTime = videoObj.getPlayerCurrentTime(); if(appConfig.useVmap == false) { adPlayObj.nvIma.currentAd.adTitle = 'AdError_' + currentAdError.code + '_' + currentAdError.vastCode; if(currentAdError.type == 'adLoadError') { if(appConfig.enableAdPodding == false) { // i.e. no client side podding, server side podding if(adPlayObj.nvIma.currentAd.type == 'midroll') { var adPodSize = adObj.midrollsize; } else { var adPodSize = adObj.nonmidrollsize; } for(var i = 0; i < adPodSize; i++) { adPlayObj.nvIma.initAdLog(adPlayObj.nvIma.currentAd.type, false, false); } } else { adPlayObj.nvIma.initAdLog(adPlayObj.nvIma.currentAd.type, false, false); } } else { adPlayObj.nvIma.initAdLog(adPlayObj.nvIma.currentAd.type, true, false); } adHandler.resetAdState(); adPlayObj.nvIma.currentAd.adTitle = ''; } } } catch (e) { logger.printLog('error', 'IMA new error type caught', ''); appState.player.pausedTime = videoObj.getPlayerCurrentTime(); if(appConfig.useVmap == false) { adHandler.resetAdState(); adPlayObj.nvIma.currentAd.adTitle = ''; } } if(mainVideoPlayer == null) return; adPlayObj.onContentResumeRequested(); // if(adErrorEvent.getError().g.errorCode == 1009 // || adErrorEvent.getError().g.errorCode == 1010 // || adErrorEvent.getError().g.errorCode == 1005 // ) { // VAST empty or response not understood // } adPlayObj.resetIma(); }, /* @desc - To perform necessary actions on ad loaded event. @param - no parameters */ customIma.prototype.onAdLoaded = function(adType = 'video') { if(appState.player.rwdFwdStatus == true || appState.currentPage !== 'video') { logger.printLog('adlog', 'appState.player.rwdFwdStatus is in progress - discarding ad break', ''); adPlayObj.stopAdPlay(); return; } adHandler.setAdState(adType); if(videoObj.bugAds !== null && videoObj.bugAds.adDisplayedStatus == false) { helper.preloaderDisplay('hide'); } videoObj.vodInfo.hideDisplayInfo(); playbarOptions.hidePlayerControls(); videoObj.vodPlaylist.exitPlayerGridNavigation(); // if(adType !== 'bugad') helper.preloaderDisplay('show'); // until ad starts if(appState.player.rwdFwdStatus == true || appState.currentPage !== 'video') { adPlayObj.adsManager.discardAdBreak(); helper.preloaderDisplay('show'); } if(adType !== 'bugad') { adPlayObj.nvIma.sendLogForMissingAds(); adPlayObj.nvIma.setCurrentAdDetails(); } } customIma.prototype.onAdStarted = function() { helper.preloaderDisplay('hide'); adHandler.showHideAdLabel('show'); var adPod = adPlayObj.adsManager.getCurrentAd().getAdPodInfo().getPodIndex(); var adPosition = adPlayObj.adsManager.getCurrentAd().getAdPodInfo().getAdPosition(); var totalAdsInPod = adPlayObj.adsManager.getCurrentAd().getAdPodInfo().getTotalAds(); logger.printLog('adlog', 'pod info: adPod, adPosition, totalAdsInPod - ', [adPod, adPosition, totalAdsInPod]); adHandler.updateAdLabel(adPosition, totalAdsInPod); if(appState.player.pausedTime > 0) { appState.ads.currentlyRequestedAdType = 'midroll'; adPlayObj.nvIma.currentAd.type = 'midroll' } else { appState.ads.currentlyRequestedAdType = 'preroll'; adPlayObj.nvIma.currentAd.type = 'preroll'; appState.ads.lastPrerollTimestamp = Date.now(); } logger.printLog('adlog', 'CURRENT AD >>> AD STARTED --- ' + adPlayObj.nvIma.currentAd.type); } /* @desc - To perform necessary actions on ad completed event. @param - no parameters */ customIma.prototype.onAdComplete = function() { adHandler.showHideAdLabel('hide'); adHandler.resetAdState(); if(videoObj.bugAds !== null && videoObj.bugAds.adDisplayedStatus == false) { helper.preloaderDisplay('show'); playbarOptions.showPlayerControls(); } if(appConfig.useVmap == false) { adPlayObj.nvIma.initAdLog(adPlayObj.nvIma.currentAd.type, true, true); adHandler.resetAdState(); } } /* @desc - To be used in case the ad play needs to be stopped mid way due to some reasons. @param - no parameters */ customIma.prototype.stopAdPlay = function() { logger.printLog('adlog', 'stopAdPlay() called ...', ''); adHandler.resetAdState('statusOnly'); if(helper.isValidValue(adPlayObj.adsManager)) adPlayObj.adsManager.discardAdBreak(); this.resetIma(); }, /* @description - Pauses the current video playback. This function is where you should setup UI for showing ads (e.g. display ad timer countdown, disable seeking etc.) @param - none @returnValue - none */ customIma.prototype.onContentPauseRequested = function() { logger.printLog('adlog', 'onContentPauseRequested', ''); adPlayObj.videoContent.pause(); appState.player.pausedTime = videoObj.getPlayerCurrentTime(); // setupUIForAds(); }, /* @description - Resumes the current video playback. This function is where you should ensure that your UI is ready to play content. @param - none @returnValue - none */ customIma.prototype.onContentResumeRequested = function(type = 'resume', calledfrom = '') { logger.printLog('adlog', 'onContentResumeRequested called ... type, calledfrom, appState.ads.adPlaying, appState.ads.midAdPlaying - ', type + ' | ' + calledfrom + ' | ' + appState.ads.adPlaying + ' | ' + appState.ads.midAdPlaying); if( (appConfig.useVmap == false && (appState.ads.adPlaying == true || appState.ads.midAdPlaying == true || !videoObj.isPaused() || appState.videoMode == false) ) ) { helper.preloaderDisplay('hide'); logger.printLog('info', 'returning from onContentResumeRequested method...'); return; } adHandler.resetAdState(); adHandler.showHideAdLabel('hide'); if(appState.player.rwdFwdStatus == false) { logger.processUserAction('ResumingVideoAfterAdBreak'); if(appState.player.videoStartedFromResumePoint !== 0 && appState.player.pausedTime == 0) { videoObj.resumeVideoPlayback(appState.player.videoStartedFromResumePoint, 'onContentResumeRequested'); } else { videoObj.resumeVideoPlayback(appState.player.pausedTime, 'onContentResumeRequested'); } } } customIma.prototype.onContentVideoEnded = function() { if(appConfig.disableAds == false && typeof this.adsLoader !== 'undefined') { this.adsLoader.contentComplete(); } } /* @description - This method utilizes js based code (defined in vmap.js) to create a VMAP on the fly. @param - videoInfo - information about the current video for which ads are being setup @returnValue - none */ customIma.prototype.createVmapJs = function(videoInfo) { var queryArr = {}; queryArr.noPreAds = ((appState.player.noVideosStarted - 1) > (adObj.firstadInterval - 1) ? adObj.nonmidrollsize : 0); // queryArr.noPreAds = adObj.nonmidrollsize; var diff = Date.now() - appState.ads.lastPrerollTimestamp; if(appState.player.isResume == true || (diff < 120000)) { queryArr.noPreAds = 0; } queryArr.noMidAds = adObj.midrollsize; queryArr.cuePoints = appState.ads.currentVodCuePoints; // queryArr.noMidAds = 1; // queryArr.cuePoints = [804, 1449, 2110]; queryArr.adProviders = []; var adProvider = adObj.adsdklist[adObj.adsdklist.length - 1]; var finalAdUrl = adProvider.url; if(testInfo.testAdMode == true) { finalAdUrl = adObj.adUrl; } queryArr.adProviders.push({ name: adProvider.name, provider : adProvider.provider, priority: adProvider.priority, type: adProvider.type, // url: adHandler.replaceMacros(finalAdUrl) url: finalAdUrl }); queryArr.videoInfo = videoInfo; var vast = Vmap(queryArr); logger.printLog('adlog', 'AD: client Vast: ', vast); logger.printLog('adlog', 'AD: noVideosStarted: ', appState.player.noVideosStarted); logger.printLog('adlog', 'AD: firstadInterval: ', adObj.firstadInterval); logger.printLog('adlog', 'AD: nonmidrollsize', adObj.nonmidrollsize); logger.printLog('adlog', 'AD: midrollsize', adObj.midrollsize); logger.printLog('adlog', 'AD: Break Points', appState.ads.currentVodCuePoints); logger.printLog('adlog', 'AD: adUrl: ', adObj.adUrl); appState.ads.adResp = vast; // customIma.requestVmapAds(); var adsRequest = new google.ima.AdsRequest(); adsRequest.adsResponse = appState.ads.adResp; if(this.adsLoader !== undefined && this.adsLoader !== null) { this.adsLoader.requestAds(adsRequest); } return; } /* @description - This method replaces the various macros with real values in an ad tag. This method is called before requesting for an ad. @param - "adUrl" @returnValue - "adUrl" with replaced values */ customIma.prototype.replaceMacros = function (adUrl, context = '', breakPosition = '', slotPosition = '') { logger.printLog('data', 'replacing macros adUrl: ', adUrl); if (adUrl !== undefined) { var newAdUrl = adUrl; // newAdUrl += '&dedup=[FT_DEDUPE_ID]'; // temp only for testing logger.printLog('adlog', 'replacing macros adUrl is defined '); // REQUIRED - Highest Priority if (newAdUrl.indexOf('[FT_TRACKING_ID]') > -1) { // newAdUrl = newAdUrl.split('[FT_TRACKING_ID]').join(appConfig.currentDeviceId); newAdUrl = newAdUrl.split('[FT_TRACKING_ID]').join(''); } if (newAdUrl.indexOf('[FT_TRACKING_ENABLED]') > -1) { newAdUrl = newAdUrl.split('[FT_TRACKING_ENABLED]').join(0); //harcoded for now } if (newAdUrl.indexOf('[FT_USER_AGENT]') > -1) { if(appConfig.modifyUAMacro) { var ua = navigator.userAgent; var dm = appConfig.deviceModel; if(appConfig.deviceModel.indexOf('_') !== -1) { dm = dm.split('_')[1]; } if(adObj.adUrl.indexOf('springserve') !== -1) { // changed for areas where direct request to springserve is being sent for kids apps, 27 Apr 2023 var ftUserAgent = helper.fixedEncodeURIComponent(ua + ', X1_STB_/1.0.0.0 (X1, ' + dm + ', )'); } else { var ftUserAgent = helper.fixedEncodeURIComponent(encodeURI(ua + ', X1_STB_/1.0.0.0 (X1, ' + dm + ', )')); } newAdUrl = newAdUrl.split('[FT_USER_AGENT]').join(ftUserAgent); } else { newAdUrl = newAdUrl.split('[FT_USER_AGENT]').join(encodeURI(navigator.userAgent)); } } if (newAdUrl.indexOf('[FT_PLAYER_HEIGHT]') > -1) { // newAdUrl = newAdUrl.split('[FT_PLAYER_HEIGHT]', '1080'); newAdUrl = newAdUrl.split('[FT_PLAYER_HEIGHT]').join('1080'); } if (newAdUrl.indexOf('[FT_PLAYER_WIDTH]') > -1) { newAdUrl = newAdUrl.split('[FT_PLAYER_WIDTH]').join('1920'); } if (newAdUrl.indexOf('[FT_IP_ADDRESS]') > -1) { newAdUrl = newAdUrl.split('[FT_IP_ADDRESS]').join(appConfig.ipAddress); } if (newAdUrl.indexOf('[FT_APP_NAME]') > -1) { newAdUrl = newAdUrl.split('[FT_APP_NAME]').join(encodeURI(appApiConfig.appConfig.site_name)); } if (newAdUrl.indexOf('[FT_BUNDLE_ID]') > -1) { newAdUrl = newAdUrl.split('[FT_BUNDLE_ID]').join(adHandler.getBundleId()); } if (newAdUrl.indexOf('[FT_APP_STORE_ID]') > -1) { newAdUrl = newAdUrl.split('[FT_APP_STORE_ID]').join(''); } if (newAdUrl.indexOf('[FT_TIMESTAMP]') > -1) { newAdUrl = newAdUrl.split('[FT_TIMESTAMP]').join(Date.now()); } try { //RECOMMENDED - Medium Priority var vodInfo = videoObj.vodInfo.getCurrentVideoDetailsFromArr(); // var vodInfo = this.videoInfo; if (newAdUrl.indexOf('[FT_CONTENT_ID]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_ID]').join(vodInfo['node_id']); } if (newAdUrl.indexOf('[FT_CONTENT_TITLE]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_TITLE]').join($.trim(vodInfo['title'])); } if (newAdUrl.indexOf('[FT_CONTENT_SERIES]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_SERIES]').join($.trim(vodInfo['series_name'])); } if (newAdUrl.indexOf('[FT_CONTENT_LENGTH]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_LENGTH]').join(vodInfo['runtime']); } if (newAdUrl.indexOf('[FT_CONTENT_RATING]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_RATING]').join($.trim(vodInfo['age_appropriate_rating'])); } if (newAdUrl.indexOf('[FT_CONTENT_GENRE]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_GENRE]').join($.trim(vodInfo['content_genre'])); } if (newAdUrl.indexOf('[FT_PRIMARY_GENRE]') > -1) { newAdUrl = newAdUrl.split('[FT_PRIMARY_GENRE]').join($.trim(vodInfo['primary_genre'])); } if (newAdUrl.indexOf('[FT_CONTENT_CATEGORY]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_CATEGORY]').join($.trim(vodInfo['primary_category'])); } if (newAdUrl.indexOf('[FT_CONTENT_SEASON]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_SEASON]').join($.trim(vodInfo['season'])); } if (newAdUrl.indexOf('[FT_CONTENT_EPISODE]') > -1) { newAdUrl = newAdUrl.split('[FT_CONTENT_EPISODE]').join($.trim(vodInfo['episode'])); } // New macros - BEGIN if (newAdUrl.indexOf('[FT_VIDEO_ID]') > -1) { newAdUrl = newAdUrl.split('[FT_VIDEO_ID]').join(vodInfo['node_id']); } if (newAdUrl.indexOf('[FT_PUBLISHER]') > -1) { newAdUrl = newAdUrl.split('[FT_PUBLISHER]').join(encodeURI($.trim(vodInfo['author']))); } if (newAdUrl.indexOf('[FT_PUBLISHER_ID]') > -1) { newAdUrl = newAdUrl.split('[FT_PUBLISHER_ID]').join(encodeURI($.trim(vodInfo['uid']))); } if (newAdUrl.indexOf('[FT_L1_AG]') > -1) { newAdUrl = newAdUrl.split('[FT_L1_AG]').join(encodeURI(appState.grid.currentCategory)); } if (newAdUrl.indexOf('[FT_PLAYLIST]') > -1) { if(appState.previousPage == 'listoflist') { newAdUrl = newAdUrl.split('[FT_PLAYLIST]').join(encodeURI(subChannels[appState.grid.currentRowFocus].name)); } else { newAdUrl = newAdUrl.split('[FT_PLAYLIST]').join(encodeURI(subCategories[appState.grid.currentRowFocus].name)); } } // New macros - END } catch(e) { logger.printLog('error', 'error getting medium macros'); } if (newAdUrl.indexOf('[FT_DEVICE_OS]') > -1) { var deviceOS = navigator.platform; if (platform_id == 1217562 && typeof window.VIZIO !== 'undefined' && typeof navigator !== 'undefined') { deviceOS = navigator.platform; } newAdUrl = newAdUrl.split('[FT_DEVICE_OS]').join(deviceOS); } if (newAdUrl.indexOf('[FT_DEVICE_OS_VER]') > -1) { newAdUrl = newAdUrl.split('[FT_DEVICE_OS_VER]').join(''); } if (newAdUrl.indexOf('[FT_DEVICE_MAKE]') > -1) { var deviceMake = ''; if (platform_id == 1217562 && typeof window.VIZIO !== 'undefined') { if (typeof window.VIZIO.deviceInfo !== 'undefined' && window.VIZIO.deviceInfo !== null && typeof window.VIZIO.deviceInfo.modelSeries !== 'undefined') { deviceMake = window.VIZIO.deviceInfo.modelSeries; } } newAdUrl = newAdUrl.split('[FT_DEVICE_MAKE]').join(deviceMake); } if (newAdUrl.indexOf('[FT_DEVICE_MODEL]') > -1) { if(appState.playlistPlayMode == false) { if (platform_id == 1217562 && typeof window.VIZIO !== 'undefined' && typeof window.VIZIO.deviceModel !== 'undefined') { var deviceModel = window.VIZIO.deviceModel; } else { var deviceModel = appConfig.deviceModel; } } else { var deviceModel = appConfig.deviceModel; } newAdUrl = newAdUrl.split('[FT_DEVICE_MODEL]').join(deviceModel); } if (newAdUrl.indexOf('[FT_DEVICE_LANGUAGE]') > -1) { newAdUrl = newAdUrl.split('[FT_DEVICE_LANGUAGE]').join(navigator.language); } if (newAdUrl.indexOf('[FT_APP_VERSION]') > -1) { newAdUrl = newAdUrl.split('[FT_APP_VERSION]').join(appInfo.buildVersion); } if (newAdUrl.indexOf('[FT_APP_STORE_URL]') > -1) { newAdUrl = newAdUrl.split('[FT_APP_STORE_URL]').join(''); } if (newAdUrl.indexOf('[appurl]') > -1) { var appUrl = appConfig.baseAppUrl + '?iptv=true&siteId=' + appConfig.siteId + '&platform_id=' + appConfig.platform_id; newAdUrl = newAdUrl.split('[appurl]').join(encodeURIComponent(appUrl)); } // New macros - BEGIN if (newAdUrl.indexOf('[FT_CONTEXT]') > -1) { if(context == 'preroll') { var contextVal = 1; } else { var contextVal = 2; } newAdUrl = newAdUrl.split('[FT_CONTEXT]').join(contextVal); } if (newAdUrl.indexOf('[FT_AD_BREAK_POSITION]') > -1) { if(context == 'preroll') { breakPosition = 0; } newAdUrl = newAdUrl.split('[FT_AD_BREAK_POSITION]').join(breakPosition); } if (newAdUrl.indexOf('[FT_AD_SLOT_POSITION]') > -1) { newAdUrl = newAdUrl.split('[FT_AD_SLOT_POSITION]').join(slotPosition); } if (newAdUrl.indexOf('[FT_SESSION_ID]') > -1) { newAdUrl = newAdUrl.split('[FT_SESSION_ID]').join(appState.currentSessionId); } if (newAdUrl.indexOf('[FT_SITE_ID]') > -1) { newAdUrl = newAdUrl.split('[FT_SITE_ID]').join(appConfig.siteId); } if (newAdUrl.indexOf('[FT_US_PRIVACY]') > -1) { newAdUrl = newAdUrl.split('[FT_US_PRIVACY]').join(appApiConfig.appConfig.us_privacy); } // New macros - END // Live Macros - BEGIN // try { if (newAdUrl.indexOf('[APP_NAME]') > -1) { newAdUrl = newAdUrl.split('[APP_NAME]').join(encodeURI(appApiConfig.appConfig.site_name)); } if (newAdUrl.indexOf('[DID]') > -1) { newAdUrl = newAdUrl.split('[DID]').join(appConfig.deviceLmtVal); } if (newAdUrl.indexOf('[APP_BUNDLE]') > -1) { newAdUrl = newAdUrl.split('[APP_BUNDLE]').join(adHandler.getBundleId()); } if (newAdUrl.indexOf('[FT_CACHEBUSTER]') > -1) { newAdUrl = newAdUrl.split('[FT_CACHEBUSTER]').join(encodeURI(Date.now())); } if (newAdUrl.indexOf('[IP]') > -1) { newAdUrl = newAdUrl.split('[IP]').join(encodeURI(appConfig.ipAddress)); } if (newAdUrl.indexOf('[UA]') > -1) { newAdUrl = newAdUrl.split('[UA]').join(encodeURI(navigator.userAgent)); } if (newAdUrl.indexOf('[LIMITED_AD_TRACKING]') > -1) { newAdUrl = newAdUrl.split('[LIMITED_AD_TRACKING]').join(appConfig.deviceLmtVal); } if (newAdUrl.indexOf('[CONTENT_ID]') > -1) { newAdUrl = newAdUrl.split('[CONTENT_ID]').join(vodInfo['node_id']); } if (newAdUrl.indexOf('[CONTENT_GENRE]') > -1) { newAdUrl = newAdUrl.split('[CONTENT_GENRE]').join(encodeURI($.trim(vodInfo['primary_genre']))); } if (newAdUrl.indexOf('[CONTENT_SERIES]') > -1) { newAdUrl = newAdUrl.split('[CONTENT_SERIES]').join(encodeURI($.trim(vodInfo['series_name']))); } if (newAdUrl.indexOf('[CONTENT_TITLE]') > -1) { newAdUrl = newAdUrl.split('[CONTENT_TITLE]').join(encodeURI($.trim(vodInfo['title']))); } if (newAdUrl.indexOf('[US_PRIVACY]') > -1) { newAdUrl = newAdUrl.split('[US_PRIVACY]').join(appConfig.deviceUsPrivacy); } if (newAdUrl.indexOf('[FT_DEDUPE_ID]') > -1) { appState.ads.adBreakNumber = context == 'preroll' ? 0 : (appState.ads.adBreakNumber + 1); var dedupeId = appConfig.currentDeviceId + Date.now() + vodInfo['node_id'] + appState.ads.adBreakNumber; newAdUrl = newAdUrl.split('[FT_DEDUPE_ID]').join(dedupeId); } // Adding support for nonce macro for google inventory enabling - 10 Jan 2023 newAdUrl = newAdUrl + '&nonce=[GOOGLE_INSTREAM_VIDEO_NONCE]'; // } catch(e) { // } // Live Macros - END logger.printLog('data', 'replacing macros adUrl after replacing macros: ', newAdUrl); return newAdUrl; } else { return; } } /******** FOR SERVER SIDE PODDING ******/ var nonVmapIma = function() { this.currentAd = { adId: '', adTitle: '', type: 'preroll', adDuration: 0 } this.missingLogsSent = false; } nonVmapIma.prototype.initAdLog = function(adType, adAvailable, adPlayed) { var adSdkInfo = adObj.adsdklist[appState.ads.adSdkCalled]; var adDetails = {}; adDetails.adProvider = adSdkInfo.provider; adDetails.adProviderName = adSdkInfo.name; adDetails.adPriority = adSdkInfo.priority; adDetails.adAvailable = adAvailable; adDetails.adPlayed = adPlayed; adDetails.adType = adType; adDetails.transactionId = helper.guid(); if(this.currentAd.adId == undefined) { adDetails.adId = ''; } else { adDetails.adId = this.currentAd.adId; } if(this.currentAd.adTitle == undefined) { adDetails.adTitle = this.currentAd.adTitle; } else { adDetails.adTitle = this.currentAd.adTitle; } logger.logAdView(adDetails); } nonVmapIma.prototype.sendLogForMissingAds = function() { if(appConfig.useVmap == false && appConfig.enableAdPodding == false && this.missingLogsSent == false) { // log for any missing ads this.currentAd.adTitle = 'AdError_NoAdReceived'; var adsReceived = adPlayObj.adsManager.getCurrentAd().getAdPodInfo().getTotalAds(); if(this.currentAd.type == 'midroll') { var adPodSize = adObj.midrollsize; } else { var adPodSize = adObj.nonmidrollsize; } if(adsReceived < adPodSize) { var diff = adPodSize - adsReceived; for(var i = 0; i < diff; i++) { this.initAdLog(this.currentAd.type, false, false); } this.missingLogsSent = true; } this.currentAd.adTitle = ''; } } nonVmapIma.prototype.setCurrentAdDetails = function() { if(appConfig.useVmap == false) { try { // this.currentAd.adTitle = adPlayObj.adsManager.getCurrentAd().getTitle(); this.currentAd.adTitle = 'adId_' + adPlayObj.adsManager.getCurrentAd().getAdId() + '_creativeAdId_' + adPlayObj.adsManager.getCurrentAd().getCreativeId() + '_adTitle_' + adPlayObj.adsManager.getCurrentAd().getTitle(); } catch (e) { this.currentAd.adTitle = 'AdError_NotAvailable'; } } } nonVmapIma.prototype.initRequestAds = function(videoInfo, adType) { if(adPlayObj.adsLoader == undefined) { adPlayObj.cancelAdsRequest(); adPlayObj.stopAdPlay(); return; } this.currentAd.type = adType; logger.printLog('adlog', 'requestAds shouldRequestAd: ', this.checkIfPreRollBeRequested() + ' - ' + this.checkIfMidRollBeRequested()); if(adType == 'preroll' && this.checkIfPreRollBeRequested() === true) { logger.printLog('adlog', 'going to request preroll now.....!!!'); appState.ads.preRollAdsRequested++; var adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = adPlayObj.replaceMacros(adObj.adUrl, 'preroll'); adPlayObj.adsLoader.requestAds(adsRequest); logger.processUserAction('AdRequest_Preroll_Sent'); } else if(adType == 'midroll' && this.checkIfMidRollBeRequested() === true) { logger.printLog('adlog', 'going to request midroll now.....!!!'); appState.ads.midRollAdsRequested++; var adsRequest = new google.ima.AdsRequest(); if(testInfo.failAds !== undefined && testInfo.failAds.indexOf(appState.ads.midRollAdsRequested) !== -1) { adsRequest.adTagUrl = adPlayObj.replaceMacros(testInfo.adBuckets[0].url, 'midroll'); } else { adsRequest.adTagUrl = adPlayObj.replaceMacros(adObj.adUrl, 'midroll'); } adPlayObj.adsLoader.requestAds(adsRequest); logger.processUserAction('AdRequest_Midroll_Sent'); } else { logger.printLog('adlog', 'Calling resume ... as no ad is to be requested as per config'); adPlayObj.cancelAdsRequest(); adPlayObj.onContentResumeRequested('play', 'requestAds'); } } nonVmapIma.prototype.checkIfPreRollBeRequested = function() { if(adObj.adActivation == true) { if (appState.player.noVideosStarted > adObj.firstadInterval) { if ((appState.player.noVideosStarted % adObj.adInterval) == 0) { if (appState.ads.preRollAdsRequested < adObj.nonmidrollsize) { return true; } } } } return false; } nonVmapIma.prototype.checkIfMidRollBeRequested = function() { if(adObj.enableMidAd == true) { if (appState.ads.midRollAdsRequested < adObj.midrollsize) { return true; } } return false; }