Migration Overview
This page helps you migrate from the SAP Emarsys SDK for Android, iOS, and Web to the SAP Engagement Cloud SDK.
Why Migrate?
The SAP Engagement Cloud SDK is the next-generation SDK for SAP Engagement Cloud, serving all mobile and web touchpoints through a unified integration. The SDK focuses on integration consistency and ease of use, incorporating customer feedback and a redesigned architecture across all platforms. Going forward, all new features will be developed exclusively for this SDK.
The SDK offers several key improvements, including:
- A redesigned, modern architecture delivering tangible performance gains. For example, in-app messages now appear faster than with the SAP Emarsys SDK.
- One consistent API across Android, iOS, and Web, reducing integration complexity and enabling faster time-to-value.
- Fewer setup steps and an improved developer experience reduce the potential for errors and accelerate onboarding.
- Decoupled initialization and setup, allowing tracking to be enabled and disabled independently at any time while the app is running.
- First-party data collection on Web, avoiding the limitations of third-party cookies and ad blockers. This enables richer behavioral data collection for more accurate personalization across all channels.
Core Architectural Shifts
| Area | SAP Emarsys SDKs (Android / iOS / Web) | SAP Engagement Cloud SDK |
|---|---|---|
| Initialization | Native: Emarsys.setup(config); Web: queued loader script (WebEmarsysSdk(...).init) immediately starts tracking | Two-phase: EngagementCloud.initialize() then EngagementCloud.setup.enable(config) when you want data flow |
| Contact Management | setContact, setAuthenticatedContact, clearContact; Web: login, setOpenIdAuthenticatedContact, logout | link, linkAuthenticated, unlink (uniform) |
| Push Token / Subscription | setPushToken, clearPushToken, getPushToken; Web: subscribe, unsubscribe, isSubscribed | registerToken, clearToken, getToken (Web uses same naming & semantics; subscription state derived from token presence) |
| In-App Control | pause()/resume()/isPaused; Web did not have in-app messaging | pause() / resume() / isPaused (Web: not applicable yet, until WebChannel integration) |
| Custom Events | trackCustomEvent(name, attrs); Web: customEvent(name, attrs) | event.track(CustomEvent(name, attrs)) |
| Deep Link Tracking | Manual/native handlers; Web: manual link tracking not unified | deepLink.track(url) |
| Reactive Events | Various callbacks & handler interfaces; Web: multiple event listeners (onSubscribe, onUnsubscribe, permission events) | Unified reactive stream: EngagementCloud.events (Web exposes same event surface; with a convenient listener registration API) |
High-Level Migration Steps
- Remove SAP Emarsys SDK dependencies (Gradle / SPM / CocoaPods) and add the SAP Engagement Cloud SDK as a dependency.
- Replace the previous
Emarsys.setupcall with the new, two-phaseinitializeandenableapproach. Callenableonly after the user grants marketing consent. - Migrate contact calls — for example, replace
setContactwithlink. - Replace previous
setPushTokencalls withregisterTokencalls. - Migrate custom event tracking to use the new
CustomEventmodel. - Replace deep link tracking with the new API.
- (Optional) Migrate to the reactive event streams of the SDK instead of using
eventHandlers.
When to Enable Tracking
- Android
- Kotlin Multiplatform
- iOS
- Web
-
The SDK initializes automatically. You do NOT need to call
initialize()manually. -
Call
EngagementCloud.setup.enable(config)only after:
- The user has granted marketing consent.
- The
ApplicationCodeis available. - You are ready to start tracking events.
The enable() call is idempotent and safe to repeat. Repeated calls return an SdkAlreadyEnabledException inside Result.
-
For Kotlin Multiplatform projects, the SDK initializes automatically on Android. On other KMP targets, initialization is handled by the platform-specific integration.
-
Call
EngagementCloud.setup.enable(config)only after:
- The user has granted marketing consent.
- The
ApplicationCodeis available. - You are ready to start tracking events.
The enable() call is idempotent and safe to repeat. Repeated calls return an SdkAlreadyEnabledException inside Result.
-
The SDK initializes automatically. You do NOT need to call
initialize()manually. -
Call
EngagementCloud.setup.enable(config)only after:
- The user has granted marketing consent.
- The
ApplicationCodeis available. - You are ready to start tracking events.
The enable() call is idempotent and safe to repeat. Repeated calls return an SdkAlreadyEnabledException inside Result.
-
The SDK initializes automatically. You do NOT need to call
initialize()manually. -
Call
await window.EngagementCloud.setup.enable(config)only after:
- The user has granted marketing consent.
- The
ApplicationCodeis available. - You are ready to start tracking events.
The enable() call is idempotent and safe to repeat. Repeated calls return an "already enabled" error inside the Promise resolution.
Error Handling Philosophy
The completion listeners and blocks from the SAP Emarsys SDK have been replaced by suspend (Kotlin) and async (Swift) calls that return Result (Android/KMP) or throw on failure (iOS). On Web, calls return Promises. This approach provides the following benefits:
- Unified handling of success and failure without custom listener interfaces.
- Easier composition with coroutines and asynchronous await.
- Explicit error typing instead of nullable error parameters.
Patterns:
- Kotlin:
EngagementCloud.contact.link(value).onFailure { log(it) }or.getOrThrow()inside try/catch - Swift:
do { try await EngagementCloud.shared.contact.link(...) } catch { /* handle */ } - JS/TS:
await window.EngagementCloud.contact.link(...)
Example Code
- Android
- Kotlin Multiplatform
- iOS
- Web
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
// Later (after user consent or user login)
EngagementCloud.setup.enable(
config = AndroidEngagementCloudSDKConfig(
applicationCode = "ABCDE-12345",
launchActivityClass = MainActivity::class.java
),
onContactLinkingFailed = {
// Prompt user to log in and retrieve their contact identifier
val loggedInUser = showLoginDialogAndAwaitResult()
loggedInUser?.let { LinkContactData(contactFieldValue = it.userId) }
}
)
// Contact linking
EngagementCloud.contact.link(contactFieldValue)
// Custom event
EngagementCloud.event.track(CustomEvent(name, attributes))
}
}
// KMP shared code
EngagementCloud.setup.enable(
config = SdkConfig(applicationCode = "ABCDE-12345"),
onContactLinkingFailed = {
// Prompt user to log in and retrieve their contact identifier
val loggedInUser = showLoginDialogAndAwaitResult()
loggedInUser?.let { LinkContactData(contactFieldValue = it.userId) }
}
)
// Contact linking
EngagementCloud.contact.link(contactFieldValue)
// Custom event
EngagementCloud.event.track(CustomEvent(name, attributes))
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize the SDK
try? await EngagementCloud.shared.initialize()
// Later (after user consent or user login)
try? await EngagementCloud.shared.setup.enable(
config: EngagementCloudConfig(applicationCode: <String>),
onContactLinkingFailed: { onSuccess, onError in
Task {
guard let loggedInUser = await showLoginDialogAndAwaitResult() else { return }
onSuccess(LinkContactDataContactFieldValueData(contactFieldValue: loggedInUser.userId))
}
}
)
// Contact linking
try? await EngagementCloud.shared.contact.link(contactFieldValue: String)
// Custom event
try? await EngagementCloud.shared.event.track(event: CustomEvent(name: String, attributes: Dictionary<String, String>))
return true
}
}
<head>
<title>Migration Guide</title>
<script src="engagement-cloud-sdk-loader.js"></script>
</head>
<body>
<script>
// The public API is available from the window
let engagementCloud = window.EngagementCloud;
await engagementCloud.setup.enable(
{ applicationCode: '<String>' },
async () => {
// Prompt user to log in and retrieve their contact identifier
const loggedInUser = await showLoginDialogAndAwaitResult();
if (!loggedInUser) return null;
return { contactFieldValue: loggedInUser.userId };
}
);
await engagementCloud.contact.link(contactFieldValue);
await engagementCloud.event.track({ type: 'custom', name: '<name>', attributes: { key: 'value' } });
</script>
</body>
login / logout / setOpenIdAuthenticatedContact from the SAP Emarsys SDK map directly to contact.link, contact.unlink, contact.linkAuthenticated from the SAP Engagement Cloud SDK.
Migrating On Event Actions
The SAP Emarsys SDK's onEventAction handlers are replaced by the reactive EngagementCloud.events stream in the SAP Engagement Cloud SDK. Replace handler registrations with a single collector/subscriber that consumes AppEvent and other event types from the stream.
Known Limitations
For more information about known limitations, refer to Known Limitations.
Next Steps
Proceed to Detailed Migration Steps for setup instructions and use API Mapping to migrate feature-specific calls.