# Upgrade from 3.4x to 4x

This page provides steps to help you upgrade from react native 3.4 or later so you understand the development effort required to update your app and take advantage of the latest features.

## What changed?[](#what-changed)

This update provides native support for our new integrations framework. 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:

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

## Upgrade process[](#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 inAn integration that feeds data *into* Customer.io. integration 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*[](#1-get-your-new-cdp-api-key)

The new version of the SDK requires you to set up a new data inAn integration that feeds data *into* Customer.io. integration in Customer.io. As a part of this process, you’ll get your *CDP API Key*.

1.  Go to [*Data & Integrations* > *Integrations*](https://fly.customer.io/workspaces/last/journeys/integrations/all/overview) and click **Add Integration**.
2.  Select **React Native**.
3.  Enter a *Name* for your integration, like “My React Native 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.  Click **Complete Setup** to finish setting up your integration.
    
    [![Set your name, get your CDP API Key, and click Complete Setup](https://docs.customer.io/images/cdp-react-native-source-setup.png)](#40e573b250197f1c640f816429d6bf9b-lightbox)
    

Remember, you can also [connect your React Native app to services outside of Customer.io](/integrations/data-out/add-destination/)—like your analytics provider, data warehouse, or CRM.

### 2\. Update your initialization[](#2-update-your-initialization)

You’ll initialize the new version of the SDK and its packages with `CioConfig` objects instead of `CustomerioConfig`. While we’ve listed all the new configuration options, you’ll want to pay close attention to the following changes:

*   `CustomerIOEnv` is no longer necessary.
*   `Region` becomes `CioRegion`.
*   `siteId` becomes `migrationSiteId`.
*   You’ll initialize the SDK with `initialize(config)` instead of `initialize(env, config)`.

If you previously used the `backgroundQueueMinNumberOfTasks` or `backgroundQueueSecondsDelay` options, you should remove them from your configuration as well. These options are no longer supported, and may cause build errors if you use strict type checking.

```javascript
import {
  CioLogLevel, CioRegion, CustomerIO, CioConfig
} from 'customerio-reactnative';
  
const config: CioConfig = {
  cdpApiKey: 'cdp_api_key', // Mandatory
  migrationSiteId: 'site_id', // For migration
  region: CioRegion.US,
  logLevel: CioLogLevel.Debug,
  trackApplicationLifecycleEvents: true,
  inApp: {
    siteId: 'site_id', // this removes the use of enableInApp and simplifies in-app configuration
  },
  push: {
    android: {
      pushClickBehavior: PushClickBehaviorAndroid.ActivityPreventRestart
    }
  }
};
CustomerIO.initialize(config)
```

### 3\. Update your AppDelegate push notification handler[](#3-update-your-appdelegate-push-notification-handler)

In your `MyAppPushNotificationsHandler.swift` (or the associated file where you add a push notification handler in your main target), you can remove the `CioTracking` module and the `initialize` method.

**If you write native code in Objective-C**, you’ll also need to update your `MessagingPushAPN` or `MessagingPushFCM` initialization. We’ve highlighted the lines you’ll need to remove or modify in the code sample below.

 APN

#### APN[](#APN)

```swift
import Foundation
import CioMessagingPushAPN
// remove this line
import CioTracking  

@objc
public class MyAppPushNotificationsHandler : NSObject {

  public override init() {}

  @objc(setupCustomerIOClickHandling)
  public func setupCustomerIOClickHandling() {
    // remove this line
    CustomerIO.initialize(siteId: "siteId", apiKey: "apiKey", region: .US) { config in }

    // update this line to 
    MessagingPushAPN.initialize(withConfig: MessagingPushConfigBuilder().build())
  }

  @objc(application:deviceToken:)
  public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    MessagingPush.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
  }

  @objc(application:error:)
  public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    MessagingPush.shared.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
  }
}
```

 FCM

#### FCM[](#FCM)

```swift
import Foundation
import CioMessagingPushFCM
import FirebaseMessaging
// remove this line
import CioTracking

@objc
public class MyAppPushNotificationsHandler : NSObject {

  public override init() {}

  @objc(setupCustomerIOClickHandling)
  public func setupCustomerIOClickHandling() {
    // remove this line
    CustomerIO.initialize(siteId: Env.siteId, apiKey: Env.apiKey, region: Region.US) { config in }
    
    // update this line to
    MessagingPushFCM.initialize(withConfig: MessagingPushConfigBuilder().build())
  }

  // Register device on receiving a device token (FCM)
  @objc(didReceiveRegistrationToken:fcmToken:)
  public func didReceiveRegistrationToken(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    MessagingPush.shared.messaging(messaging, didReceiveRegistrationToken: fcmToken)
  }
}
```

### 4\. Update your NotificationService push notification handler[](#4-update-your-notificationservice-push-notification-handler)

In your `NotificationServicePushHandler.swift` (or the associated file where you add a push notification handler in NotificationServiceExtension), you can remove the `CioTracking` module and the `initialize` method.

**If you write native code in Objective-C**, you’ll also need to update your `MessagingPushAPN` or `MessagingPushFCM` initialization. We’ve highlighted the lines you’ll need to remove or modify in the code sample below.

 APN

#### APN[](#APN)

```swift
import Foundation
import UserNotifications
import CioMessagingPushAPN
// remove this line
import CioTracking  

@objc
public class NotificationServicePushHandler: NSObject {

  public override init() {}

  @objc(didReceive:withContentHandler:)
  public func didReceive(
    _ request: UNNotificationRequest,
    withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
  ) {
    // remove this line
    CustomerIO.initialize(siteId: "siteId", apiKey: "apiKey", region: .US) { config in }

    // update this line to
    MessagingPushAPN.initializeForExtension(
      withConfig: MessagingPushConfigBuilder(cdpApiKey: "cdpApiKey")
        // Optional: specify region where your Customer.io account is located (.US or .EU). Default: US
        // .region(.US)
        .build()
    )

    MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
  }

  @objc(serviceExtensionTimeWillExpire)
  public func serviceExtensionTimeWillExpire() {
    MessagingPush.shared.serviceExtensionTimeWillExpire()
  }
}
```

 FCM

#### FCM[](#FCM)

```swift
import Foundation
import UserNotifications
import CioMessagingPushFCM
// remove this line
import CioTracking

@objc
public class NotificationServicePushHandler: NSObject {

  public override init() {}

  @objc(didReceive:withContentHandler:)
  public func didReceive(
    _ request: UNNotificationRequest,
    withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
  ) {
    // remove this line
    CustomerIO.initialize(siteId: "siteId", apiKey: "apiKey", region: .US) { config in }

    // update this line to
    MessagingPushFCM.initializeForExtension(
      withConfig: MessagingPushConfigBuilder(cdpApiKey: "cdpApiKey")
        // Optional: specify region where your Customer.io account is located (.US or .EU). Default: US
        // .region(.US)
        .build()
    )

    MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
  }

  @objc(serviceExtensionTimeWillExpire)
  public func serviceExtensionTimeWillExpire() {
    MessagingPush.shared.serviceExtensionTimeWillExpire()
  }
}
```

### 5\. Update your `identify` call[](#5-update-your-identify-call)

Our APIs changed slightly in this release. We’ve done our best to make the new APIs as similar as possible to the old ones. The names of a few properties that you’ll pass in your calls have changed, but their functionality has not.

*   `identify`: `identifier` becomes `userId` and `body` becomes `traits`
*   `track` and `screen` calls are structured the same as previous versions, but the `data` object is now called `properties`.

We’ve highlighted changes in the sample below.

```javascript
//identify: identifier becomes userId, body becomes traits
CustomerIO.identify({
  userId: "user_id", 
  traits: {
    first_name: "user_name",
    email: "email_identifier",
  },
});

//track: no significant change to method 
//in Customer.io data object renamed properties
CustomerIO.track("track_event_name", { 
  propertyName: propertyValue 
});

//screen: no significant change to method.
//name becomes title, data object renamed properties
CustomerIO.screen("screen_event_name", { 
  propertyName: propertyValue 
});
```

## Configuration Changes[](#configuration-changes)

As a part of this release, we’ve changed a few configuration options when you initialize the SDK. You’ll use `CioConfig` to set your configuration options. The following table shows the changes to the configuration options.

Field

Type

Default

Description

`cdpApiKey`

string

Replaces `apiKey`; required to initialize the SDK and send data into Customer.io.

`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*).

`inApp`

object

Replaces the former `enableInApp` option, providing a place to set in-app configuration options. For now, it takes a single property called `siteId`.

`push`

object

Replaces the former `enablePush` option, providing a place to set push configuration options. For now, it only takes the `android.pushClickBehavior` setting.

`backgroundQueueMinNumberOfTasks`

removed

This option is no longer available.

`backgroundQueueSecondsDelay`

removed

This option is no longer available.