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

firstusers

v1.2.0

Published

Usage tracking SDK for React Native/Expo apps. Tracks authenticated user sessions with 30s heartbeat to First Users platform.

Downloads

533

Readme

firstusers

Session tracking SDK for React Native/Expo apps. Tracks authenticated user sessions with automatic 30-second heartbeat updates.

Features

Post-Login Tracking - Only tracks authenticated user sessions (excludes login screen time)
Automatic Heartbeat - Updates session duration every 30 seconds
Survives App Kill - Last heartbeat data already saved (max 30s loss)
Zero Configuration - Expo Config Plugin auto-configures your project
Privacy-Focused - No sensitive data collection
Lightweight - Minimal battery and performance impact

Installation

npm install firstusers

Or with yarn:

yarn add firstusers

Configuration

Step 1: Add Plugin to app.json

{
  "expo": {
    "plugins": [
      [
        "firstusers",
        {
          "apiUrl": "https://your-api.workers.dev"
        }
      ]
    ]
  }
}

Plugin Options:

| Option | Type | Required | Default | |--------|------|----------|---------| | apiUrl | string | No | https://cotester-api.01hunterwl.workers.dev |

Step 2: Rebuild Your App

The Config Plugin needs a native rebuild to apply changes:

# Development build
npx expo run:android

# Or prebuild for custom builds
npx expo prebuild --clean

⚠️ Important: You must rebuild the app after installing this package. Expo Go does not support custom native modules.

Usage

Basic Setup

import futracker from 'firstusers';
import { supabase } from './lib/supabase';

// Configure once at app startup
futracker.configure('https://your-api.workers.dev');
futracker.setPackageName('com.yourcompany.app');

// Start tracking after successful login
supabase.auth.onAuthStateChange((event, session) => {
  if (event === 'SIGNED_IN' && session) {
    futracker.startTracking();
  }
});

Alternative: Convenience Function

import { startTracking } from 'firstusers';

// One-line start with package name
if (loginSuccess) {
  startTracking('com.yourcompany.app');
}

Optional: Manual Stop (usually not needed)

import { stopTracking } from 'firstusers';

// Optional: Call on logout
function handleLogout() {
  stopTracking();  // Not required - heartbeat already saved data
  // ... rest of logout logic
}

API Reference

futracker.configure(apiUrl: string)

Configure the API endpoint. Call once at app startup.

Parameters:

  • apiUrl (string) - Your First Users API endpoint

Example:

futracker.configure('https://your-api.workers.dev');

futracker.setPackageName(packageName: string)

Set your app's package name (same as applicationId in build.gradle).

Parameters:

  • packageName (string) - Your app's package name

Example:

futracker.setPackageName('com.yourcompany.app');

futracker.startTracking(packageName?: string)

Start tracking user session. Call after successful login.

Parameters:

  • packageName (string, optional) - Override package name for this call

Example:

// Use pre-configured package name
futracker.startTracking();

// Or pass directly
futracker.startTracking('com.yourcompany.app');

futracker.stopTracking()

Stop tracking session. Optional - heartbeat auto-saves data every 30s.

Example:

futracker.stopTracking();

futracker.setDebug(enabled: boolean)

Enable or disable debug logging. Debug mode is enabled by default.

Parameters:

  • enabled (boolean) - Whether to enable debug logs

Example:

// Disable debug logs in production
futracker.setDebug(false);

futracker.isActive()

Check if tracking is currently active.

Returns: boolean indicating if tracking is active

Example:

if (futracker.isActive()) {
  console.log('Tracking is running');
}

How It Works

  1. Initial Record: When startTracking() is called, creates one record in fu_tracking table with session_duration = 0
  2. Heartbeat Updates: Every 30 seconds, UPDATE the same record's session_duration to current elapsed time
  3. App Kill Safety: If app is killed, last heartbeat data is already saved (accurate within ~30 seconds)
  4. No Data Loss: No need to call stopTracking() - heartbeat already persisted the duration

Database Schema

The tracker sends data to the fu_tracking table:

CREATE TABLE fu_tracking (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  fu_id TEXT NOT NULL,              -- Guest ID (gu-XXXXX) or User ID (fu-XXXXX)
  app_package TEXT NOT NULL,         -- Your app's package name
  timestamp TEXT NOT NULL,           -- ISO 8601 UTC timestamp
  action TEXT NOT NULL,              -- 'session_start'
  device_brand TEXT,                 -- Device manufacturer
  device_api_level TEXT,             -- Android version
  user_agent TEXT,                   -- Platform info
  session_id TEXT NOT NULL,          -- Unique session identifier
  session_duration INTEGER NOT NULL  -- Seconds since session start
);

Data Collected

Session Data:

  • Session start time (UTC timestamp)
  • Session duration (seconds)
  • Session ID (unique per app open)

Device Info:

  • Device manufacturer (e.g., "Google", "Samsung")
  • Android API level (e.g., "Android 33")
  • Platform (e.g., "Android/13")

No Personal Data:

  • ❌ No user location
  • ❌ No contact information
  • ❌ No sensitive permissions

Troubleshooting

Module not found error

Error: The package 'firstusers' doesn't seem to be linked

Solution: You must rebuild the native app:

npx expo run:android

Tracking not starting

Check:

  1. Did you call setPackageName() before startTracking()?
  2. Is the package name correct? (Check android/app/build.gradleapplicationId)
  3. Did you rebuild after installing the package?

Debug:

// Enable console logs
futracker.configure('https://your-api.workers.dev');
futracker.setPackageName('com.yourcompany.app');
futracker.startTracking();
// Check console for "[FirstUsers]" logs

Build errors

Error: Plugin [id: 'expo-module-gradle-plugin'] was not found

Solution: Clean and rebuild:

cd android
./gradlew clean
cd ..
npx expo prebuild --clean
npx expo run:android

Requirements

  • React Native: 0.70+
  • Expo: 50+
  • Android: API 24+ (Android 7.0)
  • Kotlin: 1.8+

Example Integration

Complete example with Supabase authentication:

// App.tsx
import React, { useEffect } from 'react';
import futracker from 'firstusers';
import { supabase } from './lib/supabase';

export default function App() {
  useEffect(() => {
    // Configure tracker once
    futracker.configure('https://cotester-api.01hunterwl.workers.dev');
    futracker.setPackageName('net.woodlogos.app.firstusers');

    // Listen for auth changes
    const { data: authListener } = supabase.auth.onAuthStateChange(
      async (event, session) => {
        if (event === 'SIGNED_IN' && session) {
          // Start tracking after successful login
          futracker.startTracking();
          console.log('✅ Tracking started for authenticated user');
        }
      }
    );

    return () => {
      authListener?.subscription.unsubscribe();
    };
  }, []);

  return (
    // Your app components
  );
}

Privacy & Compliance

GDPR Compliant: Only tracks usage duration and basic device info (no personal data)

Disclose in Privacy Policy:

This app collects anonymous usage data for beta testing:
- Session duration (start/end time)
- Device model and Android version
- App package name

No personal information is collected.

License

MIT

Support


Made with ❤️ by First Users Team