Documentation

React Native / Expo

Install the Expo / React Native SDK, register installs, track events, and read attribution. Setup takes about 5 minutes.

Requirements

  • React Native 0.71+
  • React 18+
  • iOS 14.0+ and Android 7.0+ (API 24+)

Install

npm

npm install appsprint-react-native@^1.1.9
# iOS only
cd ios && pod install

For Expo prebuild, add the config plugin to app.json and run npx expo prebuild. The plugin injects NSUserTrackingUsageDescription on iOS and INTERNET / ACCESS_NETWORK_STATE / AD_ID on Android.

Published on npm. Always use the latest version.

Configure

import { AppSprint } from 'appsprint-react-native';
// Call as early as possible. App.tsx, root layout, or _layout.tsx.
await AppSprint.configure({
apiKey: 'as_live_xxxxx',
});

Non-blocking. configure() resolves after local state is restored; install registration runs in the background on the native side. Lifecycle observers register automatically.

Track events

// Standard event
await AppSprint.sendEvent('login');
// Revenue event. Currency must be a 3-letter ISO code.
await AppSprint.sendEvent('purchase', null, {
revenue: 9.99,
currency: 'USD',
});
// Custom event with parameters
await AppSprint.sendEvent('custom', 'level_complete', {
level: 5,
score: 1200,
});

Read attribution

Once install registration completes, the SDK caches the attribution result from the install response. Native iOS and Android expose synchronous getters; React Native and Flutter bridge calls are asynchronous.

const attr = await AppSprint.getAttribution();
console.log(attr?.source); // "apple_ads", "tracking_link", or "organic"
console.log(attr?.isAttributed); // boolean
console.log(attr?.campaignName); // Campaign name when available
console.log(attr?.appleAds?.campaignId);
console.log(attr?.link?.name);

Verify the connection

Send a test event to confirm end-to-end delivery. You should see it in the AppSprint dashboard within seconds.

const result = await AppSprint.sendTestEvent();
console.log(result.success, result.message);

Reference

Configuration options
OptionTypeDefaultDescription
apiKeystringYour live API key (starts with as_live_).
apiUrlstringhttps://api.appsprint.appOverride for staging or self-hosted environments.
enableAppleAdsAttributionbooleantrueiOS only. Fetches Apple AdServices at install time.
customerUserIdstring | nullnullYour internal user ID. Persists across launches and replays automatically if the first send fails.
autoTrackSessionsbooleantrueFires session_start on configure() and on foreground, debounced to one event per 30 minutes.
autoRefreshAttributionbooleantrueRefetches /v1/sdk/attribution on configure() and foreground transitions.
googleAdsConsentGoogleAdsConsent | nullnullReserved for upcoming Google Ads uploads; not used while Google Ads is coming soon.
isDebugbooleanfalseForces debug-level logging on the native side.
logLevel0 | 1 | 2 | 32 (WARN)0 = DEBUG, 1 = INFO, 2 = WARN, 3 = ERROR.
Supported event types
session_startloginsign_upregisterpurchasesubscribestart_trialadd_payment_infoadd_to_cartadd_to_wishlistinitiate_checkoutview_contentview_itemsearchsharetutorial_completeachieve_levellevel_startlevel_completecustom

Use custom with a name parameter for any event not in this list.

Attribution fields
FieldDescription
source"apple_ads", "tracking_link", or "organic"
isAttributedfalse for organic installs, true otherwise
matchTypeBackend match method: apple_ads, idfa, idfv, gaid, ttclid, gclid, gbraid, wbraid, ip_user_agent, or organic
campaignNameSignal Campaign name when available
linkSignal link object: id, name
appleAdsApple AdServices payload: campaignId, adGroupId, keywordId, countryOrRegion, conversionType
utmSourceUTM source from the signal link
utmMediumUTM medium from the signal link
utmCampaignUTM campaign value from the signal link
API reference

configure(config)

Promise<boolean>

Initializes the SDK. Resolves true after local state is restored; install registration runs in the background.

await AppSprint.configure({ apiKey: '…' })

sendEvent(type, name?, params?)

