# Digia CleverTap Integration

***

The Digia CleverTap plugin intercepts **CleverTap In-App** and **CleverTap Native Display** campaign payloads and pipes them directly into Digia's rendering engine. When a campaign triggers, the plugin maps the incoming payload to your custom UI designs built in Digia Studio, instantly rendering a 100% native experience on the device—no WebViews required. Supported experience types include bottom sheets, dialogs, inline banners, **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.

## 1. Prerequisites

Before integrating, ensure you have:

* **Digia Access Key**: Log in to [Digia Studio](https://app.digia.tech), open your project, and copy your key from **Settings → App Settings**.
* **Active Dashboard Account**: Ensure you have an active CleverTap workspace with access to your App/Account IDs.
* **CleverTap SDK**: Installed and initialized (see [Flutter](https://developer.clevertap.com/docs/flutter-quick-start-guide), [Android](https://developer.clevertap.com/docs/android-quick-start-guide), [iOS](https://developer.clevertap.com/docs/ios-quickstart-guide), or [React Native](https://developer.clevertap.com/docs/react-native-quick-start-guide) Quick Start).

### Minimum Supported Versions

| Platform         | Environment                                                       | Minimum Dependencies                                                                                                                                            |
| ---------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Flutter**      | <p>Dart <code>>=3.3.0</code><br>Flutter <code>>=3.20.0</code></p> | <p><code>digia\_engage: ^1.1.0</code><br><code>digia\_engage\_clevertap: ^1.1.0</code><br><code>clevertap\_plugin: ^3.8.1</code></p>                            |
| **Android**      | `minSdk 25`                                                       | <p><code>tech.digia:engage:2.0.0</code><br><code>tech.digia:engage-clevertap:2.0.0</code><br><code>com.clevertap.android:clevertap-android-sdk:7.3.1</code></p> |
| **iOS (Swift)**  | iOS `16+`                                                         | <p><code>DigiaEngage: 2.0.0</code><br><code>DigiaEngageCleverTap: 1.0.0</code><br><code>CleverTapSDK: 7.5.1</code></p>                                          |
| **React Native** | React Native `0.73+`                                              | <p><code>@digia-engage/core: 2.0.1</code><br><code>@digia-engage/clevertap: 2.0.0</code><br><code>clevertap-react-native: ^4.0.0</code></p>                     |

***

## 2. Install

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

{% tabs %}
{% tab title="React Native" %}
Install the Digia packages:

```bash
npm install @digia-engage/core@2.0.1 @digia-engage/clevertap@2.0.0
```

{% endtab %}

{% tab title="Android" %}
Add dependencies in app `build.gradle.kts`:

```kotlin
dependencies {
    implementation("tech.digia:engage:2.0.0")
    implementation("tech.digia:engage-clevertap:2.0.0")
}
```

Sync the project (Gradle sync).
{% endtab %}

{% tab title="iOS (Swift)" %}
Add packages using **Xcode → File → Add Package Dependencies** (or in `Package.swift`):

```swift
dependencies: [
    .package(url: "https://github.com/Digia-Technology-Private-Limited/digia_engage_iOS.git", exact: "2.0.0"),
    .package(url: "https://github.com/Digia-Technology-Private-Limited/digia_engage_clevertap_iOS.git", exact: "1.0.0"),
],
```

Then add these products to your app target dependencies:

* `DigiaEngage`
* `DigiaEngageCleverTap`
  {% endtab %}

{% tab title="Flutter" %}
Add the Digia packages using the `flutter pub add` command:

```bash
flutter pub add digia_engage digia_engage_clevertap
```

{% endtab %}
{% endtabs %}

***

## 3. Initialize Digia with CleverTap

Initialize Digia **after** CleverTap SDK and **before** plugin registration.

{% tabs %}
{% tab title="React Native" %}

```tsx
import { useEffect } from 'react';
import CleverTap from 'clevertap-react-native';
import { Digia } from '@digia/engage-react-native';
import { DigiaCleverTapPlugin, createCleverTapClient } from '@digia/clevertap-plugin';

export function RootApp() {
  useEffect(() => {
    (async () => {
      // 1. CleverTap SDK — must be initialized as a prerequisite.

      // 2. Initialize Digia once at startup.
      await Digia.initialize({
        apiKey: 'YOUR_ACCESS_KEY',
      });

      // 3. Register the Digia CleverTap plugin.
      Digia.register(
        new DigiaCleverTapPlugin({
          cleverTap: createCleverTapClient(CleverTap),
        })
      );

      // 4. Wire screen tracking to your navigation library.
      // Call Digia.setCurrentScreen(routeName) on every navigation change so
      // screen-triggered campaigns fire on the correct screen.
    })().catch(console.error);
  }, []);

  return <AppNavigator />;
}
```

{% endtab %}

{% tab title="Android" %}

```kotlin
import android.app.Application
import com.clevertap.android.sdk.ActivityLifecycleCallback
import com.digia.engage.Digia
import com.digia.engage.DigiaConfig
import com.digia.engage.clevertap.DigiaCleverTapPlugin

class MyApplication : Application() {
    override fun onCreate() {
        // 1. In custom Application class, CleverTap recommends registering activity lifecycle callback before super.onCreate(). 
        // Read: https://developer.clevertap.com/docs/flutter-quick-start-guide#set-up-androids-application-class
        ActivityLifecycleCallback.register(this)
        super.onCreate()

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

        // 3. Register the Digia CleverTap plugin. Context is required to resolve the CleverTap default instance.
        Digia.register(DigiaCleverTapPlugin(applicationContext))
    }
}
```

{% endtab %}

{% tab title="iOS (Swift)" %}

```swift
import SwiftUI
import DigiaEngage
import DigiaEngageCleverTap

@main
struct MyApp: App {
    init() {
        // 1. CleverTap SDK — initialized as a prerequisite.
        CleverTap.autoIntegrate()

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

                // 3. Register the Digia CleverTap plugin.
                Digia.register(DigiaCleverTapPlugin())
            } catch { }
        }
    }

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

{% endtab %}

{% tab title="Flutter" %}

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

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

  // 1. CleverTap SDK — initialized as a prerequisite.

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

  // 3. Register the Digia CleverTap plugin.
  Digia.register(DigiaCleverTapPlugin());
  runApp(const MyApp());
}
```

{% endtab %}
{% endtabs %}

### Advanced Config Options (React Native)

`Digia.initialize()` accepts additional fields that control SDK behaviour:

```tsx
await Digia.initialize({
  apiKey: 'YOUR_ACCESS_KEY',
  environment: 'production',      // 'production' | 'sandbox' — defaults to 'production'
  logLevel: 'error',             // 'none' | 'error' | 'verbose' — defaults to 'error'
  onAction: (action, context) => {
    // Intercept any campaign action before the SDK handles it.
    // Return true to suppress the SDK's default handling.
  },
  linking: {
    inAppBrowser: defaultInAppBrowser, // Required if any campaign uses open_url with presentation: 'in_app'
  },
});
```

Import `defaultInAppBrowser` from `@digia/engage-react-native` to use the built-in system-browser adapter, or supply your own object matching `{ open: (url: string) => Promise<void> }`.

***

## 4. How Digia Maps to CleverTap Campaigns

| Experience Type | Digia Component               | CleverTap Campaign Type       | Description                                                                                                        |
| --------------- | ----------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Nudge**       | `DigiaHost`                   | In-App (Custom Code Template) | Receives the `DigiaTemplate` payload and renders overlay experiences (bottom sheets, dialogs) above app content.   |
| **Guide**       | `DigiaAnchor` + `DigiaHost`   | Native Display                | Step-by-step tooltip/spotlight flows anchored to specific UI elements. Each step targets a registered `anchorKey`. |
| **Survey**      | `DigiaHost` / `DigiaHostView` | In-App (Custom Code Template) | Multi-step survey flows rendered as overlays. `viewId` points to the survey page slug.                             |
| **Inline**      | `DigiaSlot`                   | Native Display                | Receives placement key/value pairs and renders inline content (banners, cards) within the app layout.              |
| **Tooltip**     | `DigiaHost`                   | Inline (Native Display)       | Anchors a Digia-designed tooltip to a specific UI element identified by `anchorKey`.                               |
| **Spotlight**   | `DigiaHost`                   | Inline (Native Display)       | Highlights a specific UI element identified by `anchorKey` with a Digia-designed spotlight overlay.                |

```mermaid
flowchart TD
    subgraph Setup["One-time Setup (Dashboard)"]
        DigiaDash["Digia Dashboard\nCreate campaign → assign campaign_key"]
        CTPDash["CleverTap Dashboard\nAdd campaign_key as a key-value pair\non the In-App / Native Display campaign"]
        DigiaDash -. "same campaign_key" .-> CTPDash
    end

    subgraph AppStart["App Start"]
        Init["Digia.initialize()"]
        Prefetch["SDK pre-fetches & caches\nall Digia campaigns"]
        Init --> Prefetch
    end

    subgraph Runtime["Campaign Trigger"]
        CTFire["CleverTap triggers campaign\n(user matches audience + event)"]
        Plugin["Digia CleverTap Plugin\nextracts campaign_key from payload"]
        Cache["SDK looks up campaign_key\nin local cache"]
        Render["Renders native experience\nNudge · Guide · Inline · Survey"]
        CTFire --> Plugin --> Cache --> Render
    end

    Prefetch -- "cached" --> Cache
```

***

## 5. Setting Up Nudges

### Custom Code Templates: What They Are and Why They're Needed

[CleverTap Custom Code In-App Templates](https://developer.clevertap.com/docs/flutter-custom-code-in-app-templates) are developer-defined presentation units registered with the CleverTap SDK that replace the built-in In-App formats (banners, interstitials, etc.) with fully custom rendering logic. Instead of CleverTap rendering the UI itself, the SDK invokes your registered template handler with the campaign payload — your code decides what to render.

The Digia CleverTap plugin ships a custom code template named `**DigiaTemplate**` that acts as this handler. When CleverTap triggers an In-App campaign built on `DigiaTemplate`, the plugin receives the payload, maps it to a `SHOW_BOTTOM_SHEET` or `SHOW_DIALOG` command, and delegates rendering to Digia's runtime. **Without syncing this template to your CleverTap dashboard, it will not appear as an option when creating In-App campaigns.**

### Custom Code Templates: Sync to Dashboard

This is a one-time, per-project step performed from a test device. Once synced, `DigiaTemplate` is available for all campaign creation in that CleverTap project.

1. **Identify user** with CleverTap SDK: `CleverTapPlugin.onUserLogin(profile)` (e.g. `{'Identity': userId, 'Email': email}`). See [medihub\_flutter](https://github.com/Digia-Technology-Private-Limited/medihub_flutter) `lib/core/services/analytics_service.dart` for an example.
2. **Mark as test user** in the CleverTap dashboard.
3. **Run app in debug mode** with Digia Engage + CleverTap plugin. `DigiaCleverTapPlugin.syncCustomTemplates()` is called automatically in debug builds; `DigiaTemplate` appears in the CleverTap dashboard under **In-App → Templates**.
4. **Create In-App campaigns** using `DigiaTemplate`.

<figure><img src="/files/ccRoEO8WKYcb8TlyKn5O" alt="DigiaTemplate in the CleverTap dashboard"><figcaption><p>DigiaTemplate in the CleverTap dashboard</p></figcaption></figure>

See [CleverTap Flutter Custom Code In-App Templates](https://developer.clevertap.com/docs/flutter-custom-code-in-app-templates) and [CleverTap Android Custom Code In-App Templates](https://developer.clevertap.com/docs/android-custom-code-in-app-templates).

{% embed url="<https://www.youtube.com/watch?v=a8iClgwCjto>" %}

### Add the Nudge Container

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

{% tabs %}
{% tab title="React Native" %}

```tsx
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { DigiaHost, DigiaHostView } from '@digia/engage-react-native';
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <View style={styles.root}>
      {/* JS-side overlays for guide experiences (tooltip / spotlight) */}
      <DigiaHost />
      {/* Native overlays for nudges and surveys */}
      <DigiaHostView style={StyleSheet.absoluteFill} />
      <Stack />
    </View>
  );
}

const styles = StyleSheet.create({
  root: { flex: 1 },
});
```

{% endtab %}

{% tab title="Android (Jetpack Compose)" %}

```kotlin
import com.digia.engage.DigiaHost

DigiaHost {
    AppNavHost()
}
```

{% endtab %}

{% tab title="Android (XML Layout)" %}
For XML-based Android layouts, use `DigiaHostView` as a full-screen overlay in your root layout. This is the View-system wrapper around `DigiaHost`, so you do not need Compose code in your `Activity` or `Fragment`.

```xml
<FrameLayout
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Your normal views / fragments -->

    <!-- Must be the last child so it draws on top -->
    <com.digia.engage.DigiaHostView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>
```

Or programmatically in your Activity:

```kotlin
import com.digia.engage.DigiaHostView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    val rootLayout = findViewById<FrameLayout>(R.id.root_layout)
    val digiaHost = DigiaHostView(this)
    rootLayout.addView(
        digiaHost,
        FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT,
        )
    )
}
```

For screen-triggered campaigns in View/XML flows, report the active screen from `onResume()`:

```kotlin
import com.digia.engage.digiaScreen

class HomeActivity : AppCompatActivity() {
    override fun onResume() {
        super.onResume()
        digiaScreen("home")
    }
}
```

{% endtab %}

{% tab title="iOS (Swift)" %}

```swift
import SwiftUI
import DigiaEngage

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

{% endtab %}

{% tab title="Flutter" %}

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

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

{% endtab %}
{% endtabs %}

### Trigger a Nudge from CleverTap

Create an In-App campaign in CleverTap using `DigiaTemplate`. In the campaign template, fill in the following fields:

| Field      | Required | Example value         | Description                                                                             |
| ---------- | -------- | --------------------- | --------------------------------------------------------------------------------------- |
| `command`  | Yes      | `SHOW_BOTTOM_SHEET`   | `SHOW_BOTTOM_SHEET` or `SHOW_DIALOG`.                                                   |
| `viewId`   | Yes      | `promo_offer_sheet`   | Digia page slug. See [Finding Slugs](/studio-workspace/builder-tool/finding-slugs.md).  |
| `screenId` | No       | `home`                | Screen on which to show the nudge. Leave blank to show on all screens.                  |
| `args`     | No       | `{"coupon":"SAVE20"}` | Enter as a raw JSON string in the text field. Available in Digia page logic at runtime. |

> **`args` 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 string automatically.

<figure><img src="/files/k2Cl7WNdWfk2BFdbf5zq" alt="SHOW_BOTTOM_SHEET campaign configured in CleverTap"><figcaption><p>SHOW_BOTTOM_SHEET — bottom sheet nudge</p></figcaption></figure>

<figure><img src="/files/e4wQRinN8IqzEzzIPfRA" alt="SHOW_DIALOG campaign configured in CleverTap"><figcaption><p>SHOW_DIALOG — dialog nudge</p></figcaption></figure>

***

## 6. 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` — a string that must match the key configured in the CleverTap Native Display campaign. When a Native Display campaign is active, Digia resolves the component to display for each placement key and renders it inside the slot. If no campaign is active for a slot, it collapses to zero height.

### Add an Inline Slot

Place `DigiaSlot` where you want Native Display content rendered inline.

{% tabs %}
{% tab title="React Native" %}

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

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>
  );
}
```

{% endtab %}

{% tab title="Android (Jetpack Compose)" %}

```kotlin
import com.digia.engage.DigiaSlot

// placementKey must match key in CleverTap Native Display campaign config
Column {
    DigiaSlot(placementKey = "home_hero_banner")
    DigiaSlot(placementKey = "product_offers")
}
```

{% endtab %}

{% tab title="Android (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 a `DigiaHostView` (or a Compose `DigiaHost`) in the same window so the Digia rendering engine is already mounted before the slot renders.
{% endtab %}

{% tab title="iOS (Swift)" %}

```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()
        }
    }
}
```

{% endtab %}

{% tab title="Flutter" %}

```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 [
          // Renders a Digia-powered banner campaign at the top of the feed.
          // placementKey must match the key in the CleverTap Native Display campaign.
          DigiaSlot('home_hero_banner'),
          SizedBox(height: 16),
          ProductCarousel(),
          SizedBox(height: 16),
          // Renders an inline offer card between content sections.
          DigiaSlot('product_offers'),
          SizedBox(height: 16),
          RecommendationList(),
        ],
      ),
    );
  }
}
```

{% endtab %}
{% endtabs %}

### Serve Inline Content from CleverTap

For Native Display campaigns, map placement keys to Digia component IDs in campaign custom data:

```json
{
  "home_hero_banner": "home_hero_banner-v2N8",
}
```

| Field                               | Required              | Description                                                                                     |
| ----------------------------------- | --------------------- | ----------------------------------------------------------------------------------------------- |
| `<placementKey>` -> `<componentId>` | Native Display inline | Key must match `DigiaSlot` / `DigiaSlotView` placement key; value is Digia component/page slug. |

See [Finding Slugs](/studio-workspace/builder-tool/finding-slugs.md) for slug lookup.

{% embed url="<https://www.youtube.com/watch?v=IKLOcM0ezmg>" %}

***

## 7. Setting Up Guide Anchors

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

{% tabs %}
{% tab title="React Native" %}

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

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

{% endtab %}

{% tab title="Android (Jetpack Compose)" %}

```kotlin
import com.digia.engage.DigiaAnchor

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

