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

@adshift/react-native-plugin

v1.0.0

Published

AdShift SDK for React Native - Mobile Attribution, Event Tracking, SKAdNetwork 4.0+, Deep Linking and GDPR/TCF 2.2 Compliance

Readme

AdShift React Native Plugin

npm version Platform React Native License

Official AdShift SDK for React Native. This plugin wraps the native iOS SDK and Android SDK, providing a unified TypeScript API for React Native apps.

Enable mobile attribution, in-app event tracking, SKAdNetwork 4.0+ integration, deep linking, and GDPR/TCF 2.2 compliance in your React Native apps.


📚 Table of Contents


Features

  • Install Attribution — Accurate install tracking across platforms
  • In-App Event Tracking — Track user actions and conversions with 30+ predefined events
  • SKAdNetwork 4.0+ — Full support for iOS privacy-preserving attribution
  • Deep Linking — Direct and deferred deep link support with unified API
  • GDPR/DMA Compliance — Manual consent and TCF 2.2 automatic collection
  • Offline Mode — Events are cached and sent when connectivity returns
  • New Architecture — Built for React Native 0.82+ with Turbo Modules
  • TypeScript First — Full type definitions with IntelliSense support
  • Cross-Platform — Single API for iOS and Android

Requirements

| Platform | Minimum Version | |----------|-----------------| | React Native | 0.82.0+ (New Architecture) | | iOS | 15.0+ | | Android | API 21+ (Android 5.0) | | Node.js | 18+ | | TypeScript | 5.0+ (recommended) |

⚠️ Note: This plugin requires React Native's New Architecture (Turbo Modules). Old Architecture (Bridge) is not supported.


Installation

Using npm

npm install @adshift/react-native-plugin

Using yarn

yarn add @adshift/react-native-plugin

iOS Setup (CocoaPods)

After installing the npm package:

cd ios && pod install

Android Setup

No additional setup required — the plugin auto-links with React Native.


Quick Start

1. Initialize the SDK

⚠️ Important: iOS and Android apps have different API keys. Get both from your AdShift dashboard.

import { Platform } from 'react-native';
import { Adshift } from '@adshift/react-native-plugin';

// API keys are different for iOS and Android
const API_KEYS = {
  ios: 'YOUR_IOS_API_KEY',
  android: 'YOUR_ANDROID_API_KEY',
};

// Initialize in your app's entry point (App.tsx or index.js)
Adshift.initialize({
  apiKey: Platform.select({
    ios: API_KEYS.ios,
    android: API_KEYS.android,
    default: API_KEYS.android,
  })!,
  isDebug: __DEV__, // Enable debug logs in development
});

2. Start Tracking

// Start the SDK (typically after user consent or app launch)
const result = await Adshift.start();

if (result.success) {
  console.log('AdShift started successfully');
}

3. Track Events

import { Adshift, AdshiftEventType } from '@adshift/react-native-plugin';

// Track a simple event
await Adshift.trackEvent(AdshiftEventType.LOGIN);

// Track event with parameters
await Adshift.trackEvent(AdshiftEventType.ADD_TO_CART, {
  product_id: 'SKU123',
  price: 29.99,
  quantity: 1,
});

// Track purchase (for SKAdNetwork conversion value)
await Adshift.trackPurchase({
  productId: 'premium_subscription',
  revenue: 9.99,
  currency: 'USD',
  transactionId: 'TXN_12345',
});

4. Handle Deep Links

import { useEffect, useRef } from 'react';
import { Adshift } from '@adshift/react-native-plugin';
import type { DeepLinkSubscription } from '@adshift/react-native-plugin';

function App() {
  const subscriptionRef = useRef<DeepLinkSubscription | null>(null);

  useEffect(() => {
    // Listen for deep links (direct and deferred)
    subscriptionRef.current = Adshift.onDeepLink((deepLink) => {
      if (deepLink.status === 'found') {
        console.log('Deep link URL:', deepLink.deepLink);
        console.log('Is deferred:', deepLink.isDeferred);
        // Navigate based on deepLink.deepLinkValue or deepLink.params
      }
    });

    return () => {
      subscriptionRef.current?.remove();
    };
  }, []);

  return <YourApp />;
}

API Reference

SDK Lifecycle

Adshift.initialize(config)

Configure the SDK. Call this before any other SDK method.

⚠️ Note: iOS and Android apps require separate API keys from the AdShift dashboard.

import { Platform } from 'react-native';
import type { AdshiftConfig } from '@adshift/react-native-plugin';

