appmachina 1.0.0 copy "appmachina: ^1.0.0" to clipboard
appmachina: ^1.0.0 copied to clipboard

AppMachina SDK for Flutter. Analytics with ATT, SKAN, and deep link integrations.

AppMachina Flutter SDK #

Flutter SDK for AppMachina analytics, built on a Rust core via dart:ffi.

Installation #

dependencies:
  appmachina: ^0.1.0

Usage #

import 'package:appmachina/appmachina.dart';

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

  await AppMachina.init(AppMachinaConfig(
    apiKey: 'your-api-key',
    appId: 'your-app-id',
  ));

  runApp(MyApp());
}

Track Events #

AppMachina.track('button_tapped', properties: {'screen': 'home'});

Screen Views #

AppMachina.screen('HomeScreen');

Automatic Screen Tracking #

Add AppMachinaNavigatorObserver to your MaterialApp to track screen views automatically when routes change:

MaterialApp(
  navigatorObservers: [AppMachinaNavigatorObserver()],
  // ...
)

Identify Users #

AppMachina.identify('user-123');

Set User Properties #

AppMachina.setUserProperties({'plan': 'premium', 'signup_date': '2025-01-15'});

Control what data the SDK collects. Set analytics and/or advertising to true or false. Null values mean "not determined".

AppMachina.setConsent(ConsentSettings(analytics: true, advertising: false));

ATT Integration #

Request App Tracking Transparency authorization on iOS. On Android, all ATT methods return safe defaults.

// Check if ATT is available (iOS 14.5+)
final available = await ATT.isAvailable();

if (available) {
  // Check current status before prompting
  final status = await ATT.getStatus();

  if (status == ATTStatus.notDetermined) {
    // Show the system ATT dialog
    final result = await ATT.requestAuthorization();

    if (result == ATTStatus.authorized) {
      // User granted tracking permission
      final idfa = await ATT.getAdvertisingId();
    }
  }
}

SKAN Integration #

Update SKAdNetwork conversion values on iOS. All methods are no-ops on Android.

// SKAN 2.0+: update fine conversion value (0-63)
await SKAN.updateConversionValue(42);

// SKAN 4.0: update with coarse value and optional window lock
await SKAN.updatePostbackConversionValue(
  fineValue: 42,
  coarseValue: SKANCoarseValue.high,
  lockWindow: true,
);

iOS Setup #

Add your URL scheme to Info.plist:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myapp</string>
    </array>
  </dict>
</array>

For Universal Links, add the Associated Domains entitlement:

applinks:yourdomain.com

Android Setup #

Add intent filters to AndroidManifest.xml:

<activity ...>
  <!-- Deep link URL scheme -->
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="myapp" />
  </intent-filter>

  <!-- App Links (verified) -->
  <intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" android:host="yourdomain.com" />
  </intent-filter>
</activity>

Dart Code #

// Get the deep link that launched the app (cold start)
final initialLink = await DeepLinks.getInitialLink();
if (initialLink != null) {
  handleDeepLink(initialLink);
}

// Listen for deep links while the app is running (warm start)
final unsubscribe = DeepLinks.addListener((data) {
  // data.url, data.scheme, data.host, data.path, data.queryParams
  handleDeepLink(data);
});

// Stop listening when done
unsubscribe();

Commerce Tracking #

Commerce.trackPurchase(
  productId: 'pro_monthly',
  revenue: 9.99,
  currency: 'USD',
  transactionId: 'txn_abc123',
  store: 'app_store',
  quantity: 1,
);

RevenueCat Integration #

Connect your existing RevenueCat Purchases instance to automatically track subscription events and sync user properties. No hard dependency on purchases_flutter -- uses duck typing.

import 'package:purchases_flutter/purchases_flutter.dart';

// Connect after RevenueCat is configured
RevenueCat.connect(Purchases.instance);

// Optionally track individual package purchases
final offerings = await Purchases.instance.getOfferings();
final package = offerings.current?.availablePackages.first;
if (package != null) {
  RevenueCat.trackPurchase(package);
}

Superwall Integration #

Track paywall events from your existing Superwall setup. No hard dependency on superwall_flutter -- uses duck typing.

// Track paywall presentation
Superwall.instance.setPaywallPresentationHandler(
  PaywallPresentationHandler()
    ..onPresent((info) {
      AppMachinaSuperwall.trackPresentation(info);
    })
    ..onDismiss((info) {
      AppMachinaSuperwall.trackDismiss(info);
    })
    ..onSkip((reason) {
      AppMachinaSuperwall.trackSkip(null, reason.toString());
    }),
);

Error Handling #

Register an onError callback to receive SDK errors. Errors are always logged via dart:developer regardless of this callback.

AppMachina.onError = (error) {
  // Forward to your crash reporter, logging service, etc.
  print(error);
};

await AppMachina.init(AppMachinaConfig(
  apiKey: 'your-api-key',
  appId: 'your-app-id',
));

The SDK also provides typed exceptions:

import 'package:appmachina/appmachina.dart';

// AppMachinaException — base type with message and optional code
// AppMachinaNotInitializedException — thrown when calling methods before init
// AppMachinaQueueFullException — thrown when the event queue is at capacity

Debug Mode #

Enable debug logging to see SDK activity in the console and dart:developer logs:

await AppMachina.init(AppMachinaConfig(
  apiKey: 'your-api-key',
  appId: 'your-app-id',
  enableDebug: true,
));

When enabled, the SDK logs track, screen, and identify calls with their arguments.

Print the full SDK state at any time:

AppMachina.debugPrintState();
// [AppMachina] === SDK Status ===
// [AppMachina] Initialized: true
// [AppMachina] Session ID: abc-123
// [AppMachina] Queue Depth: 5
// [AppMachina] User ID: user-42
// [AppMachina] Consent: analytics=true, advertising=unset
// [AppMachina] Debug Mode: true
// [AppMachina] Environment: production
// [AppMachina] App ID: your-app-id
// [AppMachina] Base URL: (default)
// [AppMachina] === End Status ===

Testing #

Use enableTestMode to inject a mock bindings implementation so tests run without the native Rust library:

import 'package:appmachina/appmachina.dart';

void main() {
  late MockAppMachinaBindings mock;

  setUp(() {
    mock = MockAppMachinaBindings();
    AppMachina.enableTestMode(mock);
  });

  tearDown(() {
    AppMachina.resetForTesting();
  });

  test('tracks events', () {
    AppMachina.track('button_tap', properties: {'screen': 'home'});
    expect(mock.trackedEvents, hasLength(1));
    expect(mock.trackedEvents.first['event'], 'button_tap');
  });
}
0
likes
125
points
40
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

AppMachina SDK for Flutter. Analytics with ATT, SKAN, and deep link integrations.

Homepage
Repository (GitHub)

License

MIT (license)

Dependencies

ffi, flutter, path_provider

More

Packages that depend on appmachina

Packages that implement appmachina