Unreal Push Notifications
Learn how to configure push notifications.
Push Notifications
Push notifications are a powerful tool for real-time user engagement. With the CleverTap Unreal SDK, you can configure and manage push notifications for Android and iOS platforms. This guide walks you through the platform-specific setup, notification behavior, and prerequisites.
CleverTap allows you to send push notifications from its dashboard after the user grants permission through the PromptForPushPermission()
method.
Prerequisites
The following are the prerequisites:
- The CleverTap Unreal SDK is integrated.
- For Android, Firebase Cloud Messaging (FCM) is configured. Refer to the Android Push Setup Guide.
- For iOS, Apple Push Notification service (APNs) is configured.
Android Setup
The following steps explain how to configure Firebase, notification channels, and app behavior for delivering push notifications on Android using the CleverTap Unreal SDK.
Configure Firebase Cloud Messaging (FCM)
To use CleverTap's default notification implementation with Firebase:
- Follow the Android Push Setup Guide to register Firebase credentials on the CleverTap dashboard.
- Copy
google-services.json
to your project directory (for example,Config
). - In your projectโs
Config/DefaultEngine.ini
, setbAndroidIntegrateFirebase
toTrue
, and specifyAndroidGoogleServicesJsonPath
as the relative path to thegoogle-services.json
file that you copied in the earlier step.
[/Script/CleverTap.CleverTapConfig]
bAndroidIntegrateFirebase=True
AndroidGoogleServicesJsonPath=Config/Android/google-services.json
Configure Push Notification Channels
Android requires push notifications to be delivered through predefined channels. These channels allow users to control how notifications behave, such as setting the sound, vibration, or visibility preferences.
Since channels must be registered during Java's GameApplication.onCreate()
(before Unreal Engine has initialized), they cannot be created dynamically in C++
.
Therefore, all required channels must be predefined in Config/DefaultEngine.ini
.
Basic Setup
You can define up to 100 notification channels in your DefaultEngine.ini
file. Each channel must include an ID field, which acts as the unique identifier for that channel. Android uses this ID to route and manage push notifications for the respective channel configuration.
[/Script/CleverTap.CleverTapConfig]
AndroidNotificationChannelSlot1=ID="general" | Name="General" | Description="General Notifications" | Importance=IMPORTANCE_DEFAULT | bShowBadge=True
AndroidNotificationChannelSlot2=ID="news" | Name="News Updates" | Description="Important news and alerts" | Importance=IMPORTANCE_HIGH | bShowBadge=True | Sound="news_alert.wav"
You can assign an Importance
level to each channel to control how prominently notifications appear. Valid values include:
IMPORTANCE_NONE
, IMPORTANCE_MIN
, IMPORTANCE_LOW
, IMPORTANCE_DEFAULT
, IMPORTANCE_HIGH
, and IMPORTANCE_MAX
.
The sound files must be added to the APK's res/raw
directory. Use AndroidSoundsDir
to configure the path.
Note
- The
CleverTap_Android_UPL.xml
reads theAndroidNotificationChannelSlot
entries to inject the required Java code intoGameApplication.onCreate()
. If theini
syntax contains errors, the build will fail during compilation ofGameApplication.java
.- You must configure
AndroidNotificationChannelSlot
settings directly in your projectโsConfig/DefaultEngine.ini
file. These settings are not exposed in the Project Settings GUI.
Channel Localization
You can set a notification channelโs display name and description at runtime using Unreal's localization system. If you localize the channel dynamically, you do not need to include Name
or Description
in the .ini
configuration.
Minimal .ini
Setup
.ini
SetupDefine the notification channel with only the essential parameters in your DefaultEngine.ini file
:
AndroidNotificationChannelSlot1=ID="general" | Importance=IMPORTANCE_DEFAULT | bShowBadge=True
Runtime Localization in C++
C++
You can localize the channel name and description at runtime using the following API:
CleverTapSys = GEngine->GetEngineSubsystem<UCleverTapSubsystem>();
ICleverTapInstance& CleverTap = CleverTapSys->SharedInstance();
CleverTap.LocalizeAndroidNotificationChannel(TEXT("general"),
NSLOCTEXT("CleverTapSample", "ChannelName_general", "General"),
NSLOCTEXT("CleverTapSample", "ChannelDesc_general", "General Notifications"));
Channel Groups
To organize related channels into categories, you can define up to 10 notification channel groups. Each group is declared in your .ini
file, and channels can reference it using Group="group_id."
.ini
Configuration Example
.ini
Configuration Example[/Script/CleverTap.CleverTapConfig]
AndroidNotificationChannelGroupSlot1=ID="general" | Name="General"
AndroidNotificationChannelSlot1=ID="general" | Group="general" | Importance=IMPORTANCE_DEFAULT | bShowBadge=True
Group names can be localized at runtime using Unreal's localization system. Call LocalizeAndroidNotificationChannelGroup()
during app initialization (after setting up the CleverTap subsystem) and again if the app detects a locale change.
CleverTapSys = GEngine->GetEngineSubsystem<UCleverTapSubsystem>();
ICleverTapInstance& CleverTap = CleverTapSys->SharedInstance();
CleverTap.LocalizeAndroidNotificationChannelGroup(
TEXT("general"),
NSLOCTEXT("CleverTapSample", "ChannelGroupName_general", "General")
); // Using NSLOCTEXT() enables translation of group names using Unreal's localization pipeline.
Default Android Notification Channel
You can define a default notification channel that CleverTap will use when the push payload refers to a channel that is not registered in your app. This ensures that push notifications are delivered consistently, even if specific channels are missing.
If the SDK cannot find the default channel ID specified in the manifest, it will automatically fall back to using a built-in channel called Miscellaneous
.
To specify the appโs preferred default channel:
[/Script/CleverTap.CleverTapConfig]
AndroidDefaultNotificationChannel=general
Note
Make sure the channel ID you specify (for example,
general
) defined in theAndroidNotificationChannelSlot
entries in yourDefaultEngine.ini
.
Android Small Notification Icon
By default, the CleverTap SDK uses your appโs icon for both the notification and the status bar icons. However, starting with Android 5.0 (Lollipop), non-alpha (non-transparent) icons are ignored when rendering the small notification icon.
To customize the icon, you can provide a project-relative path to an alpha-only .png
file:
[/Script/CleverTap.CleverTapConfig]
AndroidSmallNotificationIconPath=Config/Android/sample_small_notification_icon.png
Note
The base filename must contain only lowercase letters (
aโz
), digits (0โ9
), or underscores (_
). Avoid capital letters, dashes, or spaces.
For more information about image requirements, refer to the Android Push Notification- Set the Small Notification Icon.
Android Sound and Image Resources
You can include additional images and custom sound files in your APK for direct use by CleverTap on Android.
These resources are not part of Unreal's asset system. Instead, they are copied directly into the APK and must follow Android's resource naming conventions:
- File names must use only lowercase letters
aโz
, digits0โ9
, or underscores_
. - Avoid using capital letters, spaces, or special characters.
Android supports the following audio formats for custom sounds:
.mp3
.ogg
.wav
Define Resource Directories
Set the directories in your DefaultEngine.ini
:
[/Script/CleverTap.CleverTapConfig]
AndroidImagesDir=Config/Android/Images
AndroidSoundsDir=Config/Android/Sounds
Custom Android Notification Handling
Due to Android's limitation of allowing only one FirebaseMessagingService
per app, the CleverTap SDK cannot coexist cleanly with other Unreal plugins that declare their own FCM service (for example, Unreal Firebase plugin).
If your project uses another Firebase plugin and requires CleverTap push notifications, you must:
- Disable CleverTap's Firebase integration:
bAndroidIntegrateFirebase=False
- Create a custom multiplexer in
Java
that forwards CleverTap messages manually.
Example: Unified FCM Handler
public class UnifiedMessagingService extends SomeOtherPluginMessagingService {
@Override
public void onMessageReceived(RemoteMessage message) {
if (isCleverTapMessage(message)) {
new CTFcmMessageHandler().createNotification(getApplicationContext(), message);
} else {
// Let the base class handle it
super.onMessageReceived(message);
}
}
private boolean isCleverTapMessage(RemoteMessage message) {
Map<String, String> data = message.getData();
return data != null && data.containsKey("wzrk_pn"); // CleverTap magic key
}
}
This approach ensures that CleverTap and other Firebase plugins can handle push messages without conflict.
For more information, refer to the Custom Android Push Notification Handling.
Android OpenUrl Configuration
To handle incoming app links such as deep links, enable bIntegrateOpenUrl
and define up to four slot-based URL filters in your projectโs .ini
file.
Example Configuration
[/Script/CleverTap.CleverTapConfig]
bIntegrateOpenUrl=True
; Slot 1 - catches clevertap-unreal-sample://
DeepLinkSchemeFilterSlot1=clevertap-unreal-sample
; Slot 2 - catches clevertap://unreal.com/sample
DeepLinkSchemeFilterSlot2=clevertap
AndroidIntentFilterSlot2_Host=unreal.com
AndroidIntentFilterSlot2_PathPrefix=/sample
; Slot 3 - catches http://clevertap.com/unreal-sample (requires digital verification)
DeepLinkSchemeFilterSlot3=http
AndroidIntentFilterSlot3_Host=clevertap.com
AndroidIntentFilterSlot3_PathPrefix=/unreal-sample
AndroidIntentFilterSlot3_AutoVerify=True
Note
The
http
andhttps
schemes require digital verification using anassetlinks.json
file hosted on the target domain. For more information, refer to the Verify Android App Links.
Test Deep Link with adb
adb
You can simulate a deep link click on a connected Android device using the following command:
adb shell am start -a android.intent.action.VIEW -d "clevertap-unreal-sample://test/path"
Custom Deep Link Handling
If you need full control over how your app handles deep links:
- Disable the built-in
OpenUrlActivity
integration. - Define your activity and intent filters via custom UPL rules.
- If your custom activity forwards the intent to
GameActivity
, the event will still reach theOnOpenURL
delegate in Unreal.
iOS Setup
CleverTap's Unreal SDK provides robust support for handling push notifications and deep links on iOS. This section walks you through configuring URL handling, enabling Apple Push Notification service (APNs), applying optional engine patches, and handling push interactions.
iOS - Configuring Apple Push Notifications (APNs)
To enable push notification support on iOS using CleverTap, you must first configure APNs and ensure the correct Unreal Engine settings are in place.
- Follow the CleverTap iOS Push Guide to configure Apple Push Notification service (APNs).
- In your projectโs
Config/DefaultEngine.ini
, check that the following setting is enabled:
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
bEnableRemoteNotificationsSupport=True
Note
The CleverTap Unreal plugin does not support the following iOS features:
iOS - Optional Engine Changes for Push Notifications
Push notification features on iOS, such as handling when the app is closed or supporting rich media, require optional engine-level patches to Unreal Engine.
Install Patch Tool (Windows Only)
On Windows, install the patch utility using:
winget install GnuWin32.Patch
Patch: Push Notification Callback When App is Closed
Unreal Engine does not forward push notifications to CleverTap when the app is fully closed (not in foreground/background). To fix this, apply the engine patch to IOSAppDelegate.cpp
:
UnrealEngine % patch -p1 -u -i /path/to/CleverTapSample/EnginePatches/iOSSavedRemoteNotifications.patch
Patch: Rich Push Notification Support
To support Rich Push Notifications on iOS, CleverTap provides a Notification Service Extension. However, Unreal Engine does not natively support iOS app extensions.
The EnginePatches/UE4.27_ExtensionSupport.patch
file provides an example patch that adds this support. This patch modifies Unreal Engine's build process to include app extensions and must be applied from the Unreal Engine root directory using the Linux patch command.
Apply the Engine Patch
UnrealEngine % patch -p1 -u -i /path/to/CleverTapSample/EnginePatches/UE4.27_ExtensionSupport.patch
Once patched, the extension located at Plugins/CleverTap/Source/ThirdParty/IOS/Extensions/CTNotificationService will be included in the build. A custom signing provision can be specified for the extension via changes to the Config/DefaultEngine.ini
file.
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
MobileProvision_CTNotificationService=YourProvisioning.mobileprovision
Check that the specified .mobileprovision
file is installed before building.
Note
This engine patch adds support for app extensions located in:
{ProjectFolder}/Build/IOS/Extensions
{ProjectFolder}/Plugins/{PluginName}/Source/ThirdParty/IOS/Extensions
Currently, this integration only supports Unreal Engine 4.27 and has been tested exclusively with the
CTNotificationService
extension provided by CleverTap.
Enabling OnPushNotificationClicked
OnPushNotificationClicked
After setting up your shared CleverTap instance, enable the OnPushNotificationClicked
delegate by calling:
EnableOnPushNotificationClicked();
Make sure to register your delegate listener before invoking this method.
On iOS, if the engine patch has been applied for push notifications that launch the app, this can trigger attempting to broadcast the push notification that launched the app.
CleverTapSys = GEngine->GetEngineSubsystem<UCleverTapSubsystem>();
ICleverTapInstance& CleverTap = CleverTapSys->SharedInstance();
CleverTap.OnPushNotificationClicked.AddLambda([](const FCleverTapProperties& NotificationPayload)
{
UE_LOG(LogTemp, Log, TEXT("Push notification was tapped"));
});
CleverTap.EnableOnPushNotificationClicked();
This delegate is triggered when a user taps on a push notification, allowing you to dynamically handle deep links, In-App events, or other logic.
๐ iOS OpenUrl Configuration
To handle incoming app links on iOS, enable bIntegrateOpenUrl
and define up to four slot-based URL scheme filters in your .ini
file.
Example Configuration
[/Script/CleverTap.CleverTapConfig]
bIntegrateOpenUrl=True
; Slot 1 - catches clevertap-unreal-sample://
DeepLinkSchemeFilterSlot1=clevertap-unreal-sample
; Slot 2 - catches clevertap://
DeepLinkSchemeFilterSlot2=clevertap
; Slot 3 - catches http://
DeepLinkSchemeFilterSlot3=http
To further filter incoming URLs or handle them manually, use the RegisterCleverTapUrlHandler()
method to register a delegate.
Updated about 13 hours ago