Skip to main content
Supported on: iOS SDK 1.0.70+ · Android SDK 1.0.42+ · React Native SDK 1.0.7+ (New Architecture only)
This is the complete reference for the public methods, types, and delegate interfaces in the @appdna-ai/react-native-sdk package. The React Native SDK delegates rendering, business logic, and storage to the native iOS and Android layers, so every method here resolves to native execution. Every signature on this page is compiled against the package’s published type declarations in CI — if a signature here disagrees with the code you install, the build fails.

Core Methods

All core methods are static on the AppDNA class.

Config Methods

Session Data

Cross-module key-value bag used by Console-configured template interpolation ({{session.*}}).
The location object uses snake_case keys, exactly as the native SDKs store them. Both bridges emit every key on every answer; a value the answer does not have is null: What is filled depends on what the user did. Both platforms and both surfaces — a Location field on a form step and a Location content block — store the same shape. A coordinate that is not a finite number comes back null. A zone the lookup could not find leaves timezone and timezone_offset both null — on every platform and surface; the SDK never makes up a "UTC". Always null-check before using a field. A selected suggestion also carries mapbox_id when it was resolved through a permanent Mapbox geocode. It is an opaque marker of that, not a stable place id to look up (for an interpolated address it encodes the request that produced it and runs to hundreds of characters). place_id is set only on a Google answer (the Places id the user tapped). When a tapped suggestion cannot be resolved (with Mapbox, no permanent access on the account; with Google, the Geocoding API not enabled on the key; with either, any other provider error or a network failure), the answer is the typed text. On a resolved Mapbox answer, an address answer’s city is the place that contains the address, not the street name earlier releases stored; a place, locality, region or country answer keeps its own name as city; and a region answer also fills its own state / state_code, a country answer its own country / country_code, which earlier releases left empty. On a resolved Google answer, city is the first of the place’s locality, postal town, sublocality or second-level administrative area that Google reports — a city answer’s own name, an address answer’s town — so a region or country answer has no city: its own name is its state (a region) or its country (a country).

Experiments

Push (static helpers)

These mirror AppDNA.push.* — use either style.

Presentation

Web Entitlements


Module Namespaces

setDelegate accepts a delegate or null. The parameter is nullable on every module: passing null clears the delegate — its listeners are removed and no callback fires afterward. Registering a new delegate replaces the previous one, so register once at app startup rather than from a component that mounts and unmounts. shutdown() detaches everything.

AppDNA.push

AppDNA.billing

AppDNA.onboarding

AppDNA.paywall

AppDNA.remoteConfig

AppDNA.features

AppDNA.experiments

AppDNA.inAppMessages

AppDNA.surveys

AppDNA.screens

To embed a screen inline in your own React layout instead of presenting it over the app, use <AppDNAScreenSlot>.

AppDNA.lifecycle


Delegate Interfaces

Implement these and register them with the matching module’s setDelegate(...).

AppDNAOnboardingDelegate

AppDNAPaywallDelegate

errorType values

onPaywallPurchaseFailed always carries one of these, so you can decide whether a retry even makes sense without parsing a message:

AppDNAPushDelegate

AppDNABillingDelegate

AppDNAInAppMessageDelegate

AppDNASurveyDelegate

AppDNADeepLinkDelegate

AppDNAScreenDelegate

AppDNALifecycleDelegate

Onboarding events carry location answers unreduced. onboarding_step_completed’s selection_data and onboarding_flow_completed’s responses reach onEventTracked as the device stored them: a picked location answer arrives whole, with the address, coordinates and time zone of the place the user picked (and a Google answer’s place ID). AppDNA reduces an answer to what the geocoding providers’ terms allow only on its own server, after the event leaves the device. What you store or forward from these properties is under your terms with the provider, and for a Google answer (one carrying place_id) under your terms with Google. A Google answer you show yourself must carry Google’s attribution wherever it is shown without a Google map.
The SDK also tracks a sdk_decode_dropped event carrying the same values, so the fleet view does not depend on a host implementing this. The delegate exists so YOUR crash reporter can see your own content being dropped.

Components

AppDNAScreenSlot

The package’s only React component: it embeds a server-driven screen inline in your layout. See the Screens guide.

