{"id":31039432,"url":"https://github.com/clevertap/clevertap-unreal-sdk","last_synced_at":"2025-09-14T07:57:32.077Z","repository":{"id":287140014,"uuid":"942742888","full_name":"CleverTap/clevertap-unreal-sdk","owner":"CleverTap","description":null,"archived":false,"fork":false,"pushed_at":"2025-06-24T14:13:30.000Z","size":7511,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":5,"default_branch":"dev","last_synced_at":"2025-06-24T15:30:46.483Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CleverTap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-04T15:48:33.000Z","updated_at":"2025-06-24T14:13:34.000Z","dependencies_parsed_at":"2025-04-10T07:22:06.851Z","dependency_job_id":"47fe56fd-6906-499e-86be-26355dd51296","html_url":"https://github.com/CleverTap/clevertap-unreal-sdk","commit_stats":null,"previous_names":["clevertap/clevertap-unreal-sdk"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/CleverTap/clevertap-unreal-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleverTap%2Fclevertap-unreal-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleverTap%2Fclevertap-unreal-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleverTap%2Fclevertap-unreal-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleverTap%2Fclevertap-unreal-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CleverTap","download_url":"https://codeload.github.com/CleverTap/clevertap-unreal-sdk/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleverTap%2Fclevertap-unreal-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275076592,"owners_count":25401317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-14T07:57:30.927Z","updated_at":"2025-09-14T07:57:32.067Z","avatar_url":"https://github.com/CleverTap.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Plugin Integration\n## Clone and Copy\nClone the sample application repository into a temporary folder to get access to the CleverTap Unreal plugin.\n```bash\ngit clone --depth 1 https://github.com/CleverTap/clevertap-unreal-sdk.git\n```\nCopy the `clevertap-unreal-sdk\\Plugins\\CleverTap` folder to your Unreal project's Plugin folder.\n## Integration\n### Generic Integration\nAdd the following to the `Plugins` section of your Unreal project's `.uproject` file.\n```json\n{\n\t\"Plugins\": [\n\t\t{\n\t\t\t\"Name\": \"CleverTap\",\n\t\t\t\"Enabled\": true\n\t\t}\n\t]\n}\n```\n### C++ Integration\nAdd the following to the C++ gameplay module's `PrivateDependencyModuleNames` property in each `*.Target.cs` file's class constructor.\n```csharp\nPrivateDependencyModuleNames.Add(\"CleverTap\");\n```\nIf you use any of the public CleverTap types in your module's public types then you should add it to the `PublicDependencyModuleNames` property instead.\n## Configuration\nIn your project's `Config\\DefaultEngine.ini` file add the following block at the end.\n```ini\n[/Script/CleverTap.CleverTapConfig]\nProjectId= ;Add your project Id here. This is found on your project's CleverTap dashboard\nProjectToken= ;Add your project token here. This is found on your project's CleverTap dashboard\nRegionCode= ;Reference https://developer.clevertap.com/docs/idc#ios to determine what region code string to put here\n```\nAlternatively you can edit the Plugin's settings in the UE4Editor.\n\n## Initialization\nBy default, with `bAutoInitializeSharedInstance` set to `true` in `Config\\DefaultEngine.ini`, the `UCleverTapSubsystem`\nwill automatically initialize the CleverTap SDK and the default shared instance. It is recommended not to set this to\n`false` as it is only currently partially supported on iOS.\n\n## Encryption of PII Data\nPII data is stored across the SDK and could be sensitive information. \nYou can enable encryption for PII data such as Email, Identity, Name, and Phone.\nCurrently, two levels of encryption are supported:\n- None: All stored data is in plaintext (the default)\n- Medium: PII data is encrypted completely\n\nThe only way to set the encryption level for the default instance is from `Config/DefaultEngine.ini`:\n```ini\n[/Script/CleverTap.CleverTapConfig]\nEncryptionLevel=Medium\n```\n\nDifferent instances can have different encryption levels. To set an encryption level for an additional instance, set the `EncryptionLevel` field in the `FCleverTapInstanceConfig` used to create it.\n\n\n## Push Notification Configuration\nCleverTap allows you to send push notifications to your applications from our dashboard, once the user has granted permission in response to a call to `PromptForPushPermission()`. \n\nEach platform requires slightly different setup.\n\n### Android - Configure Firebase Cloud Messaging (FCM)\nTo use the default CleverTap notification implementation with Firebase:\n\n1. Follow [these instructions](https://developer.clevertap.com/docs/android-push) to create and register your firebase credentials in the CleverTap dashboard.\n\n2. Copy the generated `google-services.json` to somewhere in your project directory (e.g. `Config`).\n\n3. In your project's `Config/DefaultEngine.ini` ensure `bAndroidIntegrateFirebase` is `True` and `AndroidGoogleServicesJsonPath` is the project-relative path to where you copied `google-services.json`. \n\n```ini\n[/Script/CleverTap.CleverTapConfig]\nbAndroidIntegrateFirebase=True\nAndroidGoogleServicesJsonPath=Config/Android/google-services.json\n```\n\n### Android - Configure Push Notification Channels \n\nAndroid requires push notifications to be delivered via pre-defined notification channels. These channels let users customize how different types of notifications behave (e.g., sound, vibration, visibility).\n\nBecause channels must be registered during Java's `GameApplication.onCreate()` - before Unreal Engine has initialized - they cannot be created dynamically from C++. Instead, they must be preconfigured in your project’s `Config/DefaultEngine.ini`.\n\n#### Basic Setup \nDefine up to 100 channels in your DefaultEngine.ini. Only the ID field is required - this is the unique identifier for the channel.\n\n```ini\n[/Script/CleverTap.CleverTapConfig]\nAndroidNotificationChannelSlot1=ID=\"general\" | Name=\"General\" | Description=\"General Notifications\" | Importance=IMPORTANCE_DEFAULT | bShowBadge=True\nAndroidNotificationChannelSlot2=ID=\"news\" | Name=\"News Updates\" | Description=\"Important news and alerts\" | Importance=IMPORTANCE_HIGH | bShowBadge=True | Sound=\"news_alert.wav\"\n```\nValid Importance values: `IMPORTANCE_NONE`, `IMPORTANCE_MIN`, `IMPORTANCE_LOW`, `IMPORTANCE_DEFAULT`, `IMPORTANCE_HIGH`, `IMPORTANCE_MAX`.\n\nThe sound files must be included in the APK's `res/raw`; see the `AndroidSoundsDir` setting for more information.\n\n\n\u003e [!NOTE]\n\u003e - The plugin’s `CleverTap_Android_UPL.xml` reads these entries and injects the required Java into `GameApplication.onCreate()`. Errors in the `ini` syntax will cause the compilation of `GameApplication.java` to fail.\n\u003e - The `AndroidNotificationChannelSlot` settings can only be edited directly in your project’s `Config/DefaultEngine.ini`; they are **not** available in the `Project Settings` GUI.\n\n#### Channel Localization \nYou can set the channel’s display name and description at runtime using Unreal's localization system. If you use runtime localization, there's no need to specify `Name` or `Description` in the `.ini`.\n\n```ini\n[/Script/CleverTap.CleverTapConfig]\nAndroidNotificationChannelSlot1=ID=\"general\" | Importance=IMPORTANCE_DEFAULT | bShowBadge=True\nAndroidNotificationChannelSlot2=ID=\"news\" | Importance=IMPORTANCE_HIGH | bShowBadge=True\n```\n\n##### C++\n```c++\nCleverTapSys = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e();\nICleverTapInstance\u0026 CleverTap = CleverTapSys-\u003eSharedInstance();\nCleverTap.LocalizeAndroidNotificationChannel(TEXT(\"general\"),\n        NSLOCTEXT(\"CleverTapSample\", \"ChannelName_general\", \"General\"),\n        NSLOCTEXT(\"CleverTapSample\", \"ChannelDesc_general\", \"General Notifications\"));\n```\n\n##### Blueprint\n![Calling LocalizeAndroidNotificationChannel in Blueprint](/Docs/Images/BP_LocalizeAndroidNotificationChannel.png)\n\n#### Channel Grouping \nYou can define up to 10 notification channel groups to categorize related channels.\nEach group is declared in your `.ini`, and channels can reference them using `Group=\"group_id\"`.\n\n```ini\n[/Script/CleverTap.CleverTapConfig]\nAndroidNotificationChannelGroupSlot1=ID=\"general\" | Name=\"General\"\nAndroidNotificationChannelSlot1=ID=\"general\" | Group=\"general\" | Importance=IMPORTANCE_DEFAULT | bShowBadge=True\n```\n\nGroup names can be localized at runtime, just like channels.\nCall `LocalizeAndroidNotificationChannelGroup()` early in startup and again after locale changes.\n\n##### C++\n```c++\nCleverTapSys = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e();\nICleverTapInstance\u0026 CleverTap = CleverTapSys-\u003eSharedInstance();\nCleverTap.LocalizeAndroidNotificationChannelGroup( TEXT(\"general\"), \n        NSLOCTEXT(\"CleverTapSample\", \"ChannelGroupName_general\", \"General\"));\n```\n\n##### Blueprint\n![Calling LocalizeAndroidNotificationChannelGroup in Blueprint](/Docs/Images/BP_LocalizeAndroidNotificationChannelGroup.png)\n\n### Default Android Notification Channel\nYou can define a specific notification channel that CleverTap will use if the channel provided in the push payload is not registered by your app. This ensures that push notifications are displayed consistently even if the app's notification channels are not set up.\n\nIn case the SDK does not find the default channel ID specified in the manifest, it will automatically fall back to using a default channel called `Miscellaneous`. This ensures that push notifications are still delivered, even if no specific default channel is specified in the manifest.\n\nTo specify your app’s preferred default channel:\n```ini\n[/Script/CleverTap.CleverTapConfig]\nAndroidDefaultNotificationChannel=general\n```\n\n### Android Small Notification Icon\nBy default, our SDK uses the app's icon for both the notification icon and the notification bar icon; however, since Android 5, all non-alpha channels are ignored while drawing the main notification icon. \n\nYou can supply the project-relative path to an alpha-only png to use instead:\n```ini\n[/Script/CleverTap.CleverTapConfig]\nAndroidSmallNotificationIconPath=Config/Android/sample_small_notification_icon.png\n```\n\nNote that the base filename must contain only lowercase letters (`a`-`z`), digits (`0`-`9`), or underscores (`_`).\n\nFor more information about the image requirements, see https://developer.clevertap.com/docs/android-push#set-the-small-notification-icon\n\n### Android Sound and Image Resources\nAdditional Images and Sounds can be included in the APK for direct use by Android \u0026 CleverTap.\n\nThese are not part of Unreal's regular asset system. They are copied directly into the APK and must follow Android resource rules. Filenames must contain only lowercase letters (`a`-`z`), digits (`0`-`9`), or underscores (`_`).\n\nAndroid supports .mp3, .ogg, and .wav files for playing custom sounds.\n\n```ini\n[/Script/CleverTap.CleverTapConfig]\nAndroidImagesDir=Config/Android/Images\nAndroidSoundsDir=Config/Android/Sounds\n```\n\n### Custom Android Notification Handling\nDue to Android’s restriction of allowing only one `FirebaseMessagingService`, it cannot coexist cleanly with other Unreal plugins that declare their own FCM service (e.g. the Unreal Firebase plugin).\n\nIf you’re already using another Firebase plugin and also require CleverTap push features, you’ll need to disable the CleverTap Firebase integration with `bAndroidIntegrateFirebase=False`, and replace the other plug-in’s FCM service with a custom multiplexer implemented in Java.\n\nFor example:\n```java\npublic class UnifiedMessagingService extends SomeOtherPluginMessagingService {\n    @Override\n    public void onMessageReceived(RemoteMessage message) {\n        if (isCleverTapMessage(message)) {\n            new CTFcmMessageHandler().createNotification(getApplicationContext(), message);\n        } else {\n            // Let the base class handle it\n            super.onMessageReceived(message);\n        }\n    }\n\n    private boolean isCleverTapMessage(RemoteMessage message) {\n        Map\u003cString, String\u003e data = message.getData();\n        return data != null \u0026\u0026 data.containsKey(\"wzrk_pn\"); // CleverTap magic key\n    }\n}\n```\n\nFor more information, see [Custom Android Push Notification Handling](https://developer.clevertap.com/docs/android-push#custom-android-push-notification-handling) \n\n\n### Android OpenUrl Configuration\nTo handle incoming app links, enable `bIntegrateOpenUrl` and define up to four slot-based URL filters in your project’s `.ini` file.\n\n```ini\n[/Script/CleverTap.CleverTapConfig]\nbIntegrateOpenUrl=True\n\n; Example Slot1 - catches clevertap-unreal-sample://\nDeepLinkSchemeFilterSlot1=clevertap-unreal-sample \n\n; Example Slot2 - catches clevertap://unreal.com/sample\nDeepLinkSchemeFilterSlot2=clevertap\nAndroidIntentFilterSlot2_Host=unreal.com\nAndroidIntentFilterSlot2_PathPrefix=/sample\n\n; Example Slot3 - catches http://clevertap.com/unreal-sample, \n; but requires digital verification that the app is approved for this domain\n; See https://developer.android.com/training/app-links/verify-android-applinks\nDeepLinkSchemeFilterSlot3=http\nAndroidIntentFilterSlot3_Host=clevertap.com\nAndroidIntentFilterSlot3_PathPrefix=/unreal-sample\nAndroidIntentFilterSlot3_AutoVerify=True\n```\n\n\u003e [!NOTE] Http/Https schemes require digital verification via `assetlinks.json` hosted on the target domain.\n\u003e See: https://developer.android.com/training/app-links/verify-android-applinks\n\nYou can simulate clicking on a deep link with `adb`:\n```\nadb shell am start -a android.intent.action.VIEW -d \"clevertap-unreal-sample://test/path\"\n```\n\nDisable OpenUrlActivity integration if you need full control over your app’s deep link handling, and plan to define your own activity with complex intent filters via custom UPL rules. \nIf your custom activity forwards the intent to the `GameActivity`, it will still be routed to the `OnOpenURL` delegate.\n\n### iOS OpenUrl Configuration\nTo handle incoming app links, enable `bIntegrateOpenUrl` and define up to four slot-based URL scheme filters in your project’s `.ini` file.\n\n```ini\n[/Script/CleverTap.CleverTapConfig]\nbIntegrateOpenUrl=True\n\n; Example Slot1 - catches clevertap-unreal-sample://\nDeepLinkSchemeFilterSlot1=clevertap-unreal-sample \n\n; Example Slot2 - catches clevertap://\nDeepLinkSchemeFilterSlot2=clevertap\n\n; Example Slot3 - catches http://\nDeepLinkSchemeFilterSlot3=http\n```\nTo further filter the allowed links use the `RegisterCleverTapUrlHandler()` method to register a filter or do custom\nURL handling.\n\n### iOS - Configuring Apple Push Notifications (APNs)\n1. Follow the [CleverTap guide](https://developer.clevertap.com/docs/push-notifications-ios#step-1-configure-push-notifications) to set up APNs for your app.\n2. In your project's `Config/DefaultEngine.ini` ensure `bEnableRemoteNotificationsSupport` is `True` in the `[/Script/IOSRuntimeSettings.IOSRuntimeSettings]` section.\n3. If you would like push notifications to appear when your app is in the foreground make sure that `bIOSPresentPushNotificationsInForeground` is set to `True` in the `[/Script/CleverTap.CleverTapConfig]` section of your project's `Config/DefaultEngine.ini`\n\n\u003e [!NOTE]\n\u003e The CleverTap Unreal plugin currently does not support [Push Impressions](https://developer.clevertap.com/docs/push-notifications-ios#push-impressions), [Push Primers](https://developer.clevertap.com/docs/push-notifications-ios#ios-push-primer), or [Rich Push Notifications](https://developer.clevertap.com/docs/rich-push-notifications).\n\n#### iOS - Optional Engine changes for Push Notifications that launch the App\nOn Windows, a patch program equivalent can be installed using winget.\n```powershell\nwinget install GnuWin32.Patch\n```\n\n##### iOS Engine Patch - Push Notification Callback Invocation When App is Closed\nIf you're App isn't in the foreground or background then Unreal will not forward the push notification to CleverTap unless you make engine changes to `Engine/Source/Runtime/ApplicationCore/Private/IOS/IOSAppDelegate.cpp`.  An example of such changes can be found in the `EnginePatches/iOSSavedRemoteNotifications.patch` patch file. This can be applied in the Unreal root directory using the linux patch command.\n```bash\nUnrealEngine % patch -p1 -u -i /path/to/CleverTapSample/EnginePatches/iOSSavedRemoteNotifications.patch\n```\n\n##### iOS Engine Patch - Rich Push Notification Support\n[Rich Push Notifications](https://developer.clevertap.com/docs/rich-push-notifications) require a [Notification Service\nExtension](https://developer.apple.com/reference/usernotifications/unnotificationserviceextension). Unfortunately\nUnreal Engine doesn't support app extensions without modification to its build process. An example patch that adds\nsupport for app extensions can be found in the\n[EnginePatches/UE4.27_ExtensionSupport.patch](EnginePatches/UE4.27_ExtensionSupport.patch) patch file. This can\nbe applied in the Unreal root directory using the linux patch command.\n```bash\nUnrealEngine % patch -p1 -u -i /path/to/CleverTapSample/EnginePatches/UE4.27_ExtensionSupport.patch\n```\n\nOnce patched, the extension located at [Plugins/CleverTap/Source/ThirdParty/IOS/Extensions/CTNotificationService](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.\n```ini\n[/Script/IOSRuntimeSettings.IOSRuntimeSettings]\nMobileProvision_CTNotificationService=YourProvisioning.mobileprovision\n```\nPlease make sure the specified .mobileprovision file is installed before building.\n\n\u003e [!NOTE]\n\u003e This engine patch adds support for arbitrary app extensions located in `{ProjectFolder}/Build/IOS/Extensions` or any\n\u003e `{ProjectFolder}/Plugins/{PluginNameHere}/Source/ThirdParty/IOS/Extensions` folders. It only supports UE4.27 and has\n\u003e only been tested against the CTNotificationService extension provided here.\n\n### Enabling OnPushNotificationClicked\nAfter setting up your shared CleverTap instance the `OnPushNotificationClicked` delegate can be enabled by calling `EnableOnPushNotificationClicked()`. On iOS, if the engine patch has been applied for push notifications that launch the app then this can trigger attempting to broadcast the push notification that launched the app. Therefore a delegate listener should be added before calling `EnableOnPushNotificationClicked()`.\n\n#### C++\n```c++\nCleverTapSys = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e();\nICleverTapInstance\u0026 CleverTap = CleverTapSys-\u003eSharedInstance();\nCleverTap.OnPushNotificationClicked.AddLambda([](const FCleverTapProperties\u0026 NotificationPayload)\n\t{\n\t\tUE_LOG(LogTemp, Log, TEXT(\"Push notification was tapped\"));\n\t});\nCleverTap.EnableOnPushNotificationClicked();\n```\n\n#### Blueprint\n![Binding OnPushNotificationClicked in Blueprint](/Docs/Images/BP_OnPushNotificationClicked.png)\n\n## In-App Notifications\nIn-app notifications are initially suspended. When your callbacks are set up then call\n`ICleverTapInstance::ResumeInAppNotifications()` to begin receiving in-app notifications.\n\nThe payload parameters for all in-app notifications callbacks have their nested objects flattened as dot separated keys\nin the property map so that the object `{\"a\": { \"b\": 3.14 }}` would have a single entry of\n`Payload[FString{TEXT(\"a.b\")}] == FCleverTapPropertyValue{ 3.14 }`. \n\n### Callbacks\n#### OnInAppNotificationShown\nWhen an in-app notification is displayed this callback will be invoked with and the notification payload is passed as a\nparameter.\n\n##### C++\n```c++\nCleverTapSys = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e();\nICleverTapInstance\u0026 CleverTap = CleverTapSys-\u003eSharedInstance();\nCleverTap.OnInAppNotificationShown.AddLambda([](const FCleverTapProperties\u0026 Payload)\n    {\n\t\tUE_LOG(LogTemp, Log, TEXT(\"An in-app notification was shown: %s\"), *ToDebugString(Payload));\n    });\n```\n\n##### Blueprint\n![Binding OnInAppNotificationShown in Blueprint](/Docs/Images/BP_OnInAppNotificationShown.png)\n\n#### OnInAppNotificationButtonClicked\nWhen the user clicks on an in-app notification button this callback will be invoked with the key/value pairs associated\nwith that button.\n\n##### C++\n```c++\nCleverTapSys = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e();\nICleverTapInstance\u0026 CleverTap = CleverTapSys-\u003eSharedInstance();\nCleverTap.OnInAppNotificationButtonClicked.AddLambda([](const FCleverTapProperties\u0026 Payload)\n    {\n\t\tUE_LOG(LogTemp, Log, TEXT(\"An in-app notification button clicked: %s\"), *ToDebugString(Payload));\n    });\n```\n\n##### Blueprint\n![Binding OnInAppNotificationButtonClicked in Blueprint](/Docs/Images/BP_OnInAppNotificationButtonClicked.png)\n\n#### OnInAppNotificationDismissed\nWhen an in-app notification is dismissed by the user this callback will be invoked with the notification payload and any\nextra key/value pairs specified for the in-app notification in the CleverTap dashboard.\n```c++\nCleverTapSys = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e();\nICleverTapInstance\u0026 CleverTap = CleverTapSys-\u003eSharedInstance();\nCleverTap.OnInAppNotificationDismissed.AddLambda([](const FCleverTapProperties\u0026 Extras, const FCleverTapProperties\u0026 ActionExtras)\n    {\n\t\tUE_LOG(LogTemp, Log, TEXT(\"An in-app notification was dismissed. Extras: %s, ActionExtras: %s\"),\n            *ToDebugString(Extras), *ToDebugString(ActionExtras));\n    });\n```\n\n##### Blueprint\n![Binding OnInAppNotificationDismissed in Blueprint](/Docs/Images/BP_OnInAppNotificationDismissed.png)\n\n### Suspend, Resume, and Discard In-App Notifications\nIn-app notifications initially start suspended. If you like to discard any notifications that were queued while they\nwere suspended then you can invoke `ICleverTapInstance::DiscardInAppNotifications()` to do so. Notifications can be\nresumed by calling `ICleverTapInstance::ResumeInAppNotifications()`. Any queued notification that happened while\nsuspended, and which has not been explicitly discarded, will be presented to the user. If you would like to suspend\nnotifications again then call `ICleverTapInstance::SuspendInAppNotifications()`.\n\n#### Blueprint\n![Calling SuspendInAppNotifications -\u003e DiscardInAppNotifications -\u003e ResumeInAppNotifications in Blueprint](/Docs/Images/BP_SuspendDiscardResume_InAppNotifications.png)\n\n## User Profiles\n### On User Login\nThe `OnUserLogin()` method can be used when a user is identifier and logs into the app. Upon first login this enriches the\ninitial \"Anonymous\" user profile with additional properties such as name, age, and email. See [Updating the User Profile](https://developer.clevertap.com/docs/concepts-user-profiles#updating-the-user-profile) for a list of predefined properties.\n\n#### C++\n```cpp\nFCleverTapProperties Profile;\nProfile.Add(TEXT(\"Name\"), TEXT(\"Jack Montana\"));    // String\nProfile.Add(TEXT(\"Identity\"), 61026032);            // String or Number\nProfile.Add(TEXT(\"Email\"), TEXT(\"jack@gmail.com\")); // Email string\nProfile.Add(TEXT(\"Phone\"), TEXT(\"+14155551234\"));   // with country code, starting with +\nProfile.Add(TEXT(\"Gender\"), TEXT(\"M\"));             // Can be either M or F\nProfile.Add(TEXT(\"DOB\"), FCleverTapDate(1953, 3, 13));\n\nProfile.Add(TEXT(\"MSG-email\"), false);   // Disable email notifications\nProfile.Add(TEXT(\"MSG-push\"), true);     // Enable push notifications\nProfile.Add(TEXT(\"MSG-sms\"), false);     // Disable SMS notifications\nProfile.Add(TEXT(\"MSG-whatsapp\"), true); // Enable WhatsApp notifications\n\nTArray\u003cFString\u003e Stuff;\nStuff.Add(TEXT(\"bag\"));\nStuff.Add(TEXT(\"shoes\"));\nProfile.Add(TEXT(\"MyStuff\"), Stuff); // Multi-Value array of string support\n\nICleverTapInstance\u0026 CleverTap = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e()-\u003eSharedInstance();\nCleverTap.OnUserLogin(Profile);\n```\n\n#### Blueprint\n![Calling OnUserLogin in Blueprint](/Docs/Images/BP_OnUserLogin.png)\n\n### Updating a User Profile with PushProfile()\nThe user's profile can be enriched with additional properties at any time using the `PushProfile()` method. This\nsupports arbitrary single value and multi-value properties like `OnUserLogin()`.\n\n#### C++\n```cpp\nFCleverTapProperties Profile;\n// Update an existing property\nProfile.Add(TEXT(\"MSG-push\"), false);\n\n// Add new properties\nProfile.Add(TEXT(\"Tz\"), TEXT(\"Asia/Kolkata\"));\nProfile.Add(TEXT(\"Plan Type\"), TEXT(\"Silver\"));\nProfile.Add(TEXT(\"Score\"), 100);\n\nICleverTapInstance\u0026 CleverTap = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e()-\u003eSharedInstance();\nCleverTap.PushProfile(Profile);\n```\n\n#### Blueprint\n![Calling PushProfile in Blueprint](/Docs/Images/BP_PushProfile.png)\n\n### Increment or Decrement Scalar Properties\nIf a given profile property is a `int32`, `int64`, `float`, or `double` then it can be incremented or decremented by an\narbitrary positive value.\n\n#### C++\n```cpp\nICleverTapInstance\u0026 CleverTap = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e()-\u003eSharedInstance();\nCleverTap.IncrementValue(TEXT(\"Score\"), 50);\nCleverTap.DecrementValue(TEXT(\"Score\"), 100);\nCleverTap.IncrementValue(TEXT(\"Score\"), 5.5);\nCleverTap.DecrementValue(TEXT(\"Score\"), 3.14);\n```\n\n#### Blueprint\n![Calling IncrementValue or DecrementValue in Blueprint](/Docs/Images/BP_IncrementDecrementValue.png)\n\n## Event Recording\n### User Events\nUser Events can be recorded any time after initialization.\n\n#### C++\n```cpp\nICleverTapInstance\u0026 CleverTap = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e()-\u003eSharedInstance();\n\n// event without properties\nCleverTap.PushEvent(TEXT(\"Event No Props\"));\n\n// event with properties\nFCleverTapProperties Actions;\nActions.Add(\"Product Name\", \"Casio Chronograph Watch\");\nActions.Add(\"Category\", \"Mens Accessories\");\nActions.Add(\"Price\", 59.99);\nCleverTap.PushEvent(TEXT(\"Product viewed\"), Actions);\n```\nEvent values can be any type that the `FCleverTapPropertyValue` variant type supports (`int32`, `int64`, `double`, `float`, `bool`, `const ANSICHAR*`, `FString`, or `FCleverTapDate`).\n\n#### Blueprint\n![Calling PushEvent in Blueprint](/Docs/Images/BP_PushEvent.png)\n![Calling PushEventWithProperties in Blueprint](/Docs/Images/BP_PushEventWithProperties.png)\n\n### Charged Events\nCharged events are a special user event to record transaction details of a purchase. Each item in the purchase can be\nrecorded and enriched with custom properties.\n\n#### C++\n```cpp\n// charge event\nFCleverTapProperties ChargeDetails;\nChargeDetails.Add(\"Amount\", 300);\nChargeDetails.Add(\"Payment Mode\", \"Credit card\");\nChargeDetails.Add(\"Charged ID\", 24052014);\n\nFCleverTapProperties Item1;\nItem1.Add(\"Product category\", \"books\");\nItem1.Add(\"Book name\", \"The Millionaire next door\");\nItem1.Add(\"Quantity\", 1);\n\nFCleverTapProperties Item2;\nItem2.Add(\"Product category\", \"books\");\nItem2.Add(\"Book name\", \"Achieving inner zen\");\nItem2.Add(\"Quantity\", 1);\n\nFCleverTapProperties Item3;\nItem3.Add(\"Product category\", \"books\");\nItem3.Add(\"Book name\", \"Chuck it, let's do it\");\nItem3.Add(\"Quantity\", 5);\n\nTArray\u003cFCleverTapProperties\u003e Items;\nItems.Add(Item1);\nItems.Add(Item2);\nItems.Add(Item3);\n\nICleverTapInstance\u0026 CleverTap = GEngine-\u003eGetEngineSubsystem\u003cUCleverTapSubsystem\u003e()-\u003eSharedInstance();\nCleverTap.PushChargedEvent(ChargeDetails, Items);\n```\n\n#### Blueprint\n![Calling PushChargedEvent in Blueprint](/Docs/Images/BP_PushChargedEvent.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclevertap%2Fclevertap-unreal-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclevertap%2Fclevertap-unreal-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclevertap%2Fclevertap-unreal-sdk/lists"}