npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dolby-optiview/ads-sdk-react-native

v1.0.0

Published

OptiView Ads SDK for React Native - bridges the native Android/iOS/tvOS SDKs

Readme

@dolby-optiview/ads-sdk-react-native

React Native support for the OptiView Ads SDK, built by bridging the native Android/iOS/tvOS SDKs: a typed JS facade + TurboModule delegate to the native OptiViewAds orchestrator, which owns the PlayerAdapter, overlay rendering, and IMA.

RN app (JS)
  └─ @dolby-optiview/ads-sdk-react-native        typed facade: config, startSession(), events,
       │                            muted/volume, skip/click controls,
       │                            diagnostics, interceptors
       └─ TurboModule (bridge)
            └─ native OptiViewAds orchestrator (ads-sdk / OptiViewAdsSDK)
                 ├─ PlayerAdapter           wraps the *native* player instance
                 ├─ OverlayAdRenderer       native view above the player view
                 └─ GamStreamManager / VastAdManager (native IMA)

Key properties:

  • Native-thread scheduling — the RN JS thread is paused/throttled in PiP and background modes, so no scheduling, break punch-in, cue matching, or ad-progress logic depends on it. Events are buffered natively while JS is paused and delivered on resume.
  • Playback-anchored cutoff — Android and iOS/tvOS own the cutoff timer natively; RN Web uses the Web SDK. Loading does not consume the effective-duration plus adBreakCutSafetyMarginSec budget. Both native bridges preserve a custom margin, including zero. Startup remains bounded independently, and resumed playback does not reset the cutoff. No JS timer drives this behavior.
  • API parity with web — the config is the web OptiViewAdsConfig minus its DOM/function members, and events reuse OptiViewAdsEventMap verbatim.
  • New architecture only (RN ≥ 0.76): TurboModule + Fabric overlay host.
  • Host players: react-native-theoplayer and react-native-video, both resolved through the native view tag (nativeHandle; use the typed useReactVideoHandle() helper for react-native-video).

Installation

Install the beta from npm:

npm install @dolby-optiview/ads-sdk-react-native@next

For reproducible native builds, replace @next with an exact published version and use --save-exact. Native artifacts must match the installed wrapper version. Android automatically includes the THEOplayer integration when the :react-native-theoplayer Gradle project is autolinked; otherwise it builds without THEOplayer. iOS/tvOS can also install either host without the other. Keep the supported RN new-architecture toolchain (and matching react-native-tvos for Apple TV).

The minimum react-native-theoplayer version is 11.7.0 on Android and Web for the experimental PlayerFacade API. Android uses normal Gradle dependency resolution and typed API calls, without package-version or source-file probes. Web also assumes a supported wrapper is installed, without runtime version checks. iOS/tvOS may use older wrappers: they do not use PlayerFacade. The optional npm peer range therefore remains unrestricted.

If an existing .npmrc routes @dolby-optiview to another registry, configure that scope to use https://registry.npmjs.org/ for this consumer. No override is needed when the scope already resolves from public npm.

Android

Add the native repositories to the React Native projects' Gradle configuration, retaining Google and Maven Central:

// android/build.gradle
allprojects {
    repositories {
        maven { url "https://maven.theoplayer.com/releases" }
        // Also required for beta/prerelease SDK versions:
        maven {
            url "https://maven.theoplayer.com/snapshots"
            content { includeGroup "com.dolby.optiview" }
        }
        google()
        mavenCentral()
    }
}

React Native's Gradle plugin may ignore settings-level-only repositories; ensure the repositories are available to the RN projects. The bridge selects the exact Maven version from the installed wrapper's package.json; npm does not contain the native binaries. Do not add snapshotsOnly() filtering: a -beta.N version is not a -SNAPSHOT version. Keep Java 17 and enable core library desugaring in android/app/build.gradle:

android {
    compileOptions { coreLibraryDesugaringEnabled true }
}
dependencies {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}

Restrict the snapshots repository to the OptiView group as shown above, so THEOplayer's version ranges do not select nightly native SDK builds.

For react-native-video, also set this in the host app's android/gradle.properties:

RNVideo_useExoplayerIMA=true

Host selection follows Android autolinking at build time. If the :react-native-theoplayer Gradle project is present, its typed integration is compiled and linked. Otherwise THEOplayer-specific sources and dependencies are excluded. This checks dependency presence only, not versions, files or methods. No SDK host-selection flag or JS API change is needed. If both players are linked, the supplied player view determines the binding; their Media3 dependencies must still be compatible.

The IMA setting uses the real integration instead of react-native-video's stub classes, which otherwise conflict with the IMA SDK supplied by the OptiView runtime.

