Upgrade to Flutter 2.x

Updated

This 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.

  1. Go to the Data Pipelines tab. On the Connections page under Sources, click Add Source.
  2. Select the Mobile: Flutter source and then click Next: Connect Flutter.
    set up your Flutter source
    set up your Flutter source
  3. Enter a Name for the source, like “My Flutter App”.
  4. 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.
  5. 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.
    Set your name, get your CDP API Key, and click Complete Setup
    Set your name, get your CDP API Key, and click Complete Setup

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.

the connections page, showing an Flutter source connected to a journeys destination
the connections page, showing an Flutter source connected to a journeys destination

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 becomes migrationSiteId.
  • Your inAppConfig changes and requires your siteId.
  • 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:

  1. userId replaces identifier in your identify call.
  2. attributes has changed to traits in identify, setProfileAttributes, and setDeviceAttributes methods.
  3. properties replaces attributes in track, 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.

FieldTypeDefaultDescription
cdpApiKeystringReplaces 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!
migrationSiteIdstringReplaces siteId; required if you’re updating from 2.x. This is the key representing your previous version of the SDK.
trackApplicationLifeCycleEventsbooleantrueWhen true, the SDK automatically tracks application lifecycle events (like Application Installed).
inAppConfigobjectReplaces the former enableInApp option, providing a place to set in-app configuration options. For now, it takes a single property called siteId.
pushConfigobjectOptional 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.
Copied to clipboard!
  Contents
Current release
 2.1.1
Is this page helpful?