Respectlytics Respect lytics
Menu
React Native Push notification opt-in Privacy-first

How to track push notification opt-in in React Native without personal data

Push opt-in rate is one of the highest-leverage signals in mobile analytics: it gates every re-engagement channel you have. Respectlytics helps developers avoid collecting personal data in the first place: the opt-in event in React Native is just `push_optin` — no device token, no APNs identifier, no Firebase Cloud Messaging registration ID. Below: how to wire the call into the system permission callback on React Native, how to A/B-test prompt timing without per-user assignment, and the trade-off you make by not storing a per-user opt-in state.

Wire the call into the same callback that receives the system permission result. On success, emit `push_optin`. If you also want to measure declines (most teams do), emit `push_decline` on the negative result. Don't pass the device token or any registration ID as metadata — your push backend already has those.

Install the React Native SDK

bash Respectlytics
npm install @respectlytics/react-native
# or
yarn add @respectlytics/react-native

JavaScript-only — no native modules, no auto-linking, no New Architecture migration concerns. Bundle size: ~14KB minified+gzipped. Works in any Expo project (managed or bare) without `expo prebuild`.

Initialize Respectlytics in React Native

js Respectlytics
// App.tsx (or App.js)
import { useEffect } from 'react';
import Respectlytics from '@respectlytics/react-native';

export default function App() {
  useEffect(() => {
    Respectlytics.configure({ appKey: '<YOUR_APP_KEY>' });
  }, []);
  return <YourApp />;
}

Initialize once in your top-level component. No native config; no Info.plist or AndroidManifest changes. The SDK is Hermes- and JSC-compatible.

Track the event in React Native

js Respectlytics
import Respectlytics from '@respectlytics/react-native';
import messaging from '@react-native-firebase/messaging';
import { Platform, PermissionsAndroid } from 'react-native';

async function requestPushPermission() {
  if (Platform.OS === 'ios') {
    const status = await messaging().requestPermission();
    const granted = status === messaging.AuthorizationStatus.AUTHORIZED ||
                    status === messaging.AuthorizationStatus.PROVISIONAL;
    if (status === messaging.AuthorizationStatus.PROVISIONAL) {
      Respectlytics.track('push_provisional_optin');
    } else {
      Respectlytics.track(granted ? 'push_optin' : 'push_decline');
    }
  } else if (Platform.Version >= 33) {
    const result = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
    );
    Respectlytics.track(
      result === PermissionsAndroid.RESULTS.GRANTED ? 'push_optin' : 'push_decline'
    );
  }
}

If you are not using Firebase Messaging, the iOS branch translates 1:1 to `@notifee/react-native`'s `requestPermission()` API. The Android-13 logic is the same.

Privacy & implementation notes

Your push-delivery backend (APNs, FCM, OneSignal, Pusher Beams, etc.) already has the device push token — that's where it lives operationally. Sending it to Respectlytics would just be re-creating a per-user dataset you've already built elsewhere. The API rejects it.

Most push-related product decisions are about *rate*, not *state*: "does moving the prompt to post-onboarding move our DE iOS opt-in rate?". You don't need per-user opt-in state in your analytics pipeline to answer that — you need session-grouped event counts.

The React Native SDK is JavaScript-only — no Objective-C/Swift bridging on iOS, no Java/Kotlin bridging on Android. Side effects: no `react-native link`, no auto-linking, no New Architecture migration concerns, no platform-channel exception surfaces. Trade-off: no access to platform-only metadata (which we don't want to collect anyway).

Works in Expo managed workflow without `expo prebuild`. No config plugin is required. EAS Build users: nothing to configure. This is the smoothest integration path on RN — most analytics SDKs require ejecting from managed.

How this compares to other analytics SDKs

Push opt-in event Firebase Analytics Mixpanel Respectlytics
Device push token stored Yes (FCM token in user property) Yes (in profile) Never
Per-user opt-in state Yes Yes Out of scope (your push backend tracks this)
Prompt timing as event property Recommended Recommended Use distinct event_name
iOS provisional opt-in distinguishable Manual (via param) Manual (via property) Use distinct event_name (push_provisional_optin)
Opt-in rate by country / platform Yes Yes Yes (default aggregation)

Frequently asked questions

How do we know which users opted in if we don't store user state?

You don't, in your analytics. Your push-delivery backend (APNs, FCM, OneSignal, etc.) already has the authoritative opt-in state per device token — that's its job. Respectlytics tells you the opt-in *rate* over sessions, which is the metric you optimize for product decisions.

Can we A/B-test opt-in prompt timing?

Yes — emit distinct event names per prompt-timing variant: `push_optin_at_onboarding`, `push_optin_post_first_session`, etc. The aggregation gives you per-variant conversion rate without any per-user assignment stored.

Should we track when the prompt was *shown* in addition to the result?

Yes, with two event names: `push_prompt_shown` and `push_optin` (or `push_decline`). The session-grouped count gives you prompt → grant rate directly.

What about iOS 15+ provisional authorization?

If you use `provisional` authorization (which doesn't show a prompt and delivers quietly until the user upgrades to full), emit `push_provisional_optin` as a distinct event. It's a different state with different downstream implications, so don't conflate it with the explicit opt-in event.

Related guides

Track what matters. Collect nothing you don't.

Five-field event schema, RAM-only event queue, no IDFA, no AAID, no persistent user IDs. Helps developers avoid collecting personal data in the first place.