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

# Digia as Your CEP

***

Digia can drive your in-app campaigns on its own. Each campaign carries its own **trigger** and **priority**, authored in the Digia Engage Dashboard, and the SDK decides which campaign fires, when, and in what order — rendered natively on the device.

You set *where and when* a campaign appears in the same place you design it, enable managed campaigns with a single call, and wire screen tracking. That is the whole integration.

Reach for it whenever Digia should own delivery end to end — an onboarding guide on first launch, a promo nudge on the home screen, or an inline story in your feed.

{% hint style="info" %}
**React Native today.** Managed campaigns ship for React Native first; Android, iOS and Flutter support is on the way.
{% endhint %}

***

## 1. Prerequisites

* **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**.
* **Project CEP set to Digia** — In **Settings → App Settings**, set **CEP integration** to **Digia**. This adds the **Trigger** step to the campaign wizard. You can also choose it when you create the project.
* **No extra dependencies** — There is nothing else to install or initialize.

### Minimum Supported Versions

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

> Package versions aren't pinned here — install the latest `@digia-engage/core` from [npm](https://www.npmjs.com/package/@digia-engage/core).

***

## 2. Install

```bash
npm install @digia-engage/core
```

That is the whole dependency list — managed campaigns need only the core package.

***

## 3. Initialize

Two calls: initialize the SDK, then enable managed campaigns.

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

export function RootApp() {
  useEffect(() => {
    (async () => {
      // 1. Initialize Digia once at startup.
      await Digia.initialize({
        apiKey: 'YOUR_ACCESS_KEY',
      });

      // 2. Let Digia decide what fires, from each campaign's trigger and priority.
      Digia.enableManagedCampaigns();

      // 3. Wire screen tracking to your navigation library (see below) so
      //    screen-triggered campaigns fire on the right screen.
    })().catch(console.error);
  }, []);

  return <AppNavigator />;
}
```

`enableManagedCampaigns()` is **order-independent** — calling it before `initialize()` resolves is fine, and triggering begins as soon as campaigns have loaded — and **idempotent**, so a double call still fires each campaign once.

### Reporting the current screen

`Digia.setCurrentScreen(name)` is what makes **On screen** triggers work, and the names you report are exactly the ones campaign creators pick from in the dashboard.

A small hook keeps this to one line per screen. With React Navigation, `useFocusEffect` re-reports every time a screen regains focus — returning to a tab, not just first mount:

```ts
import { useFocusEffect } from '@react-navigation/native';
import { useCallback } from 'react';
import { Digia } from '@digia-engage/core';

export function useScreenTracking(screenName: string) {
  useFocusEffect(
    useCallback(() => {
      Digia.setCurrentScreen(screenName);
    }, [screenName]),
  );
}
```

Call it once in each screen — the name must match the campaign's **On screen** trigger exactly (it is case-sensitive):

```tsx
export function HomeScreen() {
  useScreenTracking('home');
  return /* … */;
}
```

{% hint style="info" %}
**Expo Router:** import `useFocusEffect` from `expo-router` instead — everything else is identical.
{% endhint %}

See [Screen Targeting](/digia-engage/developer-guides/screen-targeting.md) for more navigation-library snippets.

### Advanced configuration

`Digia.initialize()` accepts more fields that shape SDK behaviour:

```tsx
await Digia.initialize({
  apiKey: 'YOUR_ACCESS_KEY',
  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'
  },
});
```

See [Campaign Actions](/digia-engage/developer-guides/campaign-actions.md) for the full list of action types, deep link URL format, and the in-app browser adapter.

***

## 4. Experience types

A campaign's **type** decides what renders and which app surface hosts it. All four are supported:

| Experience | Digia component                 | Renders as                                                |
| ---------- | ------------------------------- | --------------------------------------------------------- |
| **Nudge**  | `DigiaHost`                     | Overlay — bottom sheet or dialog above your app           |
| **Guide**  | `DigiaAnchorView` + `DigiaHost` | Step-by-step tooltip / spotlight anchored to a UI element |
| **Survey** | `DigiaHost`                     | Multi-step questionnaire overlay                          |
| **Inline** | `DigiaSlotView`                 | Content embedded in your layout — banner, card or story   |

Every type is triggered the same way — by **App start** or **On screen**, set per campaign in the dashboard (see [section 6](#6-author-the-trigger-in-the-dashboard)). Mount the surfaces for the types your campaign creators plan to use; the next section shows each.

***

## 5. Register your app surfaces

Campaigns need somewhere to render. Which surfaces you add depends on the experience types in play.

Nudges, surveys and guides all render through **`DigiaHost`** — mount it once at the app root, as the **topmost layer**:

```tsx
import { View } from 'react-native';
import { DigiaHost } from '@digia-engage/core';

export default function RootLayout() {
  return (
    <View style={{ flex: 1 }}>
      <AppNavigator />
      {/* Mounted last, so it sits on the top layer — guide overlays paint above your app UI. */}
      <DigiaHost />
    </View>
  );
}
```

{% hint style="warning" %}
**Keep `DigiaHost` as the last child** of your root view. Being last puts it on the topmost layer, so guide overlays — the tooltips and spotlights, which render in JS — paint above your app content and appear correctly. Mount it higher up the tree and your app UI can cover them.
{% endhint %}

**Nudges** render as overlays — a bottom sheet or dialog above your app — and need nothing beyond `DigiaHost`. Design the nudge in the dashboard, give it a trigger, and it appears when the trigger fires.

**Surveys** are multi-step questionnaires shown as overlays in the same host, again with no extra surface. Build the survey in the dashboard, give it a trigger, and it appears just like a nudge.

**Guides** additionally need each anchorable element wrapped with a unique `anchorKey` — the same key the campaign's step targets in the dashboard:

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

<DigiaAnchorView anchorKey="buy_now_button">
  <BuyNowButton />
</DigiaAnchorView>;
```

