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

@metricflow-ai/react-native

v0.1.0

Published

Advanced analytics SDK for React Native applications with event tracking, crash reporting, and performance monitoring

Readme

Metricflow Analytics React Native SDK

Analytics SDK for React Native applications with automatic device/app/session properties, event tracking, batching, retry logic, region routing, crash tracking, and local persistence.

Additional Guides

Overview

The Metricflow Analytics React Native SDK provides a full analytics pipeline for React Native apps:

  • Event tracking with eventId, sessionId, timestamp, and region metadata
  • User identification (identify) with persisted traits
  • Automatic SuperProperties — device, OS, app, screen, network, battery info merged into every event
  • Automatic session trackingApp Opened events and background queue flushing
  • Crash tracking — unhandled JS errors and promise rejections captured automatically
  • In-memory event queue with periodic and batch-size flush
  • Gzip compression for event payloads
  • Retry logic with exponential backoff
  • Local persistence via AsyncStorage
  • Opt-in/opt-out tracking controls
  • Auto region detection via IP geolocation (auto mode)
  • Custom endpoint override (useful for development/staging)

Installation

npm install @metricflow-ai/react-native

Optional Peer Dependencies

These libraries must be installed in your app (not in the SDK itself). The SDK declares them as optional peer dependencies — it works without them, but you get richer auto-collected properties when they are present.

# Install in your app project
npm install react-native-device-info
npm install @react-native-community/netinfo

After installing, rebuild your app for native linking to take effect:

# Android
cd android && ./gradlew clean && cd ..
npx react-native run-android

# iOS
cd ios && pod install && cd ..
npx react-native run-ios

What you get with each library:

| Library | Properties Added | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | react-native-device-info | model, manufacturer, brand, deviceId, isTablet, isEmulator, hasNfc, hasTelephone, appVersion, buildNumber, bundleId, appName, firstInstallTime, lastUpdateTime, batteryLevel, totalMemory, freeDiskStorage, carrier | | @react-native-community/netinfo | networkType, isWifi |

Without these libraries the SDK runs normally — device/network properties are silently omitted from events.

No uuid or crypto.getRandomValues polyfill is required. The SDK uses a React Native/Hermes-safe ID generator internally.

Requirements

  • Node.js >= 16
  • npm >= 8
  • React Native >= 0.73

Quick Start

import { metricflowAnalytics } from "@metricflow-ai/react-native";

// Initialize once at app startup
await metricflowAnalytics.init({
  appId: "your-app-id",
  secretKey: "your-secret-key",
  debug: __DEV__,
});

// Track custom events
metricflowAnalytics.track("button_clicked", {
  button_id: "subscribe",
  screen: "paywall",
});

// Track screen views
metricflowAnalytics.screen("HomeScreen");

// Identify user
metricflowAnalytics.identify("user_123", {
  name: "Alex Kumar",
  email: "[email protected]",
  first_name: "Alex",
  last_name: "Kumar",
  plan: "premium",
});

// Set persistent user properties (merged into all future events)
metricflowAnalytics.setUserProperties({ ab_group: "variant_b" });

// Manually flush the event queue
await metricflowAnalytics.flush();

Autocapture Setup

Autocapture gives Heap-style baseline tracking for taps, swipes, and screen views without adding track() calls to every button.

1) Enable autocapture after init

import { metricflowAnalytics } from "@metricflow-ai/react-native";

await metricflowAnalytics.init({
  appId: "your-app-id",
  secretKey: "your-secret-key",
  endpoint: "https://your-api-domain.com/api/track",
  debug: __DEV__,
});

metricflowAnalytics.enableAutocapture({
  captureTouch: true,
  captureSwipes: true,
  captureScreenViews: true,
  captureText: true,
  captureHierarchy: true,
  captureCoordinates: false,
});

2) Wrap your app with AutocaptureProvider

Pass the same React Navigation ref to NavigationContainer and AutocaptureProvider.

import React, { useEffect } from "react";
import { NavigationContainer, useNavigationContainerRef } from "@react-navigation/native";
import { AutocaptureProvider, metricflowAnalytics } from "@metricflow-ai/react-native";

type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Settings: undefined;
};

