Integrate smaller AdSense ads into the video player interface
Introduce a new component for displaying companion ads and integrate it into the video modal, allowing for smaller, compliant ad placements alongside video content. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 946a0075-7e32-454b-b348-9e7f576d7f45 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/60d372ff-2c10-46c7-b01b-10c3435136b0/946a0075-7e32-454b-b348-9e7f576d7f45/wfV3fPt
This commit is contained in:
parent
00f9419cb8
commit
0772ae1aab
133
client/src/components/video-companion-ad.tsx
Normal file
133
client/src/components/video-companion-ad.tsx
Normal file
@ -0,0 +1,133 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { X } from 'lucide-react';
|
||||
import AdSenseAd from './adsense-ad';
|
||||
|
||||
interface VideoCompanionAdProps {
|
||||
isVideoPlaying: boolean;
|
||||
showControls: boolean;
|
||||
onClose?: () => void;
|
||||
adSlot: string;
|
||||
position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
|
||||
autoHide?: number; // Auto hide after X seconds
|
||||
size?: 'small' | 'medium';
|
||||
}
|
||||
|
||||
export default function VideoCompanionAd({
|
||||
isVideoPlaying,
|
||||
showControls,
|
||||
onClose,
|
||||
adSlot,
|
||||
position = 'bottom-left',
|
||||
autoHide = 0, // No auto-hide by default
|
||||
size = 'small'
|
||||
}: VideoCompanionAdProps) {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const [shouldShow, setShouldShow] = useState(false);
|
||||
|
||||
// Show ad after 3 seconds of video playing
|
||||
useEffect(() => {
|
||||
let showTimer: NodeJS.Timeout;
|
||||
let hideTimer: NodeJS.Timeout;
|
||||
|
||||
if (isVideoPlaying) {
|
||||
// Show ad after 3 seconds
|
||||
showTimer = setTimeout(() => {
|
||||
setShouldShow(true);
|
||||
setIsVisible(true);
|
||||
}, 3000);
|
||||
|
||||
// Auto hide if specified
|
||||
if (autoHide > 0) {
|
||||
hideTimer = setTimeout(() => {
|
||||
setIsVisible(false);
|
||||
}, (3 + autoHide) * 1000);
|
||||
}
|
||||
} else {
|
||||
setShouldShow(false);
|
||||
setIsVisible(false);
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearTimeout(showTimer);
|
||||
clearTimeout(hideTimer);
|
||||
};
|
||||
}, [isVideoPlaying, autoHide]);
|
||||
|
||||
const handleClose = () => {
|
||||
setIsVisible(false);
|
||||
onClose?.();
|
||||
};
|
||||
|
||||
if (!shouldShow || !isVisible) return null;
|
||||
|
||||
const getPositionClasses = () => {
|
||||
switch (position) {
|
||||
case 'top-left':
|
||||
return 'top-4 left-4';
|
||||
case 'top-right':
|
||||
return 'top-4 right-4';
|
||||
case 'bottom-left':
|
||||
return 'bottom-20 left-4'; // Above video controls
|
||||
case 'bottom-right':
|
||||
return 'bottom-20 right-4'; // Above video controls
|
||||
default:
|
||||
return 'bottom-20 left-4';
|
||||
}
|
||||
};
|
||||
|
||||
const getSizeClasses = () => {
|
||||
switch (size) {
|
||||
case 'small':
|
||||
return { width: '200px', height: '150px' };
|
||||
case 'medium':
|
||||
return { width: '300px', height: '200px' };
|
||||
default:
|
||||
return { width: '200px', height: '150px' };
|
||||
}
|
||||
};
|
||||
|
||||
const sizeStyle = getSizeClasses();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`absolute z-40 ${getPositionClasses()} transition-all duration-300 ${
|
||||
isVisible ? 'opacity-100 scale-100' : 'opacity-0 scale-95'
|
||||
}`}
|
||||
style={sizeStyle}
|
||||
>
|
||||
{/* Ad Container - AdSense Compliant Companion Ad */}
|
||||
<div className="relative bg-white/95 backdrop-blur-sm rounded-lg overflow-hidden border border-gray-200 shadow-xl">
|
||||
{/* Close Button */}
|
||||
<button
|
||||
onClick={handleClose}
|
||||
className="absolute top-1 right-1 z-10 w-5 h-5 bg-gray-800/80 hover:bg-gray-800 rounded-full flex items-center justify-center transition-colors"
|
||||
>
|
||||
<X className="w-3 h-3 text-white" />
|
||||
</button>
|
||||
|
||||
{/* Ad Label */}
|
||||
<div className="absolute top-1 left-1 z-10">
|
||||
<span className="bg-[#da234d] text-white text-xs px-1.5 py-0.5 rounded font-medium">
|
||||
AD
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* AdSense Companion Ad */}
|
||||
<div className="p-1 pt-6 w-full h-full">
|
||||
<AdSenseAd
|
||||
adSlot={adSlot}
|
||||
adFormat="rectangle"
|
||||
width={size === 'small' ? 200 : 300}
|
||||
height={size === 'small' ? 150 : 200}
|
||||
className="w-full h-full"
|
||||
style={{
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -12,6 +12,8 @@ import {
|
||||
|
||||
import QualityIndicator from "./quality-indicator";
|
||||
import VASTPlayer from "./vast-player";
|
||||
import AdSenseAd from "./adsense-ad";
|
||||
import VideoCompanionAd from "./video-companion-ad";
|
||||
|
||||
// HLS.js types for video streaming
|
||||
|
||||
@ -56,7 +58,7 @@ function formatDate(date: Date | string): string {
|
||||
}
|
||||
|
||||
export default function VideoModal({ video, isOpen, onClose, enableAds = true }: VideoModalProps) {
|
||||
const [useVASTPlayer, setUseVASTPlayer] = useState(true);
|
||||
const [useVASTPlayer, setUseVASTPlayer] = useState(enableAds);
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const hlsRef = useRef<Hls | null>(null);
|
||||
const [showShareMenu, setShowShareMenu] = useState(false);
|
||||
@ -71,6 +73,7 @@ export default function VideoModal({ video, isOpen, onClose, enableAds = true }:
|
||||
const [volume, setVolume] = useState(1);
|
||||
const [hoverTime, setHoverTime] = useState(-1);
|
||||
|
||||
|
||||
// All hooks must be declared before any conditional returns
|
||||
useEffect(() => {
|
||||
const handleEscape = (e: KeyboardEvent) => {
|
||||
@ -650,6 +653,25 @@ export default function VideoModal({ video, isOpen, onClose, enableAds = true }:
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Video Companion Ads (AdSense Compliant) */}
|
||||
<VideoCompanionAd
|
||||
isVideoPlaying={isPlaying}
|
||||
showControls={showControls}
|
||||
adSlot="5629279662"
|
||||
position="bottom-right"
|
||||
size="small"
|
||||
autoHide={20}
|
||||
/>
|
||||
|
||||
<VideoCompanionAd
|
||||
isVideoPlaying={isPlaying}
|
||||
showControls={showControls}
|
||||
adSlot="1372934919"
|
||||
position="top-right"
|
||||
size="small"
|
||||
autoHide={25}
|
||||
/>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user