diff --git a/CHANGELOG.md b/CHANGELOG.md index 844f8e6d..2a918740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ Change Log ========== +Version 4.2.0 *(June 12 2026)* +------------------------------------------- +**What's new** +* **[Android Platform]** + * Supports [CleverTap Android SDK v8.3.0](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTCORECHANGELOG.md#version-830-june-2026). + * App Inbox Cross-Device Sync — inbox state (read, deleted) syncs across a user's devices automatically. Includes a pull-to-refresh gesture in the built-in App Inbox view, throttled to once every 5 minutes. + * Native Display Element Click — finer-grained click analytics for individual elements within a Native Display unit. + +* **[iOS Platform]** + * Supports [CleverTap iOS SDK v7.7.1](https://github.com/CleverTap/clevertap-ios-sdk/blob/master/CHANGELOG.md#version-771-june-04-2026). + * App Inbox Cross-Device Sync — inbox state (read, deleted) syncs across a user's devices automatically. Includes a pull-to-refresh gesture in the built-in App Inbox view, throttled to once every 5 minutes. + * Native Display Element Click — finer-grained click analytics for individual elements within a Native Display unit. + * Silent-in-foreground push — push notifications can now be suppressed when the app is in the foreground via `wzrk_sif:true` in the push payload; handled automatically when using `autoIntegrate`. + +**API changes** +* **[Android and iOS Platform]** + * Adds `fetchInbox(callback?)` — triggers an on-demand App Inbox refresh from the server. The optional callback receives a boolean indicating whether the fetch succeeded. Calls are throttled to once every 5 minutes. + * Adds `pushDisplayUnitElementClickedEventForID(unitID, additionalProperties)` — records a `Notification Clicked` event for a specific element within a Native Display unit, merging caller-supplied properties (include `wzrk_element_id` from the element metadata) with cached attribution fields. + Version 4.1.0 *(April 30 2026)* ------------------------------------------- **What's new** diff --git a/Example/android/app/src/main/assets/custom/templates.json b/Example/android/app/src/main/assets/custom/templates.json new file mode 100644 index 00000000..2229e8c7 --- /dev/null +++ b/Example/android/app/src/main/assets/custom/templates.json @@ -0,0 +1,68 @@ +{ + "Example template": { + "type": "template", + "arguments": { + "bool": { + "type": "boolean", + "value": false + }, + "string": { + "type": "string", + "value": "Default" + }, + "map": { + "type": "object", + "value": { + "int": { + "type": "number", + "value": 0 + }, + "string": { + "type": "string", + "value": "Default" + } + } + }, + "action": { + "type": "action" + }, + "file": { + "type": "file" + } + } + }, + "Example function": { + "type": "function", + "isVisual": false, + "arguments": { + "double": { + "type": "number", + "value": 99.98 + }, + "string": { + "type": "string", + "value": "Default" + }, + "file": { + "type": "file" + } + } + }, + "Example visual function": { + "type": "function", + "isVisual": true, + "arguments": { + "color": { + "type": "string", + "value": "transparent" + }, + "enabled": { + "type": "boolean", + "value": false + }, + "image": { + "type": "file" + } + } + } +} diff --git a/Example/app/App.js b/Example/app/App.js index 1c362af9..148fb720 100644 --- a/Example/app/App.js +++ b/Example/app/App.js @@ -273,6 +273,7 @@ export default class App extends Component { action: Actions.INBOX_NOTIFICATION_CLICKED, name: 'pushInboxNotificationClickedEvent', }, + { action: Actions.FETCH_INBOX, name: 'fetchInbox' }, ], }, { @@ -348,6 +349,7 @@ export default class App extends Component { subCategory: [ { action: Actions.DISPLAY_UNIT_ID, name: 'getUnitID' }, { action: Actions.ALL_DISPLAY_UNITS, name: 'getAllDisplayUnits' }, + { action: Actions.PUSH_DISPLAY_UNIT_ELEMENT_CLICKED, name: 'pushDisplayUnitElementClickedEvent' }, ], }, { @@ -513,6 +515,9 @@ export default class App extends Component { case Actions.INBOX_NOTIFICATION_CLICKED: AppUtils.pushInboxNotificationClicked(); break; + case Actions.FETCH_INBOX: + AppUtils.fetchInbox(); + break; case Actions.PUSH_EVENT: AppUtils.pushevent(); break; @@ -579,6 +584,9 @@ export default class App extends Component { case Actions.ALL_DISPLAY_UNITS: AppUtils.getAllDisplayUnits(); break; + case Actions.PUSH_DISPLAY_UNIT_ELEMENT_CLICKED: + AppUtils.pushDisplayUnitElementClicked(); + break; case Actions.PRODUCT_CONFIG_FETCH: AppUtils.fetch(); break; diff --git a/Example/app/app-utils.js b/Example/app/app-utils.js index 6ec06039..75366f24 100644 --- a/Example/app/app-utils.js +++ b/Example/app/app-utils.js @@ -358,6 +358,13 @@ export const pushInboxNotificationClicked = () => { CleverTap.pushInboxNotificationClickedEventForId('Message Id'); }; +export const fetchInbox = () => { + CleverTap.fetchInbox((err, success) => { + console.log('fetchInbox result:', success, err); + showToast(`fetchInbox success: ${success}`); + }); +}; + export const printInboxMessagesArray = (data) => { if (data != null) { console.log('Total Inbox Message count = ' + data.length); @@ -552,6 +559,16 @@ export const createNotificationChannelWithGroupIdAndSound = () => { }; // Native Display +export const pushDisplayUnitElementClicked = () => { + CleverTap.pushDisplayUnitElementClickedEventForID('unit-id-001', { + wzrk_element_id: 'btn_cta_1', + title: 'Summer Sale', + campaign_type: 'display', + }); + showToast('Display Unit Element Clicked event pushed'); + console.log('pushDisplayUnitElementClickedEventForID called'); +}; + export const getUnitID = () => { CleverTap.getDisplayUnitForId('Unit Id', (err, res) => { console.log('Get Display Unit for Id:', res, err); diff --git a/Example/app/constants.js b/Example/app/constants.js index ab8c2a02..28f45a88 100644 --- a/Example/app/constants.js +++ b/Example/app/constants.js @@ -45,6 +45,8 @@ export const Actions = { CREATE_NOTIFICATION_CHANNEL_WITH_GROUP_AND_SOUND: 'CREATE_NOTIFICATION_CHANNEL_WITH_GROUP_AND_SOUND', DISPLAY_UNIT_ID: 'DISPLAY_UNIT_ID', ALL_DISPLAY_UNITS: 'ALL_DISPLAY_UNITS', + PUSH_DISPLAY_UNIT_ELEMENT_CLICKED: 'PUSH_DISPLAY_UNIT_ELEMENT_CLICKED', + FETCH_INBOX: 'FETCH_INBOX', PRODUCT_CONFIG_FETCH: 'PRODUCT_CONFIG_FETCH', PRODUCT_CONFIG_ACTIVATE: 'PRODUCT_CONFIG_ACTIVATE', PRODUCT_CONFIG_FETCH_AND_ACTIVATE: 'PRODUCT_CONFIG_FETCH_AND_ACTIVATE', diff --git a/Example/ios/.xcode.env b/Example/ios/.xcode.env new file mode 100644 index 00000000..772b339b --- /dev/null +++ b/Example/ios/.xcode.env @@ -0,0 +1 @@ +export NODE_BINARY=$(command -v node) diff --git a/Example/ios/Example.xcodeproj/project.pbxproj b/Example/ios/Example.xcodeproj/project.pbxproj index 48562268..fb9743be 100644 --- a/Example/ios/Example.xcodeproj/project.pbxproj +++ b/Example/ios/Example.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ 48BF79852AB076F20091FF16 /* NotificationContentSwift.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 48BF79792AB076F10091FF16 /* NotificationContentSwift.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 685D0A42F74FC38D84284799 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 9A4C3DD3EBC1242A62F0E22B /* PrivacyInfo.xcprivacy */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + 95FFEF509E854EAD92574543 /* templates.json in Resources */ = {isa = PBXBuildFile; fileRef = 259EE3CCAE64436A8800F81F /* templates.json */; }; C28EE22363709BEF624F9F1E /* libPods-NotificationContentSwift.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C33252DD165317E32A556B4 /* libPods-NotificationContentSwift.a */; }; FFDFBBA910887882FBEAC7E1 /* libPods-NotificationContent.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEC195091200DD33134801AA /* libPods-NotificationContent.a */; }; /* End PBXBuildFile section */ @@ -89,6 +90,7 @@ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = ""; }; 14E2F58881084EE312574B68 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = ""; }; + 259EE3CCAE64436A8800F81F /* templates.json */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = templates.json; path = ../assets/templates.json; sourceTree = ""; }; 273ED08C65D1C0D2A1CF924D /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = ""; }; 35C0D77F08F13FB76F737463 /* libPods-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 48BF78BE2AA5B5110091FF16 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -175,6 +177,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0E655508297846A9BF4257DB /* Resources */ = { + isa = PBXGroup; + children = ( + 259EE3CCAE64436A8800F81F /* templates.json */, + ); + name = Resources; + path = ""; + sourceTree = ""; + }; 13B07FAE1A68108700A75B9A /* Example */ = { isa = PBXGroup; children = ( @@ -281,6 +292,7 @@ 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, 7168044AA71FBFBA4A3B8E24 /* Pods */, + 0E655508297846A9BF4257DB /* Resources */, ); indentWidth = 2; sourceTree = ""; @@ -461,6 +473,7 @@ 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 685D0A42F74FC38D84284799 /* PrivacyInfo.xcprivacy in Resources */, + 95FFEF509E854EAD92574543 /* templates.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1295,7 +1308,10 @@ ); MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -1363,7 +1379,10 @@ "\"$(inherited)\"", ); MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; diff --git a/Example/ios/Example/Info.plist b/Example/ios/Example/Info.plist index f91f7d33..6d90d0e9 100644 --- a/Example/ios/Example/Info.plist +++ b/Example/ios/Example/Info.plist @@ -42,7 +42,7 @@ NSLocationWhenInUseUsageDescription - + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/Example/ios/Example/PrivacyInfo.xcprivacy b/Example/ios/Example/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..bad32761 --- /dev/null +++ b/Example/ios/Example/PrivacyInfo.xcprivacy @@ -0,0 +1,37 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/Example/ios/Podfile b/Example/ios/Podfile index 23b33797..7e11d7af 100644 --- a/Example/ios/Podfile +++ b/Example/ios/Podfile @@ -45,23 +45,28 @@ target 'Example' do aggregate_target.user_project.save end end + pod "SDWebImage", :modular_headers => true end target 'NotificationService' do pod_clevertap_ios_sdk pod "CTNotificationService", :modular_headers => true + pod "SDWebImage", :modular_headers => true end target 'NotificationContent' do pod "CTNotificationContent" + pod "SDWebImage", :modular_headers => true end # Added these target for sample code only in Swift target 'NotificationServiceSwift' do pod_clevertap_ios_sdk pod "CTNotificationService", :modular_headers => true + pod "SDWebImage", :modular_headers => true end target 'NotificationContentSwift' do pod "CTNotificationContent" + pod "SDWebImage", :modular_headers => true end diff --git a/Example/package-lock.json b/Example/package-lock.json index 3d4fb608..64701dec 100644 --- a/Example/package-lock.json +++ b/Example/package-lock.json @@ -19,7 +19,7 @@ "react-native-drawer": "^2.5.1", "react-native-gesture-handler": "^1.10.3", "react-native-pager-view": "^5.1.2", - "react-native-reanimated": "^3.15.0", + "react-native-reanimated": "^3.4.0", "react-native-safe-area-context": "^3.2.0", "react-native-screens": "3.31.1", "react-native-svg-transformer": "^1.3.0", @@ -49,8 +49,8 @@ } }, "..": { - "version": "3.2.0", - "extraneous": true, + "name": "clevertap-react-native", + "version": "4.2.0", "license": "MIT", "devDependencies": { "eslint": "^4.18.2", @@ -70,6 +70,7 @@ }, ".yalc/clevertap-react-native": { "version": "3.3.0", + "extraneous": true, "license": "MIT", "peerDependencies": { "react-native": ">=0.65.0" @@ -174,6 +175,7 @@ }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.7", @@ -434,6 +436,7 @@ }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { "version": "7.25.3", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", @@ -448,6 +451,7 @@ }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.25.0", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" @@ -461,6 +465,7 @@ }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.25.0", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" @@ -474,6 +479,7 @@ }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -489,6 +495,7 @@ }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.25.0", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", @@ -635,6 +642,7 @@ }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -666,6 +674,7 @@ }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" @@ -676,6 +685,7 @@ }, "node_modules/@babel/plugin-syntax-class-static-block": { "version": "7.14.5", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" @@ -712,6 +722,7 @@ }, "node_modules/@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" @@ -735,6 +746,7 @@ }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -748,6 +760,7 @@ }, "node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -761,6 +774,7 @@ }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" @@ -771,6 +785,7 @@ }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -867,6 +882,7 @@ }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" @@ -893,6 +909,7 @@ }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -920,6 +937,7 @@ }, "node_modules/@babel/plugin-transform-async-generator-functions": { "version": "7.25.0", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", @@ -951,6 +969,7 @@ }, "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -991,6 +1010,7 @@ }, "node_modules/@babel/plugin-transform-class-static-block": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", @@ -1051,6 +1071,7 @@ }, "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", @@ -1065,6 +1086,7 @@ }, "node_modules/@babel/plugin-transform-duplicate-keys": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -1078,6 +1100,7 @@ }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { "version": "7.25.0", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.0", @@ -1092,6 +1115,7 @@ }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1106,6 +1130,7 @@ }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", @@ -1120,6 +1145,7 @@ }, "node_modules/@babel/plugin-transform-export-namespace-from": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1148,6 +1174,7 @@ }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1177,6 +1204,7 @@ }, "node_modules/@babel/plugin-transform-json-strings": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1204,6 +1232,7 @@ }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1218,6 +1247,7 @@ }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -1231,6 +1261,7 @@ }, "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.24.7", @@ -1260,6 +1291,7 @@ }, "node_modules/@babel/plugin-transform-modules-systemjs": { "version": "7.25.0", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.0", @@ -1276,6 +1308,7 @@ }, "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.24.7", @@ -1304,6 +1337,7 @@ }, "node_modules/@babel/plugin-transform-new-target": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -1331,6 +1365,7 @@ }, "node_modules/@babel/plugin-transform-numeric-separator": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1345,6 +1380,7 @@ }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", @@ -1361,6 +1397,7 @@ }, "node_modules/@babel/plugin-transform-object-super": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1375,6 +1412,7 @@ }, "node_modules/@babel/plugin-transform-optional-catch-binding": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1447,6 +1485,7 @@ }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -1516,6 +1555,7 @@ }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", @@ -1530,6 +1570,7 @@ }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -1614,6 +1655,7 @@ }, "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.24.8", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" @@ -1644,6 +1686,7 @@ }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" @@ -1657,6 +1700,7 @@ }, "node_modules/@babel/plugin-transform-unicode-property-regex": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", @@ -1685,6 +1729,7 @@ }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { "version": "7.24.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", @@ -1699,6 +1744,7 @@ }, "node_modules/@babel/preset-env": { "version": "7.25.3", + "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.25.2", @@ -1809,6 +1855,7 @@ }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -4548,12 +4595,12 @@ }, "node_modules/@types/prop-types": { "version": "15.7.12", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.3", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -5628,7 +5675,7 @@ "license": "MIT" }, "node_modules/clevertap-react-native": { - "resolved": ".yalc/clevertap-react-native", + "resolved": "..", "link": true }, "node_modules/cli-cursor": { @@ -6013,18 +6060,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/css-tree": { - "version": "1.1.3", - "license": "MIT", - "peer": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/css-what": { "version": "6.1.0", "license": "BSD-2-Clause", @@ -6064,7 +6099,7 @@ }, "node_modules/csstype": { "version": "3.1.3", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/data-view-buffer": { @@ -7242,6 +7277,7 @@ }, "node_modules/esutils": { "version": "2.0.3", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -10598,11 +10634,6 @@ "version": "1.2.5", "license": "Apache-2.0" }, - "node_modules/mdn-data": { - "version": "2.0.14", - "license": "CC0-1.0", - "peer": true - }, "node_modules/memoize-one": { "version": "5.2.1", "license": "MIT" @@ -12020,20 +12051,6 @@ "react-native": "*" } }, - "node_modules/react-native-svg": { - "version": "15.5.0", - "license": "MIT", - "peer": true, - "dependencies": { - "css-select": "^5.1.0", - "css-tree": "^1.1.3", - "warn-once": "0.1.1" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, "node_modules/react-native-svg-transformer": { "version": "1.5.0", "license": "MIT", @@ -12307,6 +12324,7 @@ }, "node_modules/regenerator-transform": { "version": "0.15.2", + "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.4" @@ -13410,7 +13428,7 @@ }, "node_modules/typescript": { "version": "5.0.4", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/android/build.gradle b/android/build.gradle index 1d4067a6..8d7b409c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -35,8 +35,8 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 36 - versionCode 410 - versionName "4.1.0" + versionCode 420 + versionName "4.2.0" buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()) } @@ -54,7 +54,7 @@ android { } dependencies { - api 'com.clevertap.android:clevertap-android-sdk:8.1.0' + api 'com.clevertap.android:clevertap-android-sdk:8.3.0' implementation 'com.android.installreferrer:installreferrer:2.2' //compile 'com.android.support:appcompat-v7:28.0.0' implementation 'com.facebook.react:react-native:+' diff --git a/android/src/main/java/com/clevertap/react/CleverTapModuleImpl.java b/android/src/main/java/com/clevertap/react/CleverTapModuleImpl.java index 1768c966..61de1db4 100644 --- a/android/src/main/java/com/clevertap/react/CleverTapModuleImpl.java +++ b/android/src/main/java/com/clevertap/react/CleverTapModuleImpl.java @@ -25,6 +25,7 @@ import com.clevertap.android.sdk.events.EventDetail; import com.clevertap.android.sdk.featureFlags.CTFeatureFlagsController; import com.clevertap.android.sdk.inapp.CTLocalInApp; +import com.clevertap.android.sdk.FetchInboxCallback; import com.clevertap.android.sdk.inapp.callbacks.FetchInAppsCallback; import com.clevertap.android.sdk.inapp.customtemplates.CustomTemplateContext; import com.clevertap.android.sdk.inbox.CTInboxMessage; @@ -867,6 +868,19 @@ public void profileSetMultiValues(ReadableArray values, String key) { clevertap.setMultiValuesForKey(key, finalValues); } + public void fetchInbox(Callback callback) { + CleverTapAPI cleverTap = getCleverTapAPI(); + if (cleverTap == null) { + Log.e(TAG, ErrorMessages.CLEVERTAP_NOT_INITIALIZED); + return; + } + if (callback == null) { + cleverTap.fetchInbox(); + } else { + cleverTap.fetchInbox((FetchInboxCallback) success -> callback.invoke(null, success)); + } + } + public void pushDisplayUnitClickedEventForID(String unitID) { CleverTapAPI cleverTap = getCleverTapAPI(); if (cleverTap != null) { @@ -876,6 +890,16 @@ public void pushDisplayUnitClickedEventForID(String unitID) { } } + public void pushDisplayUnitElementClickedEventForID(String unitID, ReadableMap additionalProperties) { + CleverTapAPI cleverTap = getCleverTapAPI(); + if (cleverTap != null) { + HashMap props = eventPropsFromReadableMap(additionalProperties, Object.class); + cleverTap.pushDisplayUnitElementClickedEventForID(unitID, props); + } else { + Log.e(TAG, ErrorMessages.CLEVERTAP_NOT_INITIALIZED); + } + } + public void pushDisplayUnitViewedEventForID(String unitID) { CleverTapAPI cleverTap = getCleverTapAPI(); if (cleverTap != null) { diff --git a/android/src/newarch/CleverTapModule.kt b/android/src/newarch/CleverTapModule.kt index d9521112..b030522c 100644 --- a/android/src/newarch/CleverTapModule.kt +++ b/android/src/newarch/CleverTapModule.kt @@ -321,10 +321,18 @@ class CleverTapModule(reactContext: ReactApplicationContext?) : cleverTapModuleImpl.profileSetMultiValues(values, key) } + override fun fetchInbox(callback: Callback?) { + cleverTapModuleImpl.fetchInbox(callback) + } + override fun pushDisplayUnitClickedEventForID(unitID: String?) { cleverTapModuleImpl.pushDisplayUnitClickedEventForID(unitID) } + override fun pushDisplayUnitElementClickedEventForID(unitID: String?, additionalProperties: ReadableMap?) { + cleverTapModuleImpl.pushDisplayUnitElementClickedEventForID(unitID, additionalProperties) + } + override fun pushDisplayUnitViewedEventForID(unitID: String?) { cleverTapModuleImpl.pushDisplayUnitViewedEventForID(unitID) } diff --git a/android/src/oldarch/CleverTapModule.kt b/android/src/oldarch/CleverTapModule.kt index 1afb7165..8006e80b 100644 --- a/android/src/oldarch/CleverTapModule.kt +++ b/android/src/oldarch/CleverTapModule.kt @@ -377,11 +377,21 @@ class CleverTapModule(reactContext: ReactApplicationContext?) : cleverTapModuleImpl.profileSetMultiValues(values, key) } + @ReactMethod + fun fetchInbox(callback: Callback?) { + cleverTapModuleImpl.fetchInbox(callback) + } + @ReactMethod fun pushDisplayUnitClickedEventForID(unitID: String?) { cleverTapModuleImpl.pushDisplayUnitClickedEventForID(unitID) } + @ReactMethod + fun pushDisplayUnitElementClickedEventForID(unitID: String?, additionalProperties: ReadableMap?) { + cleverTapModuleImpl.pushDisplayUnitElementClickedEventForID(unitID, additionalProperties) + } + @ReactMethod fun pushDisplayUnitViewedEventForID(unitID: String?) { cleverTapModuleImpl.pushDisplayUnitViewedEventForID(unitID) diff --git a/clevertap-react-native.podspec b/clevertap-react-native.podspec index a978f2a8..0a57b38d 100644 --- a/clevertap-react-native.podspec +++ b/clevertap-react-native.podspec @@ -24,7 +24,7 @@ Pod::Spec.new do |s| s.dependency 'React-Core' end - s.dependency 'CleverTap-iOS-SDK', '7.6.0' + s.dependency 'CleverTap-iOS-SDK', '7.7.1' if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then s.pod_target_xcconfig = { diff --git a/docs/install.md b/docs/install.md index 9e1cb3e1..9e755348 100644 --- a/docs/install.md +++ b/docs/install.md @@ -86,7 +86,7 @@ dependencies { //clevertap - implementation 'com.clevertap.android:clevertap-android-sdk:8.1.0' + implementation 'com.clevertap.android:clevertap-android-sdk:8.3.0' // other libs diff --git a/docs/usage.md b/docs/usage.md index 372f3439..39110876 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -254,6 +254,21 @@ CleverTap.pushInboxNotificationViewedEventForId('Message Id'); CleverTap.pushInboxNotificationClickedEventForId('Message Id'); ``` +#### Fetch Inbox + +*Available from CleverTap React Native SDK v4.2.0.* + +Triggers an on-demand refresh of App Inbox messages from the server. Use this to let users pull fresh messages at a point of your choosing — for example, when they open a custom inbox screen. The optional callback receives a boolean: `true` if messages were fetched and applied to the local cache, `false` if the call was throttled, the inbox is not initialised, or the fetch failed. Calls are throttled to once every 5 minutes; a throttled call returns `false` without making a network request. + +```javascript +CleverTap.fetchInbox((err, success) => { + console.log('Inbox fetch success:', success); +}); + +// Without callback (fire-and-forget) +CleverTap.fetchInbox(); +``` + ----------- ## Push primer for notification Permission (Android and iOS) @@ -343,6 +358,20 @@ CleverTap.getAllDisplayUnits((err, res) => { }); ``` +#### Push Display Unit Element Clicked Event For ID + +*Available from CleverTap React Native SDK v4.2.0.* + +Records a `Notification Clicked` event for a specific element within a Native Display unit. Pass the unit's ID and an `additionalProperties` map that includes `wzrk_element_id` from the tapped element's metadata. The SDK merges these caller-supplied properties with cached `wzrk_*` attribution fields from the unit, enabling finer-grained click analytics beyond what `pushDisplayUnitClickedEventForID` provides. + +```javascript +CleverTap.pushDisplayUnitElementClickedEventForID('unit-id-001', { + wzrk_element_id: 'btn_cta_1', + title: 'Summer Sale', + campaign_type: 'display', +}); +``` + ----------- ## Product Config diff --git a/ios/CleverTapReact/CleverTapReact.mm b/ios/CleverTapReact/CleverTapReact.mm index 38db39d6..b277beed 100644 --- a/ios/CleverTapReact/CleverTapReact.mm +++ b/ios/CleverTapReact/CleverTapReact.mm @@ -825,6 +825,17 @@ - (void)messageDidSelect:(CleverTapInboxMessage *_Nonnull)message atIndex:(int)i [[NSNotificationCenter defaultCenter] postNotificationName:kCleverTapInboxMessageTapped object:nil userInfo:body]; } +RCT_EXPORT_METHOD(fetchInbox:(RCTResponseSenderBlock)callback) { + RCTLogInfo(@"[CleverTap fetchInbox]"); + if (callback) { + [[self cleverTapInstance] fetchInboxWithCallback:^(BOOL success) { + callback(@[[NSNull null], @(success)]); + }]; + } else { + [[self cleverTapInstance] fetchInboxWithCallback:nil]; + } +} + #pragma mark - Display Units @@ -856,6 +867,11 @@ - (void)messageDidSelect:(CleverTapInboxMessage *_Nonnull)message atIndex:(int)i [[self cleverTapInstance] recordDisplayUnitClickedEventForID:unitId]; } +RCT_EXPORT_METHOD(pushDisplayUnitElementClickedEventForID:(NSString*)unitId additionalProperties:(NSDictionary*)additionalProperties) { + RCTLogInfo(@"[CleverTap pushDisplayUnitElementClickedEventForID]"); + [[self cleverTapInstance] recordDisplayUnitElementClickedEventForID:unitId additionalProperties:additionalProperties]; +} + # pragma mark - Feature Flag diff --git a/package.json b/package.json index 957e4acd..2ff20286 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "clevertap-react-native", - "version": "4.1.0", + "version": "4.2.0", "description": "CleverTap React Native SDK.", "main": "src/index.js", "types": "src/index.d.ts", diff --git a/src/NativeCleverTapModule.ts b/src/NativeCleverTapModule.ts index 3de7ec83..9c4f299e 100644 --- a/src/NativeCleverTapModule.ts +++ b/src/NativeCleverTapModule.ts @@ -177,6 +177,8 @@ export interface Spec extends TurboModule { ): void; pushDisplayUnitViewedEventForID(unitId: string): void; pushDisplayUnitClickedEventForID(unitId: string): void; + pushDisplayUnitElementClickedEventForID(unitId: string, additionalProperties: Object | null): void; + fetchInbox(callback: ((error: Object, result: boolean) => void) | null): void; getFeatureFlag( flag: string, withdefaultValue: boolean, diff --git a/src/index.d.ts b/src/index.d.ts index 75aa3cc1..9b850cd8 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -612,9 +612,24 @@ export function isPushPermissionGranted(callback: CallbackString): void; */ export function pushDisplayUnitClickedEventForID(unitID: string): void; + /** + * Call this method to record a click on a specific element within a Native Display unit. + * The additionalProperties map should include wzrk_element_id from the element's metadata. + */ + export function pushDisplayUnitElementClickedEventForID(unitID: string, additionalProperties: object): void; + + /** + * Triggers an on-demand refresh of App Inbox messages from the server. + * The optional callback receives (err, success: boolean) when the fetch completes. + * Calls are throttled to once every 5 minutes. + * + * Available from CleverTap React Native SDK v4.2.0. + */ + export function fetchInbox(callback?: Callback): void; + /******************* * Product Configs - ******************/ + ******************/ /** * @deprecated * Since version 1.1.0 and will be removed in the future versions of this SDK. diff --git a/src/index.js b/src/index.js index d915b754..ff4b1c92 100644 --- a/src/index.js +++ b/src/index.js @@ -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 = 40100; +const libVersion = 40200; CleverTapReact.setLibrary(libName,libVersion); function defaultCallback(method, err, res) { @@ -767,6 +767,15 @@ var CleverTap = { CleverTapReact.pushInboxNotificationViewedEventForId(messageId); }, + /** + * Triggers an on-demand refresh of App Inbox messages from the server. + * Throttled to once every 5 minutes. Calls are a no-op if the inbox is not initialized. + * @param {function(err, res)} optional callback that receives (null, success: boolean) on completion + */ + fetchInbox: function (callback) { + callWithCallback('fetchInbox', null, callback); + }, + /** * Get all display units * @param {function(err, res)} callback that returns a list of json string representation of CleverTapDisplayUnit @@ -800,6 +809,15 @@ var CleverTap = { CleverTapReact.pushDisplayUnitClickedEventForID(unitID); }, + /** + * Records a Notification Clicked event for a specific element within a Display Unit. + * @param {string} unitID - unit id of display unit of type CleverTapDisplayUnit + * @param {object} additionalProperties - key-value map including wzrk_element_id from the element's metadata + */ + pushDisplayUnitElementClickedEventForID: function (unitID, additionalProperties) { + CleverTapReact.pushDisplayUnitElementClickedEventForID(unitID, additionalProperties); + }, + /** * @deprecated - Since version 1.1.0 and will be removed in the future versions of this SDK.