@applicaster/zapp-react-native-utils
Version:
Applicaster Zapp React Native utilities package
237 lines (185 loc) • 5.65 kB
text/typescript
import * as R from "ramda";
import { isTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
import { postAnalyticEvent } from "./manager";
import { isLive } from "../playerUtils";
import { extensionsEvents } from "./AnalyticsEvents/helper";
import { AD_EVENT, EVENT_TYPES, PLAYER_DISPLAY_STATES } from "./events";
import { Player } from "../appUtils/playerManager/player";
export interface PlayerAnalyticsTrackerI {
handleAnalyticEvent(
event: QuickBrickPlayer.Events,
eventData?: QuickBrickPlayer.EventData
): void;
setPlayer(player: Player): void;
}
export class PlayerAnalyticsTracker implements PlayerAnalyticsTrackerI {
adTime: number | string;
mediaTime: number | string;
eventType: string;
playerState: QuickBrickPlayer.NativePlayerState;
private player: Player;
setPlayer(player: Player) {
this.player = player;
}
isAdBreak(event: string): boolean {
const adBreakEvents = [
AD_EVENT.ad_break_start,
AD_EVENT.ad_break_completed,
];
const isAdBreak = adBreakEvents.find(
(adBreakEvent) => adBreakEvent === event
);
return !!isAdBreak;
}
get entry(): ZappEntry {
return this.player?.getEntry();
}
getDuration(
event: QuickBrickPlayer.Events,
eventData: QuickBrickPlayer.EventData
) {
const isAdBreak = this.isAdBreak(event);
const isAd = this.setEventType(event) === "ad";
const adDuration = (isAdBreak || isAd) && eventData?.duration;
const entryDuration =
this.playerState?.duration || this.entry?.extensions?.duration;
return adDuration || entryDuration;
}
getId(event: QuickBrickPlayer.Events, eventData: QuickBrickPlayer.EventData) {
const adId = eventData?.id || this.entry?.id;
const excludedEvents = [
AD_EVENT.ad_break_start,
AD_EVENT.ad_break_completed,
];
const isAnExcludedEvent = excludedEvents.find(
(excludedEvent) => excludedEvent === event
);
if (isAnExcludedEvent) {
return null;
}
return adId;
}
getDateTimestamp() {
return Math.floor(Date.now() / 1000);
}
getCurrentPosition(
event: QuickBrickPlayer.Events,
eventData: QuickBrickPlayer.EventData,
streamType: string
) {
const isAdType =
this.setEventType(event) === "ad" ||
this.isAdBreak(event) ||
this.playerState?.isAd;
const isLiveType = streamType === "live";
if (isAdType && eventData) {
this.adTime = isLiveType
? this.getDateTimestamp()
: eventData?.currentTime;
return this.adTime;
}
if (isLiveType) {
return this.getDateTimestamp();
}
this.mediaTime = this.playerState?.currentTime || eventData?.currentTime;
return this.mediaTime;
}
getPlayerState() {
if (this.playerState?.fullscreen) {
return PLAYER_DISPLAY_STATES.fullScreen;
}
if (this.playerState?.inline) {
return PLAYER_DISPLAY_STATES.inline;
}
if (this.playerState?.docked) {
return PLAYER_DISPLAY_STATES.docked;
}
if (this.playerState?.isModal) {
return PLAYER_DISPLAY_STATES.isModal;
}
}
checkEventType(
eventToCheck: string,
analyticEvents: QuickBrickPlayer.Events
): boolean {
const events = Object.values(analyticEvents);
const isOfType = events.find((event) => event === eventToCheck);
if (isOfType) {
return true;
}
return false;
}
setEventType(event) {
const allEventTypes = Object.keys(EVENT_TYPES);
allEventTypes.forEach((eventKey) => {
if (this.checkEventType(event, EVENT_TYPES[eventKey])) {
this.eventType = eventKey;
}
});
return this.eventType;
}
checkIfKeyExists(key, arrayOfKeys) {
const keyExists = arrayOfKeys.find((arrayKey) => arrayKey === key);
if (keyExists) {
return true;
}
return false;
}
prepareAnalyticPayload(
event: QuickBrickPlayer.Events,
eventData: QuickBrickPlayer.EventData
) {
this.setEventType(event);
const id = this.entry?.id;
const mediaDuration = this.getDuration(event, eventData);
const mediaType = this.entry?.type?.value;
const contentType = this.entry?.content?.type;
const isFreeItem =
this.entry?.extensions?.free || this.entry?.extensions?.isFree;
const title = this.entry?.title;
const streamType = isLive(this.entry) ? "live" : "vod"; // Todo: determine other types, channel, podcast, aod
const currentPosition = this.getCurrentPosition(
event,
eventData,
streamType
);
const nativeData = R.omit(
[
"currentTime",
"seekTime",
"seekableDuration",
"isLive",
"event",
"entry",
],
eventData
);
const playerState = this.getPlayerState();
const analyticsCustomProperties = extensionsEvents(this.entry?.extensions);
const payload = {
...nativeData,
media_id: id,
name: title,
media_type: mediaType,
stream_type: streamType,
duration: mediaDuration,
current_position: currentPosition,
player_state: playerState,
stream_format: contentType,
};
if (isFreeItem !== null) {
payload.free_or_paid = isTrue(isFreeItem) ? "free" : "paid";
}
if (analyticsCustomProperties) {
payload.analyticsCustomProperties = analyticsCustomProperties;
}
return payload;
}
handleAnalyticEvent(
event: QuickBrickPlayer.Events,
eventData: QuickBrickPlayer.EventData = {}
) {
this.playerState = this.player?.getState();
postAnalyticEvent(event, this.prepareAnalyticPayload(event, eventData));
}
}