React Native SDK

Complete reference for the AppRefer React Native SDK. @apprefer/react-native-sdk is a pure TypeScript package with zero native modules — it layers on top of React Native's built-in Platform and Linking APIs and persists state via AsyncStorage.

Installation#

The SDK is published to npm. Install it along with its single peer dependency, @react-native-async-storage/async-storage:

npm install @apprefer/react-native-sdk @react-native-async-storage/async-storage
# or
yarn add @apprefer/react-native-sdk @react-native-async-storage/async-storage

Alternatively, install the latest commit straight from GitHub:

npm install github:AppAgentic/apprefer-react-native-sdk

Expo projects

If you're on Expo (SDK 49+), AsyncStorage is commonly already part of your dependency tree — verify with npm ls @react-native-async-storage/async-storage before installing it a second time. The AppRefer SDK itself is a pure JS package, so it works in bare React Native, Expo dev builds, and Expo Go (linking requires a native build, which Expo Go supports via the built-in expo-linking).

Native autolinking & iOS pods#

AppRefer itself has no native code, so nothing to link. AsyncStorage does have a native module — on React Native 0.60+ it is autolinked, you only need to install the CocoaPod:

cd ios && pod install && cd ..

Permissions#

The SDK does not declare any Android or iOS permissions on its own. Network access comes from the host app's default INTERNET permission (Android) and App Transport Security defaults (iOS). It does not require com.google.android.gms.permission.AD_ID — no Play Data Safety disclosure is triggered by AppRefer.

Inherited native attribution signals#

When a user clicks a trk.apprefer.com/api/c/<linkId> link and installs the app, the click ID travels through platform-native channels that the React Native SDK automatically picks up:

  • iOS — AdServices / Apple Search Ads. The tracking server performs server-side AdServices token resolution for Apple Search Ads campaigns. No client-side setup required.
  • Android — Google Play Install Referrer. The server parses the referrer string at configure() time via the device fingerprint, extracting gclid, fbclid, ar_click_id and the utm_* params.
  • Both platforms — IP/UA fingerprint. If deterministic signals miss, the backend probabilistically matches the install to the most recent click from the same IP + User-Agent within a short window.

Quickstart#

Call AppRefer.configure() once at app startup — typically from the root component's useEffect or your Expo _layout.tsx.

App.tsx
import { useEffect } from 'react';
import { AppRefer } from '@apprefer/react-native-sdk';

export default function App() {
  useEffect(() => {
    (async () => {
      const attribution = await AppRefer.configure({
        apiKey: 'pk_live_your_key_here', // pk_test_ during development
        debug: __DEV__,
      });

      if (attribution) {
        console.log('Network:', attribution.network);
        console.log('Match type:', attribution.matchType);
      }
    })();
  }, []);

  return /* ...your app */ null;
}

API Reference#

The SDK never crashes the host app

