unified-video-framework
Version:
Cross-platform video player framework supporting iOS, Android, Web, Smart TVs (Samsung/LG), Roku, and more
117 lines • 3.75 kB
JavaScript
import { deviceDetection } from '../utils/DeviceDetection';
export class PlayerAnalyticsAdapter {
constructor(name, config) {
this.currentSessionId = null;
this.eventQueue = [];
this.flushTimer = null;
this.name = name;
this.enabled = true;
this.config = config;
}
async initialize() {
}
async startSession(sessionInfo) {
const sessionId = `sess_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.currentSessionId = sessionId;
const event = {
eventType: 'session_start',
timestamp: Date.now(),
video: sessionInfo.initialVideo,
device: deviceDetection.getDeviceInfo(),
metadata: {
sessionId,
playerId: this.config.playerId,
userId: sessionInfo.userId,
customData: sessionInfo.customData
}
};
await this.trackEvent(event);
return sessionId;
}
async trackEvent(event) {
if (!this.enabled) {
return;
}
this.eventQueue.push(event);
if (this.eventQueue.length >= (this.config.batchSize || 10)) {
await this.flush();
}
else {
this.scheduleFlush();
}
}
async endSession() {
if (this.currentSessionId) {
const event = {
eventType: 'session_end',
timestamp: Date.now(),
metadata: {
sessionId: this.currentSessionId,
playerId: this.config.playerId
}
};
await this.trackEvent(event);
await this.flush();
this.currentSessionId = null;
}
}
async flush() {
if (this.eventQueue.length === 0) {
return;
}
const events = [...this.eventQueue];
this.eventQueue = [];
if (this.flushTimer) {
clearTimeout(this.flushTimer);
this.flushTimer = null;
}
try {
const payload = {
session: {
sessionId: this.currentSessionId || 'unknown',
playerId: this.config.playerId,
timestamp: Date.now(),
customData: {}
},
events
};
const response = await fetch(`${this.config.baseUrl}/analytics/player/ingest`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
...(this.config.tenantId && { 'X-Tenant-ID': this.config.tenantId })
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`Analytics API error: ${response.status}`);
}
}
catch (error) {
console.error('Failed to send analytics events:', error);
this.eventQueue = [...events, ...this.eventQueue];
}
}
async destroy() {
if (this.currentSessionId) {
await this.endSession();
}
if (this.flushTimer) {
clearTimeout(this.flushTimer);
this.flushTimer = null;
}
if (this.eventQueue.length > 0) {
await this.flush();
}
}
scheduleFlush() {
if (this.flushTimer) {
return;
}
this.flushTimer = setTimeout(() => {
this.flush().catch(console.error);
}, (this.config.flushInterval || 30) * 1000);
}
}
//# sourceMappingURL=PlayerAnalyticsAdapter.js.map