# Digia WebEngage Integration

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

WebEngage Change your setup in the sidebar
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.

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

- React Native - Flutter

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

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

## Install

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

- React Native - Flutter
Install the Digia packages:
```bash
npm install @digia-engage/core@2.22.0 @digia-engage/webengage@1.1.0
```

#### 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 => '3.14.0'
```

Then run:
```bash
cd ios && pod install
```

Add the Digia packages using the `flutter pub add` command:
```bash
flutter pub add digia_engage:1.19.0 digia_webengage_plugin:1.2.0
```

## Initialize Digia with WebEngage

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

- React Native - Flutter
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
)
```

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

## How Digia Maps to WebEngage Campaigns

> If you haven't read [How It Works](/docs/#how-it-works) in the overview, start there. The section below covers only what is 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):

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

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

## Setting Up Nudges

### Add the Nudge Container

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

- React Native - Flutter

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

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

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

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

- React Native - Flutter

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

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

      <ProductCarousel />

      <DigiaSlotView placementKey="product_offers" />

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

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

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

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

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

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

## Setting Up Guides

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

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

- React Native - Flutter

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

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

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

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

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

## Setting Up Surveys

Surveys are multi-step questionnaire flows you design in the Digia dashboard and render as overlays in the nudge host — no extra app-side widget is required beyond the nudge container . A survey is just another campaign type: create it in Digia, then trigger it from 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.

## 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). SeeReporting the Current Screen for per-stack and per-router wiring, andScreen Targeting to scope campaigns to specific screens.

## Troubleshooting

### Campaign not rendering

- Confirm initialization order — `Digia.initialize(...)` then `Digia.register(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)
