> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gameball.co/llms.txt
> Use this file to discover all available pages before exploring further.

# How Do I Migrate to the Flutter SDK v4?

> Upgrade from v3 to v4.0.0, or migrate from v2 to v4.0.0

# Migration Notes & Changelog

This guide helps you upgrade from Gameball Flutter SDK v3 to v4.0.0, and migrate from v2 to v4.0.0.

## What's New in v4.0.0

> [!WARNING]
>
> **Breaking change: iOS 15.0 and Android API 24 minimums.** v4.0.0 raises the minimum supported platform versions to iOS 15.0 and Android API 24 (Android 7.0). Every v3.x call keeps its signature and behavior, so no Dart code changes are required.

### New Features in v4.0.0

* **In-App Messaging**: `startInAppMessaging(customerId:, navigatorKey:)` displays the slide-up, modal, and full-screen campaigns you create in the Gameball dashboard, and `stopInAppMessaging()` stops it on logout. Nothing runs until you call `startInAppMessaging`, so upgrading without it changes nothing. See [In-App Messaging](https://docs.gameball.co/installation-guides/v4/flutter/in-app-messaging.md)
* **In-App Messaging Hooks**: `beforeDisplay`, `onAction`, and `onNavigate` let you postpone a message, handle a tap yourself, and route `navigate` actions through go\_router or any other router. The `onInAppMessage` stream reports each selected message
* **Purchase Logging**: `logPurchase(customerId:, productId:, price:, currency:, ...)` sends a `purchase` event to Gameball that campaigns can target and filter on
* **Diagnostic Logging Switch**: `gameballInAppMessagingLogging` controls in-app messaging console logs. It is on in debug builds and off in release builds
* **Published Package**: the package on pub.dev now contains only the SDK sources. Tests, the example app, and internal docs are excluded

### Migrate v3.x → v4.0.0 (Breaking)

* Set `minSdk` to 24 in `android/app/build.gradle`.
* Set the iOS deployment target to 15.0 in `ios/Podfile` (`platform :ios, '15.0'`) and for the Runner target in Xcode, then run `pod install`.
* Update `pubspec.yaml` to `gameball_sdk: ^4.0.0`, then run `flutter pub get`.
* (Optional) Adopt in-app messaging. See [In-App Messaging](https://docs.gameball.co/installation-guides/v4/flutter/in-app-messaging.md).
* (Optional) If you build `purchase` events yourself, replace them with `logPurchase` rather than sending both.

> [!NOTE]
>
> **Coming from v3.2.x or earlier?** v4.0.0 also includes the v3.2.2 and v3.3.x releases: per-call and global widget language (`ShowProfileRequestBuilder` `lang` and `setLanguage(lang)`), push notification click tracking (`handlePushClick`), and `initializeCustomer` always registering customers, with `isGuest` ignored. See the [release history](https://github.com/gameballers/gameball-flutter/releases).

***

## What's New in v3.2.1

* **Fixed — Widget Shop Parameter**: the `shop` value was sent to the widget URL under a duplicate `platform` key, which broke widget coupon redemption (infinite loading) when both `platform` and `shop` were configured. No API changes — update the version and run `flutter pub get`.

***

## What's New in v3.2.0

> [!NOTE]
>
> **Widget Events, Dismissal & External Links** — v3.2.0 keeps all v3.x code compatible. Every new capability is opt-in, so an existing integration keeps working after a version bump.

### New Features in v3.2.0

* **Widget Event Channel**: `ShowProfileRequestBuilder().widgetEventCallback(...)` receives events posted from the widget, such as `gameCompleted`
* **Host-Initiated Dismiss**: `GameballApp.getInstance().hideProfile()` dismisses the widget programmatically
* **Web-Initiated Close**: the widget can dismiss itself via `window.GameballWidget.closeWidget()`
* **External-Link Handling**: links tagged `gbExternalBrowser=true` open in the system browser, or in your own handler via `externalLinkCallback`
* **Channel Merging**: `ShowProfileRequestBuilder` accepts optional `mobile` and `email`
* **Diagnostic Logging**: the SDK records internal diagnostic logs to aid troubleshooting. No integration changes required

### Dependency Constraints in v3.2.0

`share_plus`, `device_info_plus`, and `package_info_plus` constraints were widened. The lower bounds are unchanged, so existing apps resolve the same versions and nothing breaks on upgrade.

> [!NOTE]
>
> Apps that opt into `share_plus` 13.x require Flutter 3.38.1+ and Dart 3.10+. Staying on your current `share_plus` version needs no action.

### Migrate v3.1.x → v3.2.1 (Non-Breaking)

* Update `pubspec.yaml` to `gameball_sdk: ^3.2.1`, then run `flutter pub get`.
* No code changes are required. Adopt the new widget capabilities only if you need them — see [Show Profile Widget](https://docs.gameball.co/installation-guides/v4/flutter/show-profile.md).

***

### New Features in v3.1.1

* **Guest Mode Support**: Profile widget can open without customerId
* **Non-Throwing ShowProfileRequest**: customerId optional for guest mode
* **Session Token Support**: Optional token-based authentication (from 3.1.0)
* **Automatic Endpoint Versioning**: Routes to v4.1 API when token is present
* **Per-Request Token Override**: Override global token on individual API calls
* **Global Token Management**: Token updates globally when passed to any method
* **Backward Compatible**: All v3.0.0 code works unchanged

> [card] Improved API
>
> Cleaner API design with better error handling and null safety

> [card] Better Performance
>
> Optimized SDK initialization and reduced package size

> [card] Flutter 3.x Support
>
> Full compatibility with Flutter 3.x and latest Firebase plugins

> [card] Enhanced Type Safety
>
> Better Dart null safety support and compile-time checks

## Breaking Changes

### 1. SDK Initialization

**v2:**

```dart theme={null}
gameballApp.init("api-key", "en", "flutter", "shop-id");
```

**v3.2.0:**

```dart theme={null}
final config = GameballConfigBuilder()
    .apiKey("api-key")
    .lang("en")
    .platform("flutter")
    .shop("shop-id")
    .sessionToken("session-token")  // Optional
    .build();

final gameballApp = GameballApp.getInstance();
gameballApp.init(config);
```

### 2. Customer Registration

**v2:**

```dart theme={null}
CustomerAttributes customerAttributes = CustomerAttributes(
  displayName: "John Doe",
  mobileNumber: "0123456789",   // Note: was mobileNumber
  customAttributes: {"city": "New York"},
);

gameballApp.registerCustomer(
  "customerId",
  "customer@example.com",
  "1234567890",
  "abc123",   // referralCode
  false,      // isGuest
  (response, error) {
    // Handle response
  },
);
```

**v3.2.0:**

```dart theme={null}
final attributes = CustomerAttributesBuilder()
    .displayName("John Doe")
    .email(email)
    .mobile(mobile)
    .build();

final request = InitializeCustomerRequestBuilder()
    .customerId(playerId)
    .customerAttributes(attributes)
    .build();

GameballApp.getInstance().initializeCustomer(request, (response, error) {
  // Handle response
});

// Optional: Override session token for this request (updates global token)
GameballApp.getInstance().initializeCustomer(
  request,
  (response, error) {
    // Handle response
  },
  sessionToken: "customer-token"
);
```

### 3. Event Tracking

**v2:**

```dart theme={null}
Event eventBody = Event(
  customerId: "customerId",
  events: {
    "purchase": {"amount": "100.00"},
  },
);

gameballApp.sendEvent(eventBody, (success, error) {
  // Handle response
});
```

**v3.2.0:**

```dart theme={null}
final event = EventBuilder()
    .customerId("customer-123")
    .eventName("purchase")
    .eventMetaData("amount", 99.99)
    .eventMetaData("currency", "USD")
    .build();

GameballApp.getInstance().sendEvent(event, (success, error) {
  // Handle response
});
```

### 4. Show Profile Widget

**v2:**

```dart theme={null}
gameballApp.showProfile(
  context,
  "customerId",
  "openDetail",
  hideNavigation,
  showCloseButton,
);
```

**v3.2.0:**

```dart theme={null}
final profileRequest = ShowProfileRequestBuilder()
    .customerId("customer-123")
    .showCloseButton(true)
    .build();

GameballApp.getInstance().showProfile(context, profileRequest);
```

## Migration Steps

### From v3.x to v4.0.0

**1. Raise Platform Minimums**

Set `minSdk` to 24 in `android/app/build.gradle`, and the iOS deployment target to 15.0:

```ruby theme={null}
# ios/Podfile
platform :ios, '15.0'
```

Also set `IPHONEOS_DEPLOYMENT_TARGET` to 15.0 for the Runner target in Xcode.

**2. Update Dependency**

Update your `pubspec.yaml` to use SDK v4.0.0:

```yaml theme={null}
dependencies:
  gameball_sdk: ^4.0.0
```

Run `flutter pub get` and `cd ios && pod install`.

**3. (Optional) Adopt In-App Messaging**

Pass your `MaterialApp`'s navigator key to `startInAppMessaging` once the customer is known, and call `stopInAppMessaging()` on logout. See [In-App Messaging](https://docs.gameball.co/installation-guides/v4/flutter/in-app-messaging.md).

**4. Test**

Verify that `initializeCustomer`, `sendEvent`, and `showProfile` behave as before on both iOS and Android.

### From v2.x to v4.0.0

**1. Raise Platform Minimums**

Set `minSdk` to 24 in `android/app/build.gradle`, and the iOS deployment target to 15.0:

```ruby theme={null}
# ios/Podfile
platform :ios, '15.0'
```

Also set `IPHONEOS_DEPLOYMENT_TARGET` to 15.0 for the Runner target in Xcode.

**2. Update Dependency**

Update your `pubspec.yaml` to use SDK v4.0.0:

```yaml theme={null}
dependencies:
  gameball_sdk: ^4.0.0
```

Run `flutter pub get` and `cd ios && pod install`.

**3. Update Initialization**

Replace initialization with `GameballConfigBuilder()` pattern:

```dart theme={null}
final config = GameballConfigBuilder()
    .apiKey("your-api-key")
    .lang("en")
    .platform("flutter")
    .shop("your-shop-id")
    .build();

final gameballApp = GameballApp.getInstance();
gameballApp.init(config);
```

**4. Update Customer Registration**

Use `InitializeCustomerRequestBuilder` and `CustomerAttributesBuilder`:

```dart theme={null}
final request = InitializeCustomerRequestBuilder()
    .customerId("id")
    .customerAttributes(attributes)
    .build();
```

**5. Update Event Tracking**

Use `EventBuilder` with chained methods:

```dart theme={null}
final event = EventBuilder()
    .customerId("id")
    .eventName("purchase")
    .eventMetaData("key", value)
    .build();
```

**6. Update Show Profile**

Use `ShowProfileRequestBuilder` for showing profile:

```dart theme={null}
final request = ShowProfileRequestBuilder()
    .customerId("id")
    .build();
```

**7. Test Thoroughly**

Test all Gameball functionality on both iOS and Android to ensure the migration is successful.

## Compatibility

* **Minimum Flutter Version**: 1.17.0 (3.0+ recommended)
* **Dart**: 3.4.4+
* **Android**: API level 24+ (Android 7.0) as of v4.0.0, targetSdkVersion 34
* **iOS**: iOS 15.0+ as of v4.0.0

## Additional Resources

* Check the [gameball-flutter releases page](https://github.com/gameballers/gameball-flutter/releases) for version history and release notes
* Visit [Gameball Docs](https://docs.gameball.co/) for the latest documentation

> [!TIP]
>
> If you encounter any issues during migration, check the GitHub repository for known issues and solutions, or contact Gameball support.

## Next Steps

* [Getting Started](https://docs.gameball.co/installation-guides/v4/flutter/getting-started.md)
* [Initialize SDK](https://docs.gameball.co/installation-guides/v4/flutter/initialize-sdk.md)
* [Go-Live Checklist](https://docs.gameball.co/installation-guides/v4/flutter/go-live-checklist.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.