Upgrade to Flutter 2.x
UpdatedThis page provides steps to help you upgrade from our Flutter 1.x SDK so you understand the development effort required to update your app and take advantage of the latest features.
What changed?
This update provides native support for Data PipelinesCustomer.io’s customer data platform, helping you capture data from your sources, transform it, and send it to destinations where you can act on it. Data Pipelines is also the preferred integration path for your Customer.io workspace, as it supports all of our Journeys features and other destinations that rely on your data. as a part of the Customer.io SDK. While this represents a significant change “under the hood,” we’ve tried to make it as seamless as possible for you; much of your implementation remains the same.
This move also adds two additional features:
- You’ll use SDK methods from an
instance
: - Support for anonymous tracking: you can send events and other activity for anonymous users, and we’ll reconcile that activity with a person when you identify them.
- Built-in lifecycle events: the SDK now automatically captures events like “Application Installed” and “Application Updated” for you.
- New device-level data: the SDK captures the device
name
and other device-level context for you.
If you’re new to Data Pipelines, don’t worry! It’s free and it’s very similar to our other APIs. We’ll walk you through the process to set up your Flutter app as a data sourceA source is a website or server that you want to capture data from—it’s a source of data! and everything.
When you’re done, you’ll be able to use your app’s data in both Customer.io and other downstream destinations—like your analytics platform, data warehouse, or CRM. All that and you’ll be prepared to accept new features and improvements that we roll out in the future!
Upgrade process
You’ll update initialization calls for the SDK itself and the push and/or in-app messaging modules.
As a part of this process, your credentials change. You’ll need to set up a new data sourceA source is a website or server that you want to capture data from—it’s a source of data! in Customer.io and get a new CDP API Key. But you’ll also need to keep your previous siteId
as a migrationSiteId
when you initialize the SDK. The migrationSiteId
is a key helps the SDK send remaining traffic when people update your app.
When you’re done, you’ll also need to change a few base properties to fit the new APIs. In general, identifier
becomes userId
, body
becomes traits
, and data
becomes properties
.
1. Get your new CDP API Key
The new version of the SDK requires you to set up a new data sourceA source is a website or server that you want to capture data from—it’s a source of data! in Customer.io. As a part of this process, you’ll get your CDP API Key.
- Go to the Data Pipelines tab. On the Connections page under Sources, click Add Source.
- Select the Mobile: Flutter source and then click Next: Connect Flutter.
- Enter a Name for the source, like “My Flutter App”.
- We’ll present you with a code sample containing a
cdpApiKey
that you’ll use to initialize the SDK. Copy this key and keep it handy. - Test your connect and click Complete Setup. Or, if you don’t want to test your implementation yet, Save & Complete Later and then click Install Source to finish the setup process. In this case, Complete Later simply means that we haven’t seen any data from your Flutter app yet.
Now the Connections page shows that your Flutter source is connected to your Journeys workspace. Hover over a source or destination to see its active connections. You can also connect your Flutter source to additional destinations if you want to send your mobile data to additional services—like your analytics provider, data warehouse, or CRM.
2. Update the SDK initialization
You’ll need to update the way you initialize the SDK—with a new key and configuration options for in-app and push. We show an example configuration below.
You’ll find a complete list of configuration options on the Packages and Configuration Options page, but you’ll want to pay close attention to the following changes:
- You’ll initialize the SDK with a
cdpApiKey
. This is the key you’ll get when you create your Flutter sourceA source is a website or server that you want to capture data from—it’s a source of data! siteId
becomesmigrationSiteId
.- Your
inAppConfig
changes and requires yoursiteId
. - The optional
pushConfig
is now a part of your initialization call. You won’t set push settings as a part of a separate configuration like you did with the 1.x SDK.
CustomerIO.initialize(
config: CustomerIOConfig(
cdpApiKey: 'cdpApiKey',
migrationSiteId: 'migrationSiteId',
region: Region.us,
autoTrackDeviceAttributes: true,
inAppConfig: InAppConfig(siteId: 'siteId'),
// pushConfig is optional if you use default settings
pushConfig: PushConfig(
android: PushConfigAndroid(
pushClickBehaviorAndroid:
PushClickBehaviorAndroid.activityPreventRestart,
),
),
),
);
3. Update your podfile (iOS)
For iOS, you’ll need to update your podfile with the correct iOS dependencies. Update your Runner
and NotificationServiceExtension
targets with the code below.
target 'Runner' do
pod 'customer_io/fcm', :path => '.symlinks/plugins/customer_io/ios'
end
target 'NotificationServiceExtension' do
pod 'customer_io_richpush/fcm', :path => '.symlinks/plugins/customer_io/ios'
end
4. Update your push notification handler
In the previous version of the SDK, you had to initialize the SDK itself and the MessagingPushFCM
package. You no longer need to initialize the SDK in your notification handler.
You’ll also notice that all the configuration settings for push are a part of the SDK initialization itself. You won’t set push settings in your notification handler anymore.
import UIKit
import Flutter
import CioMessagingPushFCM
import FirebaseMessaging
import FirebaseCore
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// Depending on how you install Firebase,
// you may need to add functions to this file, like:
// FirebaseApp.configure()
//
// Read the official Firebase docs to install Firebase correctly!
Messaging.messaging().delegate = self
MessagingPushFCM.initialize(
withConfig: MessagingPushConfigBuilder()
.build()
)
// This Sets a 3rd party push event handler for the app—rather than the Customer.io SDK and FlutterFire.
// Setting the AppDelegate as the handler will internally use `flutter_local_notifications` to handle push events.
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().setAPNSToken(deviceToken, type: .unknown);
}
override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
MessagingPush.shared.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
MessagingPush.shared.messaging(messaging, didReceiveRegistrationToken: fcmToken)
}
}
5. Update your API calls
You’ll now make your calls from .instance
methods. There are also a few crucial differences between the 1.x API and the 2.x API:
userId
replacesidentifier
in youridentify
call.attributes
has changed totraits
inidentify
,setProfileAttributes
, andsetDeviceAttributes
methods.properties
replacesattributes
intrack
,screen
, and any other eventSomething that a person in your workspace did. Events can trigger campaigns, add people to segments, etc. You can access event properties in liquid with{{event.<property>}}
calls.
//new call
CustomerIO.instance.identify(userId: email, traits: {
"name": user.displayName,
"email": user.email,
"age": user.age,
});
//old call
CustomerIO.identify(identifier: email, attributes: {
"name": user.displayName,
"email": user.email,
"age": user.age,
});
//new call
CustomerIO.instance.track(name: "Movie Watched", properties: {
"movie_name": "The Incredibles",
"watch_time_in_minutes": 102,
});
//old call
CustomerIO.track(name: "Movie Watched", attributes: {
"movie_name": "The Incredibles",
"watch_time_in_minutes": 102,
});
//new call
CustomerIO.instance.screen(title: "Settings", properties: {
"source": "Dashboard",
"is_logged_in": true,
});
//old call
CustomerIO.screen(name: "Settings", attributes: {
"source": "Dashboard",
"is_logged_in": true,
});
Configuration Changes
As a part of this release, we’ve changed a few CustomerIOConfig
configuration options when you initialize the SDK. The following table shows the changes to the configuration options.
Field | Type | Default | Description |
---|---|---|---|
cdpApiKey | string | Replaces apiKey ; required to initialize the SDK. This is the key representing your Data Pipelines sourceA source is a website or server that you want to capture data from—it’s a source of data! | |
migrationSiteId | string | Replaces siteId ; required if you’re updating from 2.x. This is the key representing your previous version of the SDK. | |
trackApplicationLifeCycleEvents | boolean | true | When true, the SDK automatically tracks application lifecycle events (like Application Installed). |
inAppConfig | object | Replaces the former enableInApp option, providing a place to set in-app configuration options. For now, it takes a single property called siteId . | |
pushConfig | object | Optional push configuration settings directly in the CustomerIOConfig . For now, it only takes the android.PushClickBehavior setting. If you don’t set a pushConfig , we’ll use default push settings. |