Every public method is wrapped in a try/catch internally and fails silently with a debug log. If a method is called before configure(), it returns without throwing (you'll see a __DEV__ warning in dev builds).

AppRefer.configure(config)#

Initialize the SDK and resolve attribution. On first launch this sends a single network request; subsequent calls return the cached result with no network overhead.

FieldTypeDefaultDescription
apiKeystringrequiredYour SDK key (pk_live_... or pk_test_...)
userIdstring?undefinedOptional RevenueCat user ID to associate with the attribution at init time
debugbooleanfalseEnable verbose console logging
logLevelnumber10 = none, 1 = errors, 2 = warnings, 3 = verbose
Details
Signaturestatic configure(config: AppReferConfig): Promise<Attribution | null>
ReturnsAttribution | null — resolved attribution, or null for organic installs / kill-switch / first-run failure
ThrowsNever

AppRefer.trackEvent(eventName, options?)#

Send a custom event to AppRefer. Purchases are handled automatically via RevenueCat webhooks — use trackEvent for signup, tutorial completion, lead events, etc.

ParameterTypeDefaultDescription
eventNamestringrequiredEvent name (e.g., "signup", "tutorial_complete")
options.propertiesRecord<string, unknown>?undefinedArbitrary key-value metadata
options.revenuenumber?undefinedRevenue amount (e.g., 9.99)
options.currencystring?undefinedISO 4217 currency code (e.g., "USD")
await AppRefer.trackEvent('tutorial_complete', {
  properties: { level: 3, time_spent: 42 },
});

// With revenue
await AppRefer.trackEvent('lead_qualified', {
  revenue: 9.99,
  currency: 'USD',
});

AppRefer.setAdvancedMatching(options)#

Send hashed PII to improve Meta CAPI match rates. All values are SHA256-hashed on-device before being sent — the server never receives plaintext PII.

FieldTypeDefaultDescription
emailstring?undefinedUser's email address
phonestring?undefinedPhone number in E.164 format
firstNamestring?undefinedUser's first name
lastNamestring?undefinedUser's last name
dateOfBirthstring?undefinedDate of birth (YYYYMMDD)
await AppRefer.setAdvancedMatching({
  email: 'user@example.com',
  phone: '+15551234567',
  firstName: 'Jane',
  lastName: 'Doe',
});

AppRefer.setUserId(userId)#

Associate a user ID with the device's attribution. Typically called with the RevenueCat app user ID so purchase webhooks can be matched back to the attributed device.

appreferId must be set on RevenueCat FIRST

Before any purchase can be attributed, you must set the appreferId subscriber attribute on RevenueCat. This is how AppRefer links RevenueCat webhook events back to the attributed device. Without it, purchase events cannot be forwarded to ad networks.
App.tsx
import Purchases from 'react-native-purchases';
import { AppRefer } from '@apprefer/react-native-sdk';

await AppRefer.configure({ apiKey: 'pk_live_...' });

// REQUIRED: link AppRefer device ID to RevenueCat
const deviceId = await AppRefer.getDeviceId();
if (deviceId) {
  Purchases.setAttributes({ appreferId: deviceId });
}

// Optional: mirror RevenueCat user ID back to AppRefer
const info = await Purchases.getCustomerInfo();
await AppRefer.setUserId(info.originalAppUserId);

AppRefer.getAttribution()#

Returns the cached attribution from the last configure() call. Synchronous — no await needed.

Details
Signaturestatic getAttribution(): Attribution | null
ReturnsAttribution | null — cached attribution, or null if configure() has not completed or the install is organic

AppRefer.getDeviceId()#

Returns the stable device ID generated by AppRefer on first run and persisted in AsyncStorage. Use this as the value of the appreferId RevenueCat subscriber attribute.

Details
Signaturestatic getDeviceId(): Promise<string | null>
Returnsstring | null — device UUID, or null before configure() has run

The SDK automatically reads the cold-start launch URL during configure() and extracts any ar_click_id query parameter. For warm-start deep links (e.g. a link tapped while the app is already running), the exported AppReferDeepLinks helper exposes a static extractClickId so you can parse a click ID out of any URL your existing linking code receives:

import { Linking } from 'react-native';
import { AppReferDeepLinks } from '@apprefer/react-native-sdk';

Linking.addEventListener('url', ({ url }) => {
  const clickId = AppReferDeepLinks.extractClickId(url);
  if (clickId) {
    // Your app can now route based on the click ID.
    // The cold-start click ID was already captured during configure().
  }
});

Kill switch

The server-side kill switch ships with the SDK by default. If you disable an app in the AppRefer dashboard, the next configure() response turns the SDK off — all subsequent trackEvent and setAdvancedMatching calls become no-ops until you re-enable it. No app release required.

Attribution Model#

The Attribution type returned by configure() contains the following properties:

PropertyTypeDescription
networkstringAd network (e.g., "meta", "google", "tiktok", "apple_search_ads", "organic")
matchTypestringHow attribution was determined ("click_id", "adservices", "referrer", "organic")
campaignstring?Campaign name (compat alias)
campaignIdstring?Campaign ID from ad network
campaignNamestring?Campaign name from ad network
adGroupIdstring?Ad group / ad set ID
adIdstring?Ad creative ID
keywordstring?Search ad keyword (when applicable)
fbclidstring?Meta click ID (if present)
gclidstring?Google click ID (if present)
ttclidstring?TikTok click ID (if present)
queryParamsRecord<string, unknown>All query parameters from the tracking link
customDataRecord<string, unknown>Custom data attached to the tracking link
createdAtstringISO 8601 timestamp the attribution was resolved

Full Integration Example#

A complete integration wiring AppRefer to RevenueCat, including attribution resolution, user ID linking, and advanced matching after signup:

App.tsx
import { useEffect } from 'react';
import Purchases from 'react-native-purchases';
import { AppRefer } from '@apprefer/react-native-sdk';

export default function App() {
  useEffect(() => {
    (async () => {
      // Configure RevenueCat
      Purchases.configure({ apiKey: 'rc_public_key' });

      // 1. Initialize AppRefer and resolve attribution
      const attribution = await AppRefer.configure({
        apiKey: 'pk_live_your_key_here',
        debug: __DEV__,
      });
      console.log('Network:', attribution?.network ?? 'organic');

      // 2. CRITICAL: link AppRefer device ID to RevenueCat
      //    Without this, purchases CANNOT be attributed to ad campaigns.
      const deviceId = await AppRefer.getDeviceId();
      if (deviceId) {
        Purchases.setAttributes({ appreferId: deviceId });
      }

      // 3. Mirror the RevenueCat user ID back to AppRefer
      const info = await Purchases.getCustomerInfo();
      await AppRefer.setUserId(info.originalAppUserId);
    })();
  }, []);

  return /* ...your app */ null;
}

// Later, after the user signs up...
export async function onUserSignup(email: string, firstName: string) {
  // 4. Advanced matching (hashed on-device)
  await AppRefer.setAdvancedMatching({ email, firstName });

  // 5. Track the signup event
  await AppRefer.trackEvent('signup');
}

Best Practices#

  • Call configure() as early as possible — ideally from your root App component or Expo _layout.tsx. The sooner it runs, the tighter the attribution window.
  • Always set appreferId on RevenueCat immediately after configure(). This is how RevenueCat purchase webhooks are matched back to AppRefer attributions. Without it, purchases cannot be attributed.
  • Call setAdvancedMatching() once per user session — right after signup or login — to lift Meta CAPI match rates.
  • Don't track purchases with trackEvent(). Revenue events are forwarded automatically from RevenueCat webhooks. Use trackEvent() for signup, tutorial completion, onboarding milestones, etc.
  • Use pk_test_ keys in development. Sandbox events are isolated from production and never forwarded to ad networks. Switch to pk_live_ for release builds.
  • Set debug: __DEV__ so verbose logs appear only in development builds.

Troubleshooting#

  • Metro bundler doesn't pick up the SDK. Reset the cache with npx react-native start --reset-cache (or expo start -c on Expo).
  • iOS build fails after install. Re-run cd ios && pod install — AsyncStorage is a native module and needs its pod re-generated.
  • Android build fails with minSdk error. Ensure your app's minSdkVersion is at least 21. This is React Native's own baseline — AppRefer does not raise it further.
  • configure() returns null on every launch. Set debug: true and check the Debugger tab in the AppRefer dashboard to confirm the configure request is arriving — organic installs correctly resolve to null.

Requirements#

RequirementMinimum Version
React Native0.70+
iOS14.0+
AndroidAPI 21 (Android 5.0 Lollipop)
TypeScript5.0+ (optional — works in plain JS too)
Peer dependency@react-native-async-storage/async-storage 1.17+

Source code

The React Native SDK is open source. Browse the repository at github.com/AppAgentic/apprefer-react-native-sdk.