Ad Component Selection
The framework's SwAd* ad family is organized by ad placement scenario, using the same vocabulary as mainstream SDKs (AdMob / MAX-style BannerAd / InterstitialAd / NativeAd). This page is the single decision entry for selection: determine the scenario first, then pick the component.
Why select by scenario, not by looks
Ad components ship two things the business never sees but the data team deeply cares about:
- Tracking
ad_type: each component reports a fixedad_typefor its scenario (banner / mrec / popup / preroll / floating…). Using SwAdBanner to build a popup reportsad_type=banner, and the data team's popup reports stay at zero forever. - Impression timing semantics: most components report impressions via IntersectionObserver ("once on viewport entry"); but
SwAdPopupreports "on layer display", andSwAdPrerollreports on mount (the pre-roll layer is gated by the player, mounted = necessarily visible). Putting SwAdPreroll into a regular layout would report impressions the user never saw.
Anti-pattern (real archaeology, anonymized): one site hand-rolled a grid ad component for list pages — click tracking was written, impression tracking was entirely missing, so the data side saw clicks without impressions and every CTR report was distorted; another site's app promo card had a tracking section that was pure comments with no implementation. Hand-rolled ad components almost always end with broken tracking — which is exactly why tracking is pushed down into framework components.
Selection Table
| The ad placement I need | Use | Industry term | Impression timing | Typical data source |
|---|---|---|---|---|
| Entry / splash auto-popup (frequency capped) | SwAdSplash (mode=sequential/carousel) | App-Open / Splash | On layer display (ad_type=splash) | system/info.layers |
| Business-triggered fullscreen popup (click / every N swipes in a feed) | SwAdPopup (ref.open()) | Interstitial / Vignette | On layer display (ad_type=popup) | Business-defined |
| Page banner (top / middle / footer / around player) | SwAdBanner | Banner / Leaderboard | IO, once on entry | ads.home_banner etc. |
| Sidebar / player-page rectangle | SwAdMrec | MREC (IAB 300×250) | IO, once on entry | ads.*_mrec |
| App recommendation grid / rail / list grid | SwAdIcon | Icon ads | IO, once on entry | ads.app_info_* |
| Text links (below navbar / top) | SwAdText | Text link | IO, once on entry | ads.top_links |
| Scrolling notice strip | SwAdMarquee | Marquee | IO, once on entry | ads.*_marquee |
| In-feed native card | SwAdNative | Native / In-feed | IO, once on entry | ads.*_feed |
| Fixed side floats (hidden on narrow screens) | SwAdFloating | Floating / Anchor | On visible | ads.app_float_right |
Video pre-roll (player's #preroll-ad slot) | SwAdPreroll | IAB in-stream pre-roll | On mount | detail API play_ads / ads.app_info_player_preroll |
Video pause ad (player's #pause-ad slot) | SwAdPause | Pause Ad / Pause Screen Ad | On display (shown on gated pause, closable) | ads.app_info_player_pause |
| Compliance "Ad" badge | SwAdLabel | Ad badge | Not reported | — |
Reserved scenarios (no component yet; names are reserved — never implement under an alias): SwAdInterstitial (interstitial). File a framework issue when these arise; do not hand-roll.
How to read the "Four Essentials"
Every SwAd* component carries the same four-essentials block in its JSDoc header and docs page head:
- Use case: where on the page / when this component belongs — if it doesn't match, switch components
- Industry form: the IAB / mainstream-SDK term (aligns vocabulary with the data team and ops)
- Visual form: what it renders (single image / carousel / grid / overlay…)
- Tracking events: which events auto-report and which impression-timing semantics apply
Before coding against a component, check its "Use case" line first; looking similar does not mean the scenario matches.
Data Protocol Quick Reference
// ① system/info.layers — entry splash queue (SwAdSplash)
// each layer: { type: 'adv'|'app'|'notice', data: ... }
// ② system/info.ads.* — per-slot placements
// e.g. ads.home_banner / ads.top_links / ads.app_float_right
// ③ detail API play_ads — video pre-roll ({ id, name, content, link })
// one-line normalize: playAdsToSwAdItems(r.play_ads) → SwAdItem[]
Components only consume SwAdItem; the future AdSDK adapter (getAd data plane) will normalize to the same SwAdItem, so components switch data sources transparently.
Tracking Pipeline & Gates
- Impression / click tracking is built into components, zero config, via
useAdTrack→ WebSDK (adImpression/adClick) - Reporting sits behind a double gate —
tracker.enabledinswift.config.json+system/info.tracker; missing either means silent no-op (write the components anyway, nothing fires in dev) - For extra business analytics use the components'
@impression/@clickevents (auto-tracking already sent) - With an in-house tracking SDK: raw events pass through + useExposure exposes impression timing — you can bypass built-in tracking entirely
See Also
- Ad Components & Tracking — SwAdItem fields, full tracking payload tables
- SwVideoPlayer pre-roll phase