@cockpitify/react-native
v0.1.4
Published
Cockpitify usage analytics for React Native and Expo apps: screen views, events, sessions and AdMob ad revenue.
Maintainers
Readme
@cockpitify/react-native
Usage analytics for React Native and Expo apps: screen views, events and sessions, sent to the ops
layer that Cockpitify installs in your own Supabase project. You see them in
the Cockpitify app.
npx expo install @cockpitify/react-native @react-native-async-storage/async-storageUsing an AI coding assistant? Point it at AI.md (also in node_modules/@cockpitify/react-native/AI.md).
Expo Router
// app/_layout.tsx
import { Stack } from 'expo-router';
import { Ops } from '@cockpitify/react-native';
import { OpsProvider } from '@cockpitify/react-native/expo-router';
import { supabase } from '@/lib/supabase';
Ops.init(supabase);
export default function RootLayout() {
return <OpsProvider><Stack /></OpsProvider>;
}
// When a feature is used:
Ops.track('quiz_started', { level: 3 });Screens are recorded by route pattern (/quiz/[id]), not by the actual id.
React Navigation
import { useOpsNavigation } from '@cockpitify/react-native/react-navigation';
const ops = useOpsNavigation();
<NavigationContainer ref={ops.ref} onReady={ops.onReady} onStateChange={ops.onStateChange}>Not on Supabase Auth
import { Ops, httpTransport } from '@cockpitify/react-native';
Ops.init(httpTransport({ endpoint: 'https://api.example.com/ops', getToken: () => auth.currentUser?.getIdToken() }));Your endpoint verifies the token and passes the batch on to ops.ingest_batch.
AdMob ad revenue
With react-native-google-mobile-ads, each impression's earnings (what AdMob reports for that ad, format and country) are recorded next to the user and added to their margin. Turn on impression-level ad revenue in the AdMob UI (Settings → Account) first. This adds no dependency: the ads library's objects are recognised by shape.
import { onAdPaid, recordAdRevenue, trackAdRevenue } from '@cockpitify/react-native/admob';
<BannerAd unitId={id} size={BannerAdSize.ANCHORED_ADAPTIVE_BANNER} onPaid={onAdPaid('banner', id)} />
const rewarded = RewardedAd.createForAdRequest(id);
const stop = trackAdRevenue(rewarded, 'rewarded'); // interstitial, app_open, rewarded_interstitial too
// With the hooks (useRewardedAd, useInterstitialAd…): record the last paid event
const { revenue } = useRewardedAd(id);
useEffect(() => { if (revenue) recordAdRevenue(revenue, 'rewarded', id); }, [revenue]);Formats: banner, interstitial, rewarded, rewarded_interstitial, app_open, native. The values are
AdMob's estimates until it closes the month; other currencies are converted to USD at the day's ECB rate.
Ad revenue events are never sampled out, but Ops.optOut() stops them like everything else.
API
| | |
|---|---|
| Ops.init(target, options?) | target: a supabase-js client, an httpTransport(...), or full options. Options: appVersion (e.g. Constants.expoConfig?.version), debug. |
| Ops.track(name, props?) | An event. Props are strings, numbers or booleans. |
| Ops.screen(name) | A screen view, when you name screens yourself. |
| Ops.flush() | Sends what is queued now. |
| Ops.optOut() / Ops.optIn() | Stops or resumes recording on this device. |
Recording never throws into your code. Events are kept in AsyncStorage, sent in batches and retried when offline. A new session starts after 30 minutes away from the app.
