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

@theprivacylabs/react-native-consent

v0.2.0

Published

DPDP-compliant consent management SDK for React Native apps

Downloads

29

Readme

@theprivacylabs/react-native-consent

DPDP-compliant consent management SDK for React Native apps.

Installation

npm install @theprivacylabs/react-native-consent @react-native-async-storage/async-storage

Quick Start

1. Initialize the SDK

// App.tsx
import { PrivacyLabsConsent } from '@theprivacylabs/react-native-consent';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useEffect } from 'react';

const App = () => {
  useEffect(() => {
    PrivacyLabsConsent.init(
      {
        orgId: 'your-org-id', // From Privacy Labs dashboard
        onConsentChange: (consent) => {
          console.log('Consent changed:', consent);
          
          // Enable/disable analytics based on consent
          if (consent.preferences.analytics) {
            Analytics.enable();
          } else {
            Analytics.disable();
          }
        },
        onError: (error) => {
          console.error('Consent error:', error);
        },
        debug: __DEV__, // Enable debug logs in development
      },
      AsyncStorage
    );
  }, []);

  return <NavigationContainer>...</NavigationContainer>;
};

2. Create Privacy Settings Screen

// PrivacySettingsScreen.tsx
import React, { useEffect, useState } from 'react';
import { View, Text, Switch, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native';
import { useConsent, useConsentCategories, PrivacyLabsConsent } from '@theprivacylabs/react-native-consent';

const PrivacySettingsScreen = () => {
  const { consent, isLoading, setConsent, acceptAll } = useConsent();
  const { categories } = useConsentCategories('en');

  if (isLoading) {
    return <ActivityIndicator size="large" />;
  }

  return (
    <ScrollView style={{ flex: 1, padding: 16 }}>
      <Text style={{ fontSize: 24, fontWeight: 'bold', marginBottom: 8 }}>
        Privacy Settings
      </Text>
      <Text style={{ color: '#666', marginBottom: 24 }}>
        Control how we use your data. You can change these settings at any time.
      </Text>

      {categories.map((category) => (
        <View
          key={category.id}
          style={{
            flexDirection: 'row',
            justifyContent: 'space-between',
            alignItems: 'center',
            paddingVertical: 16,
            borderBottomWidth: 1,
            borderBottomColor: '#eee',
          }}
        >
          <View style={{ flex: 1, marginRight: 16 }}>
            <Text style={{ fontSize: 16, fontWeight: '600' }}>{category.name}</Text>
            <Text style={{ color: '#666', marginTop: 4 }}>{category.description}</Text>
          </View>
          <Switch
            value={consent?.preferences[category.id] ?? category.defaultEnabled}
            disabled={category.required}
            onValueChange={(value) => setConsent({ [category.id]: value })}
          />
        </View>
      ))}

      <View style={{ marginTop: 24, gap: 12 }}>
        <TouchableOpacity
          style={{
            backgroundColor: '#2563eb',
            padding: 16,
            borderRadius: 8,
            alignItems: 'center',
          }}
          onPress={acceptAll}
        >
          <Text style={{ color: 'white', fontWeight: '600' }}>Accept All</Text>
        </TouchableOpacity>

      </View>
    </ScrollView>
  );
};

3. Link Identity After Login

// After user logs in
const handleLogin = async (email: string, password: string) => {
  const user = await authService.login(email, password);
  
  // Link consent to user identity for cross-device sync
  await PrivacyLabsConsent.linkIdentity(email, 'login');
};

// After user signs up
const handleSignup = async (email: string, password: string) => {
  const user = await authService.signup(email, password);
  
  await PrivacyLabsConsent.linkIdentity(email, 'signup');
};

4. iOS App Tracking Transparency (Optional)

For iOS apps that use tracking, you need to request ATT permission:

import { Platform } from 'react-native';
import { PrivacyLabsConsent } from '@theprivacylabs/react-native-consent';

const requestTrackingPermission = async () => {
  if (Platform.OS === 'ios') {
    // Request ATT permission first
    const attStatus = await PrivacyLabsConsent.requestATTPermission();
    
    if (attStatus === 'authorized') {
      // User allowed tracking, show privacy settings
      navigation.navigate('PrivacySettings');
    } else {
      // User denied tracking, set consent accordingly
      await PrivacyLabsConsent.setConsent({
        analytics: false,
        marketing: false,
      });
    }
  } else {
    // Android: just show privacy settings
    navigation.navigate('PrivacySettings');
  }
};

Note: ATT requires native module integration. Install react-native-tracking-transparency for full ATT support.

API Reference

PrivacyLabsConsent

| Method | Description | |--------|-------------| | init(config, asyncStorage) | Initialize the SDK | | getConsentStatus(syncWithServer?) | Get current consent state | | hasConsent(category) | Check if user consented to a category | | getCategories(lang?) | Get available consent categories | | setConsent(preferences) | Update consent preferences | | acceptAll() | Accept all categories | | withdrawConsent() | Withdraw all consent | | linkIdentity(userKey, method?) | Link consent to user identity | | syncFromServer(userId) | Sync consent from another device | | requestATTPermission() | Request iOS ATT permission | | getATTStatus() | Get iOS ATT status | | clearLocalData() | Clear local consent data |

Hooks

useConsent()

const {
  consent,        // Current consent state
  isLoading,      // Loading state
  error,          // Error if any
  hasConsent,     // Check category consent
  setConsent,     // Update preferences
  acceptAll,      // Accept all
  withdrawConsent,// Withdraw consent
  refresh,        // Refresh from server
} = useConsent();

useConsentCategories(lang?)

const {
  categories,  // Array of ConsentCategory
  isLoading,   // Loading state
  error,       // Error if any
  refresh,     // Refresh categories
} = useConsentCategories('en');

Cross-Device Consent Sync

When a user logs in on a new device, their consent preferences are automatically synced:

  1. User gives consent on Device A (web or mobile)
  2. User logs in on Device B (mobile app)
  3. SDK calls linkIdentity() with user's email
  4. Backend finds existing consent and syncs to Device B
  5. onConsentChange callback fires with synced preferences

This ensures consistent consent across all user devices.

Integration Checklist

Before Launch

  • [ ] Install SDK and AsyncStorage
  • [ ] Initialize SDK in App.tsx with orgId
  • [ ] Create Privacy Settings screen with category toggles
  • [ ] Add "Withdraw Consent" button that calls withdrawConsent() (clears local data + records to API)
  • [ ] Add "Privacy Settings" to app settings/profile menu

On User Events

  • [ ] First app launch: Check consent status, show settings if needed
  • [ ] User login: Call linkIdentity(email, 'login')
  • [ ] User signup: Call linkIdentity(email, 'signup')
  • [ ] User logout: Optionally call clearLocalData()

SDK Integration

  • [ ] Gate analytics/marketing SDKs based on consent state
  • [ ] Implement onConsentChange callback to enable/disable SDKs dynamically
  • [ ] See SDK Integration Recipes below for per-SDK examples

SDK Integration Recipes

Important: Mobile SDKs are compiled into your app — you cannot "not load" them at runtime. Instead, consent controls whether each SDK collects data or not. Your app owns execution; Privacy Labs owns consent state + policy.

Firebase Analytics

import analytics from '@react-native-firebase/analytics';
import { PrivacyLabsConsent } from '@theprivacylabs/react-native-consent';

// On app launch — set initial state
const consent = await PrivacyLabsConsent.getConsentStatus();
await analytics().setAnalyticsCollectionEnabled(consent?.preferences.analytics ?? false);

// On consent change — update dynamically
PrivacyLabsConsent.init({
  orgId: 'your-org-id',
  onConsentChange: async (state) => {
    await analytics().setAnalyticsCollectionEnabled(state.preferences.analytics);
  },
}, AsyncStorage);

Firebase Crashlytics

import crashlytics from '@react-native-firebase/crashlytics';

// Gate on analytics (or performance) consent
await crashlytics().setCrashlyticsCollectionEnabled(consent?.preferences.analytics ?? false);

Mixpanel

import { Mixpanel } from 'mixpanel-react-native';

const mixpanel = new Mixpanel('YOUR_TOKEN', true);

// On consent change
if (consent.preferences.analytics) {
  mixpanel.optInTracking();
} else {
  mixpanel.optOutTracking();
}

Adjust (Marketing Attribution)

import { Adjust, AdjustConfig } from 'react-native-adjust';

const adjustConfig = new AdjustConfig('APP_TOKEN', AdjustConfig.EnvironmentProduction);

// Only enable if marketing consent given
if (consent?.preferences.marketing) {
  Adjust.create(adjustConfig);
} else {
  Adjust.setEnabled(false);
}

// On consent change
onConsentChange: (state) => {
  Adjust.setEnabled(state.preferences.marketing);
}

AppsFlyer

import appsFlyer from 'react-native-appsflyer';

// Gate on marketing consent
if (consent?.preferences.marketing) {
  appsFlyer.startSdk();
} else {
  appsFlyer.stop(true);
}

CleverTap / MoEngage (Marketing Push)

// CleverTap
import CleverTap from 'clevertap-react-native';

if (consent?.preferences.marketing) {
  CleverTap.setOptOut(false);
} else {
  CleverTap.setOptOut(true);
}

// MoEngage
import ReactMoE from 'react-native-moengage';

if (consent?.preferences.marketing) {
  ReactMoE.enableDataTracking();
} else {
  ReactMoE.disableDataTracking();
}

Pattern: Consent-Gated SDK Wrapper

// utils/consentGate.ts
import { PrivacyLabsConsent, ConsentPreferences } from '@theprivacylabs/react-native-consent';

export async function ifConsented(
  category: keyof ConsentPreferences,
  action: () => void | Promise<void>
): Promise<void> {
  const hasConsent = await PrivacyLabsConsent.hasConsent(category);
  if (hasConsent) {
    await action();
  }
}

// Usage
await ifConsented('analytics', () => analytics().logEvent('purchase', { value: 99 }));
await ifConsented('marketing', () => Adjust.trackEvent(adjustEvent));

License

MIT