> 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/webengage.md).

# WebEngage Integration

***

The Digia WebEngage plugin intercepts **WebEngage In-App** campaign payloads and pipes them directly into Digia's rendering engine. Each WebEngage campaign carries a single **`digia_campaign_key`** — set in a Custom HTML `digia-config` block — 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.

## 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 WebEngage Account**: Ensure you have an active WebEngage workspace with access to your License Code.
* **WebEngage SDK**: Installed and initialized (see [Flutter](https://docs.webengage.com/docs/flutter-getting-started), [Android](https://docs.webengage.com/docs/android-integration-guide), [iOS](https://docs.webengage.com/docs/ios-integration-guide), or [React Native](https://docs.webengage.com/docs/react-native-getting-started) 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/webengage`](https://www.npmjs.com/package/@digia-engage/webengage)
* **WebEngage SDK:** [`react-native-webengage`](https://www.npmjs.com/package/react-native-webengage)
  {% endtab %}

{% tab title="Flutter" %}

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

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

***

## 2. Install

> **Note:** We assume the core WebEngage 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/webengage
```

#### iOS — Additional Native Setup (CocoaPods)

Add the Digia iOS pod to your `Podfile`:

```ruby
# Use the latest release tag — see https://github.com/Digia-Technology-Private-Limited/digia_engage_iOS/releases
pod 'DigiaEngage',
  :git => 'https://github.com/Digia-Technology-Private-Limited/digia_engage_iOS.git',
  :tag => '<latest>'
```

Then run:

```bash
cd ios && pod install
```

{% endtab %}

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

```bash
flutter pub add digia_engage digia_webengage_plugin
```

{% endtab %}
{% endtabs %}

***

## 3. Initialize Digia with WebEngage

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

{% tabs %}
{% tab title="React Native" %}
In your root component (e.g. `App.tsx`), initialize Digia and register the WebEngage plugin:

```tsx
import { useEffect } from 'react';
import { Digia } from '@digia-engage/core';
import { DigiaWebEngagePlugin } from '@digia-engage/webengage';

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

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

      // 3. Register the Digia WebEngage plugin.
      Digia.register(new DigiaWebEngagePlugin());
    })().catch(console.error);
  }, []);

  return <AppNavigator />;
}
```

#### iOS — Additional Native Setup (`AppDelegate.swift`)

On React Native iOS, add the following to your `AppDelegate.swift` to wire the WebEngage in-app notification delegate through the Digia bridge:

```swift
import WebEngage
import DigiaWebEngage // 👈 Digia's React Native plugin

// Inside application(_:didFinishLaunchingWithOptions:):
WebEngage.sharedInstance().application(
    application,
    didFinishLaunchingWithOptions: launchOptions,
    notificationDelegate: WEDigiaSuppressProxy.shared()  // 👈 Digia hooks in here — the rest is standard WebEngage setup
)
```

{% endtab %}

{% tab title="Flutter" %}
In your `main.dart`, initialize Digia and register the WebEngage plugin:

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

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

  // 1. WebEngage 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 WebEngage plugin.
  Digia.register(DigiaWebEngagePlugin());

  runApp(const MyApp());
}
```

#### iOS — Additional Setup (`AppDelegate.swift`)

On Flutter iOS, add the following to your `AppDelegate.swift` to wire the WebEngage push notification delegate through the Digia bridge:

```swift
import Flutter
import UIKit
import WebEngage
import webengage_flutter
import UserNotifications
import digia_webengage_plugin  // 👈 Digia's Flutter plugin

@main
@objc class AppDelegate: FlutterAppDelegate {

  var bridge: WebEngagePlugin? = nil

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    UNUserNotificationCenter.current().delegate = self
    application.registerForRemoteNotifications()

    // Create the Flutter-WebEngage bridge.
    bridge = WebEngagePlugin()

    // Wire push notification delegates.
    WebEngage.sharedInstance().pushNotificationDelegate = self.bridge
    WebEngage.sharedInstance().application(
      application,
      didFinishLaunchingWithOptions: launchOptions,
      notificationDelegate: DigiaSuppressPlugin.shared  // 👈 Digia hooks in here — everything else in this AppDelegate is standard WebEngage setup
    )
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
```

{% endtab %}
{% endtabs %}

***

## 4. How Digia Maps to WebEngage 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 WebEngage-specific.

In short: WebEngage 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 WebEngage campaign's Custom HTML — 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 WebEngage campaign type and which SDK component handles it on the app side:

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

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

```mermaid
sequenceDiagram
    participant Dev as You
    participant Digia as Digia Dashboard
    participant WE as WebEngage Dashboard
    participant App as App (Runtime)

    Dev->>Digia: Create campaign, copy Digia campaign key
    Dev->>WE: Create In-App (Custom HTML) campaign<br/>Add digia-config block with 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 WebEngage trigger
    WE->>App: Fires In-App payload 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 WebEngage campaign carries the same contract — a Custom HTML `digia-config` block of `<meta>` tags:

```html
<template id="digia-config">
  <meta name="digia_campaign_key" content="promo_offer_sheet">
  <meta name="coupon" content="SAVE20">
  <meta name="offer_title" content="Limited Offer">
