Skip to Content
React Native
SDKs

React Native SDK

@notpixel/react-native forwards calls to your chosen AI provider and selects contextual ads in parallel. It returns the provider reply with an optional sponsored block and a structured ad for native rendering.

Installation

Choose direct installation and configure the client in code, or use the optional English assistant. Both paths work with new and existing accounts; SDK usage does not require CLI login.

Direct installation

For local processing (the default) in a React Native CLI app:

npm install @notpixel/react-native @notpixel/react-native-embedding-local cd ios && pod install

For Expo, use npx expo install with these package names and rebuild your native app. Local embeddings are unavailable in Expo Go. Use React Native’s New Architecture. Local examples below import from @notpixel/react-native/local.

For remote processing, install only @notpixel/react-native (using expo install inside Expo projects) and configure the base client explicitly:

import Ads from '@notpixel/react-native'; const ads = new Ads({ publisherId: 'YOUR_PUBLISHER_ID', embeddingMode: 'remote', });

A fresh remote installation has no local inference addon or model download.

Optional assisted installation

npx notpixel@latest install

Run inside your existing app. The assistant detects React Native/Expo, offers login or account creation, asks local/remote, installs the needed packages and generates notpixel.ts. You can then import ads from that generated file. See the installation guide for pnpm, Yarn and Bun.

Preview test ads

Set testMode: true on the client and use getAd({ input }) to preview an eligible ad from the NotPixel API with your publisher ID. The native card shows the test disclosure and disables its CTA and tracking. See Test Mode.

Provider bypass

import Ads from '@notpixel/react-native/local'; const ads = new Ads({ publisherId: 'YOUR_PUBLISHER_ID', model: 'openai/YOUR_MODEL', apiKeys: { openai: userProvidedKey }, }); const result = await ads.offer({ input: 'How can I optimize SQL?' });

Credentials are supplied at runtime. For credentials kept on your server, pass your existing authenticated providerFetch. It receives the original provider URL and request options and returns the provider response, preserving incremental SSE. Keep permanent secrets out of app bundles.

for await (const chunk of ads.stream({ input, signal: controller.signal })) { if (chunk.type === 'text') appendText(chunk.content ?? ''); if (chunk.type === 'ad') setAd(chunk.ad); }

Text streams immediately, followed by an optional ad. Ad failures preserve the provider response. Existing provider prefixes and respond({ input, llm }) are also supported.

Native presentation

import { AdCard, NotPixelProvider } from '@notpixel/react-native/react'; <NotPixelProvider client={ads}> {ad ? <AdCard ad={ad} isVisible={screenIsFocused} /> : null} </NotPixelProvider>

AdCard and AdBanner include disclosure, CTA navigation, tracking, hide/report actions and light/dark styling. Supply screen focus and list viewability through isVisible when screens stay mounted or rows are recycled.

Impressions are confirmed after half the measured area remains in the window for one second while the app is active. The confirmation settles a pending commercial impression once. Reports preserve their draft on failure and hide the ad after confirmed submission.

Render the structured ad separately from provider text to avoid showing the same sponsored block twice. Custom renderers can use ads.tracker.impression, .click, .conversion and .feedback. useAd({ input, requestId, enabled }) provides standalone selection with ad, loading, error and refetch.

Native placements and app verification

In Publisher → Settings → Domains & apps, register the iOS Bundle ID or Android Application ID, then create a placement under that app. Configure App Attest on iOS with the production entitlement, or link your Play Integrity Cloud project and enter the Play app signing certificate and dedicated service account on Android. Use a signed build on a real device to complete app verification.

For Expo, install the native modules with npx expo install @expo/app-integrity expo-crypto expo-secure-store and rebuild the app. The adapter is opt-in and the rest of the SDK works independently of it.

import * as AppIntegrity from '@expo/app-integrity'; import * as Crypto from 'expo-crypto'; import * as SecureStore from 'expo-secure-store'; import { Platform } from 'react-native'; import Ads, { createExpoIntegrityAdapter } from '@notpixel/react-native/local'; const propertyId = 'YOUR_PROPERTY_ID'; const ads = new Ads({ publisherId: 'YOUR_PUBLISHER_ID', native: { propertyId, integrity: createExpoIntegrityAdapter({ propertyId, platform: Platform.OS === 'ios' ? 'ios' : 'android', appIntegrity: AppIntegrity, storage: SecureStore, async hashChallenge(challenge) { const digest = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, challenge, { encoding: Crypto.CryptoEncoding.BASE64, }); return digest.replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, ''); }, }), }, });

Run await ads.verifyNativeApp(code) once from the signed app with the code generated in the panel, then refresh the property status. Warm up with ads.prepareNativeDelivery() before the first request and handle any error without interrupting the app. Use ads.getAd({ input, requestId, placement }) or pass the same fields to useAd. In commercial delivery the card confirms the pending opportunity before enabling the tracked CTA. Custom renderers can call ads.confirmNativeImpression(opportunityId) after qualifying visibility. Use explicit test mode on devices without attestation.

Privacy and initialization

With local processing, only vectors reach the NotPixel ad API; embedding failures never trigger a text fallback. Explicit remote processing sends sanitized context to NotPixel and its Cloudflare inference infrastructure. Your chosen LLM provider receives the original prompt independently of this setting.

Initial local loading downloads approximately 35 MB of verified model/tokenizer assets, then caches them on the device. Preload the model before the first opportunity:

await ads.embedding.preload();

The default ad budget is three seconds, including model loading. Change it with adTimeoutMs. Missing ads do not interrupt the provider response.

See the React Native example  for a demo without credentials or paid calls.

Last updated on
Was this helpful?