useExposure()
useExposure provides the generic "element entered the viewport once" timing primitive: it attaches an IntersectionObserver (default visibility ratio ≥ 0.5) to the target element, invokes the callback once on first entry, then stops observing automatically (one exposure per element).
It only handles timing — what happens inside the callback is entirely up to you: report via useTracker, call your own tracking SDK, or run pure UI logic (lazy loading / animation triggers). Internally, ad impressions (useAdTrack) and SwLink's :track.exposure are built on it.
Safe no-op in SSR / environments without
IntersectionObserver(returns an empty cleanup).
Parameters
useExposure(el, onExposed, options?)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
el | HTMLElement | ✓ | — | Target element to observe |
onExposed | () => void | ✓ | — | Callback on first viewport entry (fires once) |
options.threshold | number | 0.5 | Visibility ratio threshold |
Return value
() => void — cleanup function: stops observing manually (call on unmount; idempotent no-op once fired).
Examples
One-shot on enter viewport
threshold 0.1 vs 0.9
List exposure counting (tracking)
// Example 1: content card exposure reporting (with useTracker)
const cardRef = ref<HTMLElement>()
let stop = () => {}
onMounted(() => {
stop = useExposure(cardRef.value!, () => {
useTracker().track('appPageitemExposure', { item_id: '123', item_type: 'video', /* … */ })
})
})
onBeforeUnmount(() => stop())
// Example 2: your own tracking SDK (escape hatch — anything inside the callback)
onMounted(() => {
useExposure(bannerRef.value!, () => myOwnSdk.report('banner_seen'))
})
// Example 3: custom threshold (a tall card counts at 20% visibility)
onMounted(() => {
useExposure(listItemRef.value!, onSeen, { threshold: 0.2 })
})
Notes
- Fires once per element: it auto-
disconnects after firing; with DOM reuse (virtual scrolling), call again to re-arm exposure. - Prefer
SwLink :trackfor content cards: card-link scenarios get exposure + click tracking built in (powered by this composable). - Call inside
onMounted(a real DOM element is required); invoke the returned cleanup on unmount.
Related
SwLink— built-in exposure tracking via:track.exposureuseAdTrack— ad impressions (reuses this composable internally)useTracker— unified WebSDK reporting entry