Documentation Index
Fetch the complete documentation index at: https://docs.cello.so/llms.txt
Use this file to discover all available pages before exploring further.
Beta
The Cello Flutter SDK allows you to use Cello for iOS and Cello for Android in your Flutter apps. With a plug-n-play mobile component, your users can easily share their invite link with their friends and network using mobile sharing options convenient for them, receive rewards and get paid out.
Installation
A basic installation takes around 15 minutes, but will take a little longer if you want to customize the way the Cello Referral Component is launched.
Compatibility
- The Cello Flutter SDK supports Flutter 3.3.0 and above (Dart 3+).
- Cello for iOS supports iOS 15+.
- Cello for Android supports API 21+.
Install Cello
flutter pub add cello_sdk
Or add to your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
cello_sdk: ^0.0.1
Then run:
Android Setup
The Flutter plugin automatically handles linking for Android. Ensure your app’s android/app/build.gradle has the correct configuration:
android {
compileSdk 34
defaultConfig {
minSdk 21
// ... other config
}
}
Ensure your project’s android/build.gradle (or app-level) includes:
repositories {
google()
mavenCentral()
}
Internet Permission
Add internet permission in android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
iOS Setup
The Flutter plugin automatically handles linking for iOS via CocoaPods.
From your ios/ directory, run:
Ensure your ios/Podfile specifies iOS 15.0+:
Choose an Environment
In your Cello SDK setup, you have the flexibility to select the environment in which your application will run. This feature is especially useful for different stages of development, such as testing in a development or staging environment before going live in production. The available environments are:
production or prod (Production) (default)
sandbox (Sandbox)
You specify the environment when initializing Cello:
await Cello.initialize(
CelloInitializeOptions(
productId: 'your-product-id',
token: 'your-token',
environment: 'sandbox', // or 'production'
),
);
Customize the Cello Referral Component
The Cello Flutter SDK allows for various levels of customization to better fit into your app’s design and flow. One of the main components you might want to customize is the Referral component
Choose Your Launcher
The library provides two ways to launch the Referral component:
Default launcher
If you choose to go with the default launcher, you can call the showFab() method from the Cello library to present a Floating Action Button (FAB) within your app. This FAB is pre-styled but may not perfectly match your app’s look and feel.
import 'package:cello_sdk/cello_sdk.dart';
await Cello.showFab();
Custom launcher
If the default launcher does not fit your needs, you can implement your own custom launcher. This could be any UI element like a button, menu item, or even a gesture. To open the Referral component using a custom launcher, you can call Cello.openWidget().
import 'package:cello_sdk/cello_sdk.dart';
ElevatedButton(
onPressed: () async {
await Cello.openWidget();
},
child: Text('Open Referral'),
)
Flutter API
Cello.initialize(CelloInitializeOptions): Future<CelloConfiguration>
Initializes the Cello referral component.
CelloInitializeOptions
| Property | Type | Required | Description |
|---|
| productId | String | yes | Your product ID from Cello Portal |
| token | String | yes | User authentication token |
| environment | String? | no | Environment: "production" or "sandbox" |
| productUserDetails | ProductUserDetails | no | User details object (see below) |
| language | String? | no | Initial language of the widget |
| themeMode | String? | no | Initial theme mode: "light", "dark", or "system" |
ProductUserDetails
Optional object with user information:
| Property | Type | Description |
|---|
| firstName | String | User’s first name |
| lastName | String | User’s last name |
| fullName | String | User’s full name |
| email | String | User’s email address |
import 'package:cello_sdk/cello_sdk.dart';
final config = await Cello.initialize(
CelloInitializeOptions(
productId: 'your-product-id',
token: 'your-token',
environment: 'production',
productUserDetails: ProductUserDetails(
firstName: 'John',
lastName: 'Doe',
fullName: 'John Doe',
email: 'john.doe@example.com',
),
language: 'de',
themeMode: 'system',
),
);
Cello.showFab(): Future<void>
Shows the default Cello button that launches the Referral Component
Cello.hideFab(): Future<void>
Hides the default Cello button that launches the Referral Component
Opens the referral component.
await Cello.openWidget();
Hides the referral component.
await Cello.hideWidget();
Cello.getActiveUcc(): Future<Map<String, String>>
A method to get an active ucc and related data for the currently logged in user.
final ucc = await Cello.getActiveUcc();
// Returns: { "ucc": "...", "inviteLink": "..." } or empty map
Cello.getCampaignConfig(): Future<Map<String, dynamic>>
A method to get the campaign configuration.
final config = await Cello.getCampaignConfig();
// Returns: Map with campaign settings
Cello.changeLanguage(String language): Future<void>
A method to change the language of the Referral component at runtime without re-initialising it.
Note: Requires iOS 14+ on iOS platform.
await Cello.changeLanguage('de');
Cello.setThemeMode(String themeMode): Future<void>
A method to change the theme mode of the Referral component at runtime without re-initialising it.
Note: Requires iOS 14+ on iOS platform.
await Cello.setThemeMode('dark');
Parameters:
themeMode (String): The theme mode to set. Valid values are "light", "dark", or "system".
Cello.updateToken(String token): Future<void>
Updates the user authentication token without re-initializing.
Note: Requires iOS 14+ on iOS platform.
await Cello.updateToken('new-token');
Cello.shutdown(): Future<void>
Shuts down connection to Cello and unmounts the component
Cello.tokenEvents: Stream<CelloTokenEvent>
A broadcast stream that emits token lifecycle events.
Cello.tokenEvents.listen((event) {
switch (event.type) {
case CelloTokenEventType.tokenAboutToExpire:
// Refresh your token
refreshToken();
break;
case CelloTokenEventType.tokenHasExpired:
// Handle expired token
handleExpiredToken();
break;
}
});
Error Handling
Exception types
The Cello Flutter SDK throws PlatformException with specific error codes when operations fail:
| Code | Platform(s) | Trigger | Typical causes |
|---|
InitializationError | iOS & Android | Cello.initialize completes with native failure | Invalid/empty product ID or token, network issues, bad environment |
InitializationException | Android | Unexpected exception inside Cello.initialize | Activity finishing, SDK not linked correctly, runtime crash |
ActivityUnavailable | Android | Cello.initialize without an active Activity | Initialization triggered too early (e.g. before app fully ready) |
TokenUpdateError | iOS | Cello.updateToken failure | Token expired/invalid, network errors |
LanguageChangeError | iOS | Cello.changeLanguage failure | Unsupported language code, network errors |
ThemeModeChangeError | iOS | Cello.setThemeMode failure | Invalid theme mode value, network errors |
Unavailable | iOS | Feature requires iOS 14+ | Device running < iOS 14 when calling token, language, or theme updates |
ClientUnavailable | Android | Method called before initialization | SDK not initialized before calling other methods |
CelloError | Android | Generic SDK error | Various SDK-level errors |
UccError | Android | Cello.getActiveUcc threw | SDK not initialized, network or serialization errors |
CampaignConfigError | Android | Cello.getCampaignConfig threw | SDK not initialized, configuration not ready |
InvalidArguments | iOS & Android | Missing or invalid method arguments | Required parameters not provided or have invalid values |
Tip: Catch PlatformException and inspect error.code, error.message, and error.details for extra context.
Common error scenarios
1. Initialization exception
Symptoms: InitializationError or InitializationException in the catch block.
Fix: Validate credentials, confirm network connectivity, and ensure you selected the right environment (production vs sandbox). Check native logs for additional details.
2. Methods called before initialization
Symptoms: ClientUnavailable error on Android or native console warnings.
Fix: Ensure Cello.initialize completes successfully before calling other methods like showFab() or openWidget(). Track initialization state in your app.
Cello.changeLanguage, Cello.setThemeMode, and Cello.updateToken require iOS 14+ on iOS. On older devices these methods reject with Unavailable error. Guard these calls with a platform/version check if needed.
Error handling best practices
1. Wrap initialization in try/catch:
import 'package:flutter/services.dart';
import 'package:cello_sdk/cello_sdk.dart';
Future<void> bootstrapCello() async {
try {
if (productId.trim().isEmpty || token.trim().isEmpty) {
throw Exception('Missing credentials');
}
final config = await Cello.initialize(
CelloInitializeOptions(
productId: productId,
token: token,
productUserDetails: productUserDetails,
),
);
setState(() {
celloReady = true;
});
print('[Cello] Initialized: ${config.rawResponse}');
} on PlatformException catch (e) {
print('[Cello] Initialization failed: ${e.code} - ${e.message}');
// Show user-friendly error
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Referrals unavailable'),
content: Text('Please check your connection and try again.'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('OK'),
),
],
),
);
} catch (e) {
print('[Cello] Unexpected error: $e');
}
}
2. Delay UI interactions: Only call Cello.showFab() or Cello.openWidget() after a successful initialization. Keep a dedicated isCelloReady state flag in your widgets.
ElevatedButton(
onPressed: celloReady ? () => Cello.openWidget() : null,
child: Text('Open Referral'),
)
3. Handle token lifecycle: Listen to Cello.tokenEvents and refresh tokens proactively before they expire:
StreamSubscription<CelloTokenEvent>? _tokenSubscription;
@override
void initState() {
super.initState();
_tokenSubscription = Cello.tokenEvents.listen((event) {
if (event.type == CelloTokenEventType.tokenAboutToExpire) {
// Refresh token from your backend
_refreshCelloToken();
}
});
}
@override
void dispose() {
_tokenSubscription?.cancel();
super.dispose();
}
Future<void> _refreshCelloToken() async {
try {
// Get fresh token from your API
final newToken = await fetchFreshToken();
// Update Cello with new token
await Cello.updateToken(newToken);
print('[Cello] Token refreshed successfully');
} on PlatformException catch (e) {
print('[Cello] Token refresh failed: ${e.code} - ${e.message}');
}
}
4. Retry on transient errors: For recoverable failures (network timeouts, InitializationError), schedule a retry with exponential backoff. Limit retries to avoid looping endlessly.
5. Log error details: Capture error codes, messages, and relevant details in your logging/monitoring solution to help support diagnose issues quickly.