Reporting the Current Screen
Where to call Digia.setCurrentScreen in every stack — navigator observers, per-screen hooks, router-specific recipes, and how to pick screen names that match your campaigns.
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.
1. What the screen name drives
It is not only for targeting. One call feeds five things:
Campaign eligibility
A screen-targeted campaign renders only while the current screen is one of its targets.
Your CEP's screen view
Forwarded to CleverTap recordScreenView, MoEngage trackScreen, or WebEngage screen. This replaces your own CEP "record screen" call — you do not need both.
Analytics
Attached as screen_name to every impression Digia records.
Spotlight targeting
Anchorless 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.
2. Automatic or manual?
There are two ways to report screens, and they are not equivalent.
Automatic (wire a navigator once)
Manual (call per screen)
Effort
One-time setup
One line per screen
Name you get
Whatever your router calls the route
Whatever you choose
Covers tab switches
No
Yes
Covers unnamed routes
No
Yes
Available on
Flutter, iOS
All 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:
Flutter
DigiaNavigatorObserver
iOS
DigiaNavigationScreenObserver (opt-in UINavigationControllerDelegate)
Android
None — call manually
React Native
None — call manually
3. 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:
Then one line per screen:
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.
initState fires once per mount and not when the user navigates back — the screen underneath stays mounted the whole time. So initState alone silently under-reports.
Either let DigiaNavigatorObserver handle back-navigation (it reports the revealed route on pop), or report explicitly at each entry point:
For tabs and other cases the observer cannot see, see section 5.
Use onResume(), not onCreate(), so the call repeats when the user returns:
digiaScreen(...) is available on both Activity and Fragment.
In Compose, use the DigiaScreen composable:
DigiaScreen reports when the composable enters composition or its name changes. Inside a HorizontalPager that keeps neighbouring pages composed, swiping between pages will not re-report — drive it from the pager's selected index instead.
Use viewDidAppear, not viewDidLoad:
In SwiftUI, call from .onAppear at the screen's root view only:
Inside a List or LazyVStack, .onAppear fires per row as cells scroll into view. Attach it to the screen's root view, never to a row.
4. 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:
The same pattern applies on other stacks (scenePhase on iOS, ON_START on Android, AppLifecycleListener on Flutter). Repeating the same screen name is safe.
React Native: a screen reported before Digia.initialize(...) finishes is not applied to screen-triggered campaigns. Report your first screen after initialization resolves.
5. Flutter with your router
DigiaNavigatorObserver works with GoRouter — pass it in observers:
What name lands depends on how you declared the route:
Named route (
GoRoute(name: 'checkout', …)) → reportscheckout. 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.
Two things that silently break this:
A custom
pageBuilderreturningCustomTransitionPagemust passname:itself, otherwise that route reports nothing.GoRouter,ShellRoute, andStatefulShellBrancheach take their ownobserverslist, and a single observer instance can only be attached to oneNavigator. Nested navigators need their ownDigiaNavigatorObserver()instance each.
Any router that renders through a Navigator accepts a NavigatorObserver, so DigiaNavigatorObserver can be attached — but the name it sees is whatever that router puts in RouteSettings.name, which varies.
If the reported names don't match your dashboard, report manually from each screen instead (section 3). That is always available and always exact.
A tab switch is a screen change with no route push, so no observer can see it. If your app has a bottom navigation bar over an IndexedStack, you must report tab changes yourself:
Report in both initState (for the tab the app opens on) and onTap.
6. React Native with your navigator
Identical to React Navigation — import useFocusEffect from expo-router instead:
Everything else, including the hook in section 3, is unchanged.
7. 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:
GoRouter (unnamed route)
/product/:id
Navigation-Compose
product/{id}
iOS navigation observer
HomeViewController
React Navigation
whatever the route's name prop is
One constants file per app keeps developers and campaign owners on the same vocabulary:
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.
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.
8. 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.
9. 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— notuseEffect,onCreate, orviewDidLoad.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.
setCurrentScreenalready forwards it.
Related pages
Screen Targeting — what screen targeting does and which campaigns honor it
Last updated