1/** 2 * Nielsen analytics plugin for JW player. 3 * 4 * Note that as a JW player plugin, this is not exposed as a Drupal library. 5 * Rather, the JW player plugin will load this when ready. 6 * 7 * @param {object} player 8 * Instance of the player API with which the plugin is being registered. 9 * @param {object} pluginConfig 10 * Config block passed in player().setup(). The configuration consists of the 11 * following: 12 * - appId: Unique ID assigned to the player/site and configured by product. 13 * - debug: Turn on debug mode for verbose messaging in the Javascript console 14 * during initialization and playback. 15 * - getContentMetadataFromJwPlaylistItem: Function for mapping a JW playlist 16 * item to the content metadata expected by Nielsen. For details on the 17 * content metadata requirements see 18 * https://engineeringportal.nielsen.com/docs/DCR_Video_Browser_SDK#Content_Metadata. 19 * The function will receive a single argument, a JW playlist item. See 20 * https://docs.jwplayer.com/players/reference/playlists#playlist. The 21 * function is expected to return an object that is the Nielsen content 22 * metadata that will be sent in calls to ggPM('loadMetadata'. <object>). 23 * See https://engineeringportal.nielsen.com/docs/loadMetadata_(Browser). 24 * @param {Element} container 25 * DIV created in the DOM for this plugin. 26 * 27 * @see https://docs.jwplayer.com/players/docs/jw8-add-a-custom-or-third-party-plugin 28 */ 29function nielsenJwPlayerPlugin(player, pluginConfig, container) { 30 'use strict'; 31 32 pluginConfig = pluginConfig || {}; 33 34 const { 35 appId, 36 debug = true, 37 getContentMetadataFromJwPlaylistItem, 38 } = pluginConfig; 39 const nielsenSdk = window.NOLBUNDLE.nlsQ( 40 appId, 41 'nlsnInstance', 42 debug ? { nol_sdkDebug: 'debug' } : {}, 43 ); 44 const playbackStatus = { 45 adMetadataLoaded: false, 46 previousPlayheadSecond: 0, 47 playheadPosition: 0, 48 previousAdPlayheadSecond: 0, 49 adPlayheadPosition: 0, 50 }; 51 52 /** 53 * Log a message to the console if development mode. 54 * 55 * @param {string} message 56 * Message to log to the console. 57 * @param {object} obj 58 * (optional) Object to log. 59 * @param {object} config 60 * (optional) Config options including: 61 * - prefix: Override the prefix for the message logged to the console. 62 */ 63 const log = (message, obj = null, { prefix = 'lifestyle nielsen' } = {}) => { 64 if (debug) { 65 const output = `[${prefix}]: ${message}`; 66 if (obj === null) { 67 console.log(output); 68 } else { 69 console.log(output, obj); 70 } 71 } 72 }; 73 74 const handlePlaylistItem = ({ item }) => { 75 log('playlistItem', item); 76 // Load content metadata. 77 nielsenSdk.ggPM('loadMetadata', getContentMetadataFromJwPlaylistItem(item)); 78 }; 79 80 const handleTime = ({ position }) => { 81 log('time', position); 82 const currentSecond = Math.floor(position); 83 if (currentSecond > playbackStatus.previousPlayheadSecond) { 84 nielsenSdk.ggPM('setPlayheadPosition', currentSecond); 85 playbackStatus.previousPlayheadSecond = currentSecond; 86 } 87 playbackStatus.playheadPosition = position; 88 }; 89 90 const handleAdTime = ({ 91 adposition: adPosition, 92 duration: durationInSeconds, 93 position, 94 freewheel: { 95 ad: { adId }, 96 }, 97 }) => { 98 log('adTime', { adPosition, durationInSeconds, adId, position }); 99 if (!playbackStatus.adMetadataLoaded) { 100 nielsenSdk.ggPM('loadMetadata', { 101 type: getAdType(adPosition), 102 assetid: adId, 103 }); 104 playbackStatus.adMetadataLoaded = true; 105 } 106 const currentSecond = Math.floor(position); 107 if (currentSecond > playbackStatus.previousAdPlayheadSecond) { 108 nielsenSdk.ggPM('setPlayheadPosition', currentSecond); 109 playbackStatus.previousAdPlayheadSecond = currentSecond; 110 } 111 playbackStatus.adPlayheadPosition = position; 112 }; 113 114 const handleAdComplete = () => { 115 log('adComplete'); 116 nielsenSdk.ggPM('stop', playbackStatus.adPlayheadPosition); 117 playbackStatus.adPlayheadPosition = 0; 118 playbackStatus.adMetadataLoaded = false; 119 }; 120 121 const handleFirstFrame = () => { 122 log('firstFrame'); 123 const item = player.getPlaylistItem(player.getPlaylistIndex()); 124 nielsenSdk.ggPM('loadMetadata', getContentMetadataFromJwPlaylistItem(item)); 125 }; 126 127 const handleComplete = () => { 128 log('complete'); 129 nielsenSdk.ggPM('stop', playbackStatus.playheadPosition); 130 playbackStatus.previousPlayheadSecond = 0; 131 playbackStatus.playheadPosition = 0; 132 }; 133 134 const getAdType = (jwAdPosition) => { 135 /* eslint-disable no-nested-ternary */ 136 return jwAdPosition === 'pre' 137 ? 'preroll' 138 : jwAdPosition === 'mid' 139 ? 'midroll' 140 : jwAdPosition === 'post' 141 ? 'postroll' 142 : 'ad'; 143 /* eslint-enable no-nested-ternary */ 144 }; 145 146 // Setup all or our event handlers when the player is ready. 147 player.on('ready', () => { 148 log('ready'); 149 player.on('playlistItem', handlePlaylistItem); 150 player.on('adTime', handleAdTime); 151 player.on('adComplete', handleAdComplete); 152 player.on('firstFrame', handleFirstFrame); 153 player.on('complete', handleComplete); 154 player.on('time', handleTime); 155 }); 156 log('pluginConfig', pluginConfig); 157} 158 159// Plug entrypoint into player plugin architecture. 160(window.jwplayerPluginJsonp || window.jwplayer().registerPlugin)( 161 'nielsen_jw_player_plugin', 162 '8.24', 163 nielsenJwPlayerPlugin, 164);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.