iOS / tvOS

Add both sources to each platform's Podfile, alongside its normal React Native autolinking setup, then run bundle exec pod install in that native project:

source 'https://github.com/THEOplayer/cocoapods-specs.git'
source 'https://cdn.cocoapods.org/'

The Specs repository is publicly readable over HTTPS, but is not CocoaPods trunk. Keep one platform per Podfile and use compatible Xcode/React Native tooling.

Explicit THEOplayer header workaround

Unpatched react-native-theoplayer 11.5.0/11.6.0 imports a header absent from React Native 0.87.0 and React Native tvOS 0.87.0-0. For these Apple combinations, you may explicitly opt into this narrow workaround while waiting for an upstream wrapper fix:

  1. After installing dependencies, open node_modules/react-native-theoplayer/ios/Theoplayer-Bridging-Header.h.

  2. Remove only this unused import, retaining all other imports:

    #import <React/RCTRootContentView.h>
  3. Persist that one-line change through your app's dependency-patch process so it is reapplied after reinstalls, then run bundle exec pod install and build.

Do not apply this recipe to other versions without checking compatibility. The Ads SDK never applies it automatically or modifies published SDK artifacts.

Native dependency selection

The package autolinks its bundled OptiViewAdsReactNative.podspec and defaults to exact-version OptiViewAdsRuntime and OptiViewAdsReactBridge pods. Core/SDK arrive transitively; OptiViewAdsAdapterTHEOplayer is added at the same version only when the host includes react-native-theoplayer. The wrapper itself is installed from node_modules, not the remote Specs repo.

| Environment at pod install | OptiView native dependencies | | --- | --- | | OPTIVIEW_ADS_NATIVE_PODS unset or 1 (default) | CocoaPods, pinned exactly to the wrapper version | | OPTIVIEW_ADS_NATIVE_PODS=0 | Opt out; the host supplies the native dependencies itself |

On react-native-web, use the package's browser entry and the web SDK's normal player setup; Maven/CocoaPods configuration is only for native targets. See the SDK integration guide.

Managed sessions and React ownership

OptiViewAdsSession owns one fresh connector and one asynchronous startup. It exposes ready, connector, destroyed, getSnapshot() and subscribe(). destroy() waits for pending startup and returns the same cleanup promise on repeated calls. Startup failures automatically clean up the connector and remain observable as status: 'failed' with the original error.

For an ordinary player, let the hook own the session. Memoize the factory; changing its identity explicitly replaces the session, after the previous cleanup finishes. Return null while the player is not ready. The factory runs after React commits, not during render, and StrictMode effect replay does not create a second session.

import { useCallback } from 'react';
import {
  createOptiViewAds,
  OptiViewAdsSession,
  useOptiViewAds,
} from '@dolby-optiview/ads-sdk-react-native';

const createSession = useCallback(() => player
  ? new OptiViewAdsSession(createOptiViewAds(player, sdkConfig), sessionConfig)
  : null, [player, sdkConfig, sessionConfig]);
const ads = useOptiViewAds({ ownership: 'hook', createSession });

For floating playback, retain the session in your playback owner, outside the UI component that unmounts. Observe it from any new host:

const ads = useOptiViewAds({ ownership: 'external', session: retainedSession });

External mode only subscribes to lifecycle state. Unmounting or switching the observed session never destroys it; the playback owner must call await retainedSession.destroy() before releasing the actual native player. This does not preserve or reparent the native player for you. Do not use a React view tag as persistent identity: a restored host may have a new tag while the underlying player remains the same. Retain the session object instead.

Both modes return { session, connector, status, error }. Status is idle without a session, then starting, active, failed or destroyed. Destruction is requested immediately; await destroy() to know native cleanup has finished. Use the managed object's lifecycle rather than directly calling startSession, endSession or destroy on its connector. SDK events, diagnostics, controls and updateAssetParameters / updateAssetParameterMacros remain available through ads.connector; changing targeting does not require recreating the session. The hook does no debug polling and imports no player library or application store. The same API is exported from the native and web entries.

THEOplayer binding and optional debug state

useTHEOplayerAdsBinding works with the native and web entries. It enables usePlayerFacade, forwards host callbacks, waits for a native handle (and the web player element), and returns a memoized createSession factory. It does not create or destroy sessions itself.

