> For the complete documentation index, see [llms.txt](https://docs.digia.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.digia.tech/digia-engage/developer-guides/clevertap.md).

# 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 the Digia Engage Dashboard, instantly rendering a 100% native experience on the device—no WebViews required. Supported experience types include bottom sheets, dialogs, inline banners, **tooltips**, and **spotlights**.

{% hint style="info" %}
Prefer a quick visual walkthrough first? Watch [How to Integrate Digia Engage and CleverTap for Campaigns](https://www.youtube.com/watch?v=XOuPeDO3IHQ).
{% endhint %}

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

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

* **Environment:** React Native `0.83+`, React `19.2+`
* **Digia packages:** [`@digia-engage/core`](https://www.npmjs.com/package/@digia-engage/core), [`@digia-engage/clevertap`](https://www.npmjs.com/package/@digia-engage/clevertap)
* **CleverTap SDK:** [`clevertap-react-native`](https://www.npmjs.com/package/clevertap-react-native)
  {% endtab %}

{% tab title="Android" %}

* **Environment:** `minSdk 25`
* **Digia packages:** [`tech.digia:engage`](https://central.sonatype.com/artifact/tech.digia/engage), [`tech.digia:engage-clevertap`](https://central.sonatype.com/artifact/tech.digia/engage-clevertap)
* **CleverTap SDK:** [`com.clevertap.android:clevertap-android-sdk`](https://central.sonatype.com/artifact/com.clevertap.android/clevertap-android-sdk)
  {% endtab %}

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

* **Environment:** iOS `16+`
* **Digia packages:** [`DigiaEngage`](https://swiftpackageindex.com/Digia-Technology-Private-Limited/digia_engage_iOS), [`DigiaEngageCleverTap`](https://swiftpackageindex.com/Digia-Technology-Private-Limited/digia_engage_clevertap_iOS)
* **CleverTap SDK:** [`CleverTapSDK`](https://github.com/CleverTap/clevertap-ios-sdk)
  {% endtab %}

{% tab title="Flutter" %}

* **Environment:** Dart `3.3+`, Flutter `3.35+`
* **Digia packages:** [`digia_engage`](https://pub.dev/packages/digia_engage), [`digia_engage_clevertap`](https://pub.dev/packages/digia_engage_clevertap)
* **CleverTap SDK:** [`clevertap_plugin`](https://pub.dev/packages/clevertap_plugin)
  {% endtab %}
  {% endtabs %}

> Package versions aren't pinned in this guide — install the latest from the linked registry pages (npm, pub.dev, Maven Central, Swift Package Index).

***

## 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 @digia-engage/clevertap
```

{% endtab %}

{% tab title="Android" %}
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:<latest>")
    implementation("tech.digia:engage-clevertap:<latest>")
}
```

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

{% tab title="iOS (Swift)" %}
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: "<latest>"),
    .package(url: "https://github.com/Digia-Technology-Private-Limited/digia_engage_clevertap_iOS.git", from: "<latest>"),
],
```

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

Set up Digia and register the CleverTap plugin during app startup.

{% tabs %}
{% tab title="React Native" %}
**JS setup**

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

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

**Android native setup**

> **Important:** Even in a React Native app, the CleverTap SDK requires Activity lifecycle registration on the Android side. Without it, all In-App campaigns (including App Launch triggers), push notification click callbacks from the killed state, and session tracking will not work. See the [CleverTap React Native Android integration guide](https://github.com/CleverTap/clevertap-react-native/blob/master/docs/integration.md#android).
>
> * **Extending `CleverTapApplication`** — registration is handled automatically. No extra call needed.
> * **Not extending `CleverTapApplication`** — call `ActivityLifecycleCallback.register(this)` manually in `MainApplication.onCreate()`, **before** `super.onCreate()`:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import com.clevertap.android.sdk.ActivityLifecycleCallback
import com.clevertap.react.CleverTapRnAPI

class MainApplication : ReactApplication {
    override fun onCreate() {
        ActivityLifecycleCallback.register(this) // must be before super.onCreate()
        super.onCreate()
        CleverTapRnAPI.initReactNativeIntegration(this) // must be after super.onCreate()
        // ...
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
import com.clevertap.android.sdk.ActivityLifecycleCallback;
import com.clevertap.react.CleverTapRnAPI;

public class MainApplication implements ReactApplication {
    @Override
    public void onCreate() {
        ActivityLifecycleCallback.register(this); // must be before super.onCreate()
        super.onCreate();
        CleverTapRnAPI.initReactNativeIntegration(this); // must be after super.onCreate()
        // ...
    }
}
```

{% endtab %}
{% endtabs %}

> **Also required:** `CleverTapRnAPI.initReactNativeIntegration(this)` must be called **after** `super.onCreate()`. Without it, push notification click callbacks will not fire when the app is in the killed state (`ClevertapPushNotificationClicked` event will be lost).

**iOS native setup**

> **Important:** Even in a React Native app, `CleverTap.autoIntegrate()` must be called in your native `AppDelegate` before the React bridge initializes. Without it, CleverTap cannot intercept push notifications, deep links, or app launch events on iOS — meaning App Launch triggered campaigns, push notification handling, and In-App display will not work. See the [CleverTap React Native iOS integration guide](https://github.com/CleverTap/clevertap-react-native/blob/master/docs/integration.md#ios).

{% tabs %}
{% tab title="Swift" %}

```swift
// AppDelegate.swift
import CleverTapSDK
import CleverTapReact

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        CleverTap.autoIntegrate()
        CleverTapReactManager.sharedInstance()?.applicationDidLaunch(options: launchOptions)
        // ...
        return true
    }
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objc
// AppDelegate.mm
#import <CleverTap-iOS-SDK/CleverTap.h>
#import <clevertap-react-native/CleverTapReactManager.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [CleverTap autoIntegrate];
    [[CleverTapReactManager sharedInstance] applicationDidLaunchWithOptions:launchOptions];
    // ...
    return YES;
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="Android" %}

> **Important (Android — Activity Lifecycle Registration):** The CleverTap SDK needs to observe Activity lifecycle events to correctly handle In-App campaigns (including App Launch triggers), push notification click callbacks from the killed state, and session tracking. How you register depends on your `Application` class setup:
>
> * **Extending `CleverTapApplication`** — registration is handled automatically by the superclass. No extra call needed.
> * **Not extending `CleverTapApplication`** — you must call `ActivityLifecycleCallback.register(this)` manually, **before** `super.onCreate()`, as shown below.
>
> See [CleverTap Android integration guide](https://github.com/CleverTap/clevertap-react-native/blob/master/docs/integration.md) for full details.

```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() {
        // Must be called before super.onCreate() — see note above.
        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());
}
```

**Android native setup**

> **Important:** Even in a Flutter app, the CleverTap SDK requires Activity lifecycle registration on the Android side. Without it, In-App campaigns (including App Launch triggers), push notification click callbacks from the killed state, and session tracking will not work. See the [CleverTap Flutter Android integration guide](https://developer.clevertap.com/docs/flutter-quick-start-guide).
>
> Register `ActivityLifecycleCallback` in your `Application` class, **before** `super.onCreate()`:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import com.clevertap.android.sdk.ActivityLifecycleCallback
import io.flutter.app.FlutterApplication

class MyApplication : FlutterApplication() {
    override fun onCreate() {
        ActivityLifecycleCallback.register(this) // must be before super.onCreate()
        super.onCreate()
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
import com.clevertap.android.sdk.ActivityLifecycleCallback;
import io.flutter.app.FlutterApplication;

public class MyApplication extends FlutterApplication {
    @Override
    public void onCreate() {
        ActivityLifecycleCallback.register(this); // must be before super.onCreate()
        super.onCreate();
    }
}
```

{% endtab %}
{% endtabs %}

**iOS native setup**

> **Important:** Even in a Flutter app, `CleverTap.autoIntegrate()` must be called in your native `AppDelegate` before the Flutter engine initializes. Without it, CleverTap cannot intercept push notifications, deep links, or App Launch events on iOS — meaning App Launch triggered campaigns and In-App display will not work. See the [CleverTap Flutter iOS integration guide](https://developer.clevertap.com/docs/flutter-quick-start-guide).

{% tabs %}
{% tab title="Swift" %}

```swift
// AppDelegate.swift
import CleverTapSDK
import clevertap_plugin

@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        CleverTap.autoIntegrate()
        CleverTapPlugin.sharedInstance()?.applicationDidLaunch(options: launchOptions)
        // ...
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objc
// AppDelegate.m
#import <CleverTap-iOS-SDK/CleverTap.h>
#import <clevertap_plugin/CleverTapPlugin.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [CleverTap autoIntegrate];
    [[CleverTapPlugin sharedInstance] applicationDidLaunchWithOptions:launchOptions];
    // ...
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
```

{% endtab %}
{% endtabs %}
{% 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'
  actionHandlers: {
    // Own how specific campaign actions are handled. A registered handler
    // fully replaces the SDK's default behavior for that action.
    customKV: (payload) => {/* run an app-owned key-value command */},
    deepLink: (url) => {/* navigate in-app */},
    openURL: (url) => {/* present a web URL */},
  },
  linking: {
    inAppBrowser: defaultInAppBrowser, // Required for open_url with presentation: 'in_app'
  },
});
```

For full details on action types, deep link URL format, action handlers, and the in-app browser adapter — see [Campaign Actions](/digia-engage/developer-guides/campaign-actions.md). These apply to all CEP integrations, not just CleverTap.

***

## 4. How Digia Maps to CleverTap Campaigns

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

In short: CleverTap 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 CleverTap 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 CleverTap campaign type and which SDK component handles it on the app side:

| 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` | In-App (Custom Code Template) | Step-by-step tooltip/spotlight flows anchored to specific UI elements. Each step targets a registered `anchorKey`. |
| **Survey**      | `DigiaHost`                 | In-App (Custom Code Template) | Multi-step survey flows rendered as overlays.                                                                      |
| **Inline**      | `DigiaSlot`                 | Native Display                | Receives placement key/value pairs and renders inline content (banners, cards) within the app layout.              |

Here is the end-to-end flow for an In-App campaign (Nudge, Guide, or Survey):

```mermaid
sequenceDiagram
    participant Dev as You
    participant Digia as Digia Dashboard
    participant CT as CleverTap Dashboard
    participant App as App (Runtime)

    Dev->>Digia: Create campaign, copy Digia campaign key
    Dev->>CT: Create In-App campaign using DigiaTemplate<br/>Set digia_campaign_key = <Digia campaign key>

    Note over App: On app start
    App->>App: Digia.initialize() pre-fetches campaigns into local cache

    Note over App: User matches the CleverTap trigger
    CT->>App: Fires In-App (DigiaTemplate) with digia_campaign_key
    App->>App: Digia plugin reads key, resolves from cache
    App-->>App: Renders native experience (no network round-trip)
```

### The Campaign Contract

Whatever the experience type, a Digia-powered CleverTap campaign always carries the same two things:

* **`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 CleverTap payload.
* **`variables`** (optional) — a JSON object of runtime values interpolated into the campaign at render time (for example a coupon code or the user's name).

CleverTap is the one CEP that delivers this contract through **two different campaign types**, depending on the experience:

| Delivery channel                  | Used for             | Where you set the contract                | Prerequisite                                                                                                    |
| --------------------------------- | -------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| **In-App** (Custom Code Template) | Nudge, Guide, Survey | As fields on the `DigiaTemplate` template | `DigiaTemplate` must be synced once — see [Sync DigiaTemplate to Dashboard](#5-sync-digiatemplate-to-dashboard) |
| **Native Display**                | Inline               | As a custom key-value pair                | None                                                                                                            |

The per-experience sections below show exactly where to enter `digia_campaign_key` and `variables` for each case.

***

## 5. Sync DigiaTemplate to Dashboard

> **Required before creating any In-App campaign.** `DigiaTemplate` must be synced to your CleverTap project before you can create Nudge or Survey campaigns. This is a **one-time step per CleverTap project**, performed once from a test device.

[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 reads the `digia_campaign_key` from the payload, looks up the matching Digia campaign, and delegates rendering to Digia's runtime.

### Step 1 — Identify the user on the debug device

Call the CleverTap user login method in your debug build to associate the device with a known user.

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

```javascript
import CleverTap from 'clevertap-react-native';

CleverTap.onUserLogin({
  Identity: 'user-123',
  Email: '[email protected]',
  Name: 'Jane Doe',
});
```

{% endtab %}

{% tab title="Flutter" %}

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

CleverTapPlugin.onUserLogin({
  'Identity': 'user-123',
  'Email': '[email protected]',
  'Name': 'Jane Doe',
});
```

{% endtab %}

{% tab title="Android" %}

```kotlin
val profile = HashMap<String, Any>()
profile["Identity"] = "user-123"
profile["Email"] = "[email protected]"
profile["Name"] = "Jane Doe"

CleverTapAPI.getDefaultInstance(context)?.onUserLogin(profile)
```

{% endtab %}

{% tab title="iOS" %}

```swift
let profile: [String: AnyObject] = [
    "Identity": "user-123" as AnyObject,
    "Email": "[email protected]" as AnyObject,
    "Name": "Jane Doe" as AnyObject,
]
CleverTap.sharedInstance()?.onUserLogin(profile)
```

{% endtab %}
{% endtabs %}

### Step 2 — Mark that user as a test profile

In the CleverTap dashboard, mark only the user from Step 1 as a test profile. See [Mark a User Profile as a Test Profile](https://docs.clevertap.com/docs/user-profiles#mark-a-user-profile-as-a-test-profile) in the CleverTap docs.

### Step 3 — Open the app on the test device

No code changes needed. The Digia plugin registers `DigiaTemplate` with CleverTap automatically at startup. Simply launch the app on the device where the user from Step 1 is already identified — CleverTap will sync the template definition to your project in the background.

### Step 4 — Confirm the template is synced

Open **In-App → Templates** in the CleverTap dashboard and confirm `DigiaTemplate` appears there before creating any In-App campaign.

<div><figure><img src="/files/9Y25H3A9VQf4jiGleswT" alt="DigiaTemplate in the CleverTap dashboard"><figcaption><p>DigiaTemplate in the CleverTap dashboard</p></figcaption></figure> <figure><img src="/files/fNhFnAfYal6YN1LhkICz" alt="Inside DigiaTemplate"><figcaption><p>Inside DigiaTemplate</p></figcaption></figure></div>

***

## 6. Setting Up Nudges

### 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 { View } from 'react-native';
import { DigiaHost } from '@digia-engage/core';
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <View style={{ flex: 1 }}>
      {/* Mounts JS guide overlays + native nudge/survey overlay */}
      <DigiaHost />
      <Stack />
    </View>
  );
}
```

{% endtab %}

{% tab title="Flutter" %}

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

{% endtab %}

{% tab title="Android" %}
**Jetpack Compose**

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

DigiaHost {
    AppNavHost()
}
```

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 %}
{% 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                                                                                      |
| -------------------- | -------- | --------------------- | ------------------------------------------------------------------------------------------------ |
| `digia_campaign_key` | Yes      | `promo_offer_sheet`   | The campaign key copied from the Digia Engage Dashboard. Must match exactly (case-sensitive).    |
| `variables`          | No       | `{"coupon":"SAVE20"}` | Runtime variables to interpolate into the campaign. Enter as a raw JSON string — see note below. |

> **`variables` format:** Enter the value as a plain JSON string directly in the CleverTap field. Do **not** wrap it in outer quotes or escape the inner quotes. The plugin JSON-decodes the string automatically. An invalid JSON value is silently ignored and the campaign renders without variable substitution.

**Static variables** — hardcoded values set at campaign creation time:

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

**CleverTap personalization variables** — CleverTap resolves `{{Profile.*}}` placeholders at send time using the recipient's user profile, before the value reaches the Digia plugin:

```json
{
  "user_name": "{{Profile.Name}}",
  "account_type": "{{Profile.accounttype | default:\"standard\"}}"
}
```

See [CleverTap Personalization](https://docs.clevertap.com/docs/personalize-messages-push) for the full list of supported `{{Profile.*}}` and `{{Campaign.*}}` variables.

***

## 7. 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 slot key configured on the inline campaign in the Digia dashboard. When a Native Display campaign whose `digia_campaign_key` maps to an inline Digia campaign is active, the SDK resolves the campaign and renders it inside the matching 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/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>
  );
}
```

{% 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 [
          DigiaSlot('home_hero_banner'),
          SizedBox(height: 16),
          ProductCarousel(),
          SizedBox(height: 16),
          DigiaSlot('product_offers'),
          SizedBox(height: 16),
          RecommendationList(),
        ],
      ),
    );
  }
}
```

{% endtab %}

{% tab title="Android" %}
**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.
{% 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 %}
{% endtabs %}

### Serve Inline Content from CleverTap

Inline campaigns are delivered the same way as nudges — through a Native Display campaign carrying a `digia_campaign_key`. Build the inline campaign in the Digia dashboard (it defines which slot / `placementKey` it renders into), 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.

{% hint style="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), see [Managing Inline Content](/digia-engage/developer-guides/inline-content.md).
{% endhint %}

***

## 8. 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/core';

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

{% 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 %}

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

{% endtab %}

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

```swift
import DigiaEngage

// Anywhere in your view hierarchy:
DigiaAnchor(anchorKey: "buy_now_button") {
    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 **Digia 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 **`digia_campaign_key`** and the value set to the copied key.

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

***

## 9. 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](#add-the-nudge-container). A survey is just another campaign type: create it in Digia, then trigger it from CleverTap using `DigiaTemplate`, 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 CleverTap In-App campaign using `DigiaTemplate` and set `digia_campaign_key` to the survey's Digia campaign key.

| Field                | Required | Example value   | Description                                                                     |
| -------------------- | -------- | --------------- | ------------------------------------------------------------------------------- |
| `digia_campaign_key` | Yes      | `nps_q3_survey` | The Digia campaign key of the survey campaign copied from your Digia dashboard. |

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

***

## 10. 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 React Native, mount `<DigiaHost />` once at the app root.
3. **Sync `DigiaTemplate`** — run in debug mode as a CleverTap test user (see [Sync DigiaTemplate to Dashboard](#5-sync-digiatemplate-to-dashboard)).
4. **Create a test campaign** — create an In-App campaign using `DigiaTemplate` 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). See [Screen Targeting](/digia-engage/developer-guides/screen-targeting.md) to scope campaigns to specific screens.

***

## 11. Troubleshooting

### 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 at the app root.
* **React Native**: Ensure `<DigiaHost />` is mounted once at app root, and `app.json` contains CleverTap plugin credentials.
* 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.
* **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)
