React Native and Flutter
Both bindings are thin layers over the native iOS and Android SDKs. App start, native crashes, frames and platform HTTP clients are measured natively; the binding adds screens and requests that only exist in JavaScript or Dart.
React Native
Requirements
- React Native 0.73 or later. The new architecture and Hermes are supported; the old bridge still works.
- Expo: supported in development builds and EAS builds through the config plugin. Not available in Expo Go.
- Current version: 1.6.2.
Installation
npm install @gatepost/react-native
cd ios && pod install
The package resolves the native SDKs from the authenticated repositories described in the iOS and Android guides. Set the repository credentials in gradle.properties and in the CocoaPods environment as those pages describe. For Expo, add @gatepost/react-native to the plugins array in app.json and pass the project key there.
Starting the SDK
Native initialisation happens automatically from the injected key, so app start is measured from process creation. Call start in JavaScript as well to enable JS-side features:
import { Gatepost } from '@gatepost/react-native';
Gatepost.start({
projectKey: '4f9c2e1b8a7d63e0',
trackJsErrors: true,
trackFetch: true,
});
Screens
With React Navigation, attach the tracker to the container so every route becomes a screen:
import { NavigationContainer } from '@react-navigation/native';
import { useGatepostNavigation } from '@gatepost/react-native';
export function App() {
const navigationRef = useGatepostNavigation();
return (
<NavigationContainer ref={navigationRef}>
{/* ... */}
</NavigationContainer>
);
}
Expo Router is supported through the same hook. For other navigation libraries, call Gatepost.screen(name) when a route becomes active.
Requests
fetch and XMLHttpRequest are instrumented in JavaScript, which captures the time the app waited including bridge overhead. Native requests made by third-party modules are recorded by the native SDK. If both layers see the same request it is de-duplicated by request ID.
JavaScript errors
Unhandled JS exceptions and unhandled promise rejections are reported as errors with the JS stack and the last screens. Upload source maps so stacks are readable:
gatepost-cli upload-sourcemap \
--project-key 4f9c2e1b8a7d63e0 \
--release 4.12.0 --platform ios \
--bundle main.jsbundle --map main.jsbundle.map
Custom traces
const trace = Gatepost.trace('checkout.submit');
trace.set('items', cart.length);
try {
await api.submit(cart);
trace.end();
} catch (e) {
trace.end(e);
throw e;
}
Flutter
Requirements
- Flutter 3.16 or later, Dart 3.2 or later.
- Current version: 1.4.0.
Installation
flutter pub add gatepost_flutter
The plugin pulls the native SDKs through the platform build systems, so the repository credentials from the iOS and Android guides apply.
Starting the SDK
import 'package:gatepost_flutter/gatepost_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Gatepost.start(
projectKey: '4f9c2e1b8a7d63e0',
options: GatepostOptions(trackDartErrors: true),
);
runApp(const ShopApp());
}
Wrapping runApp in Gatepost.runZoned additionally captures errors thrown outside the framework's error handler.
Screens
MaterialApp(
navigatorObservers: [GatepostNavigatorObserver()],
// ...
)
Routes are named after their RouteSettings.name. For go_router, pass the observer to the router's observers. Rendering metrics come from the native frame timing on both platforms, so slow frames in Flutter are measured the same way as in native views.
Requests
Add the interceptor for dio, or wrap an http.Client:
final dio = Dio()..interceptors.add(GatepostDioInterceptor());
final client = GatepostHttpClient(http.Client());
Custom traces
final trace = Gatepost.trace('checkout.submit');
trace.set('items', cart.length);
try {
await api.submit(cart);
trace.end();
} catch (e) {
trace.end(error: e);
rethrow;
}
What is measured natively and what is not
| Signal | Measured by | Note |
|---|---|---|
| App start | Native SDK | From process creation to the first frame of the JS or Dart UI. |
| Screens | Binding | Requires the navigation integration; native screens hosting the framework are hidden by default. |
| Frames | Native SDK | Identical to native apps. |
| HTTP requests | Both | De-duplicated when both layers observe the same request. |
| Native crashes, ANRs | Native SDK | Identical to native apps. |
| JS or Dart errors | Binding | Needs source maps for readable stacks in React Native. Dart stacks are readable without upload. |