const config: AdshiftConfig = {
  apiKey: Platform.OS === 'ios' ? 'IOS_KEY' : 'ANDROID_KEY', // Required - platform-specific!
  isDebug: true,                     // Optional: Enable debug logs
  appOpenDebounceMs: 10000,          // Optional: Debounce for app_open events (ms)
  
  // iOS only
  disableSKAN: false,                // Optional: Disable SKAdNetwork
  waitForATTBeforeStart: true,       // Optional: Wait for ATT before install event
  attTimeoutMs: 30000,               // Optional: ATT timeout (ms)
  
  // Android only
  collectOaid: false,                // Optional: Collect OAID (China devices)
};

Adshift.initialize(config);

Adshift.start()

Start the SDK and begin tracking. Returns a promise with the result.

const result = await Adshift.start();
// result: { success: boolean, message?: string }

Adshift.stop()

Stop the SDK. Events will not be tracked until start() is called again.

Adshift.stop();

Adshift.isStarted()

Check if the SDK is currently running.

const isRunning = Adshift.isStarted(); // boolean

Event Tracking

Adshift.trackEvent(eventName, values?)

Track an in-app event with optional parameters.

// Simple event
await Adshift.trackEvent(AdshiftEventType.LOGIN);

// Event with parameters
await Adshift.trackEvent(AdshiftEventType.SEARCH, {
  search_term: 'running shoes',
  results_count: 42,
});

// Custom event
await Adshift.trackEvent('custom_button_click', {
  button_name: 'checkout',
});

Adshift.trackPurchase(params)

Track a purchase event. Use this for accurate SKAdNetwork conversion value calculation.

await Adshift.trackPurchase({
  productId: 'com.app.premium',
  revenue: 9.99,           // Use 'revenue' for SKAN CV calculation
  currency: 'USD',
  transactionId: 'txn_123',
});

💡 Tip: Use revenue (not price) for accurate SKAdNetwork attribution.

Predefined Event Types

import { AdshiftEventType } from '@adshift/react-native-plugin';

// Available events
AdshiftEventType.LOGIN
AdshiftEventType.PURCHASE
AdshiftEventType.ADD_TO_CART
AdshiftEventType.ADD_TO_WISHLIST
AdshiftEventType.COMPLETE_REGISTRATION
AdshiftEventType.INITIATED_CHECKOUT
AdshiftEventType.ADD_PAYMENT_INFO
AdshiftEventType.SUBSCRIBE
AdshiftEventType.START_TRIAL
AdshiftEventType.LEVEL_ACHIEVED
AdshiftEventType.ACHIEVEMENT_UNLOCKED
AdshiftEventType.TUTORIAL_COMPLETION
AdshiftEventType.CONTENT_VIEW
AdshiftEventType.LIST_VIEW
AdshiftEventType.SEARCH
AdshiftEventType.RATE
AdshiftEventType.SHARE
AdshiftEventType.INVITE
AdshiftEventType.RE_ENGAGE
AdshiftEventType.UPDATE
AdshiftEventType.OPENED_FROM_PUSH_NOTIFICATION
AdshiftEventType.AD_CLICK
AdshiftEventType.AD_VIEW
AdshiftEventType.SPENT_CREDITS
AdshiftEventType.TRAVEL_BOOKING
AdshiftEventType.LOCATION_CHANGED
AdshiftEventType.LOCATION_COORDINATES
AdshiftEventType.ORDER_ID
AdshiftEventType.CUSTOMER_SEGMENT

Consent Management

Manual Consent (GDPR/DMA)

import { AdshiftConsent } from '@adshift/react-native-plugin';

// For GDPR users — grant all consent
Adshift.setConsentData(
  AdshiftConsent.forGDPRUser({
    hasConsentForDataUsage: true,
    hasConsentForAdsPersonalization: true,
    hasConsentForAdStorage: true,
  })
);

// For GDPR users — deny consent
Adshift.setConsentData(
  AdshiftConsent.forGDPRUser({
    hasConsentForDataUsage: false,
    hasConsentForAdsPersonalization: false,
    hasConsentForAdStorage: false,
  })
);

// For non-GDPR users (e.g., US users without state privacy laws)
Adshift.setConsentData(AdshiftConsent.forNonGDPRUser());

TCF 2.2 Automatic Collection

If you use a CMP (Consent Management Platform) that stores IAB TCF data:

// Enable TCF collection BEFORE calling start()
Adshift.enableTCFDataCollection(true);

// Start SDK after CMP dialog completes
await Adshift.start();

