Exposed Pause Ad
The Pause Ad integration enables high-impact, non-intrusive advertising within the StreamLayer Web SDK. When a user pauses a video, the SDK handles the asynchronous loading and rendering of a VAST-compliant ad overlay. It features a robust state management system to help developers synchronize their video player UI with the ad’s lifecycle, ensuring that interactive controls (like play/resume) and animations work seamlessly on desktop.
Alpha Version: This feature is currently in alpha. Expect potential instability, including occasional freezes.
Prerequisites
1. PAL SDK (Optional)
Add the Google PAL SDK to your HTML <head> if you use video ad content and Google Ads:
<script type="text/javascript" src="https://imasdk.googleapis.com/pal/sdkloader/pal.js"></script>Integration
Import UI Component
Import the StreamLayerPauseAd component from the @streamlayer/react/pause-ad package:
import { StreamLayerPauseAd } from '@streamlayer/react/pause-ad'React 17 (Classic) Build
If your app is on React 17 or earlier, use our classic build with integrated polyfills by importing from the classic path:
@streamlayer/react/classic/pause-ad
Standalone Usage (Without Wrapping Video)
StreamLayerPauseAd accepts optional children. If you don't want to wrap your video element, you can render it as a standalone sibling alongside your video. No children are required — the component works on its own.
<App>
{/* Your video — not wrapped by the SDK */}
<div className="video-container">
<video ref={videoRef} onPause={onVideoPause} onPlay={onVideoPlay} />
</div>
<StreamLayerProvider sdkKey="your-sdk-key">
{/* Pause ad rendered independently */}
<StreamLayerPauseAd
showPauseAd={showPauseAd}
onRenderPauseAd={onRenderPauseAd}
onClosePauseAd={onClosePauseAd}
videoPlayerController={videoPlayerController}
pauseAdVastUrl={[{ template: 'default', url: 'https://your-vast-tag-url.com' }]}
/>
</StreamLayerProvider>
</App>When used this way, you control the pause ad's size and position through CSS by targeting the .SL_PauseAd class name:
.SL_PauseAd {
width: 300px !important;
left: auto !important;
}You can inspect the rendered pause ad element in your browser's developer tools to discover additional internal class names for further styling.
Props
| Prop | Type | Description |
|---|---|---|
showPauseAd | boolean | Controls pause ad visibility. Set to true when video pauses. |
onRenderPauseAd | (params: { rendered: boolean }) => void | Called when pause ad overlay renders. Use to hide your UI elements. |
onClosePauseAd | () => void | Called when pause ad closes without resuming video (user dismissed overlay). |
videoPlayerController | VideoPlayerCallback | Called when user resumes video via the pause ad overlay button. |
pauseAdVastUrl | Array<{ template?: 'default'; url: string }> | VAST tag configuration. |
options | StreamLayerPauseAdOptions | Optional configuration (see Options below). |
Options
type StreamLayerPauseAdOptions = {
showPauseButton?: boolean // toggle render our pause ad button or use your button, default is true
pauseAdDelay?: number // delay in ms before showing pause ad after video pause, default is 0 (no delay)
pauseAdRefetchInterval?: number // background refetch interval in ms, used only when pauseAdDelay is 0
}pauseAdVastUrl Configuration
pauseAdVastUrl={[
{
template: 'default', // Currently only 'default' template is supported
url: 'https://your-vast-tag-url.com/vast.xml',
},
]}Note: Only the first item in the array is used. Multi-item rotation is not yet supported.
Ad Loading Strategies
The SDK supports two ad loading strategies depending on the pauseAdDelay and pauseAdRefetchInterval options. This gives you control over whether ads are loaded on-demand when the user pauses, or prefetched in the background for instant display.
On-Demand Loading
When pauseAdDelay is set to a value greater than 0, the SDK does not prefetch or refresh ads in the background. Instead, the ad is loaded during the delay between the video pause and the pause ad display.
How it works:
- User pauses the video,
showPauseAdis set totrue. - The SDK starts the
pauseAdDelaytimer and simultaneously begins loading the VAST ad. - If the ad finishes loading before the timer expires, the ad is displayed when the timer completes.
- If the ad has not finished loading when the timer expires, the SDK continues waiting without rendering — the ad is displayed as soon as loading completes.
- If no ad is available (empty VAST response or load failure), nothing is rendered.
Video pauses
│
▼
pauseAdDelay timer starts + ad load begins
│
├── Ad loads before timer expires → show ad when timer completes
│
└── Timer expires before ad loads → continue waiting → show ad when load completes
(or skip if no ad available)
options={{
pauseAdDelay: 5000, // load ad during this 5s delay
}}Prefetch with Background Refresh
When pauseAdDelay is set to 0 and pauseAdRefetchInterval is defined, the SDK prefetches the ad immediately on initialization and keeps it fresh in the background.
How it works:
- On SDK initialization, the VAST ad is loaded and cached immediately.
- The SDK refreshes the cached ad in the background at the specified
pauseAdRefetchInterval. - When the user pauses the video, the cached ad is displayed instantly (no delay).
- After the ad is displayed, the cache is invalidated and a new ad is loaded right away — this guarantees the user sees a new advertisement every time.
- The background refetch interval restarts after the new ad is loaded.
Because the cache is always invalidated after each display, the pauseAdRefetchInterval only serves as a background keep-alive to ensure the cached ad stays fresh between pauses. You do not need a short interval to guarantee fresh ads — that is already handled by the post-display invalidation.
Recommended: Set
pauseAdRefetchIntervalto a high value (up to 1 hour). Google restricts VAST ad caching to a maximum of 1 hour, so3600000(1 hour) is the upper limit. A longer interval reduces unnecessary network requests and lowers costs while still keeping the cache ready for instant display.
SDK initializes
│
▼
Load ad → cache ready
│
├── refetch interval ──→ refresh cache ──→ refetch interval ──→ ...
│
▼
Video pauses → show cached ad instantly
│
▼
Invalidate cache → load new ad immediately (guarantees fresh ad next time)
│
▼
Restart refetch interval
options={{
pauseAdDelay: 0, // no delay — use prefetched ad
pauseAdRefetchInterval: 3300000, // refresh cached ad every 55 minutes (Google max is 1 hour)
}}Note: Even if both
pauseAdDelayandpauseAdRefetchIntervalare set to0, there will still be a minimal delay before the pause ad appears. This delay is the time the SDK needs to load and prepare the ad content for rendering.
Choosing a Strategy
| Strategy | pauseAdDelay | pauseAdRefetchInterval | Best For |
|---|---|---|---|
| On-Demand | > 0 | Not set | Lower bandwidth usage; acceptable to wait before showing ad |
| Prefetch | 0 (default) | Set (e.g. 3300000) | Instant ad display; always-ready ad experience |
Understanding showPauseAd vs pauseAdRendered
showPauseAd vs pauseAdRenderedThese two flags serve different purposes and are controlled by different parties:
| Flag | Controlled By | Purpose |
|---|---|---|
showPauseAd | You (integrator) | Request to show/hide pause ad |
pauseAdRendered | SDK (via callback) | Actual visibility state on screen |
Why two flags?
showPauseAd is your intent — "I want the pause ad to appear/disappear."
pauseAdRendered is the actual state — "The pause ad is currently visible on screen."
These values don't always match due to animation delays:
- Opening delay: SDK waits for the configured
pauseAdDelaybefore showing the overlay - Closing delay (400ms): SDK animates the overlay before removing it
State combinations
showPauseAd | pauseAdRendered | State |
|---|---|---|
false | false | Video playing or paused without ad |
true | false | Video paused, SDK preparing overlay |
true | true | Pause ad visible on screen |
false | true | Closing animation in progress (400ms) |
Timeline
Video pauses
│
▼
showPauseAd = true ← You set this on video pause
pauseAdRendered = false
│
│ ← pauseAdDelay (SDK loads/retrieves ad, prepares overlay)
▼
showPauseAd = true
pauseAdRendered = true ← SDK calls onRenderPauseAd({ rendered: true })
Hide your UI controls now
│
│ ← User resumes video or closes overlay
▼
showPauseAd = false ← You set this on play/close
pauseAdRendered = true ← Still true! Closing animation playing
│
│ ← 400ms closing animation
▼
showPauseAd = false
pauseAdRendered = false ← SDK calls onRenderPauseAd({ rendered: false })
Safe to show your UI controls
Why this matters
Always use pauseAdRendered to control your UI visibility:
// Correct: hide UI based on actual render state
const showControls = !pauseAdRendered
// This ensures:
// 1. Your controls don't disappear before the ad appears
// 2. Your controls don't reappear during the 400ms closing animationIf you used showPauseAd instead, your controls would:
- Disappear immediately on pause (before the ad actually shows)
- Reappear during the closing animation (overlapping with the ad)
Implementation Example
import { useState, useCallback, useRef } from 'react'
import { StreamLayerProvider, type VideoPlayerCallback } from '@streamlayer/react'
import { StreamLayerPauseAd } from '@streamlayer/react/pause-ad'
export const VideoView = () => {
const [showPauseAd, setShowPauseAd] = useState(false)
const [pauseAdRendered, setPauseAdRendered] = useState(false)
const videoRef = useRef<HTMLVideoElement>(null)
// Called when pause ad overlay renders/hides
const onRenderPauseAd = useCallback((params: { rendered: boolean }) => {
setPauseAdRendered(params.rendered)
}, [])
// Called when pause ad closes without video resumption
const onClosePauseAd = useCallback(() => {
setShowPauseAd(false)
}, [])
// Called when user clicks resume on pause ad overlay
const videoPlayerController: VideoPlayerCallback = useCallback((data) => {
if (data.play === true) {
videoRef.current?.play()
}
}, [])
// Video event handlers
const onVideoPause = useCallback(() => {
setShowPauseAd(true)
}, [])
const onVideoPlay = useCallback(() => {
setShowPauseAd(false)
}, [])
// Hide your UI controls when pause ad is rendered
const showControls = !pauseAdRendered
return (
<StreamLayerProvider sdkKey="your-sdk-key">
<StreamLayerPauseAd
showPauseAd={showPauseAd}
onRenderPauseAd={onRenderPauseAd}
onClosePauseAd={onClosePauseAd}
videoPlayerController={videoPlayerController}
pauseAdVastUrl={[
{
template: 'default',
url: 'https://your-vast-tag-url.com',
},
]}
>
{/* Your video container */}
<div>
<video
ref={videoRef}
onPause={onVideoPause}
onPlay={onVideoPlay}
/>
{/* Hide controls when pause ad is displayed */}
{showControls && (
<div className="video-controls">
{/* Play button, timeline, etc. */}
</div>
)}
</div>
</StreamLayerPauseAd>
</StreamLayerProvider>
)
}Key Points
- You control
showPauseAd: Set it totrueon video pause,falseon play/resume. - Hide UI on render: When
onRenderPauseAdfires withrendered: true, hide your video controls (play button, timeline, etc.). - Handle both exit paths: User can either resume video (via
videoPlayerController) or dismiss the overlay (viaonClosePauseAd). - Single VAST tag: Only one item in
pauseAdVastUrlis processed; additional items are ignored.
Updated 2 days ago
