zixflow-reactnative 1.1.3 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/README.md +631 -261
  2. package/android/build.gradle +18 -1
  3. package/android/consumer-rules.pro +3 -2
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/java/com/zixflow/reactnative/sdk/NativeZixflowModule.kt +40 -5
  6. package/android/src/main/java/com/zixflow/reactnative/sdk/ZixflowReactNativePackage.kt +25 -1
  7. package/android/src/main/java/com/zixflow/reactnative/sdk/constant/Keys.kt +19 -0
  8. package/android/src/main/java/com/zixflow/reactnative/sdk/geofence/NativeGeofenceModule.kt +65 -0
  9. package/android/src/main/java/com/zixflow/reactnative/sdk/liveactivities/NativeLiveActivitiesModule.kt +310 -0
  10. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginapp/NativeMessagingInAppModule.kt +150 -0
  11. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginapp/ReactInboxEventListener.kt +99 -0
  12. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/NotificationInboxBellViewManager.kt +38 -0
  13. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/NotificationInboxViewManager.kt +30 -0
  14. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/ReactComposeHostView.kt +96 -0
  15. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/ReactNotificationInboxBellView.kt +48 -0
  16. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/ReactNotificationInboxView.kt +17 -0
  17. package/android/src/main/java/com/zixflow/reactnative/sdk/messagingpush/NativeMessagingPushModule.kt +11 -1
  18. package/android/src/main/res/values/zixflow_config.xml +1 -1
  19. package/android/zixflow-core.gradle +17 -7
  20. package/docs/cocoapods-deployment-target-normalization.md +139 -0
  21. package/ios/cocoapods_deployment_target.rb +432 -0
  22. package/ios/wrappers/NativeZixflow.mm +37 -0
  23. package/ios/wrappers/NativeZixflow.swift +135 -1
  24. package/ios/wrappers/ZixflowReactNativeDeepLinkRequestStore.swift +123 -0
  25. package/ios/wrappers/ZixflowReactNativeDeepLinkRouter.swift +312 -0
  26. package/ios/wrappers/geofence/NativeGeofence.mm +46 -0
  27. package/ios/wrappers/geofence/NativeGeofence.swift +27 -0
  28. package/ios/wrappers/inapp/NativeMessagingInApp.mm +22 -0
  29. package/ios/wrappers/inapp/NativeMessagingInApp.swift +90 -0
  30. package/ios/wrappers/inbox/InboxHostContainment.swift +40 -0
  31. package/ios/wrappers/inbox/RCTNotificationInboxBellNative.h +12 -0
  32. package/ios/wrappers/inbox/RCTNotificationInboxBellNative.mm +98 -0
  33. package/ios/wrappers/inbox/RCTNotificationInboxViewNative.h +12 -0
  34. package/ios/wrappers/inbox/RCTNotificationInboxViewNative.mm +78 -0
  35. package/ios/wrappers/inbox/ReactInboxEventListener.swift +76 -0
  36. package/ios/wrappers/inbox/ReactNotificationInboxBellView.h +22 -0
  37. package/ios/wrappers/inbox/ReactNotificationInboxBellView.swift +109 -0
  38. package/ios/wrappers/inbox/ReactNotificationInboxView.h +22 -0
  39. package/ios/wrappers/inbox/ReactNotificationInboxView.swift +69 -0
  40. package/ios/wrappers/liveactivities/NativeLiveActivities.mm +83 -0
  41. package/ios/wrappers/liveactivities/NativeLiveActivities.swift +390 -0
  42. package/ios/wrappers/location/NativeLocation.swift +7 -5
  43. package/ios/wrappers/utils/ZixflowConstants.swift +4 -0
  44. package/ios/wrappers/zixflow_reactnative.h +6 -0
  45. package/lib/commonjs/components/NotificationInboxBellView.js +49 -0
  46. package/lib/commonjs/components/NotificationInboxBellView.js.map +1 -0
  47. package/lib/commonjs/components/NotificationInboxView.js +36 -0
  48. package/lib/commonjs/components/NotificationInboxView.js.map +1 -0
  49. package/lib/commonjs/components/index.js +14 -0
  50. package/lib/commonjs/components/index.js.map +1 -1
  51. package/lib/commonjs/index.js +81 -4
  52. package/lib/commonjs/index.js.map +1 -1
  53. package/lib/commonjs/notification-inbox.js +1 -0
  54. package/lib/commonjs/notification-inbox.js.map +1 -1
  55. package/lib/commonjs/specs/components/NotificationInboxBellNativeComponent.ts +24 -0
  56. package/lib/commonjs/specs/components/NotificationInboxViewNativeComponent.ts +22 -0
  57. package/lib/commonjs/specs/modules/NativeZixflow.js.map +1 -1
  58. package/lib/commonjs/specs/modules/NativeZixflowGeofence.js +15 -0
  59. package/lib/commonjs/specs/modules/NativeZixflowGeofence.js.map +1 -0
  60. package/lib/commonjs/specs/modules/NativeZixflowLiveActivities.js +23 -0
  61. package/lib/commonjs/specs/modules/NativeZixflowLiveActivities.js.map +1 -0
  62. package/lib/commonjs/specs/modules/NativeZixflowMessagingInApp.js +3 -1
  63. package/lib/commonjs/specs/modules/NativeZixflowMessagingInApp.js.map +1 -1
  64. package/lib/commonjs/specs/modules/NativeZixflowMessagingPush.js +3 -1
  65. package/lib/commonjs/specs/modules/NativeZixflowMessagingPush.js.map +1 -1
  66. package/lib/commonjs/types/data-pipelines.js +13 -1
  67. package/lib/commonjs/types/data-pipelines.js.map +1 -1
  68. package/lib/commonjs/types/in-app.js +24 -1
  69. package/lib/commonjs/types/in-app.js.map +1 -1
  70. package/lib/commonjs/types/inbox.js +79 -0
  71. package/lib/commonjs/types/inbox.js.map +1 -0
  72. package/lib/commonjs/types/index.js +22 -0
  73. package/lib/commonjs/types/index.js.map +1 -1
  74. package/lib/commonjs/types/live-activities.js +85 -0
  75. package/lib/commonjs/types/live-activities.js.map +1 -0
  76. package/lib/commonjs/utils/param-validation.js +76 -1
  77. package/lib/commonjs/utils/param-validation.js.map +1 -1
  78. package/lib/commonjs/zixflow-cdp.js +99 -1
  79. package/lib/commonjs/zixflow-cdp.js.map +1 -1
  80. package/lib/commonjs/zixflow-geofence.js +55 -0
  81. package/lib/commonjs/zixflow-geofence.js.map +1 -0
  82. package/lib/commonjs/zixflow-inapp.js +120 -0
  83. package/lib/commonjs/zixflow-inapp.js.map +1 -1
  84. package/lib/commonjs/zixflow-liveactivities.js +85 -0
  85. package/lib/commonjs/zixflow-liveactivities.js.map +1 -0
  86. package/lib/module/components/NotificationInboxBellView.js +44 -0
  87. package/lib/module/components/NotificationInboxBellView.js.map +1 -0
  88. package/lib/module/components/NotificationInboxView.js +31 -0
  89. package/lib/module/components/NotificationInboxView.js.map +1 -0
  90. package/lib/module/components/index.js +5 -0
  91. package/lib/module/components/index.js.map +1 -1
  92. package/lib/module/index.js +8 -3
  93. package/lib/module/index.js.map +1 -1
  94. package/lib/module/notification-inbox.js +1 -1
  95. package/lib/module/notification-inbox.js.map +1 -1
  96. package/lib/module/specs/components/NotificationInboxBellNativeComponent.ts +24 -0
  97. package/lib/module/specs/components/NotificationInboxViewNativeComponent.ts +22 -0
  98. package/lib/module/specs/modules/NativeZixflow.js.map +1 -1
  99. package/lib/module/specs/modules/NativeZixflowGeofence.js +13 -0
  100. package/lib/module/specs/modules/NativeZixflowGeofence.js.map +1 -0
  101. package/lib/module/specs/modules/NativeZixflowLiveActivities.js +21 -0
  102. package/lib/module/specs/modules/NativeZixflowLiveActivities.js.map +1 -0
  103. package/lib/module/specs/modules/NativeZixflowMessagingInApp.js +3 -1
  104. package/lib/module/specs/modules/NativeZixflowMessagingInApp.js.map +1 -1
  105. package/lib/module/specs/modules/NativeZixflowMessagingPush.js +3 -1
  106. package/lib/module/specs/modules/NativeZixflowMessagingPush.js.map +1 -1
  107. package/lib/module/types/data-pipelines.js +13 -0
  108. package/lib/module/types/data-pipelines.js.map +1 -1
  109. package/lib/module/types/in-app.js +24 -0
  110. package/lib/module/types/in-app.js.map +1 -1
  111. package/lib/module/types/inbox.js +75 -0
  112. package/lib/module/types/inbox.js.map +1 -0
  113. package/lib/module/types/index.js +2 -0
  114. package/lib/module/types/index.js.map +1 -1
  115. package/lib/module/types/live-activities.js +88 -0
  116. package/lib/module/types/live-activities.js.map +1 -0
  117. package/lib/module/utils/param-validation.js +76 -1
  118. package/lib/module/utils/param-validation.js.map +1 -1
  119. package/lib/module/zixflow-cdp.js +99 -1
  120. package/lib/module/zixflow-cdp.js.map +1 -1
  121. package/lib/module/zixflow-geofence.js +50 -0
  122. package/lib/module/zixflow-geofence.js.map +1 -0
  123. package/lib/module/zixflow-inapp.js +99 -1
  124. package/lib/module/zixflow-inapp.js.map +1 -1
  125. package/lib/module/zixflow-liveactivities.js +80 -0
  126. package/lib/module/zixflow-liveactivities.js.map +1 -0
  127. package/lib/typescript/commonjs/components/NotificationInboxBellView.d.ts +39 -0
  128. package/lib/typescript/commonjs/components/NotificationInboxBellView.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/components/NotificationInboxView.d.ts +25 -0
  130. package/lib/typescript/commonjs/components/NotificationInboxView.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/components/index.d.ts +4 -0
  132. package/lib/typescript/commonjs/components/index.d.ts.map +1 -1
  133. package/lib/typescript/commonjs/index.d.ts +8 -1
  134. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  135. package/lib/typescript/commonjs/notification-inbox.d.ts +5 -0
  136. package/lib/typescript/commonjs/notification-inbox.d.ts.map +1 -1
  137. package/lib/typescript/commonjs/specs/components/NotificationInboxBellNativeComponent.d.ts +13 -0
  138. package/lib/typescript/commonjs/specs/components/NotificationInboxBellNativeComponent.d.ts.map +1 -0
  139. package/lib/typescript/commonjs/specs/components/NotificationInboxViewNativeComponent.d.ts +12 -0
  140. package/lib/typescript/commonjs/specs/components/NotificationInboxViewNativeComponent.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/specs/modules/NativeZixflow.d.ts +6 -1
  142. package/lib/typescript/commonjs/specs/modules/NativeZixflow.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/specs/modules/NativeZixflowGeofence.d.ts +13 -0
  144. package/lib/typescript/commonjs/specs/modules/NativeZixflowGeofence.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/specs/modules/NativeZixflowLiveActivities.d.ts +31 -0
  146. package/lib/typescript/commonjs/specs/modules/NativeZixflowLiveActivities.d.ts.map +1 -0
  147. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingInApp.d.ts +5 -1
  148. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingInApp.d.ts.map +1 -1
  149. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingPush.d.ts +1 -1
  150. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingPush.d.ts.map +1 -1
  151. package/lib/typescript/commonjs/types/data-pipelines.d.ts +53 -1
  152. package/lib/typescript/commonjs/types/data-pipelines.d.ts.map +1 -1
  153. package/lib/typescript/commonjs/types/in-app.d.ts +22 -0
  154. package/lib/typescript/commonjs/types/in-app.d.ts.map +1 -1
  155. package/lib/typescript/commonjs/types/inbox.d.ts +97 -0
  156. package/lib/typescript/commonjs/types/inbox.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/types/index.d.ts +2 -0
  158. package/lib/typescript/commonjs/types/index.d.ts.map +1 -1
  159. package/lib/typescript/commonjs/types/live-activities.d.ts +161 -0
  160. package/lib/typescript/commonjs/types/live-activities.d.ts.map +1 -0
  161. package/lib/typescript/commonjs/utils/param-validation.d.ts +7 -0
  162. package/lib/typescript/commonjs/utils/param-validation.d.ts.map +1 -1
  163. package/lib/typescript/commonjs/zixflow-cdp.d.ts +38 -0
  164. package/lib/typescript/commonjs/zixflow-cdp.d.ts.map +1 -1
  165. package/lib/typescript/commonjs/zixflow-geofence.d.ts +36 -0
  166. package/lib/typescript/commonjs/zixflow-geofence.d.ts.map +1 -0
  167. package/lib/typescript/commonjs/zixflow-inapp.d.ts +36 -2
  168. package/lib/typescript/commonjs/zixflow-inapp.d.ts.map +1 -1
  169. package/lib/typescript/commonjs/zixflow-liveactivities.d.ts +66 -0
  170. package/lib/typescript/commonjs/zixflow-liveactivities.d.ts.map +1 -0
  171. package/lib/typescript/module/components/NotificationInboxBellView.d.ts +39 -0
  172. package/lib/typescript/module/components/NotificationInboxBellView.d.ts.map +1 -0
  173. package/lib/typescript/module/components/NotificationInboxView.d.ts +25 -0
  174. package/lib/typescript/module/components/NotificationInboxView.d.ts.map +1 -0
  175. package/lib/typescript/module/components/index.d.ts +4 -0
  176. package/lib/typescript/module/components/index.d.ts.map +1 -1
  177. package/lib/typescript/module/index.d.ts +8 -1
  178. package/lib/typescript/module/index.d.ts.map +1 -1
  179. package/lib/typescript/module/notification-inbox.d.ts +5 -0
  180. package/lib/typescript/module/notification-inbox.d.ts.map +1 -1
  181. package/lib/typescript/module/specs/components/NotificationInboxBellNativeComponent.d.ts +13 -0
  182. package/lib/typescript/module/specs/components/NotificationInboxBellNativeComponent.d.ts.map +1 -0
  183. package/lib/typescript/module/specs/components/NotificationInboxViewNativeComponent.d.ts +12 -0
  184. package/lib/typescript/module/specs/components/NotificationInboxViewNativeComponent.d.ts.map +1 -0
  185. package/lib/typescript/module/specs/modules/NativeZixflow.d.ts +6 -1
  186. package/lib/typescript/module/specs/modules/NativeZixflow.d.ts.map +1 -1
  187. package/lib/typescript/module/specs/modules/NativeZixflowGeofence.d.ts +13 -0
  188. package/lib/typescript/module/specs/modules/NativeZixflowGeofence.d.ts.map +1 -0
  189. package/lib/typescript/module/specs/modules/NativeZixflowLiveActivities.d.ts +31 -0
  190. package/lib/typescript/module/specs/modules/NativeZixflowLiveActivities.d.ts.map +1 -0
  191. package/lib/typescript/module/specs/modules/NativeZixflowMessagingInApp.d.ts +5 -1
  192. package/lib/typescript/module/specs/modules/NativeZixflowMessagingInApp.d.ts.map +1 -1
  193. package/lib/typescript/module/specs/modules/NativeZixflowMessagingPush.d.ts +1 -1
  194. package/lib/typescript/module/specs/modules/NativeZixflowMessagingPush.d.ts.map +1 -1
  195. package/lib/typescript/module/types/data-pipelines.d.ts +53 -1
  196. package/lib/typescript/module/types/data-pipelines.d.ts.map +1 -1
  197. package/lib/typescript/module/types/in-app.d.ts +22 -0
  198. package/lib/typescript/module/types/in-app.d.ts.map +1 -1
  199. package/lib/typescript/module/types/inbox.d.ts +97 -0
  200. package/lib/typescript/module/types/inbox.d.ts.map +1 -0
  201. package/lib/typescript/module/types/index.d.ts +2 -0
  202. package/lib/typescript/module/types/index.d.ts.map +1 -1
  203. package/lib/typescript/module/types/live-activities.d.ts +161 -0
  204. package/lib/typescript/module/types/live-activities.d.ts.map +1 -0
  205. package/lib/typescript/module/utils/param-validation.d.ts +7 -0
  206. package/lib/typescript/module/utils/param-validation.d.ts.map +1 -1
  207. package/lib/typescript/module/zixflow-cdp.d.ts +38 -0
  208. package/lib/typescript/module/zixflow-cdp.d.ts.map +1 -1
  209. package/lib/typescript/module/zixflow-geofence.d.ts +36 -0
  210. package/lib/typescript/module/zixflow-geofence.d.ts.map +1 -0
  211. package/lib/typescript/module/zixflow-inapp.d.ts +36 -2
  212. package/lib/typescript/module/zixflow-inapp.d.ts.map +1 -1
  213. package/lib/typescript/module/zixflow-liveactivities.d.ts +66 -0
  214. package/lib/typescript/module/zixflow-liveactivities.d.ts.map +1 -0
  215. package/package.json +11 -2
  216. package/src/components/NotificationInboxBellView.tsx +55 -0
  217. package/src/components/NotificationInboxView.tsx +30 -0
  218. package/src/components/index.ts +6 -0
  219. package/src/index.ts +8 -3
  220. package/src/notification-inbox.ts +1 -1
  221. package/src/specs/components/NotificationInboxBellNativeComponent.ts +24 -0
  222. package/src/specs/components/NotificationInboxViewNativeComponent.ts +22 -0
  223. package/src/specs/modules/NativeZixflow.ts +9 -1
  224. package/src/specs/modules/NativeZixflowGeofence.ts +14 -0
  225. package/src/specs/modules/NativeZixflowLiveActivities.ts +39 -0
  226. package/src/specs/modules/NativeZixflowMessagingInApp.ts +12 -1
  227. package/src/specs/modules/NativeZixflowMessagingPush.ts +3 -1
  228. package/src/types/data-pipelines.ts +54 -1
  229. package/src/types/in-app.ts +23 -0
  230. package/src/types/inbox.ts +110 -0
  231. package/src/types/index.ts +2 -0
  232. package/src/types/live-activities.ts +170 -0
  233. package/src/utils/param-validation.ts +103 -0
  234. package/src/zixflow-cdp.ts +117 -1
  235. package/src/zixflow-geofence.ts +56 -0
  236. package/src/zixflow-inapp.ts +125 -2
  237. package/src/zixflow-liveactivities.ts +86 -0
  238. package/zixflow-reactnative-richpush.podspec +4 -1
  239. package/zixflow-reactnative.podspec +26 -0