Key Types

AppDNAEnvironment

There is no 'staging'. Which backend data you touch is decided by the API-key prefix (adn_test_ for a test key, adn_live_ for a live one); this value only tags the SDK’s own environment. Pass 'sandbox' alongside an adn_test_ key for a test build.

AppDNAOptions

AppDNALogLevel

AppDNABillingProvider

Adapty is the one provider with an associated value. A keyless Adapty is refused natively — both platforms fall back to the platform store rather than run without a key — so the type makes it impossible to write:

StepAdvanceResult

The plain object you return from onBeforeStepAdvance. The hook’s TypeScript return type is Promise<Record<string, unknown>> — native decodes the type discriminator:
An unrecognised type is not an error: native falls back to proceed and the user advances. On a sign-in action it blocks instead (“Sign-in isn’t available right now. Please try again later.”). Get the string right.

StepConfigOverride

The plain object you return from onBeforeStepRender (or null to render the step unchanged):

PaywallContext

PaywallAction

The action string passed to onPaywallAction:
All five cases are emitted from iOS SDK 1.0.84 and Android SDK 1.0.56. Before that, cta_tapped was sent by Android only — the iOS SDK never called onPaywallAction at all, so the same published paywall reported a tap on one platform and nothing on the other — and the remaining four had no emitter anywhere.🔴 plan_changed is not sent for the default selection. A paywall selects its default plan as it appears; that is not a choice the user made, and reporting it would put one event at the top of every paywall session that looks like engagement and is not.🔴 The action fires BEFORE the SDK decides whether the tap can do anything. A CTA tap that cannot resolve a plan is reported and then does nothing else — no purchase_started, no purchase callback. That ordering is what lets you tell “the SDK never received the tap” from “the purchase was attempted and failed”, which is otherwise the same silence. custom behaves the same way: the renderer still falls back to its default handling, and you are told it was an action you defined.Feature rows became tappable in iOS 1.0.84 / Android 1.0.56 so that feature_selected could exist. Nothing about them looks or reads differently, and the paywall still scrolls — the row takes a tap, not a drag.

PushPayload

The notification map, with the keys native actually sends — snake_case:

PushAction

One structured notification action button. id echoes back as onPushTapped’s actionId.

Entitlement

The union of what the two platforms know. A key that the running platform has no concept of is omitted, never faked — so the platform-specific fields are optional, and an absent one means “this platform does not know”, not false or "". Ask isActive. It is the cross-platform question: both platforms send it, and on Android it is derived from the Play status so you never have to learn that vocabulary.

TransactionInfo

What a successful purchase(...) resolves with. There is no status field: a resolved promise is the purchase. A cancellation, a pending (deferred / ask-to-buy) purchase, and a store error all reject — catch them, do not test a status.

ProductInfo

Platform-specific keys are omitted, never faked: an absent key means the platform has no concept of it.
There is no numeric price field. iOS’s native price is a Decimal, which cannot cross the bridge without loss, so both platforms send integer priceMicros. Render displayPrice (already localized and currency-formatted), or divide priceMicros by 1,000,000 when you need the number.

WebEntitlement


Notes

Architecture

The React Native package exposes API facades, DTOs, and bridge calls; rendering, business logic, network I/O, and storage execute in the native iOS (Swift) and Android (Kotlin) SDKs. The delegate interfaces and the native module spec are generated from the same source as the iOS and Android surfaces, so the TypeScript API cannot silently drift from them.

Platform-specific behavior

  • billingProvider applies on both platforms ('storeKit2' = StoreKit 2 on iOS, Google Play Billing on Android). Under 'revenueCat', Adapty or 'none' the SDK never buys, restores, finishes or acknowledges; purchase and restore reject with providerNotAvailable.
  • requestPermission() on AppDNA.push triggers the iOS APNs prompt or the Android 13+ POST_NOTIFICATIONS runtime permission.
  • shutdown() flushes queued events and releases native resources on both platforms, and the wrapper additionally detaches every delegate, veto handler, and cached snapshot.
  • offerToken on purchase(...) selects an Android base-plan offer and is ignored on iOS.
  • onBillingUnavailable fires on Android only.
  • notificationIcon applies on Android only.