const binding = useTHEOplayerAdsBinding({
  config: playerConfig,
  adsConfig: sdkConfig,
  sessionConfig,
  enabled: adsEnabled,
  onPlayerReady,
  onPlayerDestroy,
});
const ads = useOptiViewAds({ ownership: 'hook', createSession: binding.createSession });
const debug = useOptiViewAdsDebug({
  connector: ads.connector,
  status: ads.status,
  enabled: debugEnabled,
  maxEvents: 50,
});
return <THEOplayerView config={binding.playerConfig}
  onPlayerReady={binding.playerHandlers.onPlayerReady}
  onPlayerDestroy={binding.playerHandlers.onPlayerDestroy} />;

Import both new hooks from @dolby-optiview/ads-sdk-react-native. The binding's enabled defaults to true; missing adsConfig or sessionConfig keeps its factory idle. Equivalent configuration data, including reordered object keys, keeps the same factory. Changed configuration, session data, player, enabled state, or targeting-macro callback identity changes it. Memoize macro callbacks; use connector targeting-update methods for changes that must not restart playback. The bridge-safe config plus session macro callbacks are supported, not DOM-based web SDK configuration. Configurations must be acyclic.

External owners can use createSession, configKey, and sessionKey to retain and compare sessions. Keys are opaque in-process values, may contain configuration data, and must not be logged or persisted. The owner decides whether to replace a retained session. After restoring a retained player, call binding.playerHandlers.onPlayerRestored(player); this updates the binding and forwards the optional onPlayerRestored callback. It is not a THEOplayerView prop. The hook never retains native views, transfers player IDs, or chooses floating policy.

useOptiViewAdsDebug is player-independent and opt-in by calling it. enabled defaults to true; false removes its subscriptions and timer. It returns events, details, clearEvents, and exportDiagnostics. History contains only IDs, local receipt timestamps and event names, newest first, without progress ticks or raw event payloads. maxEvents defaults to 50, is clamped to 0–1000, and changing it clears history and metadata. details includes current ad IDs, channel, SDK version, break status and presentation state. These details are for local inspection, not a redacted telemetry payload.

Polling runs once per second only when status is active (the default), never overlaps requests, and ignores late results after cleanup. Metadata and history reset on connector change or disabling. No polling runs in useOptiViewAds itself. clearEvents resets history only. exportDiagnostics remains an explicit on-demand operation even with automatic observation disabled; it returns null without a connector and propagates export failures to the caller. Neither debug observation nor its cleanup controls playback or destroys sessions.

Usage

import { createOptiViewAds } from '@dolby-optiview/ads-sdk-react-native';

const ads = createOptiViewAds({ nativeHandle: viewTag }, config); // config: OptiViewAdsReactNativeConfig
await ads.startSession({ channelId: 'my-channel' });
ads.addEventListener('adbreakbegin', (e) => console.log(e.break.id));
const skipped = await ads.skipAd(); // false until the manifest skipOffset is reached
const clickThrough = await ads.clickAd(); // URL or null; the app decides whether to navigate
ads.setManifestRequestInterceptor(async (request) => ({ ...request }), { timeoutMs: 1500 });
await ads.destroy();

For react-native-theoplayer, pass the player received by onPlayerReady directly on Android, iOS, tvOS, and react-native-web:

const ads = createOptiViewAds(player, config);

The browser entry unwraps player.nativeHandle, creates the THEOplayer web adapter, and uses the browser player's element as the overlay container. No app-side adapter import or handle cast is needed. Create the connector only after the player is mounted; an invalid handle or missing element throws. Destroying the connector releases its adapter listeners without destroying the host player. Native targets still resolve a positive integer view tag.

On web, use the package's browser export condition, or explicitly import createOptiViewAds from @dolby-optiview/ads-sdk-react-native/web. The web SDK runs in-process, without a bridge or TurboModule. The existing one-argument createOptiViewAds(webConfig) remains supported for custom adapters and overlay containers; their lifecycle remains the caller's responsibility. react-native-video continues to use the native bridge only.

THEOplayer Android ad events

Enable usePlayerFacade: true before player creation with react-native-theoplayer 11.7.0 or newer. The native integration registers with com.theoplayer.integration.Integration, supplies its own Ads API, and forwards ad lifecycle and playback events without routing timing through JavaScript. Android ads and breaks use GOOGLE_IMA for CSAI reporting compatibility because Bitmovin treats CUSTOM as SSAI and the native API has no generic CSAI kind. customIntegration: optiview-ads preserves provider identity. OptiView still owns playback; this metadata does not activate THEOplayer's native IMA integration.

single and lshape_ad breaks own the player clock and playback state throughout creative gaps. Active-break adtimeupdate values become player timeupdate unchanged, including whole-pod GAM time. Raw content playback events are hidden; source changes and destruction remain visible. SDK background pauses and seeks are suppressed through their eventual completion. Other formats retain content playback controls. Audio and skip commands delegate to the SDK.

