Skip to content
Merged
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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
Change Log
==========

Version 3.9.0 *(February 17 2026)*
-------------------------------------------
**What's new**
* **[Android Platform]**
* Supports [CleverTap Android SDK v7.8.0](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTCORECHANGELOG.md#version-780-january-22-2026).

* **[iOS Platform]**
* Supports [CleverTap iOS SDK v7.5.0](https://github.com/CleverTap/clevertap-ios-sdk/blob/master/CHANGELOG.md#version-750-february-9-2026).

* **[Android and iOS Platform]**
* Adds support for inaction in-app notifications. This server-side feature allows triggering in-app notifications when users do not perform specific actions within a defined timeframe.
* Adds support for nested objects ingestion in event and profile properties, enabling more complex data structures for richer user profiling and event tracking.

Version 3.8.1 *(January 14 2026)*
-------------------------------------------
**What's new**
Expand Down
12 changes: 12 additions & 0 deletions Example/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export default class App extends Component {
categoryName: 'User Properties',
subCategory: [
{ action: Actions.SET_USER_PROFILE, name: 'pushProfile' },
{ action: Actions.PROFILE_PUSH_WITH_NESTED_PROPERTIES, name: 'pushProfile with nested properties' },
{ action: Actions.SET_MULTI_VALUES, name: 'set Multi Values For Key' },
{
action: Actions.REMOVE_MULTI_VALUE,
Expand All @@ -139,6 +140,7 @@ export default class App extends Component {
categoryName: 'Identity Management',
subCategory: [
{ action: Actions.USER_LOGIN, name: 'onUserLogin' },
{ action: Actions.USER_LOGIN_WITH_NESTED_PROPERTIES, name: 'onUserLogin with nested properties' },
{ action: Actions.CLEVERTAP_ID, name: 'getCleverTapID' },
],
},
Expand All @@ -153,6 +155,7 @@ export default class App extends Component {
categoryName: 'Events',
subCategory: [
{ action: Actions.PUSH_EVENT, name: 'pushEvent' },
{ action: Actions.RECORD_EVENT_WITH_NESTED_PROPERTIES, name: 'recordEvent with nested properties' },
{ action: Actions.PUSH_CHARGED_EVENT, name: 'pushChargedEvent' },
],
},
Expand Down Expand Up @@ -430,6 +433,9 @@ export default class App extends Component {
case Actions.SET_USER_PROFILE:
AppUtils.set_userProfile();
break;
case Actions.PROFILE_PUSH_WITH_NESTED_PROPERTIES:
AppUtils.set_userProfileWithNestedProperties();
break;
case Actions.SET_MULTI_VALUES:
CleverTap.profileSetMultiValuesForKey(['a', 'b', 'c'], 'letters');
break;
Expand Down Expand Up @@ -458,6 +464,9 @@ export default class App extends Component {
case Actions.USER_LOGIN:
AppUtils.onUser_Login();
break;
case Actions.USER_LOGIN_WITH_NESTED_PROPERTIES:
AppUtils.onUser_LoginWithNestedProperties();
break;
case Actions.CLEVERTAP_ID:
AppUtils.getCleverTap_id();
break;
Expand Down Expand Up @@ -506,6 +515,9 @@ export default class App extends Component {
case Actions.PUSH_EVENT:
AppUtils.pushevent();
break;
case Actions.RECORD_EVENT_WITH_NESTED_PROPERTIES:
AppUtils.recordEventWithNestedProperties();
break;
case Actions.PUSH_CHARGED_EVENT:
AppUtils.pushChargedEvent();
break;
Expand Down
97 changes: 97 additions & 0 deletions Example/app/app-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,40 @@ export const set_userProfile = () => {
});
};

export const set_userProfileWithNestedProperties = () => {
const profile = {
Name: 'testUserNested',
Identity: '123456',
Email: 'nested@test.com',
JoiningDate : new Date('2025-03-03T06:35:31'),
Address: {
street: '123 Main St',
city: 'San Francisco',
state: 'CA',
zipCode: 94105,
coordinates: {
lat: 37.7749,
lng: -122.4194
}
},
Preferences: {
newsletter: true,
notifications: {
email: true,
push: false,
sms: true
},
subscriptionDate: new Date('2026-03-03T06:35:31'),
categories: ['sports', 'tech', 'news'],
dateProps: [new Date('2025-03-03T06:35:31'), new Date('2026-03-03T06:35:31'), new Date('2025-03-03T06:35:31')]
}
};

showToast('User Profile with Nested Properties', JSON.stringify(profile));
console.log('Profile Push with nested properties: ', JSON.stringify(profile));
CleverTap.profileSet(profile);
};

// Identity_Management
export const onUser_Login = () => {
showToast('User Profile Updated');
Expand All @@ -64,6 +98,35 @@ export const onUser_Login = () => {
});
};

export const onUser_LoginWithNestedProperties = () => {
const profile = {
Name: 'testUserLogin',
Identity: new Date().getTime() + '',
Email: new Date().getTime() + 'logintest@test.com',
Company: {
name: 'TechCorp',
department: 'Engineering',
role: 'Senior Developer',
location: {
office: 'HQ',
floor: 5
}
},
Settings: {
theme: 'dark',
language: 'en',
privacy: {
shareData: false,
analytics: true
}
}
};

showToast('User Login with Nested Properties', JSON.stringify(profile));
console.log('OnUserLogin with nested properties: ', JSON.stringify(profile));
CleverTap.onUserLogin(profile);
};

export const getCleverTap_id = () => {
// Below method is deprecated since 0.6.0, please check index.js for deprecation, instead use CleverTap.getCleverTapID()
/*CleverTap.profileGetCleverTapID((err, res) => {
Expand Down Expand Up @@ -103,6 +166,40 @@ export const pushevent = () => {
CleverTap.recordEvent('pushEvent');
};

export const recordEventWithNestedProperties = () => {
const eventProps = {
'Product Name': 'Premium Subscription',
'Amount': 99.99,
'Currency': 'USD',
'Payment Details': {
method: 'credit_card',
provider: 'Stripe',
cardType: 'Visa',
lastFourDigits: '4242',
billingAddress: {
street: '456 Market St',
city: 'New York',
state: 'NY',
zipCode: 10001
}
},
'User Metadata': {
isPremium: true,
tier: 'gold',
features: ['feature1', 'feature2', 'feature3'],
limits: {
apiCalls: 10000,
storage: 100
}
},
'timestamp': new Date()
};

showToast('Event with Nested Properties', 'Product Purchased');
console.log('Recording event with nested properties: ', JSON.stringify(eventProps));
CleverTap.recordEvent('Product Purchased', eventProps);
};

export const pushChargedEvent = () => {
showToast('Charged Event Recorded');

Expand Down
5 changes: 4 additions & 1 deletion Example/app/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,8 @@ export const Actions = {
SYNC_CUSTOM_TEMPLATES_PROD: 'SYNC_CUSTOM_TEMPLATES_PROD',
FILE_CHANGED: 'FILE_CHANGED',
FILES_VARIABLES_CHANGED_AND_DOWNLOADED:'FILES_VARIABLES_CHANGED_AND_DOWNLOADED',
FILES_VARIABLES_CHANGED_AND_DOWNLOADED_ONCE:'FILES_VARIABLES_CHANGED_AND_DOWNLOADED_ONCE'
FILES_VARIABLES_CHANGED_AND_DOWNLOADED_ONCE:'FILES_VARIABLES_CHANGED_AND_DOWNLOADED_ONCE',
RECORD_EVENT_WITH_NESTED_PROPERTIES: 'RECORD_EVENT_WITH_NESTED_PROPERTIES',
PROFILE_PUSH_WITH_NESTED_PROPERTIES: 'PROFILE_PUSH_WITH_NESTED_PROPERTIES',
USER_LOGIN_WITH_NESTED_PROPERTIES: 'USER_LOGIN_WITH_NESTED_PROPERTIES'
};
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 21
targetSdkVersion 35
versionCode 381
versionName "3.8.1"
versionCode 390
versionName "3.9.0"
buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString())
}

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

dependencies {
api 'com.clevertap.android:clevertap-android-sdk:7.7.1'
api 'com.clevertap.android:clevertap-android-sdk:7.8.0'
implementation 'com.android.installreferrer:installreferrer:2.2'
//compile 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.facebook.react:react-native:+'
Expand Down
27 changes: 27 additions & 0 deletions android/src/main/java/com/clevertap/react/CleverTapModuleImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,24 @@ private <T> HashMap<String, T> eventPropsFromReadableMap(ReadableMap propsMap, C
Log.e(TAG, "Unhandled ReadableType.Number from ReadableMap");
}
}
} else if (readableType == ReadableType.Map) {
try {
ReadableMap nestedMap = propsMap.getMap(key);
if (nestedMap != null) {
props.put(key, tClass.cast(CleverTapUtils.MapUtil.toMap(nestedMap)));
}
} catch (Throwable t) {
Log.e(TAG, "Unhandled ReadableType.Map from ReadableMap");
}
} else if (readableType == ReadableType.Array) {
try {
ReadableArray nestedArray = propsMap.getArray(key);
if (nestedArray != null) {
props.put(key, tClass.cast(CleverTapUtils.MapUtil.ArrayUtil.toArray(nestedArray)));
}
} catch (Throwable t) {
Log.e(TAG, "Unhandled ReadableType.Array from ReadableMap");
}
} else {
Log.e(TAG, "Unhandled event property ReadableType");
}
Expand Down Expand Up @@ -1721,6 +1739,15 @@ private HashMap<String, Object> profileFromReadableMap(ReadableMap profileMap) {
} catch (Throwable t) {
Log.e(TAG, "Unhandled ReadableType.Array from ReadableMap");
}
} else if (readableType == ReadableType.Map) {
try {
ReadableMap nestedMap = profileMap.getMap(key);
if (nestedMap != null) {
profile.put(key, CleverTapUtils.MapUtil.toMap(nestedMap));
}
} catch (Throwable t) {
Log.e(TAG, "Unhandled ReadableType.Map from ReadableMap");
}
} else {
Log.e(TAG, "Unhandled profile property ReadableType");
}
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.4.2'
s.dependency 'CleverTap-iOS-SDK', '7.5.0'

if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
s.pod_target_xcconfig = {
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": "3.8.1",
"version": "3.9.0",
"description": "CleverTap React Native SDK.",
"main": "src/index.js",
"types": "src/index.d.ts",
Expand Down
16 changes: 14 additions & 2 deletions 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 = 30801;
const libVersion = 30900;
CleverTapReact.setLibrary(libName,libVersion);

function defaultCallback(method, err, res) {
Expand Down Expand Up @@ -1244,12 +1244,24 @@ var CleverTap = {
function convertDateToEpochInProperties(map) {
/**
* Conversion of date object in suitable CleverTap format(Epoch)
* Recursively handles nested objects and arrays
*/
if (map) {
for (let [key, value] of Object.entries(map)) {
if (Object.prototype.toString.call(value) === '[object Date]') {
map[key] = "$D_" + Math.floor(value.getTime() / 1000);
}
} else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
// Recursively convert dates in nested objects
convertDateToEpochInProperties(value);
} else if (Array.isArray(value)) {
value.forEach((item, index) => {
if (Object.prototype.toString.call(item) === '[object Date]') {
value[index] = "$D_" + Math.floor(item.getTime() / 1000);
} else if (item !== null && typeof item === 'object') {
convertDateToEpochInProperties(item);
}
});
}
}
}

Expand Down