rybbit-flutter-sdk

Rybbit analytics SDK for Flutter apps: screens, events, errors and user identification.

Preview of rybbit-flutter-sdk

rybbit-flutter-sdk is a library that sends screens, events, errors and user identification from Flutter apps to Rybbit analytics. Rybbit is open source analytics you can run on your own server. On the web it is driven by a script that Rybbit serves itself, but a mobile app has no page to load that script into. Anyone who wants to see their Flutter app in the same dashboard needs a library that sends screen views, events and errors from the phone and copes with things the web does not have to handle: signal dropouts, apps in the background and a device that switches between several networks during the day.

Why one phone should not count as four users

When the server does not get a device identifier, it derives the user from a fingerprint of the IP address and user agent. That is enough on the web but not on mobile: a phone changes its IP address every time it switches between Wi-Fi and mobile data, and the user agent changes with every app update. In production, one person showed up under four different identifiers in a single day. Since version 0.3.0 the SDK therefore sends a persistent anonymous_id with every event. It generates and stores the ID on first launch, and when the app already has its own device identifier, such as the one it sends to its backend, the analytics uses that one. Rybbit data can then be matched with your own records. The ID survives an app restart, but not a reinstall.

Version 0.4.0 solves a second problem. An unmodified Rybbit server rejects an event with a field it does not know with code 400, and only a server with the mobile changes from pull request #921 knows the app_version and device_model fields. The SDK detects this on the first rejected event, sends it again without those two fields and leaves them out for the rest of the session. Nothing needs to be configured, and a server that supports the fields keeps receiving them.

What the app gets

  • Screen views without writing code for each screen: just add RybbitNavigatorObserver to the navigator. For custom navigation there is a manual screenView().
  • Errors you would otherwise learn about from reviews. Starting the app with Rybbit.runApp catches Flutter framework errors, asynchronous exceptions and zone errors and sends them to Rybbit with a stack trace; trackError() adds manually handled errors with context.
  • Events that do not vanish in a tunnel. Whatever fails to send, the library stores in a queue in Hive and sends when the connection comes back or on the next launch. The queue holds at most 1,000 events for seven days; when it is full, the oldest are dropped, and an event that fails on the third attempt is dropped too. Events are sent every ten seconds or after twenty events, whichever comes first. All of these values can be changed in init().
  • The app lifecycle as app_open, app_foreground and app_background events, so you can see how often users come back.
  • 24 typed GA4-style methods for online stores, sign-in, content, forms and lead generation, from trackPurchase to trackNewsletterSubscribe. Event and property names match across apps and with the website.
  • Identification of the logged-in user via identify() with traits such as plan or role. Rybbit links it back up to 30 days.
  • A dryRun mode that only prints instead of sending, and a debug mode with a detailed log. Development and test builds do not pollute production data.

How to set it up

Initialisation is one call with the server address and the site ID. It works against a self-hosted instance as well as Rybbit Cloud.

void main() {
  Rybbit.runApp(() async {
    WidgetsFlutterBinding.ensureInitialized();

    await Rybbit.init(
      host: 'https://your-rybbit-instance.com',
      siteId: 'your-site-id',
    );

    runApp(MaterialApp(
      navigatorObservers: [RybbitNavigatorObserver()],
      home: const HomeScreen(),
    ));
  });
}

Rybbit.instance.event('button_click', properties: {'button': 'cta'});
Rybbit.instance.identify('user-123', traits: {'plan': 'pro'});

The library takes device and app version details from device_info_plus and package_info_plus, the network state from connectivity_plus, and sends through the http package. Since version 0.4.1 it also sends the device user agent in the request header, because an unmodified server uses it to determine the browser and operating system; before that, the app showed up on such a server without an operating system. The web code has its own branch without dart:io, so the app also builds for the browser.

Disposing the SDK in the middle of sending used to be able to crash the host app with a closed storage error. Since version 0.2.5 everything that touches the queue goes through a single chain that dispose() waits for, and any error ends up in the log, not in the app.

Where it helps

  • An online store app that wants purchases, the cart and search in the same events as the website. On the web they are sent by rybbit-ts with the same GA4-style event names.
  • An app with its own backend that already has a device identifier. It passes it to anonymousId, and the analytics and the backend talk about the same device.
  • An internal or industry app whose data must not go to an advertising company. Rybbit runs on your own server and the SDK sends only to the address it gets in init().

The library is one of the dependencies of the Rybbit Mobile app, a mobile client for the same analytics.

Project status

pub.dev has version 0.4.1 from 10 October 2026; the first public version, 0.2.0, was published there at the end of February 2026. The package has 140 of 160 pub.dev points, and pub.dev lists Android, iOS, macOS, Windows and Linux for it. Tests cover the queue, sending, device details and GA4-style events and run without a network. A separate suite is run manually against a real unmodified server and verifies that an event with mobile fields gets through.

Automatic upload of the app icon to the Rybbit dashboard is off by default since version 0.2.5. Rybbit allows it only for a logged-in site administrator, so from a released app it always returned error 403; the icon is uploaded in the site settings. The repository has no GitHub releases; versions are published only on pub.dev and described in CHANGELOG.md.

Getting started

dependencies:
  rybbit_flutter_sdk: ^0.4.1

You need Flutter 3.10 or later, Dart 3.0 and a Rybbit server, self-hosted or in the cloud. The API description and examples for navigation, online stores, errors and testing are in the doc/ directory of the repository.

Source code

The code is on GitHub in the nks-hub/rybbit-flutter-sdk repository, and the package is on pub.dev as rybbit_flutter_sdk. The licence is GPL-3.0, which needs to be considered for closed-source apps. pub.dev also has a rybbit_flutter package by a different author, which is unrelated to this one.

← Back to overview