The SDK scheduler reads the raw content engine, never the facade ad clock. Session end resets integration state; destruction unregisters it. The Android THEOplayer integration is included only when its Gradle project is autolinked; apps without that project automatically use the video-only build. Combining native players still requires compatible Media3 dependencies. Native ads must finish before registration.

THEOplayer web ad events

With react-native-theoplayer 11.7.0 or newer, enable usePlayerFacade: true in the player configuration before onPlayerReady. The shared factory automatically registers AdsSDKIntegration: Dolby break/ad lifecycle, quartiles, ad errors and clicks become THEOplayer ad events, identified by integration: 'csai' with customData.provider: 'optiview-ads'. Web clicks use adclicked; the wrapper must support forwarding that event. Analytics must observe the facade, not its raw contentPlayer.

The facade owns the clock throughout single and lshape_ad breaks. It starts at zero and retains the last SDK sample across creative gaps and terminal callbacks. Valid adtimeupdate samples for the active break update the clock and forward player timeupdate unchanged. GAM samples use whole-pod time, including slate, not time relative to each creative. Other formats leave the content clock alone. The SDK itself always uses the underlying content player so its scheduler never reads the facade's ad clock. No skip, impression or completion reason is inferred. Session end clears unfinished break state; destruction also unregisters the integration. Plain browser players remain supported without this event bridge.

The integration supplies an Ads API object with its own subscriptions, current state, empty scheduled lists and skip() delegation. A compatible facade keeps existing listeners attached across registration and removal. Ad playing, waiting and sampled progress events represent full-surface ad playback; paused stays false, including buffering. Public play/pause are consumed during these ads; pausing the ad itself is not supported. Non-content-replacing formats keep content playback state and controls.

With catch-all facade interception, single and lshape_ad breaks suppress raw content playback events until break end; sourcechange and destroy remain visible. SDK-owned content seeks, including deferred resume writes, keep their seeking / seeked events hidden through completion after the break. Public seeking stays false during takeover and pending background seeks. Viewer seeks through the facade or connector after handoff remain visible. Raw SDK listeners are never filtered; older facade builds retain limited per-event filtering.

Facade mute/volume, including changes during content, use the SDK's effective audio owner and existing handoff synchronization, including double-box audio focus. Duplicate audio notifications are absorbed. The sampled clock follows the SDK ad asset or GAM pod; a continuous combined content-and-ad timeline is not implemented. Direct Ads scheduling and target-position break skipping are unsupported.

THEOplayer iOS and tvOS ad events

When react-native-theoplayer is installed, the native bridge automatically registers the Dolby Ads integration on the resolved THEOplayer instance. Ad lifecycle, quartiles, errors, playing, waiting and sampled progress are exposed through THEOplayer's native player and Ads APIs without crossing the JavaScript thread.

For content-replacing breaks, THEOplayer reports the SDK's sampled ad-local time while the backing content is paused. The internal content pause and resume seek sequence are not exposed to player API consumers. The integration is removed before the native Ads SDK instance is destroyed. Other host players do not install this THEOplayer-specific integration.

A persistent Dolby-owned view controller owns the overlay for the connector's lifetime. When react-native-theoplayer reparents its React container for fullscreen, or a native host moves it into a floating-player controller, overlay reanchoring moves the Dolby controller before its view. GAM and VAST IMA retain an owner that still matches the ad view hierarchy.

The native ad models currently identify as Google IMA for compatibility with analytics collectors that classify this integration kind as client-side. The underlying GAM/IMA ad metadata remains available on the translated ad object.

API reference

Every exported function, type and connector method carries TypeScript documentation, visible in the editor and rendered as an HTML API reference that is published with each release next to the web SDK's reference. The connector methods are grouped by task (lifecycle, playback and UI, events, diagnostics), the same way the web OptiViewAds class is.

Supported platforms

  • Android — native bridge with react-native-theoplayer or react-native-video (Media3/ExoPlayer) as the host player.
  • iOS and tvOS — native bridge with the same host players; tvOS through react-native-tvos.
  • react-native-web — the browser entry over the web SDK and its adapters.

Platform notes

  • Anvato break signaling over DASH (ptsSource: 'anvatoCue'): the config value bridges verbatim on all native RN platforms. On RN Android the native Media3/ExoPlayer and THEOplayer adapters deliver Anvato DASH emsg cues (both the direct urn:anvato:es1:052016 scheme and the standardized ID3-in-emsg carriage). On RN iOS/tvOS playback goes through AVFoundation, which has no DASH engine — Anvato signaling there arrives as HLS ID3 GEOB frames, which are already supported; a DASH source simply cannot be played on those platforms.