Skip to main content

Architecture Overview

High-Level Diagram

Application Code ──► Public API (EngagementCloud.* namespaces)


Domain Modules (Contact, Event, Push, InApp, DeepLink, Setup)


Orchestration / State (SdkContext + ReRegistration States)


Networking Layer (Ktor clients per platform)


Database (SQLDelight + Key/Value Store)


Platform Adapters (Android Services, iOS Delegates, JS SW)

Core Concepts

  • Initialization vs. Enabling: Initialization wires dependencies and sets up the database and coroutines. Enabling (enable) starts tracking, event processing, and network communication.
  • Central Context (SdkContext): Stores mutable runtime data (applicationCode, contact identifiers, push token, language) across launches.
  • Event Bus: Internal events are emitted through EngagementCloud.events as EngagementCloudEvent instances (app events, badge count). On Web, use the type property to filter events.
  • Re-registration State Machine: Manages contact linking and push token persistence across app restarts and SDK updates. Maintains consistency even during temporary network failures.
  • Multiplatform Abstraction: All business logic lives in commonMain. Dedicated adapters handle platform-specific operations such as Android Startup, iOS UserNotificationCenter, and JS service worker registration.

Threading & Concurrency

  • All asynchronous work uses Kotlin coroutines. Public suspend functions run off the UI thread.
  • On Swift and JS, suspend functions are wrapped as async/await-compatible calls.
  • The SDK serializes operations that mutate shared context (for example, linking a contact) to avoid race conditions.

Error Handling Philosophy

  • Public asynchronous APIs return Result<Unit> (Kotlin) or throw/promise reject (Swift/JS) on failure.
  • Non-fatal conditions (already enabled, duplicate link) return domain-specific exceptions inside the result. These idempotent errors are safe to ignore.

Event Flow

  1. User calls public API (e.g., EngagementCloud.event.track(CustomEvent))
  2. The SDK validates and maps the event to an internal model.
  3. The event is stored locally (SQLDelight) for reliability.
  4. A dispatch job schedules the network request.
  5. On success, the local entry is removed. On failure, the SDK retries with backoff.
  6. State changes such as badge count updates also emit events.

Database Strategy

  • Lightweight key-value for context fields and SQLDelight for queued events.
  • All writing operations are persisted immediately for crash resilience.
  • A migration layer handles backward-compatible schema updates.

SDK Lifecycle States

StateDescriptionTransitions
UninitializedClasses loaded, context not yet available.app start -> Initialized
InitializedDependency graph ready; no tracking/network.enable() -> Enabled
EnabledFull feature set active (events, push token registration).disable() -> Initialized

Performance Considerations

  • Batching: Multiple events are batched by scheduler to reduce network traffic under high activity.
  • Memory: Event objects are short-lived. The database avoids large in-memory queues.
  • Push Token: Only sent when changed (deduped).

Security Notes

  • All network calls rely on transport layer security. Image URLs for rich push must be HTTPS.
  • Cryptography libraries provide secure randomness and hashing.

When to Call What

OperationRecommended Timing
initialize() (iOS only)App launch before UI shows
enable(config)After consent and applicationCode are available
contact.link(...)After user authentication and identification
push.registerToken(token)Immediately after system issues token
event.track(...)Any time after enabling
inapp.pause()/resume()Around sensitive flows (checkout, payment)