</template>
```

* **`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 WebEngage payload.
* **Variables** (optional) — every other `<meta>` tag is a runtime value. Its `name` must match a variable defined on the campaign in the Digia dashboard; `content` is the value injected at render time.

Every experience type — nudge, guide, survey, and inline — is delivered through the same **In-App (Custom HTML)** campaign with this same `digia-config` block. The per-experience sections below show it in context.

***

## 5. In-App Campaigns (Custom HTML)

WebEngage delivers in-app notification payloads to your app code when a campaign triggers. The Digia WebEngage plugin registers an in-app notification listener that intercepts this payload, reads the **`digia_campaign_key`** from the campaign's `digia-config` block, resolves it against the Digia campaigns pre-fetched at startup, and delegates rendering to Digia's runtime. **Without configuring the WebEngage campaign as Custom HTML with a `digia-config` block, the experience will not render.**

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

1. Log in to the **WebEngage dashboard** and go to **Campaigns → In-App Notifications**.
2. Click **Create** and give the campaign a name.
3. Configure the trigger event, audience, and schedule as required.
4. In the **Content** step, choose **Custom HTML** as the template type.
5. In the **Custom HTML** editor, add a `digia-config` block with your `digia_campaign_key` (see [Trigger a Nudge from WebEngage](#trigger-a-nudge-from-webengage) below).

***

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

### Trigger a Nudge from WebEngage

In the WebEngage campaign **Custom HTML** editor, add a `digia-config` block. The `digia_campaign_key` links to your Digia campaign; any additional `<meta>` tags are passed through as runtime variables:

```html
<template id="digia-config">
  <meta name="digia_campaign_key" content="promo_offer_sheet">
  <meta name="coupon" content="SAVE20">
  <meta name="offer_title" content="Limited Offer">
</template>
```

| Meta tag             | 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. |
| any other `name`     | No       | `coupon`            | A runtime variable. The `name` must match a variable defined on the Digia campaign; `content` is its value.                     |

> **Variables:** Every `<meta>` tag other than `digia_campaign_key` is a runtime variable. Its `name` **must match** a variable you defined on the campaign in the Digia dashboard — otherwise it is ignored. The `content` is the value injected at render time.

***

## 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`. When an 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.

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

### Serve Inline Content from WebEngage

Inline campaigns are delivered the same way as nudges — through an In-App (Custom HTML) campaign carrying a `digia_campaign_key`. Build the inline campaign in the Digia dashboard (it defines which slot / `placementKey` it renders into), then reference its Digia campaign key from the `digia-config` block:

```html
<template id="digia-config">
  <meta name="digia_campaign_key" content="home_hero_banner_campaign">
</template>
```

| Meta tag             | 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 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.

{% 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 %}
{% 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 WebEngage Campaign to Digia

To connect a WebEngage campaign to your Digia Guide, copy the **Digia campaign key** assigned to your Guide campaign in the Digia dashboard. Then, in the WebEngage In-App (Custom HTML) campaign, add a `digia-config` block with that key:

```html
<template id="digia-config">
  <meta name="digia_campaign_key" content="onboarding_tour">
</template>
```

> **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 WebEngage 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 WebEngage In-App (Custom HTML) campaign and add a `digia-config` block set to the survey's Digia campaign key.

```html
<template id="digia-config">
  <meta name="digia_campaign_key" content="nps_q3_survey">
</template>
```

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(DigiaWebEngagePlugin())`, before `runApp` / first activity.
2. **Verify host placement** — `DigiaHost` must be in `MaterialApp.builder` (Flutter), the root Composable (Android Compose), the root SwiftUI wrapper (iOS), or mounted once at the app root (React Native).
3. **Verify Flutter iOS AppDelegate** — confirm `DigiaSuppressPlugin.shared` is passed as the `notificationDelegate` in `AppDelegate.swift`.
4. **Create a test campaign** — create an In-App (Custom HTML) campaign with a `digia-config` block 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 an 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). 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(DigiaWebEngagePlugin())`.
* Ensure the WebEngage campaign uses **Custom HTML** as the template type and the `digia-config` block is present in the HTML editor.
* **Flutter iOS**: Confirm `DigiaSuppressPlugin.shared` is passed as the `notificationDelegate` in `AppDelegate.swift` and `import digia_webengage_plugin` is present.
* Ensure `DigiaHost` is mounted at the app root.
* Check `digia_campaign_key` exactly matches the Digia campaign key (case-sensitive).
* Verify campaign eligibility and trigger conditions in the WebEngage dashboard.

### Inline content not showing

* Confirm the `digia-config` block's `digia_campaign_key` 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.

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

### WebEngage SDK not initialized (Android)

* Ensure `registerActivityLifecycleCallbacks(WebEngageActivityLifeCycleCallbacks(this, webEngageConfig))` is called in `Application.onCreate()` before `Digia.register(...)`.
* Verify the WebEngage license key is correctly set in `WebEngageConfig.Builder().setWebEngageKey(...)` and matches your WebEngage dashboard.

***

## Official WebEngage References

* [Flutter SDK](https://docs.webengage.com/docs/flutter-getting-started)
* [Android Integration Guide](https://docs.webengage.com/docs/android-integration-guide)
* [iOS Integration Guide](https://docs.webengage.com/docs/ios-integration-guide)
* [React Native Getting Started](https://docs.webengage.com/docs/react-native-getting-started)