{% endtab %}

{% tab title="Android (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>
```

{% endtab %}

{% tab title="iOS (Swift)" %}

```swift
import DigiaEngage

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

{% endtab %}

{% tab title="Flutter" %}

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

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

{% endtab %}
{% endtabs %}

> **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 CleverTap Campaign to Digia

To connect a Native Display campaign to your Digia Guide, you must tell CleverTap which Digia campaign to render. In the Digia dashboard, copy the **`campaign_key`** assigned to your Guide campaign. Then, in the CleverTap Native Display campaign, add a **Custom key-value pair** with the key set to **`digiaKey`** and the value set to the copied `campaign_key`.

<figure><img src="/files/OPxa1hEuAt8AbS0H7RUV" alt="digiaKey key-value pair configured in a CleverTap Native Display campaign"><figcaption><p>Set the <code>digiaKey</code> key to the <code>campaign_key</code> copied from the Digia dashboard</p></figcaption></figure>

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

***

## 8. Test Your Integration

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

1. **Verify initialization order** — `Digia.initialize` completes, then `Digia.register(DigiaCleverTapPlugin())`, 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 Android View/XML apps, `DigiaHostView` should be mounted once as the last full-screen child of the root `ViewGroup`. For React Native, both `<DigiaHost />` (JS-side guide overlays) and `<DigiaHostView />` (native nudge/survey overlays) must be mounted at the app root.
3. **Sync `DigiaTemplate`** — run in debug mode as a CleverTap test user (see [Custom Templates: Sync to Dashboard](#custom-templates-sync-to-dashboard)).
4. **Create a test campaign** — create an In-App campaign using `DigiaTemplate` with a known `viewId` and trigger it immediately for your test device.
5. **Verify inline slots** — place `DigiaSlot` / `DigiaSlotView` on a visible screen, create a Native Display campaign with matching placement keys, and confirm content renders.
6. **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).

### Health Check

Use `plugin.healthCheck()` to verify plugin wiring. The report shape is platform-specific, but always includes `isHealthy` plus diagnostic metadata.

{% tabs %}
{% tab title="React Native" %}

```tsx
import CleverTap from 'clevertap-react-native';
import { Digia } from '@digia/engage-react-native';
import { DigiaCleverTapPlugin, createCleverTapClient } from '@digia/clevertap-plugin';

const plugin = new DigiaCleverTapPlugin({
  cleverTap: createCleverTapClient(CleverTap),
});

Digia.register(plugin);

// Later, for testing:
const report = plugin.healthCheck();
if (!report.isHealthy) {
  console.warn('Plugin health check failed', report.metadata);
}
```

{% endtab %}

{% tab title="Android (Jetpack Compose)" %}

```kotlin
val plugin = DigiaCleverTapPlugin(applicationContext)
Digia.register(plugin)

// Later, for testing:
val report = plugin.healthCheck()
if (!report.isHealthy) {
  Log.w("Digia", "Plugin issue: ${report.issue} - ${report.resolution}")
}
```

{% endtab %}

{% tab title="iOS (Swift)" %}

```swift
let plugin = DigiaCleverTapPlugin()
Digia.register(plugin)

// Later, for testing:
let report = plugin.healthCheck()
if !report.isHealthy {
    print("Plugin issue: \(report.issue)")
    print("Resolution: \(report.resolution)")
}
```

{% endtab %}

{% tab title="Flutter" %}

```dart
final plugin = DigiaCleverTapPlugin();
Digia.register(plugin);

// Later, for testing:
final report = plugin.healthCheck();
if (!report.isHealthy) {
  debugPrint('Plugin issue: ${report.issue}');
  debugPrint('Resolution: ${report.resolution}');
}
```

{% endtab %}
{% endtabs %}

***

## 9. Troubleshooting

Reference open-source example apps for integration patterns:

* [medihub\_flutter](https://github.com/Digia-Technology-Private-Limited/medihub_flutter)
* [medihub\_android](https://github.com/Digia-Technology-Private-Limited/medihub_android)
* [medihub\_swift](https://github.com/Digia-Technology-Private-Limited/medihub_swift)
* [medihub\_rn](https://github.com/Digia-Technology-Private-Limited/medihub_rn)

### Campaign not rendering

* Confirm initialization order — `Digia.initialize(...)` then `Digia.register(DigiaCleverTapPlugin())`.
* **Android only**: Confirm `CleverTapAPI.getDefaultInstance(this)` is called before `Digia.register(...)`.
* **iOS (Swift)**: Confirm `CleverTap.autoIntegrate()` runs at app start and `Info.plist` includes `CleverTapAccountID` / `CleverTapToken`.
* **React Native**: Confirm `Digia.initialize(...)` and `Digia.register(new DigiaCleverTapPlugin(...))` are called once during app startup.
* Ensure `DigiaHost` is mounted in `MaterialApp.builder` (Flutter), the root Composable (Android Compose), or `DigiaHostView` is mounted as the last full-screen child in your Android View/XML root layout.
* **React Native**: Ensure both `<DigiaHost />` and `<DigiaHostView />` are mounted once at app root, and `app.json` contains CleverTap plugin credentials.
* Check `viewId` exactly matches the published Digia page slug (case-sensitive). See [Finding Slugs](/studio-workspace/builder-tool/finding-slugs.md).
* Verify campaign eligibility and trigger conditions in the CleverTap dashboard.

### Inline content not showing

* Confirm Native Display payload includes placement key/value pairs.
* Ensure placement key in payload matches `DigiaSlot('placement_key')` or `DigiaSlotView app:placementKey`.
* Verify the slot exists on the currently visible screen.
* **Android XML**: Ensure a `DigiaHostView` is mounted in the same window before `DigiaSlotView` renders.
* **React Native**: `DigiaSlotView` auto-sizes to match native content height. If it still appears collapsed, confirm the Native Display campaign is active and the `placementKey` matches. To pin a fixed height, pass `style={{ height: 180 }}`.

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

### CleverTap default instance is null (Android)

* Ensure `ActivityLifecycleCallback.register(this)` and `CleverTapAPI.getDefaultInstance(this)` are called before `Digia.register(DigiaCleverTapPlugin(applicationContext))`.
* Verify CleverTap credentials are correctly set in `AndroidManifest.xml` per [CleverTap Android Quick Start](https://developer.clevertap.com/docs/android-quick-start-guide).

***

## Official CleverTap References

* [Flutter SDK](https://developer.clevertap.com/docs/flutter-sdk)
* [Flutter In-App](https://developer.clevertap.com/docs/flutter-in-app)
* [Flutter Custom Code In-App Templates](https://developer.clevertap.com/docs/flutter-custom-code-in-app-templates)
* [Android Quick Start](https://developer.clevertap.com/docs/android-quick-start-guide)
* [Android In-App Notifications](https://developer.clevertap.com/docs/android-in-app-notifications)
* [Android Native Display](https://developer.clevertap.com/docs/android-native-display)
* [Android Custom Code In-App Templates](https://developer.clevertap.com/docs/android-custom-code-in-app-templates)
* [iOS Quick Start](https://developer.clevertap.com/docs/ios-quickstart-guide)
* [iOS Custom Code In-App Templates](https://developer.clevertap.com/docs/ios-custom-code-in-app-templates)
* [React Native Quick Start Guide](https://developer.clevertap.com/docs/react-native-quick-start-guide)
* [React Native Custom Code In-App Templates](https://developer.clevertap.com/docs/react-native-custom-code-in-app-templates)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.digia.tech/engagement-sdk/digia-engage/clevertap-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
