SDKs
JavaScript core and API reference
@traqio/core is the engine behind the React Native, Expo and Capacitor SDKs: its init options, methods, queue, storage and the native bridge, documented once.
@traqio/core is Traqio's platform-neutral JavaScript engine: the persisted offline queue, the batching and retries, the SKAdNetwork conversion-value driver, the Apple Ads token report and deep-link resolution. It has no React Native, Expo or browser dependency; everything platform-specific arrives through a native bridge. @traqio/react-native (and its alias @traqio/expo) and @traqio/capacitor re-export it with their bridge, so this page is the API reference of all three.
Install#
npm install @traqio/coreOnly for a direct integration. On React Native, Expo or Capacitor, install the platform package instead — it depends on the core at an exact version.
API reference#
The SDK is a singleton, Traqio. Calls made while init is still resolving are queued; calls made before init is called at all are ignored — except setConsent, which is kept and written once storage is available. Initialise first.
init(options)#
import { Traqio } from "@traqio/core";
await Traqio.init({
sdkKey: "YOUR_SDK_KEY",
endpoint: "https://api.traqio.app", // origin only — the SDK appends the paths
userId: currentUserId, // optional, settable later with setUserId
storage, // { getItem, setItem } — see "Storage"
native, // a NativeBridge; omit and there is no attribution
});interface InitOptions {
sdkKey: string;
endpoint: string;
storage?: { getItem(key: string): Promise<string | null>; setItem(key: string, value: string): Promise<void> };
native?: NativeBridge;
userId?: string;
appVersion?: string;
collectContext?: boolean; // default true — model, OS, locale; never an advertising id
testAds?: boolean; // AdMob test ad units: logged, never counted as revenue
skan?: boolean; // iOS: drive SKAdNetwork conversion values (default true)
appleAds?: boolean; // iOS: report the AdServices token (default true)
deepLinking?: boolean; // default true
consent?: boolean; // the user's answer to YOUR consent prompt, when known at launch
collectAdvertisingId?: boolean; // default false — send the IDFA / GAID with the install (never prompts)
}Idempotent: a second call does nothing. On first launch it reports the install once — on Android with the Play Install Referrer, waiting up to three launches if Google Play is momentarily unavailable — then resolves the deferred deep link, records the app open, fetches the SKAdNetwork mapping and reports the Apple Ads token on iOS. endpoint is the origin only: https://api.traqio.app.
track(name, props?)#
Traqio.track("signup");
Traqio.track("purchase", {
value: 9.99,
currency: "EUR",
transactionId: "2000000812345678", // the store's id for this purchase
store: "app_store", // defaults to the platform's store
});| Prop | Type | Meaning |
|---|---|---|
value | number | Revenue declared by the app — the SDK does not verify it against a receipt. |
currency | string | ISO 4217 code. |
transactionId | string | The store's id for the purchase (StoreKit transactionId, Play orderId). Keys the event like RevenueCat does, so one purchase reported by both is counted once. |
store | string | app_store · play_store · mac_app_store · amazon · stripe. Defaults to the platform's store. |
On iOS every valued event also moves the SKAdNetwork conversion value. Names that Meta and TikTok can optimise on are listed in Event names.
trackAdRevenue(ad)#
// In AdMob's paid-event callback, once per impression:
Traqio.trackAdRevenue({
valueMicros: 21500, // the AdValue in micros — 0.0215 of the currency; never pre-round it
currency: "USD", // ISO 4217, as AdMob reports it
precision: "estimated", // AdMob's precisionType
adUnitId: "ca-app-pub-0000000000000000/0000000000",
adFormat: "rewarded",
adSourceName: "AdMob Network", // the mediation source that filled it, when known
});Impressions have their own queue (up to 1,000, sent in batches of 100) and a batch id persisted with it, so a crash between sending and the answer cannot count the same revenue twice. With testAds: true they are logged by the server and never counted. See AdMob.
setUserId(id)#
Attaches your own user id to everything sent from then on — use the same value you give RevenueCat as app_user_id. Call it after sign-in. See Identity.
onDeepLink, handleUrl, getDeferredDeepLink#
const unsubscribe = Traqio.onDeepLink(({ deepLink, code, deferred, via }) => {
if (deepLink) router.push(deepLink);
});
await Traqio.handleUrl(url); // hosts other than React Native: a URL opened the app
await Traqio.getDeferredDeepLink(); // this install's deferred link, or null
await Traqio.getInstallReferrer(); // Android: the raw Play Install ReferreronDeepLink returns its unsubscribe function. Each link has deepLink (the destination set on the link, or null), code (the link's slug), deferred and via (referrer, ip_match or link). React Native wires Linking itself; other hosts call handleUrl.
setConsent, forgetMe#
await Traqio.setConsent(userAgreed); // sharing with ad networks — not measurement
const ok = await Traqio.forgetMe(); // erase this device and user on the server, then go silent
if (!ok) showError(); // nothing changed on either side — let the user retrysetConsent is read at send time, so events queued before a “no” leave under the “no”. forgetMe is irreversible on both sides: the server deletes the device's and the user's data, and the SDK goes silent for good on this install. See Privacy.
flush, appOpened#
Traqio.flush(); // send the queue now (React Native does it on background)
Traqio.appOpened(); // the app came back to the foreground (React Native does it for you)An app open is reported at init and on each return to the foreground after at least 30 minutes away — the convention GA4, Adjust and AppsFlyer share. It is what retention on day n is computed from.
Read-only properties#
Traqio.forgotten— true onceforgetMe()has been honoured.Traqio.skanMapping— the conversion-value mapping in force on this device, once fetched (iOS).
Storage#
Storage is what makes the install fire exactly once and the queue survive a kill. The core takes any object with async getItem / setItem; on React Native it uses AsyncStorage automatically when the app has it. Without storage it warns at launch and reports the install again at every start.
The native bridge#
interface NativeBridge {
platform: "ios" | "android";
getInstallReferrer(): Promise<InstallReferrerResult>; // Android; never rejects
getContext?(): Promise<{ deviceModel?: string; osVersion?: string }>;
updateConversionValue?(fine: number, coarse?: "low" | "medium" | "high", lockWindow?: boolean): void; // iOS
getAttributionToken?(): Promise<string | null>; // iOS 14.3+, Apple Ads
getAdvertisingId?(): Promise<string | null>; // only with collectAdvertisingId; never prompts
}The platform packages implement it. Without a bridge, the core sends events but has no referrer and no SKAdNetwork — events, not attribution.
Advertising id (opt-in)#
Off by default: the SDK sends no IDFA or GAID. Turn on collectAdvertisingId only if you buy from networks that attribute by the advertising id — Unity Ads and AppLovin match their click to your install on it. It is sent with the install and never used as its identity.
Traqio.init({
sdkKey: "YOUR_SDK_KEY",
endpoint: "https://api.traqio.app",
native: getNativeBridge(),
collectAdvertisingId: true, // off by default
});- iOS: the SDK never shows the App Tracking Transparency prompt — ask for it yourself before
init, and link AdSupport. The IDFA is read only if the user already allowed tracking. - Android: add
com.google.android.gms:play-services-ads-identifierand thecom.google.android.gms.permission.AD_IDpermission to your app; the SDK declares neither. - Declare the advertising id in your App Store privacy details and Google Play Data safety form.
What it sends#
| Request | When |
|---|---|
POST /ingest | The install (once), then event batches of up to 20. Queue capped at 500 events. |
POST /ingest/session | An app open — not queued: a failed one is retried by the next open. |
POST /ingest/ad-revenue | AdMob impression batches of up to 100. |
POST /ingest/adservices | iOS: the Apple Ads attribution token. |
GET /skan/mapping/<sdkKey> | iOS: the conversion-value mapping. |
POST /deeplink/deferred · /deeplink/open | Deep-link resolution. |
POST /privacy/forget | forgetMe(). |
Every request carries the SDK key, the first-party device id and — once set — your user id and the consent answer. No advertising id, unless you set collectAdvertisingId: the install then carries it. These are the SDK's own routes, not a public server-to-server contract; for reading data from your servers, use the public API.
Frequently asked questions#
- Can I use @traqio/core on its own?
- Yes, but what you get alone is event ingestion, not attribution: attribution needs the platform evidence — the Google Play Install Referrer, SKAdNetwork — that only a native bridge can read. Apps on React Native, Expo or Capacitor should install their platform package, which includes the core and its bridge.
- Are tracking calls blocking or can they throw?
- Neither. track() and trackAdRevenue() only append to an in-memory queue persisted to storage; sending happens in the background, in batches, with exponential backoff up to five minutes. Network and HTTP errors are swallowed by design, which is also why a mistyped endpoint fails silently.