// Refresh consent after user changes preferences
const snapshot = await Adshift.refreshConsent();
console.log('Consent source:', snapshot.source);
console.log('Has consent:', snapshot.hasConsent);

Consent Snapshot Response

interface ConsentSnapshot {
  source: 'manual' | 'tcf' | 'gpp' | 'none';
  gdprApplies?: number;
  tcStringPresent: boolean;
  adUserDataEnabled?: boolean;
  adPersonalizationEnabled?: boolean;
  adStorageEnabled?: boolean;
  appliedAtMillis: number;
  hasConsent: boolean; // Convenience field
}

Deep Linking

Listen for Deep Links

Subscribe to deep link events for both direct and deferred deep links:

import { Adshift, AdshiftDeepLinkStatus } from '@adshift/react-native-plugin';
import type { DeepLinkSubscription, AdshiftDeepLink } from '@adshift/react-native-plugin';

const subscription: DeepLinkSubscription = Adshift.onDeepLink((deepLink: AdshiftDeepLink) => {
  switch (deepLink.status) {
    case AdshiftDeepLinkStatus.FOUND:
      console.log('URL:', deepLink.deepLink);
      console.log('Value:', deepLink.deepLinkValue);
      console.log('Is Deferred:', deepLink.isDeferred);
      console.log('Params:', deepLink.params);
      // Navigate to appropriate screen
      break;
      
    case AdshiftDeepLinkStatus.NOT_FOUND:
      // No deep link available
      break;
      
    case AdshiftDeepLinkStatus.ERROR:
      console.error('Deep link error:', deepLink.errorMessage);
      break;
  }
});

// Clean up when done
subscription.remove();

Handle Incoming URLs

When your app receives a URL (e.g., from Linking API):

import { Linking } from 'react-native';

// Handle URL when app is already open
Linking.addEventListener('url', async ({ url }) => {
  const result = await Adshift.handleDeepLink(url);
  console.log('Deep link result:', result);
});

// Handle URL that launched the app
const initialUrl = await Linking.getInitialURL();
if (initialUrl) {
  await Adshift.handleDeepLink(initialUrl);
}

Deep Link Response

interface AdshiftDeepLink {
  status: 'found' | 'notFound' | 'error';
  deepLink?: string;           // Full URL
  deepLinkValue?: string;      // Routing value (e.g., 'product/123')
  deepLinkSub1?: string;       // Sub-parameter 1
  deepLinkSub2?: string;       // Sub-parameter 2
  deepLinkSub3?: string;       // Sub-parameter 3
  deepLinkSub4?: string;       // Sub-parameter 4
  deepLinkSub5?: string;       // Sub-parameter 5
  params?: Record<string, string>; // All query parameters
  isDeferred: boolean;         // true if from deferred flow
  errorMessage?: string;       // Error description
}

Configuration

Set Customer User ID

Associate events with your own user identifier:

Adshift.setCustomerUserId('user_12345');

💡 Tip: Set CUID before start() to associate it with the install event.

Debug Mode

Adshift.setDebugEnabled(true);

App Open Debounce

Control how often app_open events are sent when the app returns from background:

// Only send app_open if user was away for 30+ seconds
Adshift.setAppOpenDebounceMs(30000);

// Send app_open every time (no debounce)
Adshift.setAppOpenDebounceMs(0);

Get SDK Info

const info = Adshift.getInfo();
console.log(info.platform); // 'ios' or 'android'
console.log(info.version);  // Plugin version

Platform-Specific Setup

iOS Setup

1. Update Podfile

Ensure your iOS deployment target is 15.0+:

# ios/Podfile
platform :ios, '15.0'

Then run:

cd ios && pod install

2. Add App Tracking Transparency (Recommended)

To request IDFA permission, add to Info.plist:

<key>NSUserTrackingUsageDescription</key>
<string>This app uses tracking to provide personalized ads and measure ad effectiveness.</string>

Then configure SDK to wait for ATT:

Adshift.initialize({
  apiKey: 'YOUR_API_KEY',
  waitForATTBeforeStart: true,
  attTimeoutMs: 30000, // 30 seconds
});

3. Configure SKAdNetwork Postback

Add to Info.plist to receive direct SKAN postbacks:

<key>NSAdvertisingAttributionReportEndpoint</key>
<string>https://adshift-skadnetwork.com</string>

4. Configure Universal Links (Deep Linking)

  1. Add Associated Domains capability in Xcode
  2. Add your domain: applinks:yourapp.rightlink.me
  3. Configure apple-app-site-association on your server

