Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
Change Log
==========

Version 4.3.0 *(August 11 2026)*
-------------------------------------------
**What's new**
* **[Android Platform]**
* Supports [CleverTap Android SDK v8.4.1](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTCORECHANGELOG.md#version-841-august-2026).
* Spin-the-Wheel and Scratch Card gamified in-app templates — available to campaigns built with the Advanced InApp Builder, no app-side wiring needed.
* Per-element click attribution for in-apps — the `Notification Clicked` event now records which element of the in-app was tapped, across all templates. Swipe-to-dismiss is now configurable per campaign and is tracked as a `Notification Clicked` event too.
* Accessibility improvements across in-apps and App Inbox — dynamic text scaling, screen-reader announcements, content descriptions for close buttons/images/media controls, a larger 48dp dismiss tap target, and corrected carousel navigation for TalkBack.
Comment on lines +9 to +11

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@piyush-kukadiya I think these changelog can be added in Android and iOS section below to skip redundant changelog, we can update it later in skill

* Custom-HTML header and footer in-apps now render when the host Activity is not a `FragmentActivity` (for example Unity or Unreal game engines). Opt in with the `CLEVERTAP_INAPP_FRAGMENTLESS_BANNERS` manifest flag; it is off by default, so existing apps are unaffected.

* **[iOS Platform]**
* Supports [CleverTap iOS SDK v7.8.1](https://github.com/CleverTap/clevertap-ios-sdk/blob/master/CHANGELOG.md#version-781-august-07-2026).
* Spin-the-Wheel and Scratch Card gamified in-app templates — available to campaigns built with the Advanced InApp Builder, no app-side wiring needed.
* Per-element click attribution for in-apps — the `Notification Clicked` event now records which element of the in-app was tapped, across all templates. Tap-outside and swipe-to-dismiss gestures are now configurable per campaign and are tracked as `Notification Clicked` events too.
* Accessibility improvements across in-apps and App Inbox — VoiceOver labels, a larger dismiss-button tap area, and better handling of image content descriptions.

**API changes**
* **[Android and iOS Platform]**
* Adds `dismissPipInApp()` — dismisses the Picture-in-Picture in-app notification currently on screen. It does nothing when no PIP in-app is visible, and never affects other in-app types.

**Bug Fixes**
* **[Android Platform]**
* Fixes App Inbox messages never being saved on Android 6.0 through Android 10 (API 23–29), which left the inbox permanently empty on those devices. Affects every app using App Inbox on RN SDK v4.1.0 and v4.2.0; messages reappear on the next inbox fetch after updating, with no code change on your side.
* Fixes the built-in App Inbox not repainting the message list after a pull-to-refresh — newly fetched messages previously appeared only after closing and reopening the inbox.
* Fixes a crash when a Picture-in-Picture in-app played video on Android 6.0. Only affects apps whose `minSdkVersion` is below 24; the same fix also covers in-app and App Inbox video playback on that OS version.

* **[iOS Platform]**
* Fixes the built-in App Inbox not repainting the message list after a pull-to-refresh — newly fetched messages previously appeared only after closing and reopening the inbox.
* Fixes in-apps that were missed while the app was in the background not being shown when the app returned to the foreground.
* Fixes the `Notification Clicked` event not carrying deeplink properties for custom-HTML in-apps.
* Fixes client-side in-apps not being persisted when an empty campaign list was received.
* Fixes full-screen cover in-apps built with the Advanced InApp Builder not respecting the device safe area.
* Fixes two potential crashes — one while saving variable diffs, and one during simultaneous variable updates.

Version 4.2.0 *(June 5 2026)*
-------------------------------------------
**What's new**
Expand Down
4 changes: 4 additions & 0 deletions Example/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ export default class App extends Component {
{ action: Actions.IN_APPS_DISCARD, name: 'discardInAppNotifications' },
{ action: Actions.IN_APPS_DISCARD_WITH_DISMISS, name: 'discardInAppNotifications(true)' },
{ action: Actions.IN_APPS_RESUME, name: 'resumeInAppNotifications' },
{ action: Actions.IN_APPS_DISMISS_PIP, name: 'dismissPipInApp' },
],
},
{
Expand Down Expand Up @@ -676,6 +677,9 @@ export default class App extends Component {
case Actions.IN_APPS_RESUME:
CleverTap.resumeInAppNotifications();
break;
case Actions.IN_APPS_DISMISS_PIP:
AppUtils.dismissPipInApp();
break;
case Actions.ENABLE_PERSONALIZATION:
AppUtils.enablePersonalization();
break;
Expand Down
7 changes: 7 additions & 0 deletions Example/app/app-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,13 @@ export const getFeatureFlag = () => {
});
};

// InApp Controls
export const dismissPipInApp = () => {
CleverTap.dismissPipInApp();
console.log('dismissPipInApp -> requested dismissal of the visible PIP InApp, if any');
showToast('Dismiss PIP InApp', 'No-op when no PIP InApp is on screen');
};

// App Personalisation
export const enablePersonalization = () => {
CleverTap.enablePersonalization();
Expand Down
1 change: 1 addition & 0 deletions Example/app/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const Actions = {
IN_APPS_DISCARD: 'IN_APPS_DISCARD',
IN_APPS_DISCARD_WITH_DISMISS: 'IN_APPS_DISCARD_WITH_DISMISS',
IN_APPS_RESUME: 'IN_APPS_RESUME',
IN_APPS_DISMISS_PIP: 'IN_APPS_DISMISS_PIP',
ENABLE_PERSONALIZATION: 'ENABLE_PERSONALIZATION',
ATTRIBUTION_IDENTIFIER: 'ATTRIBUTION_IDENTIFIER',
OPT_IN: 'OPT_IN',
Expand Down
3 changes: 2 additions & 1 deletion Example/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ android {
defaultConfig {
minSdkVersion 23
targetSdkVersion 36
versionCode 420
versionName "4.2.0"
versionCode 430
versionName "4.3.0"
buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString())
}

Expand All @@ -54,7 +54,7 @@ android {
}

dependencies {
api 'com.clevertap.android:clevertap-android-sdk:8.3.0'
api 'com.clevertap.android:clevertap-android-sdk:8.4.1'
implementation 'com.android.installreferrer:installreferrer:2.2'
//compile 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.facebook.react:react-native:+'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,13 @@ public void resumeInAppNotifications() {
}
}

public void dismissPipInApp() {
CleverTapAPI cleverTap = getCleverTapAPI();
if (cleverTap != null) {
cleverTap.dismissPipInApp();
}
}

public void unmute() {
CleverTapAPI cleverTap = getCleverTapAPI();
if (cleverTap != null) {
Expand Down
4 changes: 4 additions & 0 deletions android/src/newarch/CleverTapModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ class CleverTapModule(reactContext: ReactApplicationContext?) :
cleverTapModuleImpl.resumeInAppNotifications()
}

override fun dismissPipInApp() {
cleverTapModuleImpl.dismissPipInApp()
}

override fun unmute() {
cleverTapModuleImpl.unmute()
}
Expand Down
5 changes: 5 additions & 0 deletions android/src/oldarch/CleverTapModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,11 @@ class CleverTapModule(reactContext: ReactApplicationContext?) :
cleverTapModuleImpl.resumeInAppNotifications()
}

@ReactMethod
fun dismissPipInApp() {
cleverTapModuleImpl.dismissPipInApp()
}

@ReactMethod
fun unmute() {
cleverTapModuleImpl.unmute()
Expand Down
2 changes: 1 addition & 1 deletion clevertap-react-native.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Pod::Spec.new do |s|
s.dependency 'React-Core'
end

s.dependency 'CleverTap-iOS-SDK', '7.7.1'
s.dependency 'CleverTap-iOS-SDK', '7.8.1'

if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
s.pod_target_xcconfig = {
Expand Down
2 changes: 1 addition & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ dependencies {


//clevertap
implementation 'com.clevertap.android:clevertap-android-sdk:8.3.0'
implementation 'com.clevertap.android:clevertap-android-sdk:8.4.1'


// other libs
Expand Down
12 changes: 12 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,18 @@ CleverTap.discardInAppNotifications();
CleverTap.resumeInAppNotifications();
```

#### Dismiss PIP InApp Notification

*Available from CleverTap React Native SDK v4.3.0.*

Dismisses the Picture-in-Picture (PIP) InApp notification that is currently on screen. Calling it when no PIP InApp is visible does nothing, and other InApp notification types are never affected.

Dismissing frees the InApp display slot, so the next queued InApp notification (if any) may appear right away. To keep a screen free of all InApp notifications, call `suspendInAppNotifications()` when the screen opens and `resumeInAppNotifications()` when it closes.

```javascript
CleverTap.dismissPipInApp();
```


### For more information,
- [See included Example Application](/Example/app/App.js)
Expand Down
5 changes: 5 additions & 0 deletions ios/CleverTapReact/CleverTapReact.mm
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,11 @@ - (void)messageDidSelect:(CleverTapInboxMessage *_Nonnull)message atIndex:(int)i
[[self cleverTapInstance] resumeInAppNotifications];
}

RCT_EXPORT_METHOD(dismissPipInApp) {
RCTLogInfo(@"[CleverTap dismissPipInApp]");
[[self cleverTapInstance] dismissPipInApp];
}

RCT_EXPORT_METHOD(unmute) {
RCTLogInfo(@"[CleverTap unmute]");
[[self cleverTapInstance] unmute];
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "clevertap-react-native",
"version": "4.2.0",
"version": "4.3.0",
"description": "CleverTap React Native SDK.",
"main": "src/index.js",
"types": "src/index.d.ts",
Expand Down
1 change: 1 addition & 0 deletions src/NativeCleverTapModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export interface Spec extends TurboModule {
suspendInAppNotifications(): void;
discardInAppNotifications(dismissInAppIfVisible?: boolean): void;
resumeInAppNotifications(): void;
dismissPipInApp(): void;
fetchInApps(callback: ((error: Object, result: boolean) => void) | null): void;
clearInAppResources(expiredOnly: boolean): void;
customTemplateSetDismissed(templateName: string): Promise<void>;
Expand Down
12 changes: 12 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,18 @@ export function isPushPermissionGranted(callback: CallbackString): void;
*/
export function resumeInAppNotifications(): void;

/**
* Dismisses the currently visible Picture-in-Picture (PIP) InApp Notification, if any.
*
* This is a no-op when no PIP InApp Notification is visible, and other InApp Notification
* types are never affected.
*
* Note: dismissing frees the InApp display slot, so the next queued InApp Notification (if
* any) may show immediately. To keep a screen free of all InApp Notifications, pair this with
* suspendInAppNotifications() on screen entry and resumeInAppNotifications() on exit.
*/
export function dismissPipInApp(): void;

/**
* Fetches In Apps from server.
*
Expand Down
16 changes: 15 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const EventEmitter = Platform.select({
* @param {int} libVersion - The updated library version. If current version is 1.1.0 then pass as 10100
*/
const libName = 'React-Native';
const libVersion = 40200;
const libVersion = 40300;
CleverTapReact.setLibrary(libName,libVersion);

function defaultCallback(method, err, res) {
Expand Down Expand Up @@ -981,6 +981,20 @@ var CleverTap = {
CleverTapReact.resumeInAppNotifications();
},

/**
* Dismisses the currently visible Picture-in-Picture (PIP) InApp Notification, if any.
*
* This is a no-op when no PIP InApp Notification is visible, and other InApp Notification
* types are never affected.
*
* Note: dismissing frees the InApp display slot, so the next queued InApp Notification (if
* any) may show immediately. To keep a screen free of all InApp Notifications, pair this with
* suspendInAppNotifications() on screen entry and resumeInAppNotifications() on exit.
*/
dismissPipInApp: function () {
CleverTapReact.dismissPipInApp();
},

/**
* Set the SDK debug level
* @param {int} 0 = off, 1 = on
Expand Down