@nuviad/ads-sdk
v1.0.2
Published
Nuviad mobile ad SDK for React Native / Expo
Keywords
Readme
@nuviad/ads-sdk
OpenRTB-driven mobile ad SDK for React Native and Expo. Renders banner, native, video, and interstitial ads sourced from the Nuviad SSP; supports AdMob as a no-fill fallback.
- OpenRTB 2.5 BidRequest / BidResponse over JSON
- Geo + device signal: optional
expo-locationGPS, IDFA viaexpo-tracking-transparency, IP via public lookup - Formats: banner, native, full-screen interstitial, in-banner / VAST video
- AdMob fallback: when Nuviad returns 204 no-fill the host app can serve a Google Mobile Ads creative instead (optional peer dep)
- Testable: test-mode request logging, error boundary, fast XML VAST parser
Install
# pnpm
pnpm add @nuviad/ads-sdk
# npm
npm install @nuviad/ads-sdkThen install the peer deps via Expo (handles correct SDK-matched versions):
npx expo install \
@react-native-async-storage/async-storage \
expo-application \
expo-device \
expo-location \
expo-tracking-transparency \
react-native-webviewOptional peers
| Package | When to install |
|---|---|
| expo-tracking-transparency | iOS — required to get a real IDFA (device.ifa). Without it the SDK omits the field. |
| react-native-google-mobile-ads | If you want AdMob fallback for 204 no-fill responses. |
| expo-av | Only if you render <NuviadVideo> (VAST) ads. |
iOS setup
- Configure
expo-tracking-transparencyso iOS knows why you're asking:// app.json "plugins": [ ["expo-tracking-transparency", { "userTrackingPermission": "..." }] ] - Call
requestTrackingPermissionsAsync()once per session before the SDK fires its first request — without it the user sees the zero-UUID and the bid won't carry an IDFA.
Quick start
// App.tsx
import { NuviadAdsProvider, NuviadBanner } from '@nuviad/ads-sdk';
const config = {
appId: 'com.example.myapp',
appName: 'My App',
apiKey: 'nuviad_live_myapp', // public app identifier, not a secret
baseUrl: 'https://rtb.nuviad.com/ssp/publishers',
testMode: false,
collectLocation: true,
collectDeviceId: true,
};
export default function App() {
return (
<NuviadAdsProvider config={config}>
<NuviadBanner placementId="my-banner" width={320} height={50} />
</NuviadAdsProvider>
);
}Interstitial
import { useNuviadInterstitial } from '@nuviad/ads-sdk';
function PostLevelScreen() {
const { show, isReady } = useNuviadInterstitial('end-of-level');
return <Button title="Continue" disabled={!isReady} onPress={() => void show()} />;
}Native ad
import { NuviadNative } from '@nuviad/ads-sdk';
<NuviadNative placementId="feed-native" />VAST video
import { NuviadVideo } from '@nuviad/ads-sdk';
<NuviadVideo placementId="rewarded" onComplete={() => grantReward()} />Configuration
interface NuviadAdsConfig {
appId: string; // OpenRTB app.id / app.bundle
appName?: string; // OpenRTB app.name
apiKey: string; // public Nuviad publisher ID (X-API-Key)
baseUrl: string; // bidder URL — POSTed verbatim
testMode: boolean; // adds `test: 1`; enables `onRequestLog`
collectLocation: boolean; // pull GPS via expo-location
collectDeviceId: boolean; // pull IDFA / GAID
bidFloor?: number; // default 0.01
bidFloorCur?: string; // default 'USD'
auctionType?: number; // 1 = first-price (default), 2 = second
tmax?: number; // exchange timeout hint in ms (default 1500)
timeoutMs?: number; // SDK fetch timeout (default 10_000)
frequencyCap?: Partial<Record<AdFormat, { maxPerSession: number; minInterval: number }>>;
bidRequestExt?: Record<string, unknown>; // merged into request.ext
admobAppId?: string; // initialize AdMob on mount
admobUnits?: Partial<Record<AdFormat, string>>;
onRequestLog?: (entry: RequestLogEntry) => void; // fires only when testMode is true
}Capturing request bodies for debugging
const config = {
...,
testMode: true,
onRequestLog: (entry) => {
// entry.requestBody is the full OpenRTB BidRequest
console.log('[Nuviad]', entry.endpoint, entry.responseStatus, entry.durationMs);
},
};Repository layout
src/
provider/ NuviadAdsProvider, ErrorBoundary, useAdManager, useAdmobReady
components/ NuviadBanner, NuviadNative, NuviadVideo
hooks/ useNuviadInterstitial, useNuviadNative, useNuviadVideo
core/ AdManager (request orchestration), HttpClient (retry + log),
LocationService, DeviceInfoService
openrtb/ parser (BidResponse → AdData), vastParser
types/ public type surfaceDevelop
npm install # or pnpm install
npm run typecheck # tsc --noEmit
npm test # jest
npm run build # tsup → dist/{index.js,index.mjs,index.d.ts}dist/ is gitignored; rebuild before publishing.
Publish a new version
# bump version
npm version patch # or minor / major
npm run build
npm publish --access public # @nuviad scope
git push --tagsLicense
Proprietary — © Nuviad. All rights reserved.
