npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@trevosdk/react-native

v0.1.1

Published

Trevo React Native SDK — deterministic variant assignment and durable event tracking for iOS and Android

Readme

@trevosdk/react-native

Experiments and event tracking for React Native and Expo, assigning the same variants the web SDK does for the same user.

npm install @trevosdk/react-native @react-native-async-storage/async-storage

Pure TypeScript — no native module, no linking step, no config plugin.

Quick start

import { createClient } from '@trevosdk/react-native';

export const trevo = createClient({
  apiKey: process.env.EXPO_PUBLIC_TREVO_KEY,
  appVersion: '1.4.0',
});

await trevo.ready();

const variant = trevo.getVariant('checkout-v2');
trevo.track('add_to_cart', { sku: 'ABC' });

Use a publishable key (tsk_live_…). A shipped binary can be unpacked, so a secret key in an app is a leaked key.

Read this before you plan your first mobile experiment

Three properties of mobile are not choices we made, and every vendor shares them. Planning around them is easier than discovering them mid-experiment.

A mobile cohort ramps over weeks, not days. Experiment code ships inside an app release, so your population is whoever has updated. Web reaches full traffic within a day of activation; mobile climbs as adoption climbs, and both variants coexist across app versions for as long as old builds stay installed.

An experiment can be switched off without a release, but not changed. Config is re-read on every foreground, so pausing or stopping is immediate. Changing what a variant does is code, and code ships through App Store review.

Anonymous users are per-device. A visitor who browses on a laptop and then opens the app is two participants until they sign in. identify() links them from that point forward; nothing can link them retroactively.

Durability

Phones lose the network constantly, are killed without warning, and have wrong clocks more often than desktops. The SDK is built around that:

  • Events survive a cold start. The queue is written to AsyncStorage and replayed on next launch. Delivery is at-least-once, and every event carries an idempotency key so a replay is recorded once.
  • Timestamps survive a wrong clock. Each batch is stamped with sentAt when it leaves the device. Ingestion compares that against its own clock to recover the device's offset and correct every event in the batch, which is what lets a queue drained three days late land on a real timeline. Nothing is dropped for being out of range — out-of-bounds values are clamped and marked.
  • Assignment survives no network at all. Config is persisted, so a cold start in a lift assigns the same variant it assigned yesterday instead of falling back to control and silently switching once the network returns.

minAppVersion

An experiment whose variant code only exists from a given build onward should not enrol devices that cannot render it:

{ "experimentKey": "checkout-v2", "minAppVersion": { "ios": "1.4.0", "android": "1.4.0" } }

Builds below the threshold get control and record no exposure, so they never appear in the results. This requires you to pass appVersion — without it, a gated experiment returns control for everyone, because the SDK cannot prove the build is new enough and guessing wrong means a broken screen.

API

createClient(options)

| Option | Default | Notes | | --- | --- | --- | | apiKey | — | Required. tsk_live_… | | appVersion | — | This build's version. Required for minAppVersion gating | | platform | Platform.OS | Override for tests | | bootstrapConfig | — | Assign before storage and network answer | | pollIntervalMs | 300000 | Foreground config refresh happens regardless | | flushIntervalMs | 15000 | Also flushes on background | | maxBatchSize | 50 | Capped at 500 by the server | | storage | AsyncStorage | Override for tests | | appState | RN AppState | Override for tests | | fetch | global | Override for tests | | onError | console.warn | Background failures surface here |

Methods

  • getVariant(key, { trackExposure }) — deterministic and synchronous. Returns control until ready() resolves.
  • track(event, properties, { insertId }) — queues an event.
  • identify(userId) — associates subsequent events and assignment with a user.
  • reset() — clears the user and mints a new anonymous id. Call on sign-out.
  • getAnonymousId() — the device's stable id, once storage has been read.
  • ready() — resolves once stored state is loaded and the first fetch settles.
  • flush() / shutdown().

Runtime constraints

Hermes is not a browser. The SDK avoids sendBeacon, CompressionStream, AbortSignal.timeout and crypto.randomUUID, none of which exist there; the build fails if one is reintroduced.

Expo

Works in Expo Go and in development builds with no config plugin — there is no native code to link. AsyncStorage is a required peer, so install it too:

npx expo install @react-native-async-storage/async-storage

It is not optional: without persistence the anonymous id is re-minted on every launch, which re-buckets every user and corrupts any running experiment.

Store compliance

Apple

The package ships ios/PrivacyInfo.xcprivacy. Xcode aggregates third-party manifests automatically — an app embedding an SDK without one is rejected at submission. It declares product interaction and a user id, both linked, neither used for tracking, and no required-reason APIs.

Google Play

Data safety content you can paste into the Play Console:

| Question | Answer | | --- | --- | | Does your app collect or share user data? | Yes | | Data type | App activity → App interactions | | Data type | App info and performance → Crash logs (only if you forward SDK errors) | | Data type | Device or other IDs → No — the id is generated by the SDK, not read from the device | | Collected or shared? | Collected | | Is it processed ephemerally? | No | | Is collection required? | Optional, if you gate initialisation on consent | | Purpose | Analytics; App functionality | | Is data encrypted in transit? | Yes | | Can users request deletion? | Yes — via your Trevo workspace |

The anonymous id is minted on device and is not an advertising or hardware identifier, which is why "Device or other IDs" is No. Declaring it there invites a policy review you do not need.

Correctness

This package runs the shared conformance vectors against its public API in CI, so a change that would bucket a user differently from the browser fails the build. The normative rules are in the bucketing spec.

License

MIT