TTesterFlow
Before you start Sign in and create your app in the Developer portal. Copy its appId and API key; use your hosted dashboard URL for apiUrl: Sign in → Open Developer portal.
  • appId — the exact app slug, for example my-cool-app
  • apiKey — the API key, which starts with hk_ (required in production)
  • apiUrl — the hosted dashboard URL: https://saraayab.shop

The app-specific key is included in the mobile build and can be extracted. Treat it as public; never use your dashboard admin password in the app.

File paths are relative to your project root. Use the matching files in your app's folder structure.

How it works: the app embeds the tester-analytics-sdk, which posts lightweight telemetry directly to this dashboard (no Firebase, Google Analytics, or any third-party analytics). Testers and events register automatically after the first event. Create the app once in the Developer portal so its API key exists.
Flutter app? The dashboard is a plain HTTP + JSON API, so a Flutter app can send the same telemetry without any plugin — see the Flutter setup guide. For native Kotlin/Android, see the Kotlin setup guide.

Quick path — Expo Go, no Firebase

1

Install the published SDK + Expo dependencies

Open a terminal at your project root, then run:

npm install tester-analytics-sdk
npx expo install expo-secure-store expo-constants
MODIFY (AUTOMATIC)
your project/package.json
This installs the published npm package. No local SDK folder or Metro configuration is needed.

expo-secure-store securely stores the persistent Tester ID, expo-constants lets the SDK read app.json. Both work in Expo Go.

2

Set the config in app.json

MODIFY FILE
your project/app.json
Merge this into your existing app.json. Keep all other keys.
{
  "expo": {
    "extra": {
      "testerAnalytics": {
        "appId": "my-cool-app",
        "apiKey": "hk_your_key_here",
        "apiUrl": "https://saraayab.shop"
      }
    }
  }
}

All three values come from the Developer portal.

  • appId — the exact app slug
  • apiKey — the API key (starts with hk_) (required in production)
  • apiUrl — https://saraayab.shop (HTTPS)
3

Create src/tester.ts and initialize the SDK

CREATE FILE
your project/src/tester.ts
// src/tester.ts
import { initializeExpoTesterAnalytics } from 'tester-analytics-sdk/expo';

export const tester = initializeExpoTesterAnalytics();

SecureStore keeps the persistent anonymous Tester ID, expo-constants reads the config from app.json. Both work in Expo Go.

4

Import the tracker in your app entry file

Choose the entry file that matches your project:

Classic Expo project (App.tsx or index.ts)

MODIFY FILE
your project/App.tsx
Import it once, at the very top. The import starts the Tester ID and the first session.
// App.tsx (top of the file)
import './src/tester';

Expo Router project (app/_layout.tsx)

MODIFY FILE
your project/app/_layout.tsx
Import it once, at the very top. The import starts the Tester ID and the first session.
// app/_layout.tsx (top of the file)
import '../src/tester';

Track screens from the navigator:

// Add these props to your existing NavigationContainer.
import { tester } from './src/tester';

onReady={() => {
  const r = navigationRef.current?.getCurrentRoute();
  if (r?.name) tester.setScreen(r.name);
}}
onStateChange={() => {
  const r = navigationRef.current?.getCurrentRoute();
  if (r?.name) tester.setScreen(r.name);
}}

If you use Expo Router, track route changes with usePathname:

// app/_layout.tsx (inside your root layout component)
import { useEffect } from 'react';
import { usePathname } from 'expo-router';
import { tester } from '../src/tester';

const pathname = usePathname();
useEffect(() => {
  tester.setScreen(pathname);
}, [pathname]);

Track crashes with tester.reportCrash(message, stack).

Show the Tester ID in the app's settings screen via tester.getTesterId() and optionally set the contact name with tester.setContactName(name).

5

Run & verify

npx expo start
  1. Open the app once on the device.
  2. Open the app once. Events appear under the app you created.
  3. The tester shows as Active with version, device, opens, and activity history.

Done. After the first open, the tester appears as Active. Make sure you created the app and copied its API key.

Active usage tracking

For every tester the dashboard measures actual foreground / active usage time, grouped by date (e.g. tester_123 → 2026-09-07 → 42 minutes.

How it works:the SDK sends session signals (session_start, session_resume, session_pause, session_heartbeat. The server measures elapsed active time with its own clock between accepted signals — it never trusts client timestamps for totals. Time in the background is excluded automatically because a pause/close signal ends the measured interval.

Force-close / crash / no network:sessions auto-close after a no-signal window, so a lost pause or heartbeat can't inflate totals. Duplicate signals are ignored and a single continuous session is capped to a maximum length.

View it:theUsagetab in the dashboard shows today's totals, per-tester daily history, and date-range sums. The GET /api/usageendpoint backs it.

Privacy & opt-out

The SDK uses a stable anonymous Tester ID (a random UUID stored in secure storage) — no name, email, phone, or personal information is required. The only optional personal field is the contact name/channel the tester chooses to enter.

Testers can opt outat any time from the app's Settings → Testing & Privacy, and can erase their local + server-side data with tester.eraseMyData() Opting out stops future events from this app; it does not delete data already received. Use eraseMyData() to remove the tester's dashboard data.

Privacy policy for a temporary testing app

Add a clear, accurate disclosure to your privacy policy and store listing. Adapt this sample to your actual data, test period, hosting and retention:

During this app's [closed/open testing period], [developer/organization] uses TesterFlow to evaluate test builds, diagnose crashes and bug reports, and understand test-session activity. The app sends a random tester ID, app version, device information, screen/activity events, and foreground session signals to [hosting provider/region]. Crash details and bug-report information are sent when generated or submitted. Testers may optionally provide contact details. This data is used only to operate this testing program, not for advertising or production-user analytics. Collection will stop when [test end condition/date]. Data is retained for [actual retention period]. To stop future collection, use [in-app opt-out instructions]; to request deletion, use [erase instructions or contact details].

Only claim the collection is temporary or not used in production if that is true and you will stop or change collection when testing ends. TesterFlow does not automatically delete data when a test ends. Keep the privacy policy, Play Store listing/Data safety disclosures, and app behavior consistent. This sample cannot guarantee Google Play approval; check current Play policies for your app and testing track.

Notes & limitations

  • Reinstall → new Tester ID. The ID lives in secure storage; reinstalling or clearing app data creates a new ID.
  • Android only. This SDK uses secure storage and does not support expo start --web; use an Android device or emulator.
  • Contact name is opt-in PII and only sent if the tester enters it. tester.eraseMyData() deletes dashboard and local data.