Skip to content
Docs

Mobile

React Native module

This page is assembled from sdks/react-native/README.md in the repository. See the SDK overview for the choice between native SDKs and wrappers.

Formerly @dtrackier/react-native. Until 2.0 the deprecated DTrackier, DTrackierError and withDTrackier exports forward to Metrixed, MetrixedError and withMetrixed; change the dependency and import path to @metrixed/react-native.

@metrixed/react-native is a thin bridge over the native Android and iOS SDKs. All tracking logic (offline queue, request signing, attribution, SKAdNetwork, consent enforcement) lives in the native SDKs; this package only validates arguments and forwards them. Method names mirror the native SDKs.

Works with the legacy bridge and (through the interop layer) the new architecture. Not usable in Expo Go: build a development client (expo prebuild / expo run:*) or a bare app.

Install

sh
npm install @metrixed/react-native
cd ios && pod install      # iOS: pulls the Metrixed pod (>= 1.0)

Android resolves com.metrixed:metrixed-android from Maven Central. Until it is published use the local repo built by make sdk-android-build and point Gradle at it (maven { url "<repo>/sdks/android/metrixed/build/repo" }).

Expo

json
{ "expo": { "plugins": [["@metrixed/react-native", {
  "scheme": "myapp",
  "linkHosts": ["go.example.com"],
  "userTrackingDescription": "This identifier measures which ads led to installs.",
  "skAdNetworkIds": ["cstr6suwn9.skadnetwork"],
  "skanReportEndpoint": "https://skan.example.com"
}]] } }

The config plugin adds: Android INTERNET/ACCESS_NETWORK_STATE, a VIEW intent filter for your scheme and verified App Link filters for every host; iOS NSUserTrackingUsageDescription, SKAdNetworkItems, NSAdvertisingAttributionReportEndpoint / AdAttributionKitReportEndpoint, CFBundleURLTypes and applinks: Associated Domains. kidsMode: true removes the AD_ID permission and writes no ATT/SKAN keys. It is idempotent. Bare apps do the same by hand (see the native READMEs).

Initialise

ts
import { Metrixed } from '@metrixed/react-native';

await Metrixed.initialize({
  appToken: 'APP_TOKEN',
  environment: 'production',          // 'sandbox' is flagged on every payload and excluded from billing
  baseUrl: 'https://ingest.example.com',
  secret: 'SDK_SECRET',               // request signing
});

Call it as early as possible. JavaScript starts after the first Android activity is already visible, so the install is reported immediately but the very first session starts at the next foreground. To count the first session too, initialise the native SDK in Application.onCreate instead (and skip initialize here).

Platform-specific options are ignored on the other platform: secretId, consentRequired, collectGaid, collectAppSetId, collectAndroidId, oaid, preloadKey, referrerTimeoutMs (Android); trackingBaseUrl, attWaitInterval, readIdfa, readIdfv, linkMe*, skanEnabled, storeKitForwarding (iOS). kidsMode maps to setKidsMode / coppaCompliant.

Events and ad revenue

ts
Metrixed.trackEvent({ token: 'level_up', callbackParams: { level: '5' } });
Metrixed.trackEvent({ token: 'purchase', revenue: 9.99, currency: 'USD', dedupeId: orderId, partnerParams: { af_content: 'x' } });
Metrixed.trackAdRevenue({ source: 'applovin_max', revenue: 0.012, currency: 'USD', adUnit: 'u1', adType: 'rewarded' });
Metrixed.setCustomerUserId('user-42');

Revenue is a number plus an ISO currency (required together); the native SDK formats it as a 6-decimal string. The wrapper rejects bad input before it reaches native code. Ad revenue: call trackAdRevenue from your mediation callback, e.g. AppLovin MAX ad.revenue / ad.networkName / ad.adUnitIdentifier / ad.placement, LevelPlay impressionData.revenue, and for AdMob paid.value / 1_000_000 (AdMob reports micros) with paid.currencyCode.

ts
Metrixed.setDeeplinkHandler((link) => navigate(link.deepLinkValue ?? link.url, link.params));
// links you receive yourself (e.g. from Linking.getInitialURL / addEventListener):
await Metrixed.processDeeplink(url);

Direct (scheme / App Link / Universal Link) and deferred links are delivered with { url, source, clickId, deepLinkValue, params }. Links that arrive before a handler is set are held natively and delivered on subscribe. On Android, onNewIntent and the launching intent are handled by the module; on iOS forward openURL / continueUserActivity through Linking and processDeeplink, or use the native Metrixed.processDeeplink.

ts
Metrixed.setConsent({ thirdPartySharing: false, measurement: true, adPersonalization: false, gdprApplies: true, tcf: tcString });
Metrixed.setThirdPartySharing(false);
Metrixed.gdprForgetMe();   // server erase + local wipe; the SDK stays off afterwards

tcf, gpp, googleDMA, metaLDU are honoured on iOS; Android carries thirdPartySharing, measurement, adPersonalization, gdprApplies. setPushToken takes the FCM token (Android) or the hex APNs token (iOS).

Platform differences

CallAndroidiOS
setExternalDeviceIdyesset externalDeviceId in the config (call is a no-op)
setEnabled, setOfflineMode, setSecretyesno-op
getAttribution, setAttributionListeneryesresolves null / never fires

Tests

make sdk-rn-test (not part of make test): Jest with a mocked native module and the shared wire vectors in sdks/test-vectors/wrapper-api.json (Node image), the Android bridge compiled against the real AAR with JVM mapper tests (Android image), the iOS mapper tested on Linux (Swift image). Request signing is done and tested by the native SDKs (signing.json). The iOS module and the example app build in .github/workflows/sdk-wrappers.yml (macOS).

Sample: example/ (Expo dev client). Changelog: CHANGELOG.md.