export default function App(): React.JSX.Element {
  const navigationRef = useNavigationContainerRef<RootStackParamList>();

  useEffect(() => {
    void metricflowAnalytics
      .init({
        appId: "your-app-id",
        secretKey: "your-secret-key",
        endpoint: "https://your-api-domain.com/api/track",
        debug: __DEV__,
      })
      .then(() => {
        metricflowAnalytics.enableAutocapture({
          captureTouch: true,
          captureSwipes: true,
          captureScreenViews: true,
          captureText: true,
          captureHierarchy: true,
          captureCoordinates: false,
        });
      });
  }, []);

  return (
    <AutocaptureProvider navigationRef={navigationRef}>
      <NavigationContainer ref={navigationRef}>
        {/* Your navigators/screens */}
      </NavigationContainer>
    </AutocaptureProvider>
  );
}

Autocaptured Events

Tap and swipe interactions are sent as:

autocapture

Example properties:

{
  "screen_name": "Home",
  "interaction_type": "tap",
  "element_text": "Continue",
  "hierarchy": "HomeScreen > Pressable",
  "component_type": "Pressable",
  "target_tag": 72
}

Swipe events include:

{
  "interaction_type": "swipe",
  "swipe_direction": "left",
  "gesture_distance": 80
}

Screen changes are sent as:

screen_view

with screen_name and, when available, previous_screen.

Privacy Controls

Use MetricflowIgnore to exclude sensitive UI from autocapture:

import { MetricflowIgnore } from "@metricflow-ai/react-native";

<MetricflowIgnore>
  <PasswordInput />
</MetricflowIgnore>;

To capture the interaction but suppress text inside the subtree:

<MetricflowIgnore allowInteraction>
  <PinPad />
</MetricflowIgnore>

Autocapture respects optOutTracking(). If the user opts out, autocaptured events are not queued.

Public API

Main export: metricflowAnalytics

| Method | Description | | ------------------------------- | -------------------------------------------------------------- | | init(config) | Initialize the SDK. Must be called before any other method. | | track(eventName, properties?) | Track a custom event. | | screen(screenName, props?) | Track a screen view event. | | identify(userId, traits?) | Set the current user identity. | | alias(newId) | Create an alias for the current user. | | setUserProperties(props) | Set persistent properties merged into all future events. | | setDebug(enabled) | Enable or disable debug logging at runtime. | | enableAutocapture(options?) | Enable automatic tap, swipe, and screen view tracking. | | disableAutocapture() | Disable automatic interaction and screen view tracking. | | optOutTracking() | Stop all event tracking for the current user. | | optInTracking() | Resume event tracking. | | reset() | Clear all user identity, super properties, and queued events. | | timeEvent(eventName) | Start timing an event (placeholder — duration support coming). | | flush() | Manually flush the event queue to the API. |

User Identity And Profile Properties

Call identify() after login/signup when you know the logged-in user's id. In the current Metricflow user list flow, include name and email in the traits object so the Users table can show a readable profile instead of only the user id.

metricflowAnalytics.identify("user_123", {
  name: "Alex Kumar",
  email: "[email protected]",
  first_name: "Alex",
  last_name: "Kumar",
});
  • name is used as the primary display name in the Users table. Send the combined full name here, for example first_name + " " + last_name.
  • email is used as the primary email in the Users table.
  • first_name and last_name are optional profile fields, but send them when your app stores names separately.
  • If your app stores first and last name separately, derive name from first_name and last_name before calling identify.
  • You can call identify() again after a profile update with the latest name and email.
  • Use setUserProperties() for extra persistent properties such as plan, role, experiment, or account type. Do not rely on it as the only place where you send display name and email.
const name = [user.first_name, user.last_name].filter(Boolean).join(" ").trim();

metricflowAnalytics.identify(user.id, {
  email: user.email,
  ...(name ? { name } : {}),
  first_name: user.first_name,
  last_name: user.last_name,
});

Recommended login flow:

await metricflowAnalytics.init({
  appId: "your-app-id",
  secretKey: "your-secret-key",
});

const name = [user.first_name, user.last_name].filter(Boolean).join(" ").trim();

metricflowAnalytics.identify(user.id, {
  email: user.email,
  ...(name ? { name } : {}),
  first_name: user.first_name,
  last_name: user.last_name,
});

metricflowAnalytics.track("login_success");

Configuration

interface Config {
  appId: string; // Required. Your public project app_id.
  secretKey: string; // Required. Sends x-secret-key for SDK authentication.
  endpoint?: string; // Optional. Custom API endpoint, for example staging/local/ngrok.
  batchSize?: number; // Default: 20
  flushInterval?: number; // Default: 30000 (ms)
  optOutByDefault?: boolean; // Default: false
  enableGzip?: boolean; // Default: true
  enableCrashTracking?: boolean; // Default: true
  sessionTimeout?: number; // Default: 1800000 (30 minutes, min: 60000)
  debug?: boolean; // Default: false
}

