<!--
AppSprint docs markdown
Canonical HTML: https://appsprint.app/docs/flutter
Markdown URL: https://appsprint.app/docs/flutter.md
Docs index: https://appsprint.app/docs.md
Sitemap: https://appsprint.app/sitemap.xml
LLM guide: https://appsprint.app/llms.txt
-->

# Flutter

Installation, configuration, event tracking, and full API reference for the Flutter SDK.

## Requirements

- Flutter 3.0+
- Dart 3.0+
- iOS 14.0+ and Android API 21+

## 1. Install

pub.dev

```yaml
# pubspec.yaml
dependencies:
  appsprint_flutter: ^1.0.1

# Then run:
flutter pub get
```

> The Flutter plugin manages the iOS pod and the Android AAR for you. No extra repository setup needed.

[View on pub.dev](https://pub.dev/packages/appsprint_flutter)

## 2. Configure

```typescript
import 'package:flutter/material.dart';
import 'package:appsprint_flutter/appsprint_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await AppSprint.instance.configure(
    const AppSprintConfig(apiKey: 'as_live_xxxxx'),
  );

  runApp(const MyApp());
}
```

Non-blocking. configure() resolves after local state is restored; install registration runs in the background on the native side. Platform-specific code (AdServices on iOS, Play Install Referrer on Android) runs through method channels.

### Configuration options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `apiKey` | `String` | — | Your live API key (starts with as_live_). |
| `apiUrl` | `String` | https://api.appsprint.app | Override for staging or self-hosted environments. |
| `enableAppleAdsAttribution` | `bool` | true | iOS only. Fetches Apple AdServices at install time. |
| `customerUserId` | `String?` | null | Your internal user ID. Persists across launches and replays automatically if the first send fails. |
| `autoTrackSessions` | `bool` | true | Fires session_start on configure() and on foreground, debounced to one event per 30 minutes. |
| `autoRefreshAttribution` | `bool` | true | Refetches /v1/sdk/attribution on configure() and foreground transitions. |
| `googleAdsConsent` | `GoogleAdsConsent?` | null | Optional Google Ads ad user data consent forwarded as consent.adUserData on Google Ads uploads. |
| `isDebug` | `bool` | false | Forces debug-level logging on the native side. |
| `logLevel` | `int` | 2 (WARN) | 0 = DEBUG, 1 = INFO, 2 = WARN, 3 = ERROR. |

## 3. Track events

```typescript
// Standard event
await AppSprint.instance.sendEvent(AppSprintEventType.login);
```

```typescript
// Revenue event. Currency must be a 3-letter ISO code.
await AppSprint.instance.sendEvent(
  AppSprintEventType.purchase,
  params: {'revenue': 9.99, 'currency': 'USD'},
);
```

```typescript
// Custom event with parameters
await AppSprint.instance.sendEvent(
  AppSprintEventType.custom,
  name: 'level_complete',
  params: {'level': 5, 'score': 1200},
);
```

### Supported event types

`session_start`, `login`, `sign_up`, `register`, `purchase`, `subscribe`, `start_trial`, `add_payment_info`, `add_to_cart`, `add_to_wishlist`, `initiate_checkout`, `view_content`, `view_item`, `search`, `share`, `tutorial_complete`, `achieve_level`, `level_start`, `level_complete`, `custom`

## 4. Read attribution

```typescript
final attr = await AppSprint.instance.getAttribution();
print(attr?.source);         // "apple_ads", "tracking_link", or "organic"
print(attr?.isAttributed);   // bool
print(attr?.campaignName);   // Campaign name when available
print(attr?.appleAds?.campaignId);
print(attr?.link?.name);
```

## API reference

### `configure(config)` → Future<void>

Initializes the SDK. Resolves after local state is restored; install registration runs in the background.

```typescript
await AppSprint.instance.configure(const AppSprintConfig(apiKey: '…'));
```

### `sendEvent(type, {name, params})` → Future<void>

Enqueues an event locally and schedules a flush.

```typescript
await AppSprint.instance.sendEvent(AppSprintEventType.purchase, params: {'revenue': 9.99, 'currency': 'USD'});
```

### `flush()` → Future<void>

Drains the queue immediately.

```typescript
await AppSprint.instance.flush()
```

### `refreshAttribution()` → Future<AttributionResult?>

Fetches the latest attribution from the backend. Self-heals a 404 install_not_found by re-running install.

```typescript
final attr = await AppSprint.instance.refreshAttribution();
```

### `setCustomerUserId(id)` → Future<void>

Updates the customer user ID. Sent immediately if install is registered; otherwise queued and retried automatically.

```typescript
await AppSprint.instance.setCustomerUserId('user-123');
```

### `getAppSprintId()` → Future<String?>

Returns the install ID, or null before install registration completes.

```typescript
final id = await AppSprint.instance.getAppSprintId();
```

### `getAttribution()` → Future<AttributionResult?>

Returns the cached AttributionResult.

```typescript
final attr = await AppSprint.instance.getAttribution();
```

### `getAttributionParams()` → Future<Map<String, String>>

Partner-ready flat payload for forwarding to RevenueCat, Superwall, etc.

```typescript
final params = await AppSprint.instance.getAttributionParams();
```

### `enableAppleAdsAttribution()` → Future<bool>

Re-enables Apple Ads at runtime on iOS. Returns false on Android.

```typescript
await AppSprint.instance.enableAppleAdsAttribution()
```

### `isInitialized()` → Future<bool>

True once configure() resolved.

```typescript
await AppSprint.instance.isInitialized()
```

### `isSdkDisabled()` → Future<bool>

True if a 401 or 403 permanently disabled the SDK.

```typescript
await AppSprint.instance.isSdkDisabled()
```

### `sendTestEvent()` → Future<TestEventResult>

Posts a diagnostic event and resolves to (success, message).

```typescript
final result = await AppSprint.instance.sendTestEvent();
```

### `clearData()` → Future<void>

Wipes local state and the event queue.

```typescript
await AppSprint.instance.clearData()
```


## Offline behavior

- Events that fail to send are automatically queued in native storage (up to 100 events).
- The queue persists across app restarts.
- Queued events are retried automatically when configure() completes, when the app moves to the background, or when you call flush().
- If a queued event receives a 401/403, the SDK disables itself and clears the queue.

## Platform notes

- The Flutter plugin wraps the native iOS and Android SDKs through method channels. Behavior matches the native SDKs exactly; the Dart layer is a thin pass-through.
- configure() is non-blocking. The future resolves once local state is restored; install registration runs in the background on the native side.
- On iOS, ATT must be requested while the app is foreground-active. AppSprintNative.requestTrackingAuthorization() waits for that state internally, so calling it from main() or initState() is safe.
- On Android, GAID is read off the main thread, honoring Limit Ad Tracking and dropping the all-zero advertising ID. The plugin declares INTERNET, ACCESS_NETWORK_STATE, and AD_ID for you.
- Events persist to native storage (UserDefaults on iOS, SharedPreferences on Android) and survive app restarts. Maximum queue size is 100 events.
- iOS uses URLSession with waitsForConnectivity = true. Transient offline windows queue inside the OS rather than failing fast.

## Troubleshooting

**getAppSprintId() returns null**
configure() resolves before install registration finishes on the native side. Check isInitialized() and retry briefly, or read the value after the first event has been sent.

**Events do not appear in dashboard**
Confirm the API key starts with as_live_. Call sendTestEvent() and inspect the message. iOS logs flow into Console.app; Android logs flow into logcat under the AppSprint tag.

**SDK disabled after 401/403**
Call clearData(), then configure() with a valid key.

**pod install fails after adding the package**
Run flutter clean, flutter pub get, then cd ios && pod install --repo-update.

**Attribution returns organic on iOS when Apple Ads is expected**
Backend resolution can take up to 75 seconds. The SDK refetches automatically by default; if disabled, call refreshAttribution() manually.

## Connectivity test

```typescript
final result = await AppSprint.instance.sendTestEvent();
print('${result.success} — ${result.message}');
```

## Verification checklist

1. Create a blank Flutter app and add the pub.dev dependency.
2. Call configure() before runApp() in main().
3. Verify getAppSprintId() returns a value after first launch.
4. Send login, purchase, and custom events. Confirm they appear in the dashboard.
5. Send an event offline, restart the app online. Verify queue flush.
6. Call sendTestEvent() and confirm success is true.

---

## Docs navigation

Use the Markdown URLs when reading the docs programmatically. Use the HTML URLs when you need the interactive docs UI.

- [Overview](https://appsprint.app/docs) ([Markdown](https://appsprint.app/docs.md)) — Introduction to AppSprint
- [Quickstart](https://appsprint.app/docs/quickstart) ([Markdown](https://appsprint.app/docs/quickstart.md)) — Get up and running in 5 minutes
- [React Native](https://appsprint.app/docs/react-native) ([Markdown](https://appsprint.app/docs/react-native.md)) — React Native / Expo SDK reference
- [iOS (Swift)](https://appsprint.app/docs/ios-swift) ([Markdown](https://appsprint.app/docs/ios-swift.md)) — Native Swift SDK reference
- [Android (Kotlin)](https://appsprint.app/docs/android) ([Markdown](https://appsprint.app/docs/android.md)) — Native Android SDK reference
- [Flutter](https://appsprint.app/docs/flutter) ([Markdown](https://appsprint.app/docs/flutter.md)) — Flutter plugin reference
- [RevenueCat](https://appsprint.app/docs/revenuecat) ([Markdown](https://appsprint.app/docs/revenuecat.md)) — Webhook integration for subscription attribution
- [Superwall](https://appsprint.app/docs/superwall) ([Markdown](https://appsprint.app/docs/superwall.md)) — Webhook integration for paywall attribution
- [Apple Search Ads](https://appsprint.app/docs/apple-search-ads) ([Markdown](https://appsprint.app/docs/apple-search-ads.md)) — Campaign and keyword attribution
- [Google Ads](https://appsprint.app/docs/google-ads) ([Markdown](https://appsprint.app/docs/google-ads.md)) — Offline click conversion upload
- [TikTok Ads](https://appsprint.app/docs/tiktok-ads) ([Markdown](https://appsprint.app/docs/tiktok-ads.md)) — Events API server-side event forwarding