package/README.md CHANGED
@@ -33,25 +33,17 @@ Welcome to the **Zixflow React Native SDK** integration guide. This comprehensiv
33
33
  - [Requesting Permission](#requesting-permission)
34
34
  - [Handling Push Notifications](#handling-push-notifications)
35
35
  - [Device Token Registration](#device-token-registration)
36
- 9. [In-App Messaging](#in-app-messaging)
37
- - [Event Listeners](#event-listeners)
38
- - [Message Events](#message-events)
39
- - [Dismissing Messages](#dismissing-messages)
36
+ 9. [Push Notification Tracking](#push-notification-tracking)
40
37
  10. [Location Tracking](#location-tracking)
41
- 11. [Advanced Configuration](#advanced-configuration)
42
- - [Region Settings](#region-settings)
38
+ 11. [Geofence Tracking](#geofence-tracking)
39
+ 12. [Live Activities](#-live-activities)
40
+ 13. [Notification Inbox](#notification-inbox)
41
+ 14. [Advanced Configuration](#advanced-configuration)
43
42
  - [Log Levels](#log-levels)
44
43
  - [Auto-Tracking Options](#auto-tracking-options)
45
44
  - [Custom API Hosts](#custom-api-hosts)
46
- 12. [Troubleshooting](#troubleshooting)
47
- - [Installation Issues](#installation-issues)
48
- - [iOS Build Errors](#ios-build-errors)
49
- - [Android Build Errors](#android-build-errors)
50
- - [Push Notification Issues](#push-notification-issues)
51
- - [In-App Message Issues](#in-app-message-issues)
52
- 13. [Example Applications](#example-applications)
53
- 14. [API Reference](#api-reference)
54
- 15. [Support & Resources](#support--resources)
45
+ 15. [Example Applications](#example-applications)
46
+ 16. [API Reference](#api-reference)
55
47
 
56
48
  ---
57
49
 
@@ -98,6 +90,10 @@ The SDK is built on top of the native Zixflow iOS and Android SDKs, providing a
98
90
 
99
91
  ## Installation
100
92
 
93
+ The Zixflow React Native SDK is available on **npm**. You can browse the package here:
94
+
95
+ **[npm - zixflow-reactnative](https://www.npmjs.com/package/zixflow-reactnative)**
96
+
101
97
  ### npm Installation
102
98
 
103
99
  Install the SDK using npm:
@@ -199,7 +195,6 @@ target 'NotificationServiceExtension' do
199
195
  pod "ZixflowMessagingPush", "~> 1.0"
200
196
  pod "ZixflowDataPipelines", "~> 1.0"
201
197
  pod "ZixflowCommon", "~> 1.0"
202
- pod "ZixflowTrackingMigration", "~> 1.0"
203
198
  pod "AnalyticsSwiftZixflow", "1.7.3+zixflow.1"
204
199
  end
205
200
  ```
@@ -533,6 +528,8 @@ const handleLogout = async () => {
533
528
 
534
529
  Complete guide to implementing push notifications in React Native with Zixflow using Apple Push Notifications (APNs) or Firebase Cloud Messaging (FCM).
535
530
 
531
+ > ** Track your campaigns:** The SDK automatically tracks delivery, opens, and clicks. For advanced tracking customization and implementation details, see [Push Notification Tracking](#push-notification-tracking).
532
+
536
533
  ### Prerequisites
537
534
 
538
535
  Before implementing push notifications:
@@ -1102,8 +1099,7 @@ const handleLogin = async (userId: string, userEmail: string) => {
1102
1099
  **Important Notes:**
1103
1100
  - When users start the app, they automatically generate a device token
1104
1101
  - This token links to their Zixflow profile when you call `identify()`
1105
- - Device tokens are automatically removed from previous profiles when identifying new users
1106
- - This prevents duplicate notifications when users switch accounts
1102
+ - This ensures notifications are delivered to the correct user
1107
1103
 
1108
1104
  #### Step 5: Get Device Token
1109
1105
 
@@ -1430,94 +1426,418 @@ Zixflow.initialize(config);
1430
1426
 
1431
1427
  ---
1432
1428
 
1433
- ### Next Steps
1429
+ ---
1430
+
1431
+ ## Push Notification Tracking
1432
+
1433
+ ### Overview
1434
+
1435
+ Zixflow automatically tracks push notification delivery and engagement metrics to help you measure campaign performance. The SDK tracks three key lifecycle events:
1436
+
1437
+ 1. **Delivery Confirmed** - When the notification arrives on the device
1438
+ 2. **Notification Opened** - When the user taps the notification
1439
+ 3. **Action Button Clicked** - When the user taps an action button
1440
+
1441
+ ### How Push Tracking Works
1442
+
1443
+ When Zixflow sends a push notification, it includes special tracking fields in the data payload:
1444
+
1445
+ | Field | Purpose |
1446
+ |-------|---------|
1447
+ | `Zixflow-Delivery-ID` | Unique ID for this delivery (links to campaign record) |
1448
+ | `Zixflow-Delivery-Token` | The FCM/APNs token the notification was sent to |
1434
1449
 
1435
- - Learn about [In-App Messaging](#in-app-messaging)
1436
- - Explore [Deep Link Handling](#deep-links-and-navigation)
1437
- - See [Example Applications](#example-applications) for complete implementations
1450
+ **Example push payload:**
1451
+ ```json
1452
+ {
1453
+ "Zixflow-Delivery-ID": "626533406292836846",
1454
+ "Zixflow-Delivery-Token": "dcFRlDhiRbehM1vg...",
1455
+ "title": "Flash Sale! 70% OFF",
1456
+ "body": "Limited time only — grab your deal now!",
1457
+ "deeplink_url": "https://yourapp.com/sale",
1458
+ "image_url": "https://cdn.yourapp.com/banner.png",
1459
+ "action_buttons": "[{\"name\":\"Shop Now\",\"deeplink\":\"https://yourapp.com/sale\"},{\"name\":\"Remind Me\",\"deeplink\":\"\"}]"
1460
+ }
1461
+ ```
1462
+
1463
+ > **Note:** The SDK automatically handles most tracking for you when using the default push implementation. This section covers advanced customization scenarios.
1438
1464
 
1439
1465
  ---
1440
1466
 
1441
- ## In-App Messaging
1467
+ ### Tracking Events
1468
+
1469
+ #### 1. Delivery Confirmed
1442
1470
 
1443
- ### Event Listeners
1471
+ **When to track:** The moment the push payload arrives on the device
1444
1472
 
1445
- Register event listeners to respond to in-app message events:
1473
+ **SDK method:** `Zixflow.trackMetric({ deliveryID, deviceToken, event: MetricEvent.delivered })`
1474
+
1475
+ **Implementation:**
1446
1476
 
1447
1477
  ```typescript
1448
- import { Zixflow, InAppMessageEvent, InAppMessageEventType } from 'zixflow-reactnative';
1449
- import { useEffect } from 'react';
1478
+ import messaging from '@react-native-firebase/messaging';
1479
+ import { Zixflow, MetricEvent } from 'zixflow-reactnative';
1450
1480
 
1451
- export default function App() {
1452
- useEffect(() => {
1453
- const inAppMessaging = Zixflow.inAppMessaging;
1481
+ // Listen for foreground messages
1482
+ useEffect(() => {
1483
+ const unsubscribe = messaging().onMessage(async (remoteMessage) => {
1484
+ const deliveryId = remoteMessage.data?.['Zixflow-Delivery-ID'] ?? '';
1485
+ const deliveryToken = remoteMessage.data?.['Zixflow-Delivery-Token'] ?? cachedToken ?? '';
1486
+
1487
+ if (deliveryId && deliveryToken) {
1488
+ await Zixflow.trackMetric({
1489
+ deliveryID: deliveryId,
1490
+ deviceToken: deliveryToken,
1491
+ event: MetricEvent.delivered,
1492
+ });
1493
+ }
1494
+ });
1454
1495
 
1455
- const eventListener = inAppMessaging.registerEventsListener((event: InAppMessageEvent) => {
1456
- switch (event.eventType) {
1457
- case InAppMessageEventType.messageShown:
1458
- console.log('In-app message shown', event);
1459
- break;
1496
+ return unsubscribe;
1497
+ }, []);
1498
+ ```
1460
1499
 
1461
- case InAppMessageEventType.messageDismissed:
1462
- console.log('In-app message dismissed', event);
1463
- break;
1500
+ > **Important:** The Zixflow SDK automatically tracks delivery. Manual tracking is only needed for custom implementations.
1464
1501
 
1465
- case InAppMessageEventType.messageActionTaken:
1466
- console.log('Action taken on in-app message', event);
1467
- handleMessageAction(event);
1468
- break;
1502
+ ---
1469
1503
 
1470
- case InAppMessageEventType.errorWithMessage:
1471
- console.error('Error with in-app message', event);
1472
- break;
1504
+ #### 2. Notification Opened
1505
+
1506
+ **When to track:** When the user taps the notification banner
1507
+
1508
+ **SDK method:** `Zixflow.trackMetric({ deliveryID, deviceToken, event: MetricEvent.opened })`
1509
+
1510
+ **Implementation:**
1511
+
1512
+ ```typescript
1513
+ import messaging from '@react-native-firebase/messaging';
1514
+ import { Zixflow, MetricEvent } from 'zixflow-reactnative';
1515
+
1516
+ // Background / quit tap
1517
+ useEffect(() => {
1518
+ const unsubscribe = messaging().onNotificationOpenedApp(async (remoteMessage) => {
1519
+ trackOpened(remoteMessage.data);
1520
+ handleDeeplink(remoteMessage.data?.deeplink_url);
1521
+ });
1522
+
1523
+ return unsubscribe;
1524
+ }, []);
1525
+
1526
+ // Terminated tap
1527
+ useEffect(() => {
1528
+ messaging()
1529
+ .getInitialNotification()
1530
+ .then((remoteMessage) => {
1531
+ if (remoteMessage) {
1532
+ trackOpened(remoteMessage.data);
1533
+ handleDeeplink(remoteMessage.data?.deeplink_url);
1473
1534
  }
1474
1535
  });
1536
+ }, []);
1475
1537
 
1476
- // Cleanup listener on unmount
1477
- return () => {
1478
- eventListener.remove();
1479
- };
1538
+ const trackOpened = async (data: any) => {
1539
+ const deliveryId = data?.['Zixflow-Delivery-ID'] ?? '';
1540
+ const deliveryToken = data?.['Zixflow-Delivery-Token'] ?? cachedToken ?? '';
1541
+
1542
+ if (deliveryId && deliveryToken) {
1543
+ await Zixflow.trackMetric({
1544
+ deliveryID: deliveryId,
1545
+ deviceToken: deliveryToken,
1546
+ event: MetricEvent.opened,
1547
+ });
1548
+ }
1549
+ };
1550
+ ```
1551
+
1552
+ > **Note:** The SDK automatically tracks opens when using the default push implementation.
1553
+
1554
+ ---
1555
+
1556
+ #### 3. Action Button Clicked
1557
+
1558
+ **When to track:** When the user taps a named action button
1559
+
1560
+ **SDK method:** `Zixflow.track({ name: "Push Notification Action Clicked", properties: {...} })`
1561
+
1562
+ **Implementation:**
1563
+
1564
+ ```typescript
1565
+ import { Zixflow, MetricEvent } from 'zixflow-reactnative';
1566
+
1567
+ // Handle action press from local notification
1568
+ const handleActionPress = async (data: any, actionId: string) => {
1569
+ const deliveryId = data['Zixflow-Delivery-ID'] ?? '';
1570
+ const token = data['Zixflow-Delivery-Token'] ?? '';
1571
+ const actionIndex = parseInt(actionId.replace(/\D/g, ''), 10);
1572
+ const buttons = parseButtons(data['action_buttons']);
1573
+ const actionName = buttons[actionIndex]?.name ?? `Action ${actionIndex + 1}`;
1574
+ const actionDeeplink = buttons[actionIndex]?.deeplink ?? '';
1575
+
1576
+ // Always fire opened first
1577
+ await Zixflow.trackMetric({
1578
+ deliveryID: deliveryId,
1579
+ deviceToken: token,
1580
+ event: MetricEvent.opened,
1581
+ });
1582
+
1583
+ // Then fire action clicked
1584
+ await Zixflow.track({
1585
+ name: 'Push Notification Action Clicked',
1586
+ properties: {
1587
+ 'Zixflow-Delivery-ID': deliveryId,
1588
+ 'Zixflow-Delivery-Token': token,
1589
+ 'action_index': actionIndex,
1590
+ 'action_name': actionName,
1591
+ 'action_deeplink': actionDeeplink,
1592
+ },
1593
+ });
1594
+ };
1595
+
1596
+ const parseButtons = (raw: any) => {
1597
+ if (!raw) return [];
1598
+ try {
1599
+ return typeof raw === 'string' ? JSON.parse(raw) : raw;
1600
+ } catch {
1601
+ return [];
1602
+ }
1603
+ };
1604
+ ```
1605
+
1606
+ **Action button properties:**
1607
+
1608
+ | Property | Type | Required | Description |
1609
+ |----------|------|----------|-------------|
1610
+ | `Zixflow-Delivery-ID` | string | ✅ | Links event to campaign delivery |
1611
+ | `action_index` | integer | ✅ | 0-based index of button tapped |
1612
+ | `action_name` | string | ✅ | Button label (e.g., "Shop Now") |
1613
+ | `Zixflow-Delivery-Token` | string | Recommended | FCM/APNs token |
1614
+ | `action_deeplink` | string | Recommended | Button's URL |
1615
+
1616
+ ---
1617
+
1618
+ ### Action Buttons Format
1619
+
1620
+ The `action_buttons` field is a JSON-encoded string containing button definitions:
1621
+
1622
+ **Raw payload value:**
1623
+ ```
1624
+ "[{\"name\":\"Shop Now\",\"deeplink\":\"https://yourapp.com/sale\"},{\"name\":\"Remind Me\",\"deeplink\":\"\"}]"
1625
+ ```
1626
+
1627
+ **Parsed structure:**
1628
+ ```json
1629
+ [
1630
+ { "name": "Shop Now", "deeplink": "https://yourapp.com/sale" },
1631
+ { "name": "Remind Me", "deeplink": "" }
1632
+ ]
1633
+ ```
1634
+
1635
+ **Parsing example:**
1636
+
1637
+ ```typescript
1638
+ const parseActionButtons = (raw: any): Array<{ name: string; deeplink: string }> => {
1639
+ if (!raw) return [];
1640
+
1641
+ try {
1642
+ const decoded = typeof raw === 'string' ? JSON.parse(raw) : raw;
1643
+ return Array.isArray(decoded) ? decoded : [];
1644
+ } catch (error) {
1645
+ console.error('Error parsing action buttons:', error);
1646
+ return [];
1647
+ }
1648
+ };
1649
+
1650
+ // Usage
1651
+ const buttons = parseActionButtons(remoteMessage.data?.action_buttons);
1652
+ buttons.forEach((btn, index) => {
1653
+ console.log(`Button ${index}: ${btn.name} -> ${btn.deeplink}`);
1654
+ });
1655
+ ```
1656
+
1657
+ **Rules:**
1658
+ - Maximum 2 buttons per notification (recommended for consistency across platforms)
1659
+ - `deeplink` may be empty — handle gracefully
1660
+ - Button index is 0-based (first button = index 0)
1661
+
1662
+ ---
1663
+
1664
+ ### Complete Push Tracking Implementation
1665
+
1666
+ Here's a complete example integrating all tracking events:
1667
+
1668
+ ```typescript
1669
+ import React, { useEffect, useState } from 'react';
1670
+ import messaging, { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
1671
+ import { Zixflow, MetricEvent } from 'zixflow-reactnative';
1672
+
1673
+ const App = () => {
1674
+ const [fcmToken, setFcmToken] = useState<string | null>(null);
1675
+
1676
+ useEffect(() => {
1677
+ setupPushNotifications();
1480
1678
  }, []);
1481
1679
 
1680
+ const setupPushNotifications = async () => {
1681
+ // Request permission
1682
+ const authStatus = await messaging().requestPermission();
1683
+ const enabled =
1684
+ authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
1685
+ authStatus === messaging.AuthorizationStatus.PROVISIONAL;
1686
+
1687
+ if (enabled) {
1688
+ // Get FCM token
1689
+ const token = await messaging().getToken();
1690
+ setFcmToken(token);
1691
+
1692
+ // Register with Zixflow
1693
+ await Zixflow.registerDeviceToken({ deviceToken: token });
1694
+
1695
+ // Listen for token refresh
1696
+ messaging().onTokenRefresh(async (newToken) => {
1697
+ setFcmToken(newToken);
1698
+ await Zixflow.registerDeviceToken({ deviceToken: newToken });
1699
+ });
1700
+
1701
+ // Handle foreground messages
1702
+ messaging().onMessage(async (remoteMessage) => {
1703
+ trackDelivery(remoteMessage);
1704
+ showLocalNotification(remoteMessage);
1705
+ });
1706
+
1707
+ // Handle background/quit taps
1708
+ messaging().onNotificationOpenedApp((remoteMessage) => {
1709
+ trackOpened(remoteMessage.data);
1710
+ handleDeeplink(remoteMessage.data?.deeplink_url);
1711
+ });
1712
+
1713
+ // Handle terminated tap
1714
+ const initialNotification = await messaging().getInitialNotification();
1715
+ if (initialNotification) {
1716
+ trackOpened(initialNotification.data);
1717
+ handleDeeplink(initialNotification.data?.deeplink_url);
1718
+ }
1719
+ }
1720
+ };
1721
+
1722
+ const trackDelivery = async (message: FirebaseMessagingTypes.RemoteMessage) => {
1723
+ const deliveryId = message.data?.['Zixflow-Delivery-ID'] ?? '';
1724
+ const deliveryToken = message.data?.['Zixflow-Delivery-Token'] ?? fcmToken ?? '';
1725
+
1726
+ if (deliveryId && deliveryToken) {
1727
+ await Zixflow.trackMetric({
1728
+ deliveryID: deliveryId,
1729
+ deviceToken: deliveryToken,
1730
+ event: MetricEvent.delivered,
1731
+ });
1732
+ }
1733
+ };
1734
+
1735
+ const trackOpened = async (data: any) => {
1736
+ const deliveryId = data?.['Zixflow-Delivery-ID'] ?? '';
1737
+ const deliveryToken = data?.['Zixflow-Delivery-Token'] ?? fcmToken ?? '';
1738
+
1739
+ if (deliveryId && deliveryToken) {
1740
+ await Zixflow.trackMetric({
1741
+ deliveryID: deliveryId,
1742
+ deviceToken: deliveryToken,
1743
+ event: MetricEvent.opened,
1744
+ });
1745
+ }
1746
+ };
1747
+
1748
+ const handleDeeplink = (url?: string) => {
1749
+ if (!url) return;
1750
+ // Implement your deep link navigation logic
1751
+ console.log('Navigating to:', url);
1752
+ };
1753
+
1754
+ const showLocalNotification = async (message: FirebaseMessagingTypes.RemoteMessage) => {
1755
+ // Use local notification library to show notification
1756
+ };
1757
+
1482
1758
  return (
1483
1759
  // Your app UI
1760
+ <></>
1484
1761
  );
1485
- }
1762
+ };
1763
+
1764
+ export default App;
1486
1765
  ```
1487
1766
 
1488
- ### Message Events
1767
+ ---
1768
+
1769
+ ### Tracking Decision Flowchart
1489
1770
 
1490
- The SDK provides the following in-app message event types:
1771
+ ```
1772
+ Notification received?
1773
+ ├── YES → trackMetric(delivered) [automatic with SDK]
1774
+ │
1775
+ User interacted?
1776
+ ├── Tapped notification body
1777
+ │ └── trackMetric(opened) [automatic with SDK]
1778
+ │ └── Navigate to deeplink_url
1779
+ │
1780
+ └── Tapped action button
1781
+ ├── trackMetric(opened) [automatic with SDK]
1782
+ └── track("Push Notification Action Clicked")
1783
+ └── Navigate to button's deeplink
1784
+ ```
1491
1785
 
1492
- | Event Type | Description |
1493
- |------------|-------------|
1494
- | `messageShown` | Message was displayed to the user |
1495
- | `messageDismissed` | Message was dismissed by the user |
1496
- | `messageActionTaken` | User took an action on the message (clicked button, link, etc.) |
1497
- | `errorWithMessage` | Error occurred while displaying the message |
1786
+ ---
1498
1787
 
1499
- **Event properties**:
1500
- - `eventType`: The type of event
1501
- - `deliveryId`: Unique delivery identifier
1502
- - `messageId`: Message template identifier
1503
- - `actionName`: Name of the action taken (for `messageActionTaken`)
1504
- - `actionValue`: Value of the action (for `messageActionTaken`)
1788
+ ### Fallback for Non-Zixflow Push
1505
1789
 
1506
- ### Dismissing Messages
1790
+ If a push notification doesn't contain `Zixflow-Delivery-ID` (sent from another source), the SDK automatically skips tracking.
1507
1791
 
1508
- Programmatically dismiss the current in-app message:
1792
+ For custom analytics on non-Zixflow pushes, use a different event name:
1509
1793
 
1510
1794
  ```typescript
1511
- import { Zixflow } from 'zixflow-reactnative';
1795
+ // Don't use reserved push event names for non-Zixflow pushes
1796
+ await Zixflow.track({
1797
+ name: 'External Push Received',
1798
+ properties: {
1799
+ 'notification_id': message.messageId ?? '',
1800
+ 'title': message.notification?.title ?? '',
1801
+ 'body': message.notification?.body ?? '',
1802
+ 'source': 'external',
1803
+ },
1804
+ });
1805
+ ```
1512
1806
 
1513
- const handleMessageAction = (event: InAppMessageEvent) => {
1514
- if (event.actionValue === 'dismiss' || event.actionValue === 'close') {
1515
- // Dismiss the message
1516
- Zixflow.inAppMessaging.dismissMessage();
1517
- }
1807
+ > **Important:** Push notification event names (`Push Notification Delivered`, `Push Notification Opened`, `Push Notification Action Clicked`) are reserved for Zixflow's delivery pipeline.
1808
+
1809
+ ---
1810
+
1811
+ ### Testing Push Tracking
1812
+
1813
+ #### Verify Tracking Events
1814
+
1815
+ Enable debug logging to see tracking events:
1816
+
1817
+ ```typescript
1818
+ const config: ZixflowConfig = {
1819
+ apiKey: 'YOUR_API_KEY',
1820
+ logLevel: 'debug',
1518
1821
  };
1822
+
1823
+ await Zixflow.setup(config);
1519
1824
  ```
1520
1825
 
1826
+ Look for these log messages:
1827
+ - `[Zixflow] Push Notification Delivered tracked`
1828
+ - `[Zixflow] Push Notification Opened tracked`
1829
+ - `[Zixflow] Push Notification Action Clicked tracked`
1830
+
1831
+ #### Check Campaign Analytics
1832
+
1833
+ 1. Log into Zixflow dashboard
1834
+ 2. Navigate to **Messaging** → **Push Notifications**
1835
+ 3. View campaign metrics:
1836
+ - **Sent** - Total notifications sent
1837
+ - **Delivered** - Arrived on device
1838
+ - **Opened** - User tapped notification
1839
+ - **Clicked** - User tapped action button
1840
+
1521
1841
  ---
1522
1842
 
1523
1843
  ## Location Tracking
@@ -1561,249 +1881,334 @@ const requestLocationPermission = async () => {
1561
1881
  };
1562
1882
  ```
1563
1883
 
1564
- ---
1565
-
1566
- ## Advanced Configuration
1884
+ On iOS, a React Native 0.88+ `UIScene` host using the acknowledged handler must declare that ownership before React Native starts. This API is not used on Android or by AppDelegate-only hosts. Call this first in `scene(_:willConnectTo:options:)` so cold destinations wait for the JavaScript handler instead of entering the legacy `Linking` path:
1567
1885
 
1568
- ### Region Settings
1886
+ ```swift
1887
+ NativeZixflow.configureAcknowledgedSceneDeepLinkRouting()
1888
+ ```
1569
1889
 
1570
- Configure the data center region for data residency:
1890
+ Register the app's Zixflow deep-link handler before calling `Zixflow.initialize`. Return
1891
+ `true` after routing a URL. Return `false` to let the native SDK try the host AppDelegate, then pass
1892
+ a host-owned custom scheme to React Native `Linking` or open other URLs through the system. If your
1893
+ handler might decline an app-owned custom scheme, keep a `Linking` URL listener registered for that
1894
+ fallback. A thrown error, rejected promise, missing handler, or handler timeout follows the same
1895
+ native fallback. Cold URLs wait up to ten seconds for registration and are replayed once the handler
1896
+ is ready. After delivery, the handler has ten seconds to settle. If it takes longer, native fallback
1897
+ runs; a handler that later routes the URL can cause a second navigation because its acknowledgement
1898
+ cannot cancel the fallback.
1571
1899
 
1572
1900
  ```typescript
1573
- import { Zixflow } from 'zixflow-reactnative';
1901
+ const subscription = Zixflow.setDeepLinkHandler(async (url) => {
1902
+ if (!canRouteInApp(url)) {
1903
+ return false;
1904
+ }
1574
1905
 
1575
- const config = {
1576
- apiKey: 'YOUR_API_KEY',
1577
- // or
1578
- };
1906
+ await routeInApp(url);
1907
+ return true;
1908
+ });
1579
1909
 
1580
1910
  Zixflow.initialize(config);
1581
1911
  ```
1582
1912
 
1583
- **Available regions**:
1584
- - `` - United States data center
1585
- - `` - European Union data center
1913
+ Remove the returned subscription when the routing owner is torn down. If no replacement handler
1914
+ registers, later destinations wait for the readiness timeout and then use the native fallback.
1586
1915
 
1587
- ### Log Levels
1588
-
1589
- Control SDK logging for debugging:
1916
+ The existing `Linking` path remains available for backward compatibility. Keep
1917
+ `NativeZixflow.configureSceneDeepLinkRouting()` in your SceneDelegate, then signal readiness
1918
+ after registering the listener:
1590
1919
 
1591
1920
  ```typescript
1592
- import { Zixflow, ZixflowLogLevel } from 'zixflow-reactnative';
1593
-
1594
- const config = {
1595
- apiKey: 'YOUR_API_KEY',
1596
- logLevel: ZixflowLogLevel.debug, // debug, info, error, none
1597
- };
1598
-
1599
- Zixflow.initialize(config);
1921
+ const subscription = Linking.addEventListener('url', ({ url }) => {
1922
+ // Route the URL in your app.
1923
+ });
1924
+ Zixflow.setDeepLinkRoutingReady();
1600
1925
  ```
1601
1926
 
1602
- **Log levels**:
1603
- - `ZixflowLogLevel.debug` - Verbose logging (development)
1604
- - `ZixflowLogLevel.info` - Informational messages
1605
- - `ZixflowLogLevel.error` - Errors only
1606
- - `ZixflowLogLevel.none` - No logging (production)
1927
+ Cold destinations wait up to ten seconds for this readiness signal. If it does not arrive, the SDK
1928
+ tries the host AppDelegate, passes a host-owned custom scheme to React Native `Linking`, or opens
1929
+ other URLs through the system.
1607
1930
 
1608
- ### Auto-Tracking Options
1931
+ This older path cannot acknowledge whether JavaScript handled the URL, so the SDK cannot safely fall back after it publishes a `Linking` event. Prefer `setDeepLinkHandler` for new UIScene integrations. Older React Native versions and AppDelegate-only hosts keep their existing deep-link integration.
1609
1932
 
1610
- Configure automatic tracking features:
1933
+ Expo apps keep the `Linking` path. With config-plugin auto-initialization, register the app's
1934
+ `Linking` listener, then call `Zixflow.setDeepLinkRoutingReady()` after the router is ready. The
1935
+ Expo plugin configures its native scene lifecycle automatically, so Expo app code does not call a
1936
+ native configuration method. Apps using JavaScript initialization register the router before
1937
+ `Zixflow.initialize`; initialization marks Linking ready automatically.
1611
1938
 
1612
- ```typescript
1613
- import { Zixflow } from 'zixflow-reactnative';
1939
+ This integration applies after the host has adopted React Native's UIScene lifecycle; the plugin does not replace React Native's root application lifecycle.
1614
1940
 
1615
- const config = {
1616
- apiKey: 'YOUR_API_KEY',
1941
+ This release's compatibility scope is one simultaneous window scene. Multiple simultaneous React Native window scenes are not supported. React Native's URL notification is process-wide, so SDK-published destinations may reach every connected React Native instance rather than one selected window.
1617
1942
 
1618
- // Automatically track device attributes (OS, model, app version)
1619
- autoTrackDeviceAttributes: true,
1943
+ ---
1620
1944
 
1621
- // Automatically track app lifecycle events (open, close, background)
1622
- trackApplicationLifecycleEvents: true,
1945
+ ## Geofence Tracking
1623
1946
 
1624
- // Automatically track screens (requires integration)
1625
- autoTrackScreenViews: true,
1626
- };
1947
+ Geofence is an optional module, off by default. Enabling it also enables the Location module, which geofence depends on.
1627
1948
 
1628
- Zixflow.initialize(config);
1949
+ Enable it at build time:
1950
+
1951
+ ```properties
1952
+ # android/gradle.properties
1953
+ zixflow_geofence_enabled=true
1629
1954
  ```
1630
1955
 
1631
- ### Custom API Hosts
1956
+ ```ruby
1957
+ # ios/Podfile
1958
+ pod 'zixflow-reactnative', :subspecs => ['geofence']
1959
+ ```
1632
1960
 
1633
- Override API endpoints for testing or custom infrastructure:
1961
+ Then opt in by passing a `geofence` config to `initialize`:
1634
1962
 
1635
1963
  ```typescript
1636
- import { Zixflow } from 'zixflow-reactnative';
1964
+ import { Zixflow, ZixflowGeofenceLocationMode } from 'zixflow-reactnative';
1637
1965
 
1638
- const config = {
1966
+ Zixflow.initialize({
1639
1967
  apiKey: 'YOUR_API_KEY',
1968
+ geofence: {
1969
+ // AUTOMATIC (default): the SDK acquires location itself on identify and app launch.
1970
+ // MANUAL: drive refreshes yourself via Zixflow.geofence.refreshFromCurrentLocation().
1971
+ locationMode: ZixflowGeofenceLocationMode.Automatic,
1972
+ },
1973
+ ios: {
1974
+ // Whether geofence transitions are delivered in real time on a background cold-wake.
1975
+ // Defaults to on when the geofence module is enabled.
1976
+ allowBackgroundDelivery: true,
1977
+ },
1978
+ });
1979
+ ```
1640
1980
 
1641
- // Custom tracking API host
1642
- trackingApiUrl: 'https://custom-track.zixflow.com',
1981
+ Request location permissions the same way as for [Location Tracking](#location-tracking) above — geofence monitoring requires them and the SDK never requests permission itself.
1643
1982
 
1644
- // Custom in-app messaging API host
1645
- inApp: {
1646
- // Override in-app messaging API endpoint if needed
1647
- },
1648
- };
1983
+ With `MANUAL` location mode, trigger a refresh after permission is granted:
1649
1984
 
1650
- Zixflow.initialize(config);
1985
+ ```typescript
1986
+ Zixflow.geofence.refreshFromCurrentLocation();
1651
1987
  ```
1652
1988
 
1653
- ---
1989
+ This requests a one-shot location fix and refreshes the nearby geofence set from it. It no-ops if the geofence module is not enabled or a user has not been identified.
1654
1990
 
1655
- ## Troubleshooting
1991
+ ---
1656
1992
 
1657
- ### Installation Issues
1993
+ ## 🔴 Live Activities
1658
1994
 
1659
- **Issue**: `npm install` fails with dependency conflicts
1995
+ Enable the activity types you use under the `liveNotifications` key of your SDK config. On iOS, also add `NSSupportsLiveActivities` to your app's `Info.plist`, the `liveactivities` pod subspec, and a Widget Extension that renders the SDK's built-in templates. Without the `Info.plist` key, iOS refuses to start any activity:
1660
1996
 
1661
- **Solution**: Use `--legacy-peer-deps` flag:
1662
- ```bash
1663
- npm install zixflow-reactnative --legacy-peer-deps
1997
+ ```xml
1998
+ <key>NSSupportsLiveActivities</key>
1999
+ <true/>
1664
2000
  ```
1665
2001
 
1666
- Or with Yarn:
1667
- ```bash
1668
- yarn add zixflow-reactnative --legacy-peer-deps
2002
+ **One manual step is required on iOS.** Forward every opened URL to the SDK from the host's active lifecycle, or taps on a Live Activity are not attributed. `NativeLiveActivities` comes from the wrapper pod, so import it. This only compiles once the `liveactivities` subspec is installed.
2003
+
2004
+ For an AppDelegate host:
2005
+
2006
+ ```swift
2007
+ import zixflow_reactnative
2008
+ import React
2009
+
2010
+ extension AppDelegate {
2011
+ func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
2012
+ // Reports an `opened` metric and returns the deep link to route to. A non-Zixflow URL comes
2013
+ // back unchanged; `nil` means the activity carried no deep link, so there is nothing to open.
2014
+ guard let routableUrl = NativeLiveActivities.handleWidgetUrl(url) else { return true }
2015
+ return RCTLinkingManager.application(app, open: routableUrl, options: options)
2016
+ }
2017
+ }
1669
2018
  ```
1670
2019
 
1671
- ---
2020
+ A React Native `AppDelegate` conforms to `UIApplicationDelegate` directly rather than subclassing, so this method is not an `override`, and the URL is passed on to `RCTLinkingManager` instead of `super`. See [the sample app's `AppDelegate.swift`](/example/ios/SampleApp/AppDelegate.swift) for this in context.
1672
2021
 
1673
- **Issue**: Auto-linking fails after installation
2022
+ For a `UIScene` host, handle both lifecycle paths. At scene connection, pass the connection options through the wrapper so a cold Live Activity tap is attributed and its destination enters the acknowledged Zixflow router. Ordinary app links remain in React Native launch options for `Linking`:
1674
2023
 
1675
- **Solution**: Try manual linking:
2024
+ ```swift
2025
+ import zixflow_reactnative
1676
2026
 
1677
- 1. Clean the build:
1678
- ```bash
1679
- cd android && ./gradlew clean && cd ..
1680
- cd ios && rm -rf Pods && pod install && cd ..
2027
+ reactNativeFactory?.startReactNative(
2028
+ withModuleName: "YourApp",
2029
+ in: window,
2030
+ launchOptions: NativeLiveActivities.reactNativeLaunchOptions(from: connectionOptions)
2031
+ )
1681
2032
  ```
1682
2033
 
1683
- 2. Rebuild the app:
1684
- ```bash
1685
- npx react-native run-ios
1686
- npx react-native run-android
2034
+ Then replace the ordinary React Native URL-forwarding body in the existing `SceneDelegate` for warm opens. This reports Live Activity taps, sends Zixflow destinations through the configured Zixflow router, and forwards ordinary app links to React Native `Linking`:
2035
+
2036
+ ```swift
2037
+ import zixflow_reactnative
2038
+
2039
+ func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
2040
+ for context in URLContexts {
2041
+ NativeLiveActivities.handleAndRouteWidgetUrl(context.url)
2042
+ }
2043
+ }
1687
2044
  ```
1688
2045
 
1689
- ### iOS Build Errors
2046
+ Do not also pass those URLs to `RCTLinkingManager`. The helper already routes them through the
2047
+ Zixflow bridge, and forwarding them again can deliver the same URL twice.
1690
2048
 
1691
- **Issue**: `Module 'Zixflow' not found`
2049
+ Android needs no equivalent native step.
1692
2050
 
1693
- **Solution**:
1694
- 1. Ensure you've run `pod install` in the `ios` directory
1695
- 2. Clean build folder in Xcode: Product > Clean Build Folder
1696
- 3. Rebuild the project
2051
+ For Expo Router, unwrap the URL once in the app's top-level `app/+native-intent.tsx` file:
1697
2052
 
1698
- ---
2053
+ ```typescript
2054
+ import { Zixflow } from 'zixflow-reactnative';
1699
2055
 
1700
- **Issue**: Swift compiler errors in native modules
2056
+ export async function redirectSystemPath({ path }: { path: string }) {
2057
+ return Zixflow.liveActivities.handleWidgetUrl(path);
2058
+ }
2059
+ ```
1701
2060
 
1702
- **Solution**:
1703
- 1. Check Xcode version (14.0+ required)
1704
- 2. Update CocoaPods: `sudo gem install cocoapods`
1705
- 3. Update pod dependencies: `cd ios && pod update && cd ..`
2061
+ This reports the opened event, returns the customer's destination, preserves ordinary URLs, and
2062
+ returns `null` for a Zixflow tracking URL without a destination. Do not also call the helper
2063
+ from a `Linking` listener because processing the same tracking URL twice reports two opened events.
2064
+ Expo apps without Expo Router can apply the helper once in their central `Linking` initial-URL and
2065
+ subscription pipeline.
1706
2066
 
1707
2067
  ---
1708
2068
 
1709
- **Issue**: Notification Service Extension not working
2069
+ ## Notification Inbox
1710
2070
 
1711
- **Solution**:
1712
- 1. Ensure the extension target has the correct dependencies in Podfile
1713
- 2. Run `pod install` after adding the extension
1714
- 3. Check that the extension's deployment target is iOS 13.0+
1715
- 4. Verify the extension is added to your app's target dependencies
2071
+ The Visual Notification Inbox renders received messages in a list the SDK owns the design of. Two components are available:
1716
2072
 
1717
- ### Android Build Errors
2073
+ - `NotificationInboxBellView` — a bell icon with an unread badge. Tapping it opens the SDK's own inbox panel; the host presents nothing.
2074
+ - `NotificationInboxView` — the message list itself, embeddable directly in your own screen with no surrounding chrome (no bell, no scrim).
1718
2075
 
1719
- **Issue**: `Cannot find symbol class Zixflow`
2076
+ ```tsx
2077
+ import { NotificationInboxBellView, NotificationInboxView } from 'zixflow-reactnative';
1720
2078
 
1721
- **Solution**:
1722
- 1. Clean Gradle cache:
1723
- ```bash
1724
- cd android && ./gradlew clean && cd ..
1725
- ```
2079
+ // Place the bell wherever your layout calls for it. Give it a fixed size for
2080
+ // predictable layout — at least 88 points/dp square.
2081
+ <NotificationInboxBellView
2082
+ style={{ width: 88, height: 88 }}
2083
+ onTap={() => analytics.track('inbox_bell_tapped')}
2084
+ />
1726
2085
 
1727
- 2. Rebuild the app:
1728
- ```bash
1729
- npx react-native run-android
2086
+ // Or embed the message list directly in a screen of your own.
2087
+ <NotificationInboxView style={{ flex: 1 }} />
1730
2088
  ```
1731
2089
 
1732
- ---
2090
+ `onTap` on `NotificationInboxBellView` is observational only — the SDK opens the inbox panel itself. Message actions inside `NotificationInboxView` are reported through the global inbox event listener below, not a per-message callback.
1733
2091
 
1734
- **Issue**: Duplicate class errors with Firebase
2092
+ Remote branding styles the bell and list themselves (colors, icon); the host still owns layout and placement via `style`.
1735
2093
 
1736
- **Solution**:
1737
- 1. Check that you're not including Firebase dependencies manually if using FCM
1738
- 2. Ensure all Firebase dependencies use the same version
1739
- 3. Add to `android/gradle.properties`:
1740
- ```properties
1741
- android.enableJetifier=true
2094
+ The SDK ships no text of its own in the visual inbox, so accessibility labels are the one place a string is still needed. Every label is optional — an omitted label leaves that element unlabeled rather than falling back to English:
2095
+
2096
+ ```typescript
2097
+ Zixflow.initialize({
2098
+ apiKey: 'YOUR_API_KEY',
2099
+ inApp: {
2100
+ notificationInboxAccessibilityLabels: {
2101
+ bell: t('inbox.bell'),
2102
+ bellWithUnreadCount: t('inbox.unread'), // e.g. "{count} unread notifications"
2103
+ loadingIndicator: t('inbox.loading'),
2104
+ emptyState: t('inbox.empty'),
2105
+ },
2106
+ },
2107
+ });
1742
2108
  ```
1743
2109
 
1744
- ---
2110
+ Register a listener to observe inbox events (shown, opened, dismissed, and non-dismiss actions taken on a message):
1745
2111
 
1746
- **Issue**: Minimum SDK version error
2112
+ ```typescript
2113
+ import { InboxEventType } from 'zixflow-reactnative';
2114
+
2115
+ const subscription = Zixflow.inAppMessaging.registerInboxEventListener((event) => {
2116
+ switch (event.eventType) {
2117
+ case InboxEventType.messageActionTaken:
2118
+ // event.actionName / event.actionValue are only present for this event
2119
+ console.log('Inbox action taken:', event.actionName, event.actionValue);
2120
+ break;
2121
+ case InboxEventType.messageShown:
2122
+ case InboxEventType.messageOpened:
2123
+ case InboxEventType.messageDismissed:
2124
+ console.log(event.eventType, event.message);
2125
+ break;
2126
+ }
2127
+ });
1747
2128
 
1748
- **Solution**: Update `android/build.gradle`:
1749
- ```gradle
1750
- ext {
1751
- minSdkVersion = 24
1752
- }
2129
+ // Remove listener
2130
+ subscription.remove();
1753
2131
  ```
1754
2132
 
1755
- ### Push Notification Issues
2133
+ You can also fetch and manage inbox messages directly through `Zixflow.inAppMessaging.inbox()`:
1756
2134
 
1757
- **Issue**: Push notifications not received on iOS
2135
+ ```typescript
2136
+ const inbox = Zixflow.inAppMessaging.inbox();
1758
2137
 
1759
- **Checklist**:
1760
- - [ ] Push Notifications capability enabled in Xcode
1761
- - [ ] APNs certificate uploaded to Zixflow dashboard
1762
- - [ ] Device token registered (check logs)
1763
- - [ ] Permission granted by user
1764
- - [ ] App not in foreground (notifications shown in background/killed state)
2138
+ const messages = await inbox.getMessages();
2139
+
2140
+ inbox.markMessageOpened(message);
2141
+ inbox.markMessageDeleted(message);
2142
+ ```
1765
2143
 
1766
2144
  ---
1767
2145
 
1768
- **Issue**: Push notifications not received on Android
2146
+ ## Advanced Configuration
1769
2147
 
1770
- **Checklist**:
1771
- - [ ] `google-services.json` file added to `android/app/`
1772
- - [ ] Google Services plugin applied in `android/app/build.gradle`
1773
- - [ ] FCM server key uploaded to Zixflow dashboard
1774
- - [ ] Device registered for push (check logs)
1775
- - [ ] Notification permissions granted (Android 13+)
2148
+ ### Log Levels
1776
2149
 
1777
- ---
2150
+ Control SDK logging for debugging:
1778
2151
 
1779
- **Issue**: Rich push notifications (images) not working
2152
+ ```typescript
2153
+ import { Zixflow, ZixflowLogLevel } from 'zixflow-reactnative';
1780
2154
 
1781
- **Solution**: Ensure Notification Service Extension is properly configured on iOS (see [Notification Service Extension](#notification-service-extension))
2155
+ const config = {
2156
+ apiKey: 'YOUR_API_KEY',
2157
+ logLevel: ZixflowLogLevel.debug, // debug, info, error, none
2158
+ };
1782
2159
 
1783
- ### In-App Message Issues
2160
+ Zixflow.initialize(config);
2161
+ ```
1784
2162
 
1785
- **Issue**: In-app messages not displaying
2163
+ **Log levels**:
2164
+ - `ZixflowLogLevel.debug` - Verbose logging (development)
2165
+ - `ZixflowLogLevel.info` - Informational messages
2166
+ - `ZixflowLogLevel.error` - Errors only
2167
+ - `ZixflowLogLevel.none` - No logging (production)
1786
2168
 
1787
- **Checklist**:
1788
- - [ ] In-app messaging module initialized
1789
- - [ ] Event listener registered
1790
- - [ ] User identified before triggering message
1791
- - [ ] Message created and published in Zixflow dashboard
1792
- - [ ] Check logs for error events
2169
+ ### Auto-Tracking Options
1793
2170
 
1794
- ---
2171
+ Configure automatic tracking features:
2172
+
2173
+ ```typescript
2174
+ import { Zixflow } from 'zixflow-reactnative';
2175
+
2176
+ const config = {
2177
+ apiKey: 'YOUR_API_KEY',
2178
+
2179
+ // Automatically track device attributes (OS, model, app version)
2180
+ autoTrackDeviceAttributes: true,
2181
+
2182
+ // Automatically track app lifecycle events (open, close, background)
2183
+ trackApplicationLifecycleEvents: true,
2184
+
2185
+ // Automatically track screens (requires integration)
2186
+ autoTrackScreenViews: true,
2187
+ };
1795
2188
 
1796
- **Issue**: In-app message events not firing
2189
+ Zixflow.initialize(config);
2190
+ ```
2191
+
2192
+ ### Custom API Hosts
2193
+
2194
+ Override API endpoints for testing or custom infrastructure:
1797
2195
 
1798
- **Solution**: Ensure event listener is registered before messages are triggered:
1799
2196
  ```typescript
1800
- useEffect(() => {
1801
- const listener = Zixflow.inAppMessaging.registerEventsListener((event) => {
1802
- console.log('In-app event:', event);
1803
- });
2197
+ import { Zixflow } from 'zixflow-reactnative';
1804
2198
 
1805
- return () => listener.remove();
1806
- }, []);
2199
+ const config = {
2200
+ apiKey: 'YOUR_API_KEY',
2201
+
2202
+ // Custom tracking API host
2203
+ trackingApiUrl: 'https://custom-track.zixflow.com',
2204
+
2205
+ // Custom in-app messaging API host
2206
+ inApp: {
2207
+ // Override in-app messaging API endpoint if needed
2208
+ },
2209
+ };
2210
+
2211
+ Zixflow.initialize(config);
1807
2212
  ```
1808
2213
 
1809
2214
  ---
@@ -1950,7 +2355,6 @@ Configuration object for SDK initialization.
1950
2355
  ```typescript
1951
2356
  interface ZixflowConfig {
1952
2357
  apiKey: string;
1953
- region?: Region;
1954
2358
  logLevel?: ZixflowLogLevel;
1955
2359
  inApp?: {
1956
2360
  };
@@ -1961,17 +2365,6 @@ interface ZixflowConfig {
1961
2365
  }
1962
2366
  ```
1963
2367
 
1964
- #### `Region`
1965
-
1966
- Data center region enum.
1967
-
1968
- ```typescript
1969
- enum Region {
1970
- US = 'US',
1971
- EU = 'EU'
1972
- }
1973
- ```
1974
-
1975
2368
  #### `ZixflowLogLevel`
1976
2369
 
1977
2370
  Log level enum.
@@ -2024,26 +2417,3 @@ interface InAppMessageEvent {
2024
2417
  }
2025
2418
  ```
2026
2419
 
2027
- ---
2028
-
2029
- ## Support & Resources
2030
-
2031
- ### Documentation
2032
-
2033
- - **GitHub Repository**: https://github.com/zixflow/zixflow-reactnative
2034
- - **iOS SDK Documentation**: https://github.com/zixflow/zixflow-ios
2035
- - **Android SDK Documentation**: https://github.com/zixflow/zixflow-android
2036
- - **API Reference**: See [API Reference](#api-reference) section above
2037
-
2038
- ### Getting Help
2039
-
2040
- - **GitHub Issues**: https://github.com/zixflow/zixflow-reactnative/issues
2041
- - **Support Email**: support@zixflow.com
2042
-
2043
- ### Changelog
2044
-
2045
- See [CHANGELOG.md](../CHANGELOG.md) for version history and release notes.
2046
-
2047
- ---
2048
-
2049
- **Need help?** Contact our support team at support@zixflow.com or open an issue on GitHub.