Init Config

Use init() once when the app starts, before calling track, screen, identify, or flush.

await metricflowAnalytics.init({
  appId: "scamguradlocaltesting_062fb12c216a",
  secretKey: "your-secret-key",
  endpoint: "https://your-api-domain.com/api/track",
  debug: __DEV__,
});

Pass these values:

| Field | Required | Meaning | | ----- | -------- | ------- | | appId | Yes | Public project/app id. This is sent as x-metricflow-app-id. | | secretKey | Yes | Secret SDK key. This is sent as x-secret-key so the backend can authenticate the mobile SDK. | | endpoint | No | Track API URL. Use this for local, staging, ngrok, or custom backend. Defaults to MetricFlow's configured endpoint. | | debug | No | Enables SDK logs during development. | | batchSize | No | Number of queued events before automatic flush. | | flushInterval | No | Time interval in milliseconds for automatic flush. | | sessionTimeout | No | Inactivity window before a new session starts. Default is 30 minutes. |

writeKey is no longer used by the React Native SDK. Use secretKey instead.

Auto-Collected Properties (SuperProperties)

The SDK automatically collects and merges these into every event:

Always collected:

  • os, osVersion — platform and OS version
  • libraryVersion — SDK version
  • screenWidth, screenHeight, dpi, orientation
  • timezone, language
  • networkType, isWifi (requires @react-native-community/netinfo)

With react-native-device-info installed:

  • model, manufacturer, brand, deviceId
  • isTablet, isEmulator, hasNfc, hasTelephone
  • appVersion, buildNumber, bundleId, appName
  • firstInstallTime, lastUpdateTime
  • batteryLevel, totalMemory, freeDiskStorage, carrier

You can also set custom super properties that persist across sessions:

metricflowAnalytics.setUserProperties({ user_tier: "gold", experiment: "v2" });

Event Properties

Every event sent by the SDK has two levels:

  1. Top-level event fields (event identity)
  2. properties object (context and custom details)

1) Top-level event fields

  • eventId: Unique ID for this one event.
  • eventName: What happened. Example: App Opened, Screen View, signup_started.
  • userId: Which user did this action. If user is not identified yet, it may be anonymous.
  • sessionId: Which app session this event belongs to.
  • timestamp: Event time in milliseconds.
  • region: Which routing region is used (eu, india, or default).

2) properties fields

These are extra details attached to the event.

Device and OS

  • os: Device platform (android or ios).
  • osVersion: OS version string.
  • model: Device model (example: Redmi Note 8 Pro).
  • manufacturer: Device maker (example: Xiaomi).
  • brand: Device brand (example: Redmi).
  • deviceId: Device unique ID from device-info library.
  • isTablet: true if tablet, else false.
  • isEmulator: true if emulator, else false.

App Info

  • appVersion: App version name.
  • buildNumber: App build number.
  • bundleId: App package/bundle ID.
  • appName: App display name.
  • firstInstallTime: First install time in milliseconds.
  • lastUpdateTime: Last update time in milliseconds.

Screen and Display

  • screenWidth: Screen width.
  • screenHeight: Screen height.
  • dpi: Screen density.
  • orientation: portrait or landscape.

Network and Locale

  • networkType: Current connection type (example: wifi, cellular, unknown).
  • isWifi: true if current type is Wi-Fi.
  • timezone: Device timezone (example: Asia/Kolkata).
  • language: Device/app locale (example: en-IN).

Hardware and Capacity

  • batteryLevel: Battery level (0 to 1).
  • totalMemory: Total device memory in bytes.
  • freeDiskStorage: Free storage in bytes.
  • carrier: Network carrier name. If unavailable, fallback can be empty/unknown.
  • hasNfc: NFC support (when available).
  • hasTelephone: Telephony support (when available).

Session and Tracking-specific fields

  • session_id: Added on App Opened event. Same value as top-level sessionId for readability.
  • is_first_open: true on first-ever app open for this installation.
  • screen_name: Added on Screen View event.

Custom properties (from your app)

Anything you pass in track(eventName, properties) is added here.

Examples:

  • method: "google" for signup method
  • plan_type: "monthly" for subscription
  • currency: "USD", amount: "9.99"

Automatic Events

| Event | Fired When | | ----------------------------- | ------------------------------------------------------------------ | | App Opened | App launches or comes to foreground (new session) | | JS Exception | Unhandled JavaScript error (requires enableCrashTracking: true) | | Unhandled Promise Rejection | Unhandled promise rejection (requires enableCrashTracking: true) |

License

MIT — see LICENSE.