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:

  1. Tracking ad_type: each component reports a fixed ad_type for its scenario (banner / mrec / popup / preroll / floating…). Using SwAdBanner to build a popup reports ad_type=banner, and the data team's popup reports stay at zero forever.
  2. Impression timing semantics: most components report impressions via IntersectionObserver ("once on viewport entry"); but SwAdPopup reports "on layer display", and SwAdPreroll reports 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 needUseIndustry termImpression timingTypical data source
Entry / splash auto-popup (frequency capped)SwAdSplash (mode=sequential/carousel)App-Open / SplashOn layer display (ad_type=splash)system/info.layers
Business-triggered fullscreen popup (click / every N swipes in a feed)SwAdPopup (ref.open())Interstitial / VignetteOn layer display (ad_type=popup)Business-defined
Page banner (top / middle / footer / around player)SwAdBannerBanner / LeaderboardIO, once on entryads.home_banner etc.
Sidebar / player-page rectangleSwAdMrecMREC (IAB 300×250)IO, once on entryads.*_mrec
App recommendation grid / rail / list gridSwAdIconIcon adsIO, once on entryads.app_info_*
Text links (below navbar / top)SwAdTextText linkIO, once on entryads.top_links
Scrolling notice stripSwAdMarqueeMarqueeIO, once on entryads.*_marquee
In-feed native cardSwAdNativeNative / In-feedIO, once on entryads.*_feed
Fixed side floats (hidden on narrow screens)SwAdFloatingFloating / AnchorOn visibleads.app_float_right
Video pre-roll (player's #preroll-ad slot)SwAdPrerollIAB in-stream pre-rollOn mountdetail API play_ads / ads.app_info_player_preroll
Video pause ad (player's #pause-ad slot)SwAdPausePause Ad / Pause Screen AdOn display (shown on gated pause, closable)ads.app_info_player_pause
Compliance "Ad" badgeSwAdLabelAd badgeNot 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.enabled in swift.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 / @click events (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