Promise<boolean>

Enqueues an event locally and schedules a flush. Resolves true once the native bridge accepts it.

await AppSprint.sendEvent('purchase', null, { revenue: 9.99, currency: 'USD' })

type is a string literal — see event types below.

flush()

Promise<void>

Drains the queue immediately. Safe to call repeatedly.

await AppSprint.flush()

refreshAttribution()

Promise<AttributionResult | null>

Fetches the latest attribution from the backend. Self-heals a 404 install_not_found by re-running install.

const attr = await AppSprint.refreshAttribution()

setCustomerUserId(id)

Promise<void>

Updates the customer user ID. Sent immediately if install is registered; otherwise queued and retried automatically.

await AppSprint.setCustomerUserId('user-123')

getAppSprintId()

Promise<string | null>

Returns the install ID, or null before install registration completes.

const id = await AppSprint.getAppSprintId()

getAttribution()

Promise<AttributionResult | null>

Returns the cached AttributionResult.

const attr = await AppSprint.getAttribution()

getAttributionParams()

Promise<Record<string, string>>

Partner-ready flat payload for forwarding to RevenueCat, Superwall, etc.

const params = await AppSprint.getAttributionParams()

enableAppleAdsAttribution()

Promise<boolean>

Re-enables Apple Ads at runtime on iOS. Returns false on Android.

await AppSprint.enableAppleAdsAttribution()

isInitialized()

Promise<boolean>

True once configure() resolved.

await AppSprint.isInitialized()

isSdkDisabled()

Promise<boolean>

True if a 401 or 403 permanently disabled the SDK.

await AppSprint.isSdkDisabled()

sendTestEvent()

Promise<{ success, message }>

Posts a diagnostic event and resolves to (success, message).

const result = await AppSprint.sendTestEvent()

clearData()

Promise<void>

Wipes local state and the event queue. Removes lifecycle observers.

await AppSprint.clearData()

destroy()

Removes native lifecycle observers without wiping data.

AppSprint.destroy()
Offline behavior
  • Events that fail to send are queued in native storage (up to 100 events).
  • The queue persists across app restarts.
  • Queued events are retried when configure() completes, when another event is sent, when lifecycle flushes run, or when you call flush().
  • If a queued event receives a 401/403, the SDK disables itself and clears the queue.
Platform notes
  • The JS layer is a thin bridge. Behavior matches the standalone native iOS and Android SDKs.
  • On iOS, ATT must be requested while the app is foreground-active. NativeAppSprint.requestTrackingAuthorization() waits for that state internally.
  • On iOS, AdServices runs on iOS 14.3+. Older OS versions skip Apple Ads attribution silently.
  • On Android, GAID is read off the main thread, honoring Limit Ad Tracking and dropping the all-zero advertising ID.
  • Events persist to native storage (UserDefaults on iOS, SharedPreferences on Android) and survive app restarts. Maximum queue size is 100 events.
  • iOS uses URLSession with waitsForConnectivity = true. Transient offline windows queue inside the OS.
  • On Expo, the bundled config plugin injects NSUserTrackingUsageDescription, INTERNET, ACCESS_NETWORK_STATE, and AD_ID during prebuild.

Next steps

Troubleshooting

ProblemWhat to try
getAppSprintId() returns nullconfigure() resolves before install registration finishes on the native side. Retry briefly, or read the value after the first event has been sent.
Events do not appear in dashboardConfirm the API key starts with as_live_. Call sendTestEvent() and inspect the returned message.
SDK disabled (isSdkDisabled returns true)The API returned 401 or 403. Call clearData(), then configure() with a valid key.
Apple Ads attribution not detectedAdServices requires a real device (not the simulator). Confirm enableAppleAdsAttribution is true and that the test build is signed with a real provisioning profile.
pod install fails after adding the packageDelete ios/Podfile.lock and ios/Pods, then run pod install --repo-update.
Android build cannot find AD_IDThe package's manifest declares com.google.android.gms.permission.AD_ID and is merged at build time. If you target an app that cannot use it, remove with tools:node="remove".