For custom URL schemes, add to Info.plist:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>yourapp</string>
    </array>
  </dict>
</array>

Android Setup

1. Update build.gradle

Ensure minimum SDK is 21+:

// android/app/build.gradle
android {
    defaultConfig {
        minSdkVersion 21
    }
}

2. Permissions

These permissions are included in the SDK manifest automatically:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

To remove AD_ID permission (for COPPA compliance):

<uses-permission android:name="com.google.android.gms.permission.AD_ID"
    tools:node="remove" />

3. Configure App Links (Deep Linking)

Add intent filter to AndroidManifest.xml:

<activity android:name=".MainActivity">
  <!-- Existing intent filters... -->
  
  <!-- App Links for deep linking -->
  <intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
      android:scheme="https"
      android:host="yourapp.rightlink.me" />
  </intent-filter>
  
  <!-- Custom URL Scheme -->
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="yourapp" android:host="open" />
  </intent-filter>
</activity>

4. ProGuard Rules (if using code shrinking)

Add to proguard-rules.pro:

# AdShift SDK
-keep class com.adshift.sdk.** { *; }
-keep interface com.adshift.sdk.** { *; }

TypeScript Support

This plugin is written in TypeScript and provides full type definitions out of the box.

Importing Types

import {
  Adshift,
  AdshiftEventType,
  AdshiftConsent,
  AdshiftDeepLinkStatus,
} from '@adshift/react-native-plugin';

import type {
  AdshiftConfig,
  AdshiftDeepLink,
  StartResult,
  EventValues,
  PurchaseParams,
  DeepLinkSubscription,
  DeepLinkCallback,
} from '@adshift/react-native-plugin';

Type Definitions

// Configuration
interface AdshiftConfig {
  apiKey: string;
  isDebug?: boolean;
  appOpenDebounceMs?: number;
  // iOS only
  disableSKAN?: boolean;
  waitForATTBeforeStart?: boolean;
  attTimeoutMs?: number;
  // Android only
  collectOaid?: boolean;
}

// Event values
type EventValues = Record<string, string | number | boolean>;

// Purchase parameters
interface PurchaseParams {
  productId: string;
  revenue: number;
  currency: string;
  transactionId: string;
}

// Start result
interface StartResult {
  success: boolean;
  message?: string;
}

// Deep link callback
type DeepLinkCallback = (deepLink: AdshiftDeepLink) => void;

// Subscription handle
interface DeepLinkSubscription {
  remove: () => void;
}

Example App

The plugin includes a comprehensive example app demonstrating all features:

cd example
yarn install
cd ios && pod install && cd ..

# Run on iOS
yarn ios

# Run on Android
yarn android

The example app includes:

  • SDK initialization and lifecycle management
  • All event types with parameter examples
  • Consent management UI (GDPR/TCF)
  • Deep link testing
  • Live event log console

Troubleshooting

iOS Issues

"Module 'AdshiftSDK' not found"

cd ios
pod deintegrate
pod install

ATT Dialog Not Showing

  1. Ensure NSUserTrackingUsageDescription is in Info.plist
  2. Set waitForATTBeforeStart: true in config
  3. Test on physical device (simulator may not show ATT)

Deep Links Not Working

  1. Verify Associated Domains capability is enabled
  2. Check apple-app-site-association file is accessible
  3. Test with: xcrun simctl openurl booted "yourapp://open?test=1"

Android Issues

Build Fails with Dependency Conflicts

Add to android/build.gradle:

allprojects {
    configurations.all {
        resolutionStrategy {
            force 'com.google.android.gms:play-services-ads-identifier:18.0.1'
        }
    }
}

Deep Links Not Working

  1. Verify intent-filter in AndroidManifest.xml
  2. Check App Links verification: adb shell pm get-app-links your.package.name
  3. Test with: adb shell am start -W -a android.intent.action.VIEW -d "yourapp://open?test=1"

General Issues

Events Not Sending

  1. Check Adshift.isStarted() returns true
  2. Enable debug mode: Adshift.setDebugEnabled(true)
  3. Check network connectivity
  4. Verify API key is correct

TypeScript Errors

Ensure you're using TypeScript 5.0+ and have the latest types:

yarn add @adshift/react-native-plugin@latest

Support

  • 📖 Documentation: https://dev.adshift.com/docs/react-native-sdk
  • 🐛 Issues: https://github.com/AdShift/react_native_plugin/issues
  • 📧 Email: [email protected]

License

This SDK is proprietary software. See LICENSE for details.


© 2024-2026 AdShift. All rights reserved.