Plugin overview

Every Playerstack feature beyond “play a video” is a plugin. The standalone bundle pre-registers 16 of them; sellf-adapter is opt-in.

Marketing

PluginWhat it does
intro-cardPre-roll splash with title, subtitle, badge, CTA, big play button
branded-thumbCustom poster + click-to-load (LCP + GDPR)
cta-endOverlay HTML at end of video, button with UTM, replay
action-barMid-video dismissible banner with CTA
email-gateLead capture: pause and require email to keep watching
yt-subscribeSubscribe-on-YouTube bar below the player
autopreviewMuted autoplay when in viewport

E-Learning

PluginWhat it does
chaptersClickable chapter list, syncs with playback
saved-positionResume watching where the visitor left off
focus-modeAuto-pause when the tab loses focus

Performance & UX

PluginWhat it does
sourcesAuto-detects YT/Vimeo/MP4/HLS/WebM/DASH from one URL
controls-policyTheme color, show/hide controls
stickyPin to viewport corner when scrolled past

Branding

PluginWhat it does
watermarkCorner-pinned logo or text overlay, optional click-through
custom-cssInject arbitrary scoped CSS — escape hatch for anything controls-policy lacks

Analytics & Integrations

PluginWhat it does
analyticsForward events to a beacon endpoint or gtag
sellf-adapterLoad config from a Sellf product endpoint (opt-in)

Plugin lifecycle

Each plugin is an object with name, init(ctx), and an optional destroy(ctx).

When <player-stack> connects to the DOM:

  1. The current ConfigProvider loads config from the element (default: inline attributes + data-config)
  2. <media-player> is mounted with the config
  3. init(ctx) runs on each registered plugin in registration order
  4. init is awaited — async plugins block later plugins (rare, but supported)

When the element disconnects:

  1. destroy(ctx) runs on each plugin in reverse order
  2. Errors in destroy are caught and logged so all plugins get cleaned up

See Core API for the full interface.

Multi-instance safety

Every first-party plugin uses a WeakMap<PlayerstackContext, ...> for per-element state. You can put dozens of <player-stack> elements on one page with different configs — they don’t collide.

When you write your own plugin (see Recipes), use the same pattern.