Skip to main content

Reporting the Current Screen

Digia.setCurrentScreen tells Digia Engage which screen the user is on. This page is the implementation guide: where the call goes in each stack, how to wire it to your navigation library, and how to choose names that actually match your campaigns.

For what screen targeting does and how a campaign owner uses it, see Screen Targeting.

info

setCurrentScreen is a Digia Engage core SDK capability. It behaves the same across React Native, Android, iOS, and Flutter, and across every integration — whether a CEP (CleverTap, MoEngage, WebEngage) drives delivery or Digia runs its own campaigns.

What the screen name drives

It is not only for targeting. One call feeds five things:

ConsumerWhat the screen name does
Campaign eligibilityA screen-targeted campaign renders only while the current screen is one of its targets.
Your CEP's screen viewForwarded to CleverTap recordScreenView, MoEngage trackScreen, or WebEngage screen. This replaces your own CEP "record screen" call — you do not need both.
AnalyticsAttached as screen_name to every impression Digia records.
Spotlight targetingAnchorless spotlight steps match on the screen name.
Component capture (debug)Anchors are skipped entirely while no screen is set, so capture comes back empty.

On Android and iOS the screen name also feeds screen-based frequency capping.

Automatic or manual?

There are two ways to report screens, and they are not equivalent.

Automatic (wire a navigator once)Manual (call per screen)
EffortOne-time setupOne line per screen
Name you getWhatever your router calls the routeWhatever you choose
Covers tab switchesNoYes
Covers unnamed routesNoYes
Available onFlutter, iOSAll stacks

Recommendation: manual, with a central constants file. It is one line per screen, it gives you names that match your dashboard, and it handles the cases a router cannot see. Reach for the automatic path when your app is large and already uses named routes that are exactly the strings your campaign owners type.

What ships today:

StackAutomatic helper
FlutterDigiaNavigatorObserver
iOSDigiaNavigationScreenObserver (opt-in UINavigationControllerDelegate)
AndroidNone — call manually
React NativeNone — call manually

Where the manual call goes

The subtle part is picking a lifecycle hook that fires on every arrival — not just the first mount. A screen the user navigates back to, or a tab they re-select, is still an arrival.

Use useFocusEffect, not useEffect. A tab screen stays mounted when you navigate away, so useEffect fires once and never again:

import { useFocusEffect } from '@react-navigation/native'; // or from 'expo-router'
import { useCallback } from 'react';
import { Digia } from '@digia-engage/core';

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

Then one line per screen:

export function HomeScreen() {
useScreenTracking(ScreenNames.home);
return /* … */;
}

Not using hooks? Digia is a plain singleton, so Digia.setCurrentScreen(...) works from componentDidMount, a navigation listener, a saga, or any non-React module. The hook is convenience, never the only path.

Set the screen before your triggers fire

This is the most common cause of a campaign that "just doesn't appear".

  • A campaign dropped for the wrong screen is not retried. If a campaign triggers while the current screen doesn't match, it is dropped there and then. It does not re-appear when the user later arrives on the targeted screen — your CEP has to trigger it again.
  • The screen is never remembered across launches. After every cold start it is unset, and while it is unset every screen-targeted campaign is dropped.

So report the first screen as early as you can — right after Digia.initialize(...), or from your first screen's arrival hook — so a launch-triggered campaign has a screen to match against.

Re-report when the app returns to the foreground

When the user backgrounds your app and comes back, they are on the same screen but your CEP may need the in-app re-requested. The SDK does not do this for you. Re-report the last screen on foreground:

import { AppState } from 'react-native';

let currentScreen = ScreenNames.home;

AppState.addEventListener('change', (state) => {
if (state === 'active') Digia.setCurrentScreen(currentScreen);
});

The same pattern applies on other stacks (scenePhase on iOS, ON_START on Android, AppLifecycleListener on Flutter). Repeating the same screen name is safe.

warning

React Native: a screen reported before Digia.initialize(...) finishes is not applied to screen-triggered campaigns. Report your first screen after initialization resolves.

Flutter with your router

DigiaNavigatorObserver works with GoRouter — pass it in observers:

final router = GoRouter(
observers: [DigiaNavigatorObserver()],
routes: [
GoRoute(name: 'checkout', path: '/checkout', builder: (_, __) => const CheckoutScreen()),
],
);

What name lands depends on how you declared the route:

  • Named route (GoRoute(name: 'checkout', …)) → reports checkout. Naming your routes gives you clean dashboard names for free — this is the recommended setup.
  • Unnamed route → reports the path pattern, for example /product/:id, not the resolved /product/42. That is stable across products (good for targeting) but is not a string a campaign owner would naturally type, so align the dashboard to it or name the route.
warning

Two things that silently break this:

  • A custom pageBuilder returning CustomTransitionPage must pass name: itself, otherwise that route reports nothing.
  • GoRouter, ShellRoute, and StatefulShellBranch each take their own observers list, and a single observer instance can only be attached to one Navigator. Nested navigators need their own DigiaNavigatorObserver() instance each.

React Native with your navigator

Per-screen with useFocusEffect is the recommended setup — see section 3.

If you cannot touch every screen, a container-level listener is a fallback:

<NavigationContainer
ref={navigationRef}
onStateChange={() => {
const routeName = navigationRef.getCurrentRoute()?.name;
if (routeName) Digia.setCurrentScreen(routeName);
}}
>
warning

This fires on any navigation state change, including route parameter updates, so the same screen is reported repeatedly. It also reports the route's name prop, which is often not the name your campaign owner would use. Prefer the per-screen hook.

Choosing screen names

The name you report is matched exactly and case-sensitively against the campaign's target screens. Checkout, checkout, and /checkout are three different screens, and a mismatch fails silently.

Use semantic names from a shared constants file — not route paths. Every automatic source hands you a string a campaign owner would not naturally type:

SourceWhat you get
GoRouter (unnamed route)/product/:id
Navigation-Composeproduct/{id}
iOS navigation observerHomeViewController
React Navigationwhatever the route's name prop is

One constants file per app keeps developers and campaign owners on the same vocabulary:

export const ScreenNames = {
home: 'home',
cart: 'cart',
productDetail: 'product_detail',
} as const;

Conventions that avoid trouble: lowercase snake_case, no leading slash, and never a trailing space — a stray space in a dashboard screen name matches on some platforms and not others.

warning

Agree the vocabulary with whoever builds campaigns, and use those exact strings on both sides. A mismatch produces no error — the campaign is simply dropped, with only a debug log.

Verify it's working

With verbose logging enabled, the SDK logs every screen you report — something like Current screen set: checkout. If you never see it, your call isn't running; if you see it with the wrong value, your naming is the problem.

When a campaign is dropped for the screen, the SDK logs both sides of the comparison — the current screen (shown as <unset> if you never reported one) and the campaign's target screens. That log line tells you immediately whether the fix is to report a screen, rename it, or change the campaign.

For an end-to-end check, use Live Testing to fire a screen-targeted campaign at your device, and SDK Debug Settings to inspect SDK state on-device.

Use it correctly

  • Report every screen the user lands on, as early as possible and on every arrival — including the first screen after launch.
  • Use a lifecycle hook that repeats: useFocusEffect, onResume, viewDidAppear — not useEffect, onCreate, or viewDidLoad.
  • Report tab switches yourself. No navigator observer can see them.
  • Keep names identical to the dashboard (exact, case-sensitive). This is the single most common reason a screen-targeted campaign doesn't appear.
  • Set the screen before campaigns trigger. A campaign dropped for the wrong screen is never retried.
  • Delete your own CEP screen-view call. setCurrentScreen already forwards it.