From 81d3f9cb7897d50a9882501ca92d449bda174b83 Mon Sep 17 00:00:00 2001 From: mustran <45851256+mustran@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:37:38 +0100 Subject: [PATCH] refactor: remove ott ping analytics (#633) * chore: remove ott ping analytics * chore: bring back playerLicenseKey --- docs/features/video-analytics.md | 191 ------------ packages/common/types/jwpltx.d.ts | 18 -- packages/hooks-react/src/useOttAnalytics.ts | 82 ----- .../ui-react/src/components/Player/Player.tsx | 7 +- platforms/web/public/jwpltx.js | 282 ------------------ platforms/web/src/containers/Root/Root.tsx | 9 +- .../web/test-cases/analytics/adv.feature | 13 - .../web/test-cases/analytics/init.feature | 36 --- .../web/test-cases/analytics/params.feature | 21 -- .../web/test-cases/analytics/quantile.feature | 74 ----- platforms/web/types/global.d.ts | 1 - platforms/web/types/jwpltx.d.ts | 18 -- 12 files changed, 2 insertions(+), 750 deletions(-) delete mode 100644 docs/features/video-analytics.md delete mode 100644 packages/common/types/jwpltx.d.ts delete mode 100644 packages/hooks-react/src/useOttAnalytics.ts delete mode 100644 platforms/web/public/jwpltx.js delete mode 100644 platforms/web/test-cases/analytics/adv.feature delete mode 100644 platforms/web/test-cases/analytics/init.feature delete mode 100644 platforms/web/test-cases/analytics/params.feature delete mode 100644 platforms/web/test-cases/analytics/quantile.feature delete mode 100644 platforms/web/types/jwpltx.d.ts diff --git a/docs/features/video-analytics.md b/docs/features/video-analytics.md deleted file mode 100644 index c51b6fac4..000000000 --- a/docs/features/video-analytics.md +++ /dev/null @@ -1,191 +0,0 @@ -# Video Analytics - -By understanding how viewers consume content across OTT Apps, customers can create informed monetization and engagement strategies. - -Video analytics also allows JW Player to calculate recommendations and trending videos, which are critical in monetizing videos. - -## Video Event Endpoint - -Updating JW Player on OTT video events happens by calling the following endpoint: - -``` -https://ihe.jwpltx.com/v1/jwplayer6/ping.gif?e=& -``` - -For advertisement events (ad impressions) the following endpoint needs to be called: - -``` -https://ihe.jwpltx.com/v1/clienta/ping.gif?e=& -``` - -## Reporting - -The data is available to customers in three ways: - -- [Dashboard](https://support.jwplayer.com/articles/jw-player-analytics-reference) -- [Reporting API](https://developer.jwplayer.com/jwplayer/docs/analytics-getting-started) -- Play Sessions Data Export which provides aggregated play session data and more detailed metrics in s3 buckets - -## Events - -The app sends the following events (param `e`) to JW platform: - -| Name | Value | Endpoint | Rqd | Description | -| -------------- | ----- | --------- | --- | -------------------------------------------------------------------- | -| Setup | e | jwplayer6 | Yes | Fired after the landing screen embedding this video has been loaded. | -| Impression | i | clienta | Yes | Fired after the first frame of an ad creative has been rendered. | -| Play | s | jwplayer6 | Yes | Fired after the first frame of a video has been rendered. | -| Quantile | t | jwplayer6 | Yes | Fired after the video plays past the threshold of a quantile. | -| Seeked | vs | jwplayer6 | Yes | Fired after the video is seeked | -| Generic Aband. | gab | jwplayer6 | Yes | Fired to try and track a user before they exit the page | - -## Event JS Script - -The event trigger implementation for the ott web app can be found at [jwpltx.js](/web/public/jwpltx.js) - -Note that `navigator.sendBeacon()` is used to call the endpoints. The browser will not do CORS checks on this operation. It furthermore minimizes performance impact as the browser doesn't wait for the response of the server. - -It also lets us to use `beforeunload` event in order to send remaining data to analytics server when closing the window during watching in progress. - -## Analytics ID - -A special data parameter is the Analytics ID (`aid`). It determines to which JW Player account & property the events belong. Each property has its unique analytics ID and is provided by a JW PLayer Solution Engineer or Account manager. - -For the OTT Web App the Analytics ID is stored in [`config.json`](/web/public/config.json) as `analyticsToken` - -## Metrics - -Each event comes with a set of data sent through the query parameters of the JWPlayer OTT Analytics endpoints: - -- Session - Timestamp and unique keys -- App - The app of the viewer -- Device - The device of the viewer -- Media - The media that is being watched -- Quantile - How much the user watched a particular movie - -These metrics are described below. - -### Session Metrics - -| Name | Key | Rqd | Values | Example | Description | -| --------------------- | --- | --- | -------------------- | ---------------------- | --------------------------------------------------------------------------- | -| Analytics ID | aid | Yes | \[a-zA-Z0-9+\_\]{22} | a17e8PTFFffxLgpVuA4vVw | See Analytics ID | -| Timestamp (Epoch, ms) | sa | Yes | Unix Epoch Time | 1539132609637 | The unix epoch time on client machine when ping sent. | -| Ping Event Type | e | Yes | e, i, s or t | s | Event code of the ping. | -| Feed ID | fed | Yes | \[0-9a-zA-Z\]{8} | ON53iLoH | Unique ID for a feed or playlist coming out of the JW platform. | -| Embed ID | emi | Yes | \[0-9a-z\]{12} | v7wabv10ynek | Unique ID generated on embed for the player instance. | -| Play ID | pli | Yes | \[0-9a-z\]{12} | rc55ceo9sozn | Unique ID generated for playlist items successfully loaded into the player | -| Play Session Sequence | pss | Yes | 1-99999 (Integer) | 1 | Counter that ticks up when the playlist item changes within the same embed. | - -### App Metrics - -| Name | Key | Rqd | Values | Example | Description | -| ------------- | ---- | --- | ------------------- | ---------------------------------------- | --------------------------------------------------- | -| App Version | av | Yes | A string | 1.0.0 | Version of the App | -| App Bundle ID | bun | Yes | Reverse domain name | com.apple.calculator | Unique ID to the App; persists through uninstalls. | -| App User ID | oaid | Yes | \[0-9a-z\]{40} | 51f8cf1797aac87ede45c2883797f124fed0258d | Hash of the app user account login ID. 1 | -| App Config ID | oiid | No | \[0-9a-z\]{8} | dGSUzs9o | Unique ID of app config. | - -1 For Cleeng `oaid` maps to the `subscriberId` - -### Device Metrics - -| Name | Key | Rqd | Values | Example | Description | -| ---------------- | ---- | --- | ------------------- | ------------------------------------ | ------------------------------------------------------- | -| Device OS | oos | Yes | See1 | RokuOS | Name of OS on the OTT device. | -| Device Model | om | No | \- | 4210R | OTT device model number. | -| OS Version | oosv | No | \- | 8.1 | Version of the OS on the OTT device. | -| OS Language | olng | No | \- | en-us | Language of the OS on the OTT device. | -| Firmware Version | ofv | No | \- | 3443.2435 | OTT Device Firmware version | -| Advertising ID | ifa | No | 32 Hex (8-4-4-4-12) | df07c7dc-cea7-4a89-b328-810ff5acb15d | Unique ID ofthe mobile device; user can opt-out /reset. | - -1 Allowed values are: `Web`, `tvOS`, `Tizen`, `SmartCast`, `RokuOS`, `iPadOS`, `iOS`, `Fire TV`, `Fire Mobile`, `Apple TVOS`, `Android TV`, `Android Mobile`, `Android` - -### Player Metrics - -| Name | Key | Rqd | Values | Example | Description | -| ----------------------- | ---- | --- | --------------------------------------- | ------- | ---------------------------------------------------------------- | -| SDK Platform | sdk | Yes | See 1 | 3 | Used to identify the platform. 2. | -| JW Partner Player ID | ppid | No | 0: reserved for JWP, 1-99: for partners | 2 | Provided JW Partner Player ID. | -| Ping Spec Version | psv | No | SemVer | 1.0.0 | Version of the JW Ping Specification referenced. | -| External Player Version | epv | No | \- | 1.2.3 | Version number of external video player (not a JW player or SDK) | - -1 Allowed values are: `0` = web, `1` = Android, `2`= iOS, `3` = Roku, `4` = tvOS, `5` = Chromecast Receiver, `6` = FireOS.
-2 This field was intended to identify the JW Player SDK. However, OTT reports use it to determine the device platform. We, therefore, keep using this field to indicate the OS platform for pragmatic reasons. As a result, it overlaps with field `oos` - -### Media Metrics - -| Name | Key | Rqd | Values | Example | Description | -| -------------------- | --- | ------------ | ---------------- | -------------------------- | ------------------------------------------------- | -| Media ID | id | Yes | \[0-9a-zA-Z\]{8} | 9u6OHIO4 | A unique identifier for a JW Player media item. | -| Media Title | t | Yes | \- | The Perfect Holiday Turkey | The provided title for the current playlist item. | -| Video Duration (sec) | vd | 1 | \- | 141 | Duration of the video | - -1Only requied for the play event `s` - -### Quantile Metrics - -Quantiles are to track how much of a video is watched. It's fired after the video plays past the threshold of a quantile. The number of quantiles in a video depends on video length. - -There are 3 related parameters: - -- Video Duration `vd` -- Video Quantiles `q` -- Quantile Watched `pw` - -The table belows defines the relations and when the Quantile (`t`) event ping should be fired. - -Any decimal values are truncated to an integer. - -#### Example - -- a video is 72 seconds long (`vd=72`) -- hence it will be split into 8 quantiles (`q=8`). Each quantile will be 72/8=9 seconds. -- the first quantile event should fire when the 9th second of the video has been crossed. Quantile watched would have value 16 (`pw=16`). -- the second time this event should fire when the 18th second is crossed. Quantile watched its value would be 32 (`pw=32`) - -#### Quantiles Table - -| | vd<30 sec | 30≤vd<60 sec | 60≤vd<180 sec | 180≤vd<300 sec | vd≥300 sec | -| ------ | --------- | ------------ | ------------- | -------------- | ---------- | -| | q=1 | q=4 | q=8 | q=16 | q=32 | -| pw=4 | | | | | t=0.03125 | -| pw=8 | | | | t=0.0625 | t=0.0625 | -| pw=12 | | | | | t=0.09375 | -| pw=16 | | | t=0.125 | t=0.125 | t=0.125 | -| pw=20 | | | | | t=0.15625 | -| pw=24 | | | | t=0.1875 | t=0.1875 | -| pw=28 | | | | | t=0.21875 | -| pw=32 | | t=0.25 | t=0.25 | t=0.25 | t=0.25 | -| pw=36 | | | | | t=0.28125 | -| pw=40 | | | | t=0.3125 | t=0.3125 | -| pw=44 | | | | | t=0.34375 | -| pw=48 | | | t=0.375 | t=0.375 | t=0.375 | -| pw=52 | | | | | t=0.40625 | -| pw=56 | | | | 0.4375 | t=0.4375 | -| pw=60 | | | | | t=0.46875 | -| pw=64 | | t=0.5 | t=0.5 | t=0.5 | t=0.5 | -| pw=68 | | | | | t=0.53125 | -| pw=72 | | | | t=0.5625 | t=0.5625 | -| pw=76 | | | | | t=0.59375 | -| pw=80 | | | t=0.625 | t=0.625 | t=0.625 | -| pw=84 | | | | | t=0.65625 | -| pw=88 | | | | t=0.6875 | t=0.6875 | -| pw=92 | | | | | t=0.71875 | -| pw=96 | | t=0.75 | t=0.75 | t=0.75 | t=0.75 | -| pw=100 | | | | | 0.78125 | -| pw=104 | | | | t=0.8125 | t=0.8125 | -| pw=108 | | | | | t=0.84375 | -| pw=112 | | | t=0.875 | t=0.875 | t=0.875 | -| pw=116 | | | | | t=0.90625 | -| pw=120 | | | | t=0.9375 | t=0.9375 | -| pw=124 | | | | | t=0.96875 | -| pw=128 | t=1 | t=1 | t=1 | t=1 | t=1 | - -### Live Streams - -For live streams, this quantile distribution is ignored and time ticks are sent at pre-set intervals of 20 seconds. The following values are sent: - -- pw (Quantile watched): -1 -- q (Quantiles): 0 -- ti (Interval in seconds): 20 diff --git a/packages/common/types/jwpltx.d.ts b/packages/common/types/jwpltx.d.ts deleted file mode 100644 index ab23e5ce3..000000000 --- a/packages/common/types/jwpltx.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -export interface Jwpltx { - ready: ( - analyticsid: string, - hostname: string, - feedid: string, - mediaid: string, - title: string, - accountid?: number, - appid?: string, - appversion?: string, - ) => void; - adImpression: () => void; - seek: (offset: number, duration: number) => void; - seeked: () => void; - time: (position: number, duration: number) => void; - complete: () => void; - remove: () => void; -} diff --git a/packages/hooks-react/src/useOttAnalytics.ts b/packages/hooks-react/src/useOttAnalytics.ts deleted file mode 100644 index c750c7fd6..000000000 --- a/packages/hooks-react/src/useOttAnalytics.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { useEffect, useState } from 'react'; -import type { PlaylistItem } from '@jwp/ott-common/types/playlist'; -import { useConfigStore } from '@jwp/ott-common/src/stores/ConfigStore'; -import { useAccountStore } from '@jwp/ott-common/src/stores/AccountStore'; -import env from '@jwp/ott-common/src/env'; -import type { Jwpltx } from '@jwp/ott-common/types/jwpltx'; - -const useOttAnalytics = (item?: PlaylistItem, feedId: string = '') => { - const analyticsToken = useConfigStore((s) => s.config.analyticsToken); - const user = useAccountStore((state) => state.user); - const { config } = useConfigStore((s) => s); - - // ott app user id (oaid) - const oaid: number | undefined = user?.id ? Number(user.id) : undefined; - // app config id (oiid) - const oiid = config?.id; - // app version number (av) - const av = env.APP_VERSION; - - const [player, setPlayer] = useState(null); - - useEffect(() => { - const jwpltx = 'jwpltx' in window ? (window.jwpltx as Jwpltx) : undefined; - - if (!jwpltx || !analyticsToken || !player || !item) { - return; - } - - const timeHandler = ({ position, duration }: jwplayer.TimeParam) => { - jwpltx.time(position, duration); - }; - - const seekHandler = ({ offset }: jwplayer.SeekParam) => { - // TODO: according to JWPlayer typings, the seek param doesn't contain a `duration` property, but it actually does - jwpltx.seek(offset, player.getDuration()); - }; - - const seekedHandler = () => { - jwpltx.seeked(); - }; - - const playlistItemHandler = () => { - if (!analyticsToken) return; - - if (!item) { - return; - } - - jwpltx.ready(analyticsToken, window.location.hostname, feedId, item.mediaid, item.title, oaid, oiid, av); - }; - - const completeHandler = () => { - jwpltx.complete(); - }; - - const adImpressionHandler = () => { - jwpltx.adImpression(); - }; - - player.on('playlistItem', playlistItemHandler); - player.on('complete', completeHandler); - player.on('time', timeHandler); - player.on('seek', seekHandler); - player.on('seeked', seekedHandler); - player.on('adImpression', adImpressionHandler); - - return () => { - // Fire remaining seconds / minutes watched - jwpltx.remove(); - player.off('playlistItem', playlistItemHandler); - player.off('complete', completeHandler); - player.off('time', timeHandler); - player.off('seek', seekHandler); - player.off('seeked', seekedHandler); - player.off('adImpression', adImpressionHandler); - }; - }, [player, item, analyticsToken, feedId, oaid, oiid, av]); - - return setPlayer; -}; - -export default useOttAnalytics; diff --git a/packages/ui-react/src/components/Player/Player.tsx b/packages/ui-react/src/components/Player/Player.tsx index d802b9f4b..9599ef86a 100644 --- a/packages/ui-react/src/components/Player/Player.tsx +++ b/packages/ui-react/src/components/Player/Player.tsx @@ -6,7 +6,6 @@ import { deepCopy } from '@jwp/ott-common/src/utils/collection'; import { testId } from '@jwp/ott-common/src/utils/common'; import { logInfo } from '@jwp/ott-common/src/logger'; import useEventCallback from '@jwp/ott-hooks-react/src/useEventCallback'; -import useOttAnalytics from '@jwp/ott-hooks-react/src/useOttAnalytics'; import { useMediaSources } from '@jwp/ott-hooks-react/src/useMediaSources'; import env from '@jwp/ott-common/src/env'; @@ -64,8 +63,6 @@ const Player: React.FC = ({ const startTimeRef = useRef(startTime); const sources = useMediaSources({ item, baseUrl: env.APP_API_BASE_URL }); - const setPlayer = useOttAnalytics(item, feedId); - const { settings } = useConfigStore((s) => s); const playerId = settings.playerId; @@ -222,10 +219,8 @@ const Player: React.FC = ({ if (playerLicenseKey) { playerOptions.key = playerLicenseKey; } - playerRef.current.setup(playerOptions); - setPlayer(playerRef.current); attachEvents(); }; @@ -236,7 +231,7 @@ const Player: React.FC = ({ if (libLoaded) { initializePlayer(); } - }, [libLoaded, item, detachEvents, attachEvents, playerId, setPlayer, autostart, adsData, playerLicenseKey, sources, feedId]); + }, [libLoaded, item, detachEvents, attachEvents, playerId, autostart, adsData, playerLicenseKey, sources, feedId]); useEffect(() => { return () => { diff --git a/platforms/web/public/jwpltx.js b/platforms/web/public/jwpltx.js deleted file mode 100644 index ab4b7af89..000000000 --- a/platforms/web/public/jwpltx.js +++ /dev/null @@ -1,282 +0,0 @@ -window.jwpltx = window.jwpltx || {}; - -(function (o) { - // Hostname for sending analytics - const URL = 'https://ihe.jwpltx.com/v1/jwplayer6/ping.gif?'; - - // Query parameters for sending analytics - const URI = { - pss: '1', - oos: 'Web', - oosv: '5', - sdk: '0', - }; - - // There are anywhere between 1 to 128 quantiles in any given video, 128 is max for every video - const MAX_DURATION_IN_QUANTILES = 128; - // Query params instance - let uri; - // Time watched after last t event was sent - let timeWatched = 0; - // Last progress of the video stored - let lastVp = 0; - // Next quantile to send t event - let nextQuantile; - // Seeking state, gets reset after 1 sec of the latest seeked event - let isSeeking = false; - // Interval for Live Streams seeking state - let liveInterval = null; - // Timeout for seeking state - let seekingTimeout = null; - - // Here we convert seconds watched to quantiles, the units accepted by the analytics service (res is 0 - 128) - function getCurrentProgressQuantile(progress, duration) { - return Math.floor(MAX_DURATION_IN_QUANTILES * (progress / duration)); - } - - // We convert `q` metric to quantiles (0 - 128) to define next breakpoint for `t` event - function getNextTriggerQuantile(progress, duration) { - return (Math.ceil((progress / duration) * uri.q) * MAX_DURATION_IN_QUANTILES) / uri.q; - } - - // Sends the last ping when closing the player or window - function sendRemainingData() { - // This is rare, but happens in e2e tests and can occur if the user closes the player really fast before any ticks. - // There is no data, so just skip. - if (!uri) { - return; - } - - if (uri.pw === -1) { - clearLiveInterval(); - } else { - uri.pw = getCurrentProgressQuantile(lastVp, uri.vd); - } - - clearSeekingTimeout(); - - if (timeWatched) { - uri.ti = Math.floor(timeWatched); - timeWatched = 0; - - sendData('gab'); - } - } - - // We set interval for sending t events for live streams where we can't get progress info - function setLiveInterval() { - liveInterval = setInterval(() => { - timeWatched += 1; - }, 1000); - } - - // We clear interval after complete or when seeking - function clearLiveInterval() { - clearInterval(liveInterval); - liveInterval = null; - } - - // There is currently a 1 sec debounce surrounding seeking event in order to logically group multiple `seeked` events - function setSeekingTimeout() { - seekingTimeout = setTimeout(() => { - isSeeking = false; - // Set new timeout when seeked event reached for live events - if (uri.pw === -1 && !liveInterval) { - setLiveInterval(); - } - sendData('vs'); - }, 1000); - } - - // We clear timeout after complete event or when new seeking events are received - function clearSeekingTimeout() { - clearTimeout(seekingTimeout); - seekingTimeout = null; - } - - // Process a player ready event - o.ready = function (aid, bun, fed, id, t, oaid, oiid, av) { - uri = JSON.parse(JSON.stringify(URI)); - uri.aid = aid; - uri.bun = bun; - uri.fed = fed; - uri.id = id; - uri.t = t; - uri.oiid = oiid; - uri.av = av; - - // Send oaid only for logged in users - if (oaid) { - uri.oaid = oaid; - } - - uri.emi = generateId(12); - uri.pli = generateId(12); - sendData('e'); - }; - - // Process an ad impression event - o.adImpression = function () { - sendData('i'); - }; - - // Process seek event - o.seek = function (offset, duration) { - isSeeking = true; - clearSeekingTimeout(); - // Clear interval in case of a live stream not to update time watched while seeking - if (uri.pw === -1) { - clearLiveInterval(); - } else { - // We need to rewrite progress of the video when seeking to have a valid ti param - lastVp = offset; - nextQuantile = getNextTriggerQuantile(offset, duration); - } - }; - - // Process seeked event - o.seeked = function () { - setSeekingTimeout(); - }; - - // When player is disconnected from the page -> send the rest of the data and cancel possible intervals - o.remove = function () { - sendRemainingData(); - }; - - // Send the rest of the data and cancel possible intervals in case a web page is closed while watching - window.addEventListener('beforeunload', () => { - sendRemainingData(); - }); - - // Process a time tick event - o.time = function (vp, vd) { - if (isSeeking) { - return; - } - - // 0 or negative vd - Live Stream with DVR - // Infinity -> Live Stream without DVR - if (vd < 1 || vd === Infinity) { - // Initial tick means play() event - if (!uri.pw) { - uri.vd = 0; - uri.q = 0; - uri.pw = -1; - - sendData('s'); - setLiveInterval(); - // Monitor ticks for 20s elapsed - } else { - if (timeWatched > 19) { - uri.ti = timeWatched; - timeWatched = 0; - sendData('t'); - } - } - - // Positive vd means VOD stream - } else { - // Initial tick means play() event - if (!uri.vd) { - uri.vd = Math.round(vd); - if (vd < 30) { - uri.q = 1; - } else if (vd < 60) { - uri.q = 4; - } else if (vd < 180) { - uri.q = 8; - } else if (vd < 300) { - uri.q = 16; - } else { - uri.q = 32; - } - - uri.ti = 0; - uri.pw = 0; - - // Initialize latest quantile to compare further quantiles with - nextQuantile = getNextTriggerQuantile(vp, vd); - // Initial values to compare watched progress - lastVp = vp; - - sendData('s'); - // Monitor ticks for entering new quantile - } else { - const pw = getCurrentProgressQuantile(vp, vd); - const quantile = getNextTriggerQuantile(vp, vd); - - // Total time watched since last t event. - timeWatched = timeWatched + (vp - lastVp); - lastVp = vp; - - if (pw >= nextQuantile) { - uri.ti = Math.round(timeWatched); - uri.pw = pw; - - sendData('t'); - - nextQuantile = quantile; - timeWatched = 0; - } - } - } - }; - - // Process a video complete events - o.complete = function () { - // Clear intervals for live streams - if (uri.pw === -1) { - clearLiveInterval(); - } else { - uri.pw = MAX_DURATION_IN_QUANTILES; - } - - clearSeekingTimeout(); - - uri.ti = Math.floor(timeWatched); - timeWatched = 0; - - sendData('gab'); - }; - - // Helper function to generate IDs - function generateId(len) { - let arr = new Uint8Array((len || 40) / 2); - window.crypto.getRandomValues(arr); - return Array.from(arr, dec2hex).join(''); - } - - function dec2hex(dec) { - return dec.toString(16).padStart(2, '0'); - } - - // Serialize and send data to JW Player - function sendData(type) { - uri.e = type; - uri.sa = Date.now(); - - // Serialize data - let str = ''; - for (let key in uri) { - if (uri[key] !== null) { - str == '' ? null : (str += '&'); - str += key + '=' + encodeURIComponent(uri[key]); - } - } - - // Ads are sent to special bucket - let url = URL; - if (uri.e == 'i') { - url = URL.replace('jwplayer6', 'clienta'); - } - - // Send data if analytics token is set - if (uri.aid) { - navigator.sendBeacon(url + str); - } else { - // eslint-disable-next-line no-console - console.log(url + str); - } - } -})(window.jwpltx); diff --git a/platforms/web/src/containers/Root/Root.tsx b/platforms/web/src/containers/Root/Root.tsx index 0b46529d4..90857290f 100644 --- a/platforms/web/src/containers/Root/Root.tsx +++ b/platforms/web/src/containers/Root/Root.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, type FC, useCallback, useRef } from 'react'; +import React, { useEffect, useState, type FC, useCallback } from 'react'; import { IS_DEMO_MODE, IS_DEVELOPMENT_BUILD, IS_PREVIEW_MODE, IS_PROD_MODE } from '@jwp/ott-common/src/utils/common'; import ErrorPage from '@jwp/ott-ui-react/src/components/ErrorPage/ErrorPage'; import AccountModal from '@jwp/ott-ui-react/src/containers/AccountModal/AccountModal'; @@ -6,7 +6,6 @@ import DevConfigSelector from '@jwp/ott-ui-react/src/components/DevConfigSelecto import LoadingOverlay from '@jwp/ott-ui-react/src/components/LoadingOverlay/LoadingOverlay'; import { type BootstrapData, type OnReadyCallback, useBootstrapApp } from '@jwp/ott-hooks-react/src/useBootstrapApp'; import { setThemingVariables } from '@jwp/ott-ui-react/src/utils/theming'; -import { addScript } from '@jwp/ott-ui-react/src/utils/dom'; import type { Config } from '@jwp/ott-common/types/config'; import { AppError } from '@jwp/ott-common/src/utils/error'; @@ -71,7 +70,6 @@ const RootLoader = ({ onReady }: { onReady: OnReadyCallback }) => { }; const Root: FC = () => { - const analyticsLoadedRef = useRef(false); const [isReady, setIsReady] = useState(false); // Register custom screen mappings @@ -89,11 +87,6 @@ const Root: FC = () => { // alternatively, we can use an events or specific callbacks or extend the AppController for each platform setThemingVariables(config); - if (config.analyticsToken && !analyticsLoadedRef.current) { - await addScript('/jwpltx.js'); - analyticsLoadedRef.current = true; - } - setIsReady(true); }, []); diff --git a/platforms/web/test-cases/analytics/adv.feature b/platforms/web/test-cases/analytics/adv.feature deleted file mode 100644 index d3450345f..000000000 --- a/platforms/web/test-cases/analytics/adv.feature +++ /dev/null @@ -1,13 +0,0 @@ -Feature: Analytics - Advertisement - - # `egpovogv` config can be used - - Scenario: Watching the video from the beginning with 1 pre-roll ad (the config should have an ad-schedule) - Given Start watching the video "Elephants Dream" - When Watch the video with advertising from "00:00 to 00:25" - Then Expect `i` event to be sent - - Scenario: Watching the video from the Continue Watching shelf with 1 pre-roll ad (the config should have an ad-schedule) - Given Start watching the video "Elephants Dream" from the 3:00 minute (from Continue Watching shelf) - When Watch the video with advertising from "03:00 to 03:25" - Then Expect `i` event to be sent diff --git a/platforms/web/test-cases/analytics/init.feature b/platforms/web/test-cases/analytics/init.feature deleted file mode 100644 index 22fb80601..000000000 --- a/platforms/web/test-cases/analytics/init.feature +++ /dev/null @@ -1,36 +0,0 @@ -Feature: Analytics - Initialization - - # `225tvq1i` config can be used - # List of expected params for `e` event: `pss`, `oos`, `oosv`, `sdk`, `aid`, `bun`, `fed`, `id`, `t`, `emi`, `pli`, `oaid` (if subscription enabled) - # List of expected params for `s` event: `pss`, `oos`, `oosv`, `sdk`, `aid`, `bun`, `fed`, `id`, `t`, `emi`, `pli`, `ti`, `pw`, `q`, `oaid` (if subscription enabled) - # Params which have constant values and need to be redifined manually: `pss`, `oos`, `oosv`, `sdk` - - Scenario: Watching the video from the beginning (`e` event) - Given Start watching the video "Elephants Dream" (`e` event) - When Watch the video from "00:00 to 00:05" - Then Expect `e` event to be the first event sent - Then Expect `e` event to be sent with params from the list in the comment above - Then Expect sent params to have correct values - - Scenario: Watching the video from the Continue Watching section (`e` event) - Given Start watching the video "Elephants Dream" from Continue Watching (`e` event) - When Watch the video from "03:00 to 03:05" - Then Expect `e` event to be the first event sent - Then Expect `e` event to be sent with params from the list in the comment above - Then Expect sent params to have correct values - - Scenario: Watching the video from the beginning (`s` event) - Given Start watching the video "Elephants Dream" (`s` event) - When Watch the video from "00:00 to 00:05" - Then Expect `s` event to be the second event sent (if no ad-schedule is used) - Then Expect `s` event to be sent with params from the list in the comment above - Then Expect `q` param to reflect the number of quantiles, `ti` to equal 0 and `pw` to equal 0 as well. - Then Expect other params from the list to have correct values - - Scenario: Watching the the video from the Continue Watching section (`s` event) - Given Start watching the video "Elephants Dream" Continue Watching (`s` event) - When Watch the video from "03:00 to 03:05" - Then Expect `s` event to be the second event sent (if no ad-schedule is used) - Then Expect `s` event to be sent with params from the list in the comment above - Then Expect `q` param to reflect the number of quantiles, `ti` to equal 0 and `pw` to equal 0 as well. - Then Expect other sent params to have correct values diff --git a/platforms/web/test-cases/analytics/params.feature b/platforms/web/test-cases/analytics/params.feature deleted file mode 100644 index 70b3f019f..000000000 --- a/platforms/web/test-cases/analytics/params.feature +++ /dev/null @@ -1,21 +0,0 @@ -Feature: Analytics - Initialization - - # `225tvq1i` config can be used - - Scenario: Watching the video from the beginning with SVOD access model (`e` event) - Given Start watching the video "Elephants Dream" - When Watch the video from "00:00 to 00:30" - Then Expect `e`, `s` and `t` events to be sent with `oaid` param - Then Expect `oaid` to equal the id of the client - - Scenario: Watching the video from the beginning, opening it from the Home page - Given Click on "Elephants Dream" card on the Home page - When Watch the video from "00:00 to 00:30" - Then Expect `e`, `s` and `t` events to be sent with `fed` param - Then Expect `fed` to equal the playlist which includes "Elephants Dream" video - - Scenario: Watching the video from the beginning, opening it from the Continue Watching section - Given Click on "Elephants Dream" card on the Home page (Continue Watching section) - When Watch 30 seconds of the video - Then Expect `e`, `s` and `t` events to be sent with `fed` param - Then Expect `fed` to equal `continueWatchingList` id of the app config diff --git a/platforms/web/test-cases/analytics/quantile.feature b/platforms/web/test-cases/analytics/quantile.feature deleted file mode 100644 index ab6e41540..000000000 --- a/platforms/web/test-cases/analytics/quantile.feature +++ /dev/null @@ -1,74 +0,0 @@ -Feature: Analytics - Quantiles - - # It is possible to see differences in `ti` param value equalling to 1-2 seconds. - # `225tvq1i` config can be used - - Scenario: Watching the video from the beginning with 1 fast-forwad - Given Start watching the video "Elephants Dream" - When Watch the video from "00:00 to 00:25" - Then Expect `t` event to be send with a value of 20 as `ti` param - When Fast-forward the video from "00:25 to 07:00" - Then Expect `vs` event to be send - When Watch the video from "7:00 to 7:15" - Then Expect `t` event to be send with a value of 14 as `ti` param - - Scenario: Watching the video from the Continue Watching shelf with 1 rewind action - Given Start watching the video "Elephants Dream" from the 6:00 minute (from Continue Watching shelf) - When Watch the video from "06:00 to 06:35" - Then Expect 2 `t` events to be sent with values of 8 and 20 as `ti` param - When Rewind the video from "6:35 to "02:00" - Then Expect `vs` event to be send - When Watch the video from "2:00 to 2:15" - Then Expect `t` event to be send with a value of 10 as `ti` param - - Scenario: Watching the video from the beginning with 1 fast-forwad and 1 rewind actions - Given Start watching the video "Elephants Dream" - When Watch the video from "00:00 to 00:25" - Then Expect `t` event to be send with a value of 20 as `ti` param - When Fast-forward the video from "00:25 to 07:00" - Then Expect `vs` event to be send - When Watch the video from "7:00 to 7:15" - Then Expect `t` event to be send with a value of 14 as `ti` param - When Rewind the video from "7:15 to "02:00" - Then Expect `vs` event to be send - When Watch the video from "2:00 to 2:15" - Then Expect `t` event to be send with a value of 9 as `ti` param - - Scenario: Watching the video from the Continue Watching shelf with 1 fast-forwad and 1 rewind actions - Given Start watching the video "Elephants Dream" from the 3:00 minute (from Continue Watching shelf) - When Watch the video from "03:00 to 03:30" - Then Expect 2 `t` events to be sent with values of 4 and 20 as `ti` param - When Fast-forward the video from "03:30 to 06:00" - Then Expect `vs` event to be sent - When Watch the video from "06:00 to 06:35" - Then Expect 2 `t` events to be sent with values of 14 and 20 as `ti` param - When Rewind the video from "6:35 to "02:00" - Then Expect `vs` event to be sent - When Watch the video from "2:00 to 2:15" - Then Expect `t` event to be sent with a value of 10 as `ti` param - - Scenario: Watching the video from the beginning with 1 fast-forwad and video closing - Given Start watching the video "Elephants Dream" - When Watch the video from "00:00 to 00:25" - Then Expect `t` event to be sent with a value of 20 as `ti` param - When Fast-forward the video from "00:25 to 07:00" - Then Expect `vs` event to be sent - When Watch the video from "7:00 to 7:15" - Then Expect `t` event to be sent with a value of 14 as `ti` param - When Click on "Back" button - Then Expect `gab` event to be sent - - Scenario: Watching the video from the Continue Watching shelf till the end - Given Start watching the video "Elephants Dream" from the 10:00 minute (from Continue Watching shelf) - When Watch the video from "10:00 to 10:53" - Then Expect 3 `t` events to be sent with values of 12, 20 and 20 as `ti` param - Then Expect `gab` event to be sent - - Scenario: Watching Live Stream and rewinding - Given Start watching "Channel 1" from any point - When Watch 25 seconds of the stream - Then Expect 1 `t` event to be sent with a value of 20 as `ti` param - When Rewind the video 2 minutes before the current point - Then Expect `vs` event to be sent - When Watch 20 seconds of video - Then Expect 1 `t` event to be sent with a value of 20 as`ti` param diff --git a/platforms/web/types/global.d.ts b/platforms/web/types/global.d.ts index e324effa9..de90d7263 100644 --- a/platforms/web/types/global.d.ts +++ b/platforms/web/types/global.d.ts @@ -1,7 +1,6 @@ // noinspection JSUnusedGlobalSymbols interface Window { jwplayer?: jwplayer.JWPlayerStatic; - jwpltx: Jwpltx; } interface HTMLDivElement { diff --git a/platforms/web/types/jwpltx.d.ts b/platforms/web/types/jwpltx.d.ts deleted file mode 100644 index 1babd5222..000000000 --- a/platforms/web/types/jwpltx.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -interface Jwpltx { - ready: ( - analyticsid: string, - hostname: string, - feedid: string, - mediaid: string, - title: string, - accountid?: number, - appid?: string, - appversion?: string, - ) => void; - adImpression: () => void; - seek: (offset: number, duration: number) => void; - seeked: () => void; - time: (position: number, duration: number) => void; - complete: () => void; - remove: () => void; -}