SwAdPreroll
Ad Placement Four Essentials
- Use case: the pre-roll phase before video playback — placed into the
#preroll-adslot ofSwVideoPlayer/SwVideoFeed; countdown / skip / release belong to the player's phase state machine, this component only owns content and tracking- Industry form: IAB in-stream pre-roll (AdSDK v0.0.1 has no matching format yet;
ad_typeuses the framework extension valuepreroll)- Visual form: single image direct render / multi-image carousel inside the pre-roll layer,
fit=contain(player's black background pads the sides), compliance "Ad" badge on by default- Tracking events:
adImpression(reported on mount — the pre-roll layer is necessarily fullscreen-visible, no IntersectionObserver) /adClick; built-in zero-config, silent no-op when the tracker gate is offPicking the wrong scenario = wrong
ad_type/ timing in tracking. See Ad Component Selection.
SwAdPreroll is the pre-roll video ad component. Like SwAdBanner it is an image-type self-rendering component (single item direct, multiple via SwCarousel), with two pre-roll-specific differences: impression reports immediately on mount (the layer is gated by the player = necessarily visible), and images default to contain.
Copy + CTA overlay (opt-in): when an item carries any of
title/description/cta/advertiser, a "headline + sub-copy + CTA button" overlay renders over the creative image (like a real ad); pass onlyimageto keep it image-only. The CTA is a button-styled<span>(the whole ad is already a link; clicks go tolink).
Multi-image carousel inside a 16:9 mock player
Multi-image carousel (autoplayDelay)
fit: contain vs cover
Inside SwVideoPlayer #preroll-ad (real home)
Impression on mount (vs IO-based)
Standard Usage (with the player's pre-roll phase)
<script setup lang="ts">
const { data: r } = await useFetch('/movie/detail/1')
// Legacy play_ads protocol ({ id, name, content, link }) normalized in one line
const items = computed(() => playAdsToSwAdItems(r.value?.play_ads))
</script>
<template>
<SwVideoPlayer
:links="r.play_links"
:preroll-ad="items.length > 0"
:preroll-ad-duration="+r.play_ads_time"
:preroll-ad-auto-close="r.play_ads_auto_jump === 'y'"
>
<template #preroll-ad="{ skip }">
<!-- @empty: release straight into the content when ad data is broken -->
<SwAdPreroll :items="items" slot-key="player_preroll" page-key="movie" @empty="skip()" />
</template>
</SwVideoPlayer>
</template>
The ads.app_info_player_preroll slot of system/info shares the same shape as play_ads — normalize with the same playAdsToSwAdItems().
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
items | SwAdItem[] | ✓ | — | Ad creatives (normalize play_ads protocol via playAdsToSwAdItems first) |
slotKey | string | ✓ | — | Slot key → tracking ad_slot_key |
slotName | string | undefined | Slot name → ad_slot_name | |
pageKey | string | undefined | Page key → page_key | |
pageName | string | undefined | Page name → page_name | |
fit | 'contain' | 'cover' | 'fill' | 'contain' | Image fit (contain shows the full creative; player's black bg pads) | |
showAdLabel | boolean | undefined | Compliance "Ad" badge (recommended on for pre-rolls); when not set it follows the global swiftConfig.ad.showLabel (default true) | |
autoplay | boolean | true | Auto-rotate when multiple items | |
autoplayDelay | number | 3000 | Carousel interval (ms) |
Events
| Name | Payload | Description |
|---|---|---|
load | — | Ad filled and ready |
empty | — | No fill (wire to skip() to release into content) |
impression | items: SwAdItem[] | Impression (auto-tracking already sent; for extra business use) |
click | item: SwAdItem | Creative clicked (auto-tracking already sent) |
playAdsToSwAdItems
Legacy play_ads protocol normalizer (auto-imported):
playAdsToSwAdItems(playAds: PlayAdProtocolItem[] | null | undefined): SwAdItem[]
// Mapping: id→id(String) / name→name / content(image)→image / link→link
// null / undefined / non-array → [] (pair with @empty)
Creative Overlay Tokens (--sw-ad-overlay-*)
The title / description / CTA overlay on the creative is rendered by the internal AdOverlay — SwAdPopup / SwAdSplash share the exact same knobs:
| Variable | Default | Description |
|---|---|---|
--sw-ad-overlay-gradient | linear-gradient(to top, rgb(0 0 0 / 72%), rgb(0 0 0 / 0%)) | Bottom gradient scrim over the creative (keeps text readable) |
--sw-ad-overlay-title-color | rgb(255 255 255) | Title text color |
--sw-ad-overlay-desc-color | rgb(255 255 255 / 88%) | Description text color |
--sw-ad-overlay-advertiser-color | rgb(255 255 255 / 75%) | Advertiser name text color |
--sw-ad-overlay-cta-bg | var(--primary) | CTA button background |
--sw-ad-overlay-cta-color | var(--primary-foreground) | CTA button text color |
--sw-ad-overlay-pb | 1rem | Bottom padding of the creative (tune it to clear safe areas / the ad label) |
Caveats
- Impression timing differs from other SwAd*: banner etc. report on viewport entry via IntersectionObserver; this component reports on mount — never place it in regular page layouts (it would report impressions while invisible); use SwAdBanner there.
- Countdown / skip button / auto-release are the player phase's responsibility (
prerollAdDuration/prerollAdAutoClose/ slot-scopeskip()), not duplicated here. - Video-based pre-roll creative (video instead of image) is reserved for v2, pending real demand.