# Digia MoEngage Integration

URL: https://www.digia.tech/docs/developer/moengage

MoEngage Change your setup in the sidebar
The Digia MoEngage plugin intercepts **MoEngage Self-Handled In-App** campaign payloads and pipes them directly into Digia's rendering engine. Each MoEngage campaign carries a single **`digia_campaign_key`** that maps to a campaign you design in the Digia Engage Dashboard. When the campaign triggers, the plugin resolves that key against the campaigns Digia pre-fetched at startup and instantly renders a 100% native experience on the device—no WebViews required. Supported experience types include bottom sheets, dialogs, inline banners, surveys, **tooltips** , and **spotlights** .

This guide walks you through the end-to-end integration process—covering SDK installation, plugin initialization, and how to map your dashboard campaigns to Digia's native components.

## Prerequisites

Before integrating, ensure you have:

- **Digia Access Key** : Log in to the [Digia Engage Dashboard](https://engage.digia.tech) , open your project, and copy your key from **Settings → App Settings** .
- **Active Dashboard Account** : Ensure you have an active MoEngage workspace with access to your App/Account IDs.
- **MoEngage SDK** : Installed and initialized (see [Flutter](https://developers.moengage.com/hc/en-us/articles/20661421128084-Getting-Started-with-Flutter-SDK) , [Android](https://developers.moengage.com/hc/en-us/categories/360006147431-Android-SDK) , [iOS](https://developers.moengage.com/hc/en-us/articles/4403900743828-SDK-Integration) , or [React Native](https://developers.moengage.com/hc/en-us/articles/22105190881044-Getting-Started-with-React-Native-SDK#h_01HEJAHP5W49AASNSHF5614AHP) Quick Start).

### Minimum Supported Versions

- React Native - Flutter - Android - iOS (Swift)

- **Environment:** React Native `0.83+` , React `19.2+`
- **Digia packages:**[`@digia-engage/core`](https://www.npmjs.com/package/@digia-engage/core) , [`@digia-engage/moengage`](https://www.npmjs.com/package/@digia-engage/moengage)
- **MoEngage SDK:**[`react-native-moengage`](https://www.npmjs.com/package/react-native-moengage)

- **Environment:** Dart `3.3+` , Flutter `3.35+`
- **Digia packages:**[`digia_engage`](https://pub.dev/packages/digia_engage) , [`digia_moengage_plugin`](https://pub.dev/packages/digia_moengage_plugin)
- **MoEngage SDK:**[`moengage_flutter`](https://pub.dev/packages/moengage_flutter)

- **Environment:**`minSdk 24`
- **Digia packages:**[`tech.digia:engage`](https://central.sonatype.com/artifact/tech.digia/engage) , [`tech.digia:engage-moengage`](https://central.sonatype.com/artifact/tech.digia/engage-moengage)
- **MoEngage SDK:**[`com.moengage:moe-android-sdk`](https://central.sonatype.com/artifact/com.moengage/moe-android-sdk)

- **Environment:** iOS `16+`
- **Digia packages:**[`DigiaEngage`](https://swiftpackageindex.com/Digia-Technology-Private-Limited/digia_engage_iOS) , [`DigiaMoEngage`](https://swiftpackageindex.com/Digia-Technology-Private-Limited/digia_moengage_iOS)
- **MoEngage SDK:**[MoEngage iOS SDK](https://developers.moengage.com/hc/en-us/categories/360006471532-iOS-SDK)

## Install

> **Note:** We assume the core MoEngage SDK is already installed and initialized as part of your standard app setup (see Prerequisites ). The snippets below only cover adding the Digia plugin packages.

- React Native - Flutter - Android - iOS (Swift)
Install the Digia packages:
```bash
npm install @digia-engage/core@2.22.0 @digia-engage/moengage@1.1.3
```

Add the Digia packages using the `flutter pub add` command:
```bash
flutter pub add digia_engage:1.19.0 digia_moengage_plugin:1.0.1
```

Add dependencies in app `build.gradle.kts` (use the latest versions from [Maven Central](https://central.sonatype.com/artifact/tech.digia/engage) ):
```kotlin
dependencies {
  implementation("tech.digia:engage:2.17.0")
  implementation("tech.digia:engage-moengage:1.0.0-beta.04")
}
```

Sync the project (Gradle sync).

Add packages using **Xcode → File → Add Package Dependencies** and choose **Up to Next Major Version** — or in `Package.swift` , use the latest versions from [Swift Package Index](https://swiftpackageindex.com/Digia-Technology-Private-Limited/digia_engage_iOS) :
```swift
dependencies: [
    .package(url: "https://github.com/Digia-Technology-Private-Limited/digia_engage_iOS.git", from: "3.14.0"),
    .package(url: "https://github.com/Digia-Technology-Private-Limited/digia_moengage_iOS.git", from: "1.0.0-beta.2"),
],
```

Then add these products to your app target dependencies:
- `DigiaEngage`
- `DigiaMoEngage`

## Initialize Digia with MoEngage

Initialize Digia **after** the MoEngage SDK and **before** plugin registration.

- React Native - Flutter - Android - iOS (Swift)

```tsx
import { useEffect } from 'react';
import ReactMoE from 'react-native-moengage';
import { Digia } from '@digia-engage/core';
import { DigiaMoEngagePlugin } from '@digia-engage/moengage';

export function RootApp() {
  useEffect(() => {
    (async () => {
      // 1. MoEngage SDK — activate the JS bridge.
      ReactMoE.initialize('YOUR_MOENGAGE_WORKSPACE_ID');

      // 2. Initialize Digia before registering any CEP plugin.
      await Digia.initialize({
        apiKey: 'YOUR_ACCESS_KEY',
      });

      // 3. Register the Digia MoEngage plugin. Pass the ReactMoE module directly.
      Digia.register(new DigiaMoEngagePlugin({ moEngage: ReactMoE }));
    })().catch(console.error);
  }, []);

  return <AppNavigator />;
}
```

```dart
import 'package:digia_moengage_plugin/digia_moengage_plugin.dart';
import 'package:digia_engage/digia_engage.dart';
import 'package:moengage_flutter/moengage_flutter.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 1. MoEngage SDK — initialise activates the native SDK already configured as a prerequisite.
  final moEngage = MoEngageFlutter('YOUR_MOENGAGE_APP_ID');
  moEngage.initialise();

  // 2. Initialize Digia before registering any CEP plugin.
  await Digia.initialize(
    DigiaConfig(apiKey: 'YOUR_ACCESS_KEY'),
  );

  // 3. Register the Digia MoEngage plugin.
  Digia.register(MoEngagePlugin(instance: moEngage));
  runApp(const MyApp());
}
```

```kotlin
import android.app.Application
import com.digia.engage.Digia
import com.digia.engage.DigiaConfig
import com.digia.engage.moengage.DigiaMoEngagePlugin

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        // 1. MoEngage SDK — initialized as a prerequisite.
        // MoEngage.initialiseDefaultInstance(moEngage)

        // 2. Initialize Digia before registering any CEP plugin.
        Digia.initialize(
            context = applicationContext,
            config = DigiaConfig(apiKey = "YOUR_ACCESS_KEY"),
        )

        // 3. Register the Digia MoEngage plugin. Context is required to resolve the MoEngage instance.
        Digia.register(DigiaMoEngagePlugin(applicationContext))
    }
}
```

```swift
import SwiftUI
import DigiaEngage
import DigiaMoEngage

@main
struct MyApp: App {
    init() {
        // 1. MoEngage SDK — initialized as a prerequisite.
        // MoEngage.sharedInstance.initializeDefaultInstance(...)

        // 2. Initialize Digia before registering any CEP plugin.
        Task {
            do {
                try await Digia.initialize(DigiaConfig(apiKey: "YOUR_ACCESS_KEY"))

                // 3. Register the Digia MoEngage plugin.
                Digia.register(DigiaMoEngagePlugin())
            } catch { }
        }
    }

    var body: some Scene {
        WindowGroup {
            RootView()
        }
    }
}
```

## How Digia Maps to MoEngage Campaigns

> If you haven't read [How It Works](/docs/#how-it-works) in the overview, start there. The section below covers only what is MoEngage-specific.

In short: MoEngage decides **who** sees a campaign and **when** . Digia decides **what** is rendered. The two are linked by a `digia_campaign_key` you set in the MoEngage dashboard — the Digia plugin reads that key, resolves it against its local cache, and renders the right experience natively.

The table below shows how each Digia experience type maps to a MoEngage campaign type and which SDK component handles it on the app side:

| Experience Type | Digia Component | MoEngage Campaign Type | Description | **Nudge** | `DigiaHost` | Self-Handled In-App | Renders overlay experiences (bottom sheets, dialogs) above app content. | **Guide** | `DigiaAnchor` + `DigiaHost` | Self-Handled In-App | Step-by-step tooltip/spotlight flows anchored to specific UI elements. Each step targets a registered `anchorKey` . | **Survey** | `DigiaHost` | Self-Handled In-App | Multi-step survey flows rendered as overlays. | **Inline** | `DigiaSlot` | Self-Handled In-App | Renders inline content (banners, cards) within the app layout at a matching placement. 

Here is the end-to-end flow for a Self-Handled In-App campaign (Nudge, Guide, Survey, or Inline):

### The Campaign Contract

Whatever the experience type, a Digia-powered MoEngage campaign carries the same payload in its **Campaign data / Key-Value Pairs** field — a single JSON object:

```json
{
  "digia_campaign_key": "promo_offer_sheet",
  "variables": {
    "coupon": "SAVE20",
    "offer_title": "Limited Offer"
  }
}
```

- **`digia_campaign_key`** (required) — the key of the Digia campaign to render. This alone determines the experience type (nudge, guide, survey, or inline) and its design; nothing about the UI lives in the MoEngage payload.
- **`variables`** (optional) — a JSON object of runtime values interpolated into the campaign at render time.
Every experience type — nudge, guide, survey, and inline — is delivered through the same **Self-Handled In-App** campaign with this same payload. The per-experience sections below show it in context.

## Self-Handled In-App Campaigns

MoEngage supports a delivery mode called **Self-Handled In-App Campaigns** — instead of MoEngage rendering its own campaign UI, the SDK delivers the campaign payload to your app code. The Digia MoEngage plugin registers a self-handled in-app listener that intercepts this payload, extracts the **`digia_campaign_key`** , resolves it against the Digia campaigns pre-fetched at startup, and delegates rendering to Digia's runtime. **Without setting the campaign template type to Self Handled in the MoEngage dashboard, the payload will not be delivered to the plugin.**

No device-side sync is required — the plugin responds automatically once registered. Configure your campaign in the MoEngage dashboard:

1. Log in to the **MoEngage dashboard** and go to **Engage → In-App (NATIV)** .
2. Click **Create Campaign** and give it a name.
3. Set the **Template type** to **Self Handled** .
4. Configure the event trigger, audience, and schedule as required.
5. In the **Campaign data / Key-Value Pairs** field, add a key named **`digia_campaign_key`** with the Digia campaign key copied from your Digia dashboard.
See [MoEngage Self-Handled In-App](https://help.moengage.com/hc/en-us/articles/360051330591-Self-Handled-In-App-Template#h_01HP6KGBAVZDEV75BEFKRZ2M7R) .

## Setting Up Nudges

### Add the Nudge Container

Wrap your app root so overlay campaigns can render above app content.

- React Native - Flutter - Android - iOS (Swift)
Mount `<DigiaHost />` once at your app root.
```tsx
import React from 'react';
import { View } from 'react-native';
import { DigiaHost } from '@digia-engage/core';

export default function RootLayout() {
  return (
    <View style={{ flex: 1 }}>
      <DigiaHost />
      <AppNavigator />
    </View>
  );
}
```

```dart
import 'package:digia_engage/digia_engage.dart';
import 'package:flutter/material.dart';

MaterialApp(
  navigatorObservers: [DigiaNavigatorObserver()],
  builder: (context, child) => DigiaHost(child: child!),
  home: const HomeScreen(),
)
```

**Jetpack Compose**
```kotlin
import com.digia.engage.DigiaHost

DigiaHost {
    AppNavHost()
}
```

```swift
import SwiftUI
import DigiaEngage

struct RootContainerView: View {
    var body: some View {
        DigiaHost {
            AppRootView()
        }
    }
}
```

### Trigger a Nudge from MoEngage

Create a Self-Handled In-App campaign in MoEngage. In the **Campaign data / Key-Value Pairs** field, provide the `digia_campaign_key` that links to your Digia campaign:

```json
{
  "digia_campaign_key": "promo_offer_sheet"
}
```

| Field | Required | Example value | Description | `digia_campaign_key` | Yes | `promo_offer_sheet` | The Digia campaign key copied from your Digia dashboard. Its type (nudge / guide / survey / inline) and design come from Digia, not the payload. | `variables` | No | `{"coupon":"SAVE20"}` | Optional JSON map of runtime variables interpolated into the campaign at render time. 

> **Linking:** In the Digia dashboard, copy the **Digia campaign key** assigned to your campaign. In the MoEngage Self-Handled In-App campaign's Key-Value Pairs, add a key named **`digia_campaign_key`** with that value. If the values differ, the plugin cannot resolve the campaign and nothing renders.

> **`variables` format:** Enter the value as plain JSON text directly in the field — e.g., `{"coupon":"SAVE20"}` . Do not wrap it in outer quotes. The plugin JSON-decodes the payload automatically.

## Setting Up Inline Widgets

`DigiaSlot` is a composable/widget that renders Digia-powered content inline within your screen layout. Each slot is identified by a `placementKey` . When a Self-Handled In-App campaign whose `digia_campaign_key` maps to an **inline** Digia campaign triggers, Digia renders that campaign into the slot whose `placementKey` matches the slot key configured on the campaign in the Digia dashboard. If no campaign is active for a slot, it collapses to zero height.

### Add an Inline Slot

Place `DigiaSlot` where you want inline content rendered.

- React Native - Flutter - Android - iOS (Swift)

```tsx
import React from 'react';
import { ScrollView } from 'react-native';
import { DigiaSlotView } from '@digia-engage/core';

export function HomeScreen() {
  return (
    <ScrollView>
      {/* Auto-sizes to match native content height. Pass style={{ height: N }} to pin a fixed height. */}
      <DigiaSlotView placementKey="home_hero_banner" />

      <ProductCarousel />

      <DigiaSlotView placementKey="product_offers" />

      <RecommendationList />
    </ScrollView>
  );
}
```

```dart
import 'package:digia_engage/digia_engage.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: ListView(
        children: const [
          DigiaSlot('home_hero_banner'),
          SizedBox(height: 16),
          ProductCarousel(),
          SizedBox(height: 16),
          DigiaSlot('product_offers'),
          SizedBox(height: 16),
          RecommendationList(),
        ],
      ),
    );
  }
}
```

**Jetpack Compose**
```kotlin
import com.digia.engage.DigiaSlot

Column {
    DigiaSlot(placementKey = "home_hero_banner")
    DigiaSlot(placementKey = "product_offers")
}
```

**XML Layout** For View/XML layouts, use `DigiaSlotView` . It wraps the Compose `DigiaSlot` API and reads `app:placementKey` from XML.
```xml
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <com.digia.engage.DigiaSlotView
        android:id="@+id/homeHeroBanner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:placementKey="home_hero_banner" />

    <com.digia.engage.DigiaSlotView
        android:id="@+id/productOffers"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:placementKey="product_offers" />

</LinearLayout>
```

Or set the placement programmatically after inflation:
```kotlin
import com.digia.engage.DigiaSlotView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_home)

    findViewById<DigiaSlotView>(R.id.homeHeroBanner).placementKey = "home_hero_banner"
    findViewById<DigiaSlotView>(R.id.productOffers).placementKey = "product_offers"
}
```

`DigiaSlotView` requires `DigiaHost` to be mounted in the same window so the Digia rendering engine is already mounted before the slot renders.

```swift
import SwiftUI
import DigiaEngage

struct HomeScreen: View {
    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                DigiaSlot(placementKey: "home_hero_banner")
                ProductCarousel()
                DigiaSlot(placementKey: "product_offers")
                RecommendationList()
            }
            .padding()
        }
    }
}
```

### Serve Inline Content from MoEngage

Inline campaigns are delivered the same way as nudges — through a Self-Handled In-App campaign carrying a `digia_campaign_key` . Build the inline campaign in the Digia dashboard (it defines which slot / `placementKey` it targets), then set `digia_campaign_key` to the Digia campaign key from that campaign:

```json
{
  "digia_campaign_key": "home_hero_banner_campaign"
}
```

| Field | Required | Description | `digia_campaign_key` | Yes | The Digia campaign key of an **inline** campaign copied from your Digia dashboard. The campaign defines which slot key it renders into. 

The app-side `DigiaSlot` / `DigiaSlotView``placementKey` must match the slot key configured on that campaign in the Digia dashboard.

info
Inline content stays loaded once a campaign renders it — it doesn't clear when the user's context changes. To clear it (for example on logout), seeManaging Inline Content .

## Setting Up Guides

`DigiaAnchor` registers a UI element as a named anchor for tooltip and spotlight Guide campaigns. When a Guide campaign runs, the SDK looks up the `anchorKey` to position the tooltip bubble or spotlight cutout relative to that element.

Wrap any element you want to anchor and give it a unique `anchorKey` . The key must match exactly what is configured for that step in the Digia dashboard Guide campaign.

- React Native - Flutter - Android - iOS (Swift)

```tsx
import { DigiaAnchorView } from '@digia-engage/core';

// Anywhere in your screen component:
<DigiaAnchorView anchorKey="buy_now_button">
  <BuyNowButton />
</DigiaAnchorView>
```

```dart
import 'package:digia_engage/digia_engage.dart';

// Anywhere in your widget tree:
DigiaAnchor(
  anchorKey: 'buy_now_button',
  child: BuyNowButton(),
)
```

**Jetpack Compose**
```kotlin
import com.digia.engage.DigiaAnchor

// Anywhere in your composable:
DigiaAnchor(anchorKey = "buy_now_button") {
    BuyNowButton()
}
```

**XML Layout**
```xml
<com.digia.engage.DigiaAnchorView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:anchorKey="buy_now_button">

    <!-- Your view -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Buy Now" />

</com.digia.engage.DigiaAnchorView>
```

```swift
import DigiaEngage

// Anywhere in your view hierarchy:
DigiaAnchor(anchorKey: "buy_now_button") {
    BuyNowButton()
}
```

> **Note:** If the anchor is not mounted when a Guide campaign fires, the SDK logs an `anchor_not_on_screen` health event and skips that step. Ensure the anchor is on screen before navigating to the Guide step.

### Link the MoEngage Campaign to Digia

To connect a MoEngage campaign to your Digia Guide, copy the **Digia campaign key** assigned to your Guide campaign in the Digia dashboard. Then, in the MoEngage Self-Handled In-App campaign's Key-Value Pairs, add a key named **`digia_campaign_key`** with that value:

```json
{
  "digia_campaign_key": "onboarding_tour"
}
```

> **Note:** The `digia_campaign_key` value must exactly match the Digia campaign key from the dashboard. If they differ, the plugin cannot resolve the campaign and nothing renders.

## Setting Up Surveys

Surveys are multi-step questionnaire flows you design in the Digia dashboard and render as overlays in the nudge host — no extra app-side widget is required beyond the nudge container . A survey is just another campaign type: create it in Digia, then trigger it from MoEngage by referencing its Digia campaign key via `digia_campaign_key` , exactly like a nudge.

1. Build the survey campaign in the Digia Engage Dashboard and copy its Digia campaign key.
2. Ensure your app mounts the nudge container — `DigiaHost` at the app root (all platforms).
3. Create a MoEngage Self-Handled In-App campaign and add a `digia_campaign_key` Key-Value Pair set to the survey's Digia campaign key.

```json
{
  "digia_campaign_key": "nps_q3_survey"
}
```

The survey renders over your app content and reports completion back through the plugin's analytics events.

## Test Your Integration

Follow these steps to verify end-to-end functionality before releasing:

1. **Verify initialization order** — `Digia.initialize` completes, then `Digia.register(...)` with the MoEngage plugin ( `MoEngagePlugin` on Flutter, `DigiaMoEngagePlugin` on React Native), before `runApp` / first activity.
2. **Verify host placement** — `DigiaHost` must be in `MaterialApp.builder` (Flutter), the root Composable (Android Compose), or the root SwiftUI wrapper (iOS). For React Native, mount `<DigiaHost />` once at the app root.
3. **Set campaign to Self Handled** — ensure the MoEngage in-app campaign template type is **Self Handled** in the MoEngage dashboard (see Self-Handled In-App Campaigns ).
4. **Create a test campaign** — create a Self-Handled In-App campaign with a `digia_campaign_key` pointing to a known Digia campaign and trigger it immediately for your test device.
5. **Verify inline slots** — place `DigiaSlot` / `DigiaSlotView` on a visible screen, trigger a Self-Handled In-App campaign whose `digia_campaign_key` points to an inline Digia campaign targeting that slot, and confirm content renders.
6. **Verify guides** — register a `DigiaAnchor` / `DigiaAnchorView` with an `anchorKey` , point a Guide campaign step at it, and confirm the tooltip/spotlight anchors correctly.
7. **Verify screen tracking** — navigate between screens and confirm that screen-triggered campaigns fire on the correct screen (use `DigiaNavigatorObserver` on Flutter, `Digia.setCurrentScreen(...)` or `digiaScreen("...")` in Android View/XML apps, route/screen change hooks calling `Digia.setCurrentScreen(...)` on Swift, and navigation listeners calling `Digia.setCurrentScreen(...)` on React Native). SeeReporting the Current Screen for per-stack and per-router wiring, andScreen Targeting to scope campaigns to specific screens.

## Troubleshooting

### Campaign not rendering

- Confirm initialization order — `Digia.initialize(...)` then `Digia.register(...)` with the MoEngage plugin ( `MoEngagePlugin` on Flutter, `DigiaMoEngagePlugin` on React Native).
- Ensure the MoEngage campaign template type is set to **Self Handled** in the MoEngage dashboard.
- **iOS (Swift)** : Confirm `MoEngage.sharedInstance.initializeDefaultInstance(...)` runs at app start and `Info.plist` includes `MOEnvType` .
- **React Native** : Confirm `Digia.initialize(...)` and `Digia.register(new DigiaMoEngagePlugin(...))` are called once during app startup.
- Ensure `DigiaHost` is mounted at the app root.
- **React Native** : Ensure `<DigiaHost />` is mounted once at app root, and confirm `Digia.initialize(...)` completes before `Digia.register(...)` .
- Check `digia_campaign_key` exactly matches the Digia campaign key (case-sensitive).
- Verify campaign eligibility and trigger conditions in the MoEngage dashboard.

### Inline content not showing

- Confirm the Self-Handled In-App payload includes a `digia_campaign_key` that maps to an **inline** Digia campaign.
- Ensure the campaign's slot key (configured in the Digia dashboard) matches `DigiaSlot('placement_key')` or `DigiaSlotView app:placementKey` exactly (case-sensitive).
- Verify the slot exists on the currently visible screen.
- **React Native** : `DigiaSlotView` auto-sizes to match native content height. If it still appears collapsed, confirm the inline campaign is active and the `placementKey` matches. To pin a fixed height, pass `style={{ height: 180 }}` .

### Guide (tooltip / spotlight) not anchoring

- Ensure the element is wrapped in `DigiaAnchor` / `DigiaAnchorView` with an `anchorKey` that exactly matches the step configured in the Digia dashboard Guide campaign.
- Confirm the anchor is mounted on screen when the campaign fires — if not, the SDK logs `anchor_not_on_screen` and skips the step.
- **React Native** : Confirm `<DigiaHost />` is mounted at the app root.

### Screen-triggered campaign not firing

- Add `DigiaNavigatorObserver()` to `navigatorObservers` (Flutter).
- Call `Digia.setCurrentScreen(...)` on navigation changes (Android Compose: `navController.addOnDestinationChangedListener` ).
- **Android XML / Views** : Call `digiaScreen("screen_name")` from `Activity.onResume()` or `Fragment.onResume()` .
- For unnamed routes, call `Digia.setCurrentScreen('screen_name')` manually.
- **iOS (Swift)** : On tab/route changes, call `Digia.setCurrentScreen("screen_name")` from your navigation layer.
- **React Native** : Wire navigation change events (React Navigation / Expo Router) to `Digia.setCurrentScreen(routeName)` .

### MoEngage SDK not initialized (Android)

- Ensure `MoEngage.initialise(moEngage)` is called in `Application.onCreate()` before `Digia.register(...)` .
- Verify MoEngage credentials are correctly configured per [MoEngage Android Quick Start](https://developers.moengage.com/hc/en-us/categories/360006147431-Android-SDK) .

## Official MoEngage References

- [Flutter SDK](https://developers.moengage.com/hc/en-us/articles/20661421128084-Getting-Started-with-Flutter-SDK)
- [Android Quick Start](https://developers.moengage.com/hc/en-us/categories/360006147431-Android-SDK)
- [iOS SDK Integration](https://developers.moengage.com/hc/en-us/categories/360006471532-iOS-SDK)
- [React Native Quick Start Guide](https://developers.moengage.com/hc/en-us/categories/4404199274900-React-Native-SDK)