**Inline** content needs a slot wherever it should appear. The `placementKey` is what campaign creators pick in the dashboard, so share the names you add:

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

<DigiaSlotView placementKey="home_top" />;
```

See [Managing Inline Content](/digia-engage/developer-guides/inline-content.md) for sizing and clearing content.

***

## 6. Author the trigger in the dashboard

With the project's CEP set to **Digia**, the campaign wizard gains a **Trigger** step between **Setup** and **Choose UI**. It asks two things.

### Trigger

| Trigger       | Fires                                                         |
| ------------- | ------------------------------------------------------------- |
| **App start** | Once each time the app launches, as soon as the SDK is ready. |
| **On screen** | Every time the user opens one of the screens you choose.      |

The screens you pick for an **On screen** trigger are also the screens the campaign is allowed to appear on. That is why this project needs no separate **Target screens** field on the Setup step — the trigger already says where the campaign belongs.

### Priority

`High`, `Normal` (default) or `Low`. It decides the order when several campaigns become eligible at the same moment — see the next section.

{% hint style="info" %}
Only **active** campaigns are fetched by the SDK. A campaign left in `draft` never fires, whatever its trigger says.
{% endhint %}

***

## 7. How Digia chooses what to show

When a trigger fires, more than one campaign can qualify at once — three campaigns with an **App start** trigger, for instance. Digia shows them in a deliberate order, one at a time.

**1. Eligible campaigns are ordered.**

1. **Priority** — `High`, then `Normal`, then `Low`.
2. **Most recent first** — among equal priority, the campaign created last wins, as the more current message.

**2. They're shown one at a time.** A nudge, guide or survey owns the whole screen surface, so the next one appears only once the previous is dismissed. The rest wait their turn.

**3. Inline never waits.** Inline campaigns live in their own slot, contend with nothing, and appear immediately — even while a nudge is on screen.

A campaign already on screen is never re-triggered. Once dismissed, it can fire again the next time its trigger matches — so an **On screen** campaign returns on a repeat visit, subject to the frequency cap set on the **Delivery** step.

***

## 8. Test your integration

Verify end-to-end before you ship:

1. **Confirm CEP integration is set to Digia** — otherwise campaigns carry no trigger (Settings → App Settings).
2. **Confirm the calls run once at startup** — `Digia.initialize(...)` then `Digia.enableManagedCampaigns()`, before your first screen.
3. **Mount `<DigiaHost />` once** at the app root for nudges, surveys and guides.
4. **Create an App start campaign** — a simple nudge is easiest — mark it active, and relaunch the app. It should appear as soon as the SDK is ready.
5. **Create an On screen campaign** and confirm it fires when you navigate to its screen. Check that the screen names in the Trigger step match exactly what your app passes to `setCurrentScreen` (they are case-sensitive).
6. **Place a `DigiaSlotView`** with a matching `placementKey` and confirm inline content renders.
7. **Watch the verbose log** — set `logLevel: 'verbose'` and confirm the campaign store loads and each trigger names the campaigns it chose.

***

## 9. Turning it off

```tsx
Digia.disableManagedCampaigns();
```

Stops triggering and clears anything queued; campaigns already on screen are left alone. Handy on logout, or any time you want Digia to stop delivering campaigns.

***

## 10. Troubleshooting

### Nothing fires at all

* Is `Digia.enableManagedCampaigns()` actually called? Without it, Digia does not fire campaigns on its own, so nothing appears.
* Is the project's **CEP integration** set to **Digia**? That is what gives each campaign a trigger to fire on.
* Is the campaign **active**?
* Turn on `logLevel: 'verbose'` in `Digia.initialize`. You should see the campaign store load and then a line naming the campaigns chosen for each trigger:

  ```
  [Digia] loaded 2 campaign(s): [home_story, welcome_nudge]
  [Digia] [triggers] trigger app_start → [welcome_nudge(high), home_story(normal)]
  ```

### A campaign is chosen but doesn't appear

The verbose log shows why:

```
[Digia] Campaign dropped by native: campaign_key=home_story … current_screen=account
```

Usual causes, in order:

* **Screen mismatch.** The campaign's screens don't include the screen the user is on. Confirm the names in the Trigger step match exactly what your app passes to `setCurrentScreen` — they are case-sensitive.
* **`setCurrentScreen` is never called**, so Digia thinks the user is nowhere and every screen-scoped campaign waits.
* **Frequency cap reached** for that campaign (Delivery step).
* **Incomplete content** — an inline story with no media items, for example — is rejected when the SDK parses it.

### An inline campaign fires but shows nothing

The slot isn't on screen. `<DigiaSlotView placementKey="…" />` must be mounted, and its `placementKey` must match the campaign's slot key exactly.

### A screen trigger never fires

Compare the screen name your app reports against the campaign's list, character for character. Add a temporary log in your navigation listener to see exactly what is passed to `setCurrentScreen`.

***

## See also

* [Screen Targeting](/digia-engage/developer-guides/screen-targeting.md) — wiring `setCurrentScreen` to your navigation library.
* [Managing Inline Content](/digia-engage/developer-guides/inline-content.md) — sizing and clearing inline slots.
* [Campaign Actions](/digia-engage/developer-guides/campaign-actions.md) — action types, deep links, and the in-app browser adapter.
