zixflow-reactnative 1.1.1 → 1.1.3
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.
- package/README.md +1868 -270
- package/android/build.gradle +1 -0
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/zixflow/reactnative/sdk/NativeZixflowModule.kt +29 -19
- package/android/src/main/java/com/zixflow/reactnative/sdk/constant/Keys.kt +1 -4
- package/android/src/main/java/com/zixflow/reactnative/sdk/logging/NativeZixflowLoggingModule.kt +2 -2
- package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginapp/NativeMessagingInAppModule.kt +2 -13
- package/ios/wrappers/inapp/NativeMessagingInApp.mm +1 -1
- package/ios/wrappers/push/NativeMessagingPush.mm +1 -1
- package/ios/wrappers/utils/ZixflowConfigUtils.swift +5 -9
- package/lib/commonjs/native-logger-listener.js +6 -2
- package/lib/commonjs/native-logger-listener.js.map +1 -1
- package/lib/commonjs/specs/modules/NativeZixflowLogging.js +1 -1
- package/lib/commonjs/specs/modules/NativeZixflowLogging.js.map +1 -1
- package/lib/commonjs/specs/modules/NativeZixflowMessagingInApp.js +1 -1
- package/lib/commonjs/specs/modules/NativeZixflowMessagingInApp.js.map +1 -1
- package/lib/commonjs/specs/modules/NativeZixflowMessagingPush.js +1 -1
- package/lib/commonjs/specs/modules/NativeZixflowMessagingPush.js.map +1 -1
- package/lib/commonjs/types/data-pipelines.js +3 -15
- package/lib/commonjs/types/data-pipelines.js.map +1 -1
- package/lib/commonjs/utils/param-validation.js +1 -1
- package/lib/commonjs/utils/param-validation.js.map +1 -1
- package/lib/commonjs/zixflow-cdp.js +3 -0
- package/lib/commonjs/zixflow-cdp.js.map +1 -1
- package/lib/commonjs/zixflow.js.map +1 -1
- package/lib/module/native-logger-listener.js +7 -3
- package/lib/module/native-logger-listener.js.map +1 -1
- package/lib/module/specs/modules/NativeZixflowLogging.js +1 -1
- package/lib/module/specs/modules/NativeZixflowLogging.js.map +1 -1
- package/lib/module/specs/modules/NativeZixflowMessagingInApp.js +1 -1
- package/lib/module/specs/modules/NativeZixflowMessagingInApp.js.map +1 -1
- package/lib/module/specs/modules/NativeZixflowMessagingPush.js +1 -1
- package/lib/module/specs/modules/NativeZixflowMessagingPush.js.map +1 -1
- package/lib/module/types/data-pipelines.js +2 -15
- package/lib/module/types/data-pipelines.js.map +1 -1
- package/lib/module/utils/param-validation.js +1 -1
- package/lib/module/utils/param-validation.js.map +1 -1
- package/lib/module/zixflow-cdp.js +3 -0
- package/lib/module/zixflow-cdp.js.map +1 -1
- package/lib/module/zixflow.js +0 -6
- package/lib/module/zixflow.js.map +1 -1
- package/lib/typescript/commonjs/native-logger-listener.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/modules/NativeZixflowLogging.d.ts +1 -1
- package/lib/typescript/commonjs/specs/modules/NativeZixflowLogging.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingInApp.d.ts +1 -1
- package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingPush.d.ts +1 -1
- package/lib/typescript/commonjs/types/data-pipelines.d.ts +4 -20
- package/lib/typescript/commonjs/types/data-pipelines.d.ts.map +1 -1
- package/lib/typescript/commonjs/zixflow-cdp.d.ts.map +1 -1
- package/lib/typescript/commonjs/zixflow.d.ts +0 -5
- package/lib/typescript/commonjs/zixflow.d.ts.map +1 -1
- package/lib/typescript/module/native-logger-listener.d.ts.map +1 -1
- package/lib/typescript/module/specs/modules/NativeZixflowLogging.d.ts +1 -1
- package/lib/typescript/module/specs/modules/NativeZixflowLogging.d.ts.map +1 -1
- package/lib/typescript/module/specs/modules/NativeZixflowMessagingInApp.d.ts +1 -1
- package/lib/typescript/module/specs/modules/NativeZixflowMessagingPush.d.ts +1 -1
- package/lib/typescript/module/types/data-pipelines.d.ts +4 -20
- package/lib/typescript/module/types/data-pipelines.d.ts.map +1 -1
- package/lib/typescript/module/zixflow-cdp.d.ts.map +1 -1
- package/lib/typescript/module/zixflow.d.ts +0 -5
- package/lib/typescript/module/zixflow.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/native-logger-listener.ts +9 -5
- package/src/specs/modules/NativeZixflowLogging.ts +1 -1
- package/src/specs/modules/NativeZixflowMessagingInApp.ts +1 -1
- package/src/specs/modules/NativeZixflowMessagingPush.ts +1 -1
- package/src/types/data-pipelines.ts +4 -21
- package/src/utils/param-validation.ts +1 -1
- package/src/zixflow-cdp.ts +4 -0
- package/src/zixflow.ts +0 -6
- package/zixflow-reactnative-richpush.podspec +2 -2
- package/zixflow-reactnative.podspec +2 -2
- /package/ios/wrappers/{CustomerioReactnative-Bridging-Header.h → ZixflowReactnative-Bridging-Header.h} +0 -0
package/README.md
CHANGED
|
@@ -1,451 +1,2049 @@
|
|
|
1
|
-
|
|
2
|
-
<a href="https://zixflow.com">
|
|
3
|
-
<img src="https://zixflow.com/logo.svg" height="60">
|
|
4
|
-
</a>
|
|
5
|
-
</p>
|
|
1
|
+
# Zixflow React Native SDK - Integration Guide
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
[](https://www.npmjs.com/package/zixflow-reactnative)
|
|
9
|
-

|
|
10
|
-

|
|
11
|
-

|
|
12
|
-
[](CODE_OF_CONDUCT.md)
|
|
3
|
+
Welcome to the **Zixflow React Native SDK** integration guide. This comprehensive document will help you install, configure, and use the Zixflow SDK in your React Native application to track user behavior, send push notifications, display in-app messages, and more.
|
|
13
4
|
|
|
14
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Introduction](#introduction)
|
|
10
|
+
2. [Requirements](#requirements)
|
|
11
|
+
3. [Installation](#installation)
|
|
12
|
+
- [npm Installation](#npm-installation)
|
|
13
|
+
- [Yarn Installation](#yarn-installation)
|
|
14
|
+
4. [iOS Setup](#ios-setup)
|
|
15
|
+
- [CocoaPods Integration](#cocoapods-integration)
|
|
16
|
+
- [Swift Package Manager Integration](#swift-package-manager-integration)
|
|
17
|
+
- [Push Notification Setup (APNs)](#push-notification-setup-apns)
|
|
18
|
+
- [Notification Service Extension](#notification-service-extension)
|
|
19
|
+
5. [Android Setup](#android-setup)
|
|
20
|
+
- [Gradle Configuration](#gradle-configuration)
|
|
21
|
+
- [Firebase Cloud Messaging Setup](#firebase-cloud-messaging-setup)
|
|
22
|
+
6. [Quick Start](#quick-start)
|
|
23
|
+
- [Basic Configuration](#basic-configuration)
|
|
24
|
+
- [SDK Initialization](#sdk-initialization)
|
|
25
|
+
7. [Core Features](#core-features)
|
|
26
|
+
- [User Identification](#user-identification)
|
|
27
|
+
- [Event Tracking](#event-tracking)
|
|
28
|
+
- [Screen Tracking](#screen-tracking)
|
|
29
|
+
- [User Profile Attributes](#user-profile-attributes)
|
|
30
|
+
- [Device Attributes](#device-attributes)
|
|
31
|
+
- [Clearing User Identity](#clearing-user-identity)
|
|
32
|
+
8. [Push Notifications](#push-notifications)
|
|
33
|
+
- [Requesting Permission](#requesting-permission)
|
|
34
|
+
- [Handling Push Notifications](#handling-push-notifications)
|
|
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)
|
|
40
|
+
10. [Location Tracking](#location-tracking)
|
|
41
|
+
11. [Advanced Configuration](#advanced-configuration)
|
|
42
|
+
- [Region Settings](#region-settings)
|
|
43
|
+
- [Log Levels](#log-levels)
|
|
44
|
+
- [Auto-Tracking Options](#auto-tracking-options)
|
|
45
|
+
- [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)
|
|
55
|
+
|
|
56
|
+
---
|
|
15
57
|
|
|
16
|
-
|
|
58
|
+
## Introduction
|
|
17
59
|
|
|
18
|
-
|
|
19
|
-
|
|
60
|
+
The **Zixflow React Native SDK** enables you to:
|
|
61
|
+
|
|
62
|
+
- **Identify users** and track their behavior across your app
|
|
63
|
+
- **Send targeted push notifications** via Apple Push Notification service (APNs) or Firebase Cloud Messaging (FCM)
|
|
64
|
+
- **Display in-app messages** to engage users at the right time
|
|
65
|
+
- **Track user location** to enable location-based messaging
|
|
66
|
+
- **Manage user profiles** with custom attributes
|
|
67
|
+
- **Track events and screen views** automatically or manually
|
|
68
|
+
|
|
69
|
+
The SDK is built on top of the native Zixflow iOS and Android SDKs, providing a unified TypeScript API for React Native applications.
|
|
20
70
|
|
|
21
71
|
---
|
|
22
72
|
|
|
23
|
-
##
|
|
73
|
+
## Requirements
|
|
74
|
+
|
|
75
|
+
### React Native
|
|
24
76
|
|
|
25
|
-
|
|
77
|
+
- **React Native**: 0.60.0 or higher
|
|
78
|
+
- **React**: 16.8.0 or higher (for hooks support)
|
|
26
79
|
|
|
27
|
-
###
|
|
80
|
+
### iOS
|
|
28
81
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
82
|
+
- **iOS**: 13.0 or higher
|
|
83
|
+
- **Xcode**: 14.0 or higher
|
|
84
|
+
- **Swift**: 5.3 or higher
|
|
85
|
+
- **CocoaPods**: 1.10.0 or higher (if using CocoaPods)
|
|
86
|
+
|
|
87
|
+
### Android
|
|
88
|
+
|
|
89
|
+
- **Android**: API level 24 (Android 7.0) or higher
|
|
90
|
+
- **Kotlin**: 1.6.0 or higher
|
|
91
|
+
- **Gradle**: 7.0 or higher
|
|
92
|
+
|
|
93
|
+
### TypeScript (Recommended)
|
|
94
|
+
|
|
95
|
+
- **TypeScript**: 4.0 or higher
|
|
37
96
|
|
|
38
97
|
---
|
|
39
98
|
|
|
40
99
|
## Installation
|
|
41
100
|
|
|
101
|
+
### npm Installation
|
|
102
|
+
|
|
103
|
+
Install the SDK using npm:
|
|
104
|
+
|
|
42
105
|
```bash
|
|
43
106
|
npm install zixflow-reactnative
|
|
44
107
|
```
|
|
45
108
|
|
|
46
|
-
|
|
109
|
+
### Yarn Installation
|
|
110
|
+
|
|
111
|
+
Or install using Yarn:
|
|
47
112
|
|
|
48
113
|
```bash
|
|
49
114
|
yarn add zixflow-reactnative
|
|
50
115
|
```
|
|
51
116
|
|
|
117
|
+
After installation, proceed with platform-specific setup for iOS and Android.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## iOS Setup
|
|
122
|
+
|
|
123
|
+
### CocoaPods Integration
|
|
124
|
+
|
|
125
|
+
The Zixflow React Native SDK automatically integrates with the native iOS SDK via CocoaPods or Swift Package Manager. If you're using **React Native 0.60 or higher**, dependencies are auto-linked.
|
|
126
|
+
|
|
127
|
+
1. **Navigate to the iOS directory**:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cd ios
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
2. **Install CocoaPods dependencies**:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pod install
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
3. **Open the workspace in Xcode**:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
open YourApp.xcworkspace
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The SDK will automatically include the necessary Zixflow iOS modules:
|
|
146
|
+
- `ZixflowCommon`
|
|
147
|
+
- `ZixflowDataPipelines`
|
|
148
|
+
- `ZixflowMessagingPush`
|
|
149
|
+
- `ZixflowMessagingPushAPN` (for APNs)
|
|
150
|
+
- `ZixflowMessagingInApp`
|
|
151
|
+
|
|
152
|
+
### Swift Package Manager Integration
|
|
153
|
+
|
|
154
|
+
If you prefer **Swift Package Manager (SPM)**, you can configure your project to use the Zixflow iOS SDK directly:
|
|
155
|
+
|
|
156
|
+
1. **Open your project in Xcode**
|
|
157
|
+
2. **Go to File > Add Package Dependencies**
|
|
158
|
+
3. **Enter the repository URL**:
|
|
159
|
+
```
|
|
160
|
+
https://github.com/zixflow/zixflow-ios.git
|
|
161
|
+
```
|
|
162
|
+
4. **Select the version**: Use `1.0.0` or higher
|
|
163
|
+
5. **Add the following modules** to your app target:
|
|
164
|
+
- `Zixflow` (umbrella module)
|
|
165
|
+
- `ZixflowDataPipelines`
|
|
166
|
+
- `ZixflowMessagingPushAPN`
|
|
167
|
+
- `ZixflowMessagingInApp`
|
|
168
|
+
|
|
169
|
+
> **Note**: The example app uses SPM for the native iOS SDK integration. See `example/ios/Podfile` for reference.
|
|
170
|
+
|
|
171
|
+
### Push Notification Setup (APNs)
|
|
172
|
+
|
|
173
|
+
To enable **Apple Push Notifications (APNs)**:
|
|
174
|
+
|
|
175
|
+
1. **Enable Push Notifications capability** in Xcode:
|
|
176
|
+
- Select your app target
|
|
177
|
+
- Go to **Signing & Capabilities**
|
|
178
|
+
- Click **+ Capability** and add **Push Notifications**
|
|
179
|
+
|
|
180
|
+
2. **Enable Background Modes**:
|
|
181
|
+
- Add **Background Modes** capability
|
|
182
|
+
- Enable **Remote notifications**
|
|
183
|
+
|
|
184
|
+
3. **Configure APNs certificates** in your Apple Developer account and upload them to Zixflow dashboard.
|
|
185
|
+
|
|
186
|
+
### Notification Service Extension
|
|
187
|
+
|
|
188
|
+
To support **rich push notifications** (images, videos, action buttons), you need to add a **Notification Service Extension**:
|
|
189
|
+
|
|
190
|
+
1. **Create a Notification Service Extension** in Xcode:
|
|
191
|
+
- File > New > Target > Notification Service Extension
|
|
192
|
+
- Name it `NotificationServiceExtension`
|
|
193
|
+
|
|
194
|
+
2. **Add Zixflow modules to the extension** in your `Podfile`:
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
target 'NotificationServiceExtension' do
|
|
198
|
+
pod "ZixflowMessagingPushAPN", "~> 1.0"
|
|
199
|
+
pod "ZixflowMessagingPush", "~> 1.0"
|
|
200
|
+
pod "ZixflowDataPipelines", "~> 1.0"
|
|
201
|
+
pod "ZixflowCommon", "~> 1.0"
|
|
202
|
+
pod "ZixflowTrackingMigration", "~> 1.0"
|
|
203
|
+
pod "AnalyticsSwiftZixflow", "1.7.3+zixflow.1"
|
|
204
|
+
end
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
3. **Update `NotificationService.swift`**:
|
|
208
|
+
|
|
209
|
+
```swift
|
|
210
|
+
import UserNotifications
|
|
211
|
+
import ZixflowMessagingPushAPN
|
|
212
|
+
|
|
213
|
+
class NotificationService: UNNotificationServiceExtension {
|
|
214
|
+
var contentHandler: ((UNNotificationContent) -> Void)?
|
|
215
|
+
var bestAttemptContent: UNMutableNotificationContent?
|
|
216
|
+
|
|
217
|
+
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
|
218
|
+
self.contentHandler = contentHandler
|
|
219
|
+
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
|
220
|
+
|
|
221
|
+
// Use Zixflow to handle rich push
|
|
222
|
+
MessagingPushAPN.didReceive(request, withContentHandler: contentHandler)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
override func serviceExtensionTimeWillExpire() {
|
|
226
|
+
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
|
227
|
+
contentHandler(bestAttemptContent)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
4. **Run `pod install`** again to install extension dependencies.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Android Setup
|
|
238
|
+
|
|
239
|
+
### Gradle Configuration
|
|
240
|
+
|
|
241
|
+
The React Native auto-linking will handle most of the Android setup. However, you need to ensure the following:
|
|
242
|
+
|
|
243
|
+
1. **Set minimum SDK version** in `android/build.gradle`:
|
|
244
|
+
|
|
245
|
+
```gradle
|
|
246
|
+
buildscript {
|
|
247
|
+
ext {
|
|
248
|
+
minSdkVersion = 24
|
|
249
|
+
compileSdkVersion = 34
|
|
250
|
+
targetSdkVersion = 34
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
2. **Add Maven repositories** in `android/build.gradle`:
|
|
256
|
+
|
|
257
|
+
```gradle
|
|
258
|
+
allprojects {
|
|
259
|
+
repositories {
|
|
260
|
+
google()
|
|
261
|
+
mavenCentral()
|
|
262
|
+
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The Zixflow Android SDK will be automatically included via the React Native module.
|
|
268
|
+
|
|
269
|
+
### Firebase Cloud Messaging Setup
|
|
270
|
+
|
|
271
|
+
To enable **Firebase Cloud Messaging (FCM)** for push notifications on Android:
|
|
272
|
+
|
|
273
|
+
1. **Add Firebase to your project**:
|
|
274
|
+
- Go to [Firebase Console](https://console.firebase.google.com/)
|
|
275
|
+
- Add your Android app
|
|
276
|
+
- Download `google-services.json` and place it in `android/app/`
|
|
277
|
+
|
|
278
|
+
2. **Add Google Services plugin** in `android/build.gradle`:
|
|
279
|
+
|
|
280
|
+
```gradle
|
|
281
|
+
buildscript {
|
|
282
|
+
dependencies {
|
|
283
|
+
classpath 'com.google.gms:google-services:4.4.2'
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
3. **Apply the plugin** in `android/app/build.gradle`:
|
|
289
|
+
|
|
290
|
+
```gradle
|
|
291
|
+
apply plugin: 'com.google.gms.google-services'
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
4. **Configure FCM in the SDK** (shown in the initialization section below).
|
|
295
|
+
|
|
52
296
|
---
|
|
53
297
|
|
|
54
298
|
## Quick Start
|
|
55
299
|
|
|
56
|
-
###
|
|
300
|
+
### Basic Configuration
|
|
57
301
|
|
|
58
|
-
|
|
302
|
+
The SDK is configured using a `ZixflowConfig` object with several options:
|
|
59
303
|
|
|
60
|
-
```
|
|
61
|
-
import {
|
|
62
|
-
Zixflow,
|
|
63
|
-
ZixflowConfig,
|
|
64
|
-
ZixflowLogLevel,
|
|
65
|
-
ZixflowRegion,
|
|
66
|
-
} from 'zixflow-reactnative';
|
|
304
|
+
```typescript
|
|
305
|
+
import { Zixflow, ZixflowConfig, ZixflowLogLevel } from 'zixflow-reactnative';
|
|
67
306
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
region: ZixflowRegion.US, // Or ZixflowRegion.EU
|
|
73
|
-
logLevel: ZixflowLogLevel.Debug,
|
|
74
|
-
trackApplicationLifecycleEvents: true,
|
|
75
|
-
inApp: {
|
|
76
|
-
siteId: 'your-site-id', // Required for in-app messaging
|
|
77
|
-
},
|
|
78
|
-
push: {
|
|
79
|
-
android: {
|
|
80
|
-
pushClickBehavior: 'ActivityPreventRestart', // Optional
|
|
307
|
+
const config: ZixflowConfig = {
|
|
308
|
+
apiKey: 'YOUR_API_KEY',
|
|
309
|
+
logLevel: ZixflowLogLevel.debug,
|
|
310
|
+
inApp: {
|
|
81
311
|
},
|
|
82
|
-
|
|
83
|
-
|
|
312
|
+
autoTrackDeviceAttributes: true,
|
|
313
|
+
trackApplicationLifecycleEvents: true,
|
|
314
|
+
};
|
|
315
|
+
```
|
|
84
316
|
|
|
85
|
-
|
|
86
|
-
|
|
317
|
+
**Configuration Options**:
|
|
318
|
+
|
|
319
|
+
| Option | Type | Required | Description |
|
|
320
|
+
|--------|------|----------|-------------|
|
|
321
|
+
| `apiKey` | string | Yes | Your Zixflow API key |
|
|
322
|
+
| `logLevel` | `ZixflowLogLevel` | No | Logging level (debug, info, error, none) |
|
|
323
|
+
| `inApp` | object | No | Enable in-app messaging (use empty object: {}) |
|
|
324
|
+
| `autoTrackDeviceAttributes` | boolean | No | Automatically track device info |
|
|
325
|
+
| `trackApplicationLifecycleEvents` | boolean | No | Automatically track app lifecycle |
|
|
326
|
+
|
|
327
|
+
### SDK Initialization
|
|
328
|
+
|
|
329
|
+
Initialize the SDK in your `App.tsx` or main component using `useEffect`:
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
import React, { useEffect } from 'react';
|
|
333
|
+
import { Zixflow, ZixflowConfig, ZixflowLogLevel } from 'zixflow-reactnative';
|
|
334
|
+
|
|
335
|
+
export default function App() {
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
// Configure the SDK
|
|
338
|
+
const config: ZixflowConfig = {
|
|
339
|
+
apiKey: 'YOUR_API_KEY',
|
|
340
|
+
logLevel: ZixflowLogLevel.debug,
|
|
341
|
+
inApp: {
|
|
342
|
+
},
|
|
343
|
+
autoTrackDeviceAttributes: true,
|
|
344
|
+
trackApplicationLifecycleEvents: true,
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// Initialize the SDK
|
|
348
|
+
Zixflow.initialize(config);
|
|
349
|
+
|
|
350
|
+
console.log('Zixflow SDK initialized');
|
|
351
|
+
}, []);
|
|
352
|
+
|
|
353
|
+
return (
|
|
354
|
+
// Your app UI
|
|
355
|
+
);
|
|
356
|
+
}
|
|
87
357
|
```
|
|
88
358
|
|
|
89
|
-
>
|
|
359
|
+
> **Important**: Initialize the SDK as early as possible in your app's lifecycle, ideally in the root component's `useEffect`.
|
|
90
360
|
|
|
91
361
|
---
|
|
92
362
|
|
|
93
363
|
## Core Features
|
|
94
364
|
|
|
95
|
-
###
|
|
365
|
+
### User Identification
|
|
366
|
+
|
|
367
|
+
Identify users to track their behavior across sessions and devices:
|
|
96
368
|
|
|
97
|
-
|
|
369
|
+
```typescript
|
|
370
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
371
|
+
|
|
372
|
+
// Identify user with ID only
|
|
373
|
+
Zixflow.identify({
|
|
374
|
+
userId: 'user-123'
|
|
375
|
+
});
|
|
98
376
|
|
|
99
|
-
|
|
377
|
+
// Identify user with traits
|
|
100
378
|
Zixflow.identify({
|
|
101
|
-
userId: '
|
|
379
|
+
userId: 'user-123',
|
|
102
380
|
traits: {
|
|
103
381
|
email: 'user@example.com',
|
|
104
382
|
firstName: 'John',
|
|
105
383
|
lastName: 'Doe',
|
|
106
|
-
plan: 'premium'
|
|
107
|
-
}
|
|
384
|
+
plan: 'premium'
|
|
385
|
+
}
|
|
108
386
|
});
|
|
109
387
|
```
|
|
110
388
|
|
|
111
|
-
|
|
389
|
+
**When to identify users**:
|
|
390
|
+
- After successful login
|
|
391
|
+
- When user information becomes available
|
|
392
|
+
- After account creation
|
|
393
|
+
|
|
394
|
+
### Event Tracking
|
|
112
395
|
|
|
113
|
-
Track custom events to
|
|
396
|
+
Track custom events to understand user behavior:
|
|
114
397
|
|
|
115
|
-
```
|
|
116
|
-
Zixflow
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
398
|
+
```typescript
|
|
399
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
400
|
+
|
|
401
|
+
// Track event without properties
|
|
402
|
+
Zixflow.track('button_clicked');
|
|
403
|
+
|
|
404
|
+
// Track event with properties
|
|
405
|
+
Zixflow.track('product_viewed', {
|
|
406
|
+
product_id: '12345',
|
|
407
|
+
product_name: 'Premium Plan',
|
|
408
|
+
category: 'subscription',
|
|
409
|
+
price: 29.99
|
|
121
410
|
});
|
|
411
|
+
|
|
412
|
+
// Track with Map (alternative syntax)
|
|
413
|
+
const properties = new Map<string, any>();
|
|
414
|
+
properties.set('item_count', 3);
|
|
415
|
+
properties.set('total_amount', 89.97);
|
|
416
|
+
Zixflow.track('checkout_completed', properties);
|
|
122
417
|
```
|
|
123
418
|
|
|
124
|
-
|
|
419
|
+
**Common events to track**:
|
|
420
|
+
- User actions (button clicks, form submissions)
|
|
421
|
+
- E-commerce events (product views, purchases)
|
|
422
|
+
- Content interactions (article reads, video plays)
|
|
423
|
+
- Feature usage
|
|
424
|
+
|
|
425
|
+
### Screen Tracking
|
|
125
426
|
|
|
126
|
-
Track screen views
|
|
427
|
+
Track screen views to understand user navigation:
|
|
127
428
|
|
|
128
|
-
```
|
|
129
|
-
Zixflow
|
|
130
|
-
|
|
131
|
-
|
|
429
|
+
```typescript
|
|
430
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
431
|
+
|
|
432
|
+
// Track screen view
|
|
433
|
+
Zixflow.screen('HomeScreen');
|
|
434
|
+
|
|
435
|
+
// Track screen with properties
|
|
436
|
+
Zixflow.screen('ProductDetailScreen', {
|
|
437
|
+
product_id: '12345',
|
|
438
|
+
category: 'electronics'
|
|
132
439
|
});
|
|
133
440
|
```
|
|
134
441
|
|
|
135
|
-
|
|
442
|
+
**Automatic screen tracking** with React Navigation:
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import { NavigationContainer, NavigationContainerRef } from '@react-navigation/native';
|
|
446
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
447
|
+
import React, { useRef } from 'react';
|
|
448
|
+
|
|
449
|
+
export default function App() {
|
|
450
|
+
const navigationRef = useRef<NavigationContainerRef>(null);
|
|
451
|
+
const routeNameRef = useRef<string>();
|
|
452
|
+
|
|
453
|
+
return (
|
|
454
|
+
<NavigationContainer
|
|
455
|
+
ref={navigationRef}
|
|
456
|
+
onReady={() => {
|
|
457
|
+
routeNameRef.current = navigationRef.current?.getCurrentRoute()?.name;
|
|
458
|
+
}}
|
|
459
|
+
onStateChange={async () => {
|
|
460
|
+
const previousRouteName = routeNameRef.current;
|
|
461
|
+
const currentRouteName = navigationRef.current?.getCurrentRoute()?.name;
|
|
462
|
+
|
|
463
|
+
if (previousRouteName !== currentRouteName && currentRouteName) {
|
|
464
|
+
// Track screen change
|
|
465
|
+
Zixflow.screen(currentRouteName);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Save current route name
|
|
469
|
+
routeNameRef.current = currentRouteName;
|
|
470
|
+
}}
|
|
471
|
+
>
|
|
472
|
+
{/* Your navigation setup */}
|
|
473
|
+
</NavigationContainer>
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### User Profile Attributes
|
|
136
479
|
|
|
137
|
-
|
|
480
|
+
Set custom attributes on user profiles:
|
|
138
481
|
|
|
139
|
-
```
|
|
482
|
+
```typescript
|
|
483
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
484
|
+
|
|
485
|
+
// Set profile attributes
|
|
140
486
|
Zixflow.setProfileAttributes({
|
|
141
|
-
plan: '
|
|
142
|
-
|
|
487
|
+
plan: 'premium',
|
|
488
|
+
subscription_status: 'active',
|
|
489
|
+
last_login: new Date().toISOString(),
|
|
143
490
|
preferences: {
|
|
144
|
-
notifications: true,
|
|
145
491
|
newsletter: true,
|
|
146
|
-
|
|
492
|
+
notifications: true
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### Device Attributes
|
|
498
|
+
|
|
499
|
+
Set custom attributes on the current device:
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
503
|
+
|
|
504
|
+
// Set device attributes
|
|
505
|
+
Zixflow.setDeviceAttributes({
|
|
506
|
+
app_version: '2.1.0',
|
|
507
|
+
build_number: '421',
|
|
508
|
+
theme: 'dark',
|
|
509
|
+
language_preference: 'en-US'
|
|
147
510
|
});
|
|
148
511
|
```
|
|
149
512
|
|
|
513
|
+
### Clearing User Identity
|
|
514
|
+
|
|
515
|
+
Clear user identity when users log out:
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
519
|
+
|
|
520
|
+
// Clear identify on logout
|
|
521
|
+
const handleLogout = async () => {
|
|
522
|
+
// Clear Zixflow identity
|
|
523
|
+
Zixflow.clearIdentify();
|
|
524
|
+
|
|
525
|
+
// Perform other logout actions
|
|
526
|
+
// ...
|
|
527
|
+
};
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Push Notifications
|
|
533
|
+
|
|
534
|
+
Complete guide to implementing push notifications in React Native with Zixflow using Apple Push Notifications (APNs) or Firebase Cloud Messaging (FCM).
|
|
535
|
+
|
|
536
|
+
### Prerequisites
|
|
537
|
+
|
|
538
|
+
Before implementing push notifications:
|
|
539
|
+
|
|
540
|
+
1. **Configure push credentials in Zixflow dashboard** - Add APNs certificates or FCM Server Key
|
|
541
|
+
2. **Complete iOS/Android native setup** - Ensure native dependencies are installed
|
|
542
|
+
3. **Device tokens must be associated with users** - Call `identify()` before sending notifications
|
|
543
|
+
|
|
544
|
+
**Important Limitation**: The Zixflow React Native SDK currently supports deep links and images in push notifications. Custom action buttons require additional native code.
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
### Platform-Specific Requirements
|
|
549
|
+
|
|
550
|
+
#### iOS Requirements
|
|
551
|
+
|
|
552
|
+
- **APNs or FCM**: Choose either Apple Push Notification service or Firebase Cloud Messaging
|
|
553
|
+
- **Xcode Capabilities**: Push Notifications and Background Modes
|
|
554
|
+
- **Notification Service Extension**: Required for rich push (images, videos)
|
|
555
|
+
- **Physical Device**: iOS Simulator cannot receive push notifications
|
|
556
|
+
|
|
557
|
+
#### Android Requirements
|
|
558
|
+
|
|
559
|
+
- **Firebase Project**: Required for FCM integration
|
|
560
|
+
- **google-services.json**: Must be in `android/app/` directory
|
|
561
|
+
- **Minimum API Level 24**: Android 7.0 or higher
|
|
562
|
+
- **POST_NOTIFICATIONS Permission**: Required for Android 13+ (API 33+)
|
|
563
|
+
|
|
150
564
|
---
|
|
151
565
|
|
|
152
|
-
|
|
566
|
+
### iOS Setup
|
|
567
|
+
|
|
568
|
+
You can use either **APNs (Apple Push Notification service)** or **FCM (Firebase Cloud Messaging)** on iOS.
|
|
569
|
+
|
|
570
|
+
#### Step 1: Enable Push Capabilities in Xcode
|
|
571
|
+
|
|
572
|
+
1. Open your project's `.xcworkspace` file in Xcode
|
|
573
|
+
2. Select your app target
|
|
574
|
+
3. Go to **Signing & Capabilities** tab
|
|
575
|
+
4. Click **+ Capability** → Add **Push Notifications**
|
|
576
|
+
5. Click **+ Capability** → Add **Background Modes**
|
|
577
|
+
6. Enable **Remote notifications** under Background Modes
|
|
153
578
|
|
|
154
|
-
|
|
579
|
+
#### Step 2: Choose APNs or FCM
|
|
155
580
|
|
|
156
|
-
|
|
581
|
+
**Option A: APNs (Recommended for iOS-only apps)**
|
|
157
582
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
583
|
+
Update your `ios/Podfile`:
|
|
584
|
+
|
|
585
|
+
```ruby
|
|
586
|
+
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
|
587
|
+
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
|
588
|
+
|
|
589
|
+
platform :ios, '13.0'
|
|
590
|
+
|
|
591
|
+
target 'YourApp' do
|
|
592
|
+
config = use_native_modules!
|
|
593
|
+
|
|
594
|
+
use_react_native!(:path => config[:reactNativePath])
|
|
595
|
+
|
|
596
|
+
# Add Zixflow with APNs support
|
|
597
|
+
pod 'zixflow-reactnative/apn', :path => '../node_modules/zixflow-reactnative'
|
|
598
|
+
|
|
599
|
+
# Your other dependencies...
|
|
600
|
+
end
|
|
161
601
|
```
|
|
162
602
|
|
|
163
|
-
|
|
603
|
+
**Option B: FCM (For cross-platform Firebase apps)**
|
|
164
604
|
|
|
165
|
-
|
|
166
|
-
// Track when user receives a notification
|
|
167
|
-
Zixflow.pushMessaging.onMessageReceived((message) => {
|
|
168
|
-
console.log('Notification received:', message);
|
|
169
|
-
});
|
|
605
|
+
Update your `ios/Podfile` with static linkage:
|
|
170
606
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
607
|
+
```ruby
|
|
608
|
+
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
|
609
|
+
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
|
610
|
+
|
|
611
|
+
platform :ios, '13.0'
|
|
612
|
+
|
|
613
|
+
# Required for FCM
|
|
614
|
+
use_frameworks! :linkage => :static
|
|
615
|
+
|
|
616
|
+
target 'YourApp' do
|
|
617
|
+
config = use_native_modules!
|
|
618
|
+
|
|
619
|
+
use_react_native!(:path => config[:reactNativePath])
|
|
620
|
+
|
|
621
|
+
# Add Zixflow with FCM support
|
|
622
|
+
pod 'zixflow-reactnative/fcm', :path => '../node_modules/zixflow-reactnative'
|
|
623
|
+
|
|
624
|
+
# Your other dependencies...
|
|
625
|
+
end
|
|
175
626
|
```
|
|
176
627
|
|
|
177
|
-
|
|
628
|
+
**Install dependencies:**
|
|
178
629
|
|
|
179
|
-
|
|
630
|
+
```bash
|
|
631
|
+
cd ios
|
|
632
|
+
pod install
|
|
633
|
+
cd ..
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
#### Step 3: Configure AppDelegate (Swift - Recommended)
|
|
637
|
+
|
|
638
|
+
For modern Swift-based React Native apps with APNs:
|
|
639
|
+
|
|
640
|
+
**AppDelegate.swift:**
|
|
641
|
+
|
|
642
|
+
```swift
|
|
643
|
+
import UIKit
|
|
644
|
+
import ZixflowMessagingPushAPN
|
|
645
|
+
|
|
646
|
+
@main
|
|
647
|
+
class AppDelegateWithZixflowIntegration: ZixflowAppDelegateWrapper<AppDelegate> {}
|
|
180
648
|
|
|
181
|
-
|
|
649
|
+
class AppDelegate: NSObject, UIApplicationDelegate {
|
|
182
650
|
|
|
183
|
-
|
|
651
|
+
func application(
|
|
652
|
+
_ application: UIApplication,
|
|
653
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
654
|
+
) -> Bool {
|
|
655
|
+
// Set notification delegate
|
|
656
|
+
UNUserNotificationCenter.current().delegate = self
|
|
184
657
|
|
|
185
|
-
|
|
186
|
-
|
|
658
|
+
// Initialize Zixflow push messaging (APNs)
|
|
659
|
+
MessagingPushAPN.initialize(
|
|
660
|
+
withConfig: MessagingPushConfigBuilder()
|
|
661
|
+
.build()
|
|
662
|
+
)
|
|
187
663
|
|
|
188
|
-
|
|
189
|
-
Zixflow.inAppMessaging.registerEventsListener((event: InAppMessageEvent) => {
|
|
190
|
-
switch (event.eventType) {
|
|
191
|
-
case InAppMessageEventType.MessageShown:
|
|
192
|
-
console.log('In-app message shown:', event.message);
|
|
193
|
-
break;
|
|
194
|
-
case InAppMessageEventType.MessageClicked:
|
|
195
|
-
console.log('In-app message clicked:', event.message);
|
|
196
|
-
break;
|
|
197
|
-
case InAppMessageEventType.MessageDismissed:
|
|
198
|
-
console.log('In-app message dismissed:', event.message);
|
|
199
|
-
break;
|
|
664
|
+
return true
|
|
200
665
|
}
|
|
201
|
-
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
extension AppDelegate: UNUserNotificationCenterDelegate {
|
|
669
|
+
// Show notifications when app is in foreground
|
|
670
|
+
func userNotificationCenter(
|
|
671
|
+
_ center: UNUserNotificationCenter,
|
|
672
|
+
willPresent notification: UNNotification,
|
|
673
|
+
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
|
674
|
+
) {
|
|
675
|
+
completionHandler([.banner, .list, .badge, .sound])
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
```
|
|
202
679
|
|
|
203
|
-
|
|
204
|
-
|
|
680
|
+
**For FCM**, import `ZixflowMessagingPushFCM` instead:
|
|
681
|
+
|
|
682
|
+
```swift
|
|
683
|
+
import ZixflowMessagingPushFCM
|
|
684
|
+
|
|
685
|
+
// Initialize with FCM
|
|
686
|
+
MessagingPushFCM.initialize(
|
|
687
|
+
withConfig: MessagingPushConfigBuilder()
|
|
688
|
+
.build()
|
|
689
|
+
)
|
|
205
690
|
```
|
|
206
691
|
|
|
207
|
-
|
|
692
|
+
#### Step 4: Configure AppDelegate (Objective-C)
|
|
208
693
|
|
|
209
|
-
|
|
694
|
+
If your React Native app uses Objective-C, create a Swift bridge:
|
|
210
695
|
|
|
211
|
-
|
|
212
|
-
const inbox = Zixflow.inAppMessaging.inbox();
|
|
696
|
+
**Create `MyAppPushNotificationsHandler.swift`:**
|
|
213
697
|
|
|
214
|
-
|
|
215
|
-
|
|
698
|
+
```swift
|
|
699
|
+
import Foundation
|
|
700
|
+
import ZixflowMessagingPushAPN
|
|
216
701
|
|
|
217
|
-
|
|
218
|
-
|
|
702
|
+
@objc
|
|
703
|
+
public class MyAppPushNotificationsHandler: NSObject {
|
|
219
704
|
|
|
220
|
-
|
|
221
|
-
|
|
705
|
+
@objc(setupZixflowClickHandling)
|
|
706
|
+
public func setupZixflowClickHandling() {
|
|
707
|
+
MessagingPushAPN.initialize(
|
|
708
|
+
withConfig: MessagingPushConfigBuilder().build()
|
|
709
|
+
)
|
|
710
|
+
}
|
|
222
711
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
712
|
+
@objc(application:deviceToken:)
|
|
713
|
+
public func application(
|
|
714
|
+
_ application: UIApplication,
|
|
715
|
+
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
|
716
|
+
) {
|
|
717
|
+
MessagingPush.shared.application(
|
|
718
|
+
application,
|
|
719
|
+
didRegisterForRemoteNotificationsWithDeviceToken: deviceToken
|
|
720
|
+
)
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
@objc(application:error:)
|
|
724
|
+
public func application(
|
|
725
|
+
_ application: UIApplication,
|
|
726
|
+
didFailToRegisterForRemoteNotificationsWithError error: Error
|
|
727
|
+
) {
|
|
728
|
+
MessagingPush.shared.application(
|
|
729
|
+
application,
|
|
730
|
+
didFailToRegisterForRemoteNotificationsWithError: error
|
|
731
|
+
)
|
|
732
|
+
}
|
|
733
|
+
}
|
|
227
734
|
```
|
|
228
735
|
|
|
229
|
-
|
|
736
|
+
**Update `AppDelegate.mm`:**
|
|
737
|
+
|
|
738
|
+
```objc
|
|
739
|
+
#import "YourApp-Swift.h"
|
|
740
|
+
|
|
741
|
+
@implementation AppDelegate
|
|
742
|
+
|
|
743
|
+
MyAppPushNotificationsHandler* pnHandlerObj;
|
|
744
|
+
|
|
745
|
+
- (BOOL)application:(UIApplication *)application
|
|
746
|
+
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
|
747
|
+
// ... existing initialization code ...
|
|
230
748
|
|
|
231
|
-
|
|
749
|
+
// Register for remote notifications
|
|
750
|
+
[application registerForRemoteNotifications];
|
|
232
751
|
|
|
233
|
-
|
|
752
|
+
// Initialize push handling
|
|
753
|
+
pnHandlerObj = [[MyAppPushNotificationsHandler alloc] init];
|
|
754
|
+
[pnHandlerObj setupZixflowClickHandling];
|
|
234
755
|
|
|
235
|
-
|
|
236
|
-
|
|
756
|
+
return YES;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
- (void)application:(UIApplication *)application
|
|
760
|
+
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
|
761
|
+
[pnHandlerObj application:application deviceToken:deviceToken];
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
- (void)application:(UIApplication *)application
|
|
765
|
+
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
|
766
|
+
[pnHandlerObj application:application error:error];
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
@end
|
|
237
770
|
```
|
|
238
771
|
|
|
239
|
-
|
|
772
|
+
#### Step 5: Rich Push with Notification Service Extension
|
|
240
773
|
|
|
241
|
-
|
|
774
|
+
To support rich push notifications (images, videos, GIFs), add a Notification Service Extension:
|
|
242
775
|
|
|
243
|
-
|
|
776
|
+
**1. Create Notification Service Extension:**
|
|
244
777
|
|
|
245
|
-
|
|
778
|
+
1. In Xcode: **File** → **New** → **Target**
|
|
779
|
+
2. Select **Notification Service Extension**
|
|
780
|
+
3. Name it `NotificationServiceExtension`
|
|
781
|
+
4. Click **Finish** (activate scheme when prompted)
|
|
246
782
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
783
|
+
**2. Add Zixflow to Extension:**
|
|
784
|
+
|
|
785
|
+
Update your `ios/Podfile` to include the extension:
|
|
786
|
+
|
|
787
|
+
```ruby
|
|
788
|
+
# Main app target
|
|
789
|
+
target 'YourApp' do
|
|
790
|
+
# ... existing configuration ...
|
|
791
|
+
pod 'zixflow-reactnative/apn', :path => '../node_modules/zixflow-reactnative'
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
# Notification Service Extension target
|
|
795
|
+
target 'NotificationServiceExtension' do
|
|
796
|
+
pod 'zixflow-reactnative-richpush/apn', :path => '../node_modules/zixflow-reactnative'
|
|
797
|
+
end
|
|
253
798
|
```
|
|
254
799
|
|
|
255
|
-
|
|
800
|
+
For FCM:
|
|
801
|
+
|
|
802
|
+
```ruby
|
|
803
|
+
target 'NotificationServiceExtension' do
|
|
804
|
+
pod 'zixflow-reactnative-richpush/fcm', :path => '../node_modules/zixflow-reactnative'
|
|
805
|
+
end
|
|
806
|
+
```
|
|
256
807
|
|
|
257
|
-
|
|
808
|
+
**3. Install dependencies:**
|
|
258
809
|
|
|
259
|
-
```
|
|
260
|
-
|
|
810
|
+
```bash
|
|
811
|
+
cd ios
|
|
812
|
+
pod install
|
|
813
|
+
cd ..
|
|
261
814
|
```
|
|
262
815
|
|
|
263
|
-
|
|
816
|
+
**4. Update `NotificationService.swift`:**
|
|
817
|
+
|
|
818
|
+
```swift
|
|
819
|
+
import UserNotifications
|
|
820
|
+
import ZixflowMessagingPushAPN
|
|
821
|
+
|
|
822
|
+
class NotificationService: UNNotificationServiceExtension {
|
|
823
|
+
var contentHandler: ((UNNotificationContent) -> Void)?
|
|
824
|
+
var bestAttemptContent: UNMutableNotificationContent?
|
|
825
|
+
|
|
826
|
+
override func didReceive(
|
|
827
|
+
_ request: UNNotificationRequest,
|
|
828
|
+
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
|
|
829
|
+
) {
|
|
830
|
+
self.contentHandler = contentHandler
|
|
831
|
+
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
|
832
|
+
|
|
833
|
+
// Initialize SDK for extension
|
|
834
|
+
MessagingPushAPN.initializeForExtension(
|
|
835
|
+
withConfig: MessagingPushConfigBuilder(apiKey: "YOUR_API_KEY")
|
|
836
|
+
.build()
|
|
837
|
+
)
|
|
838
|
+
|
|
839
|
+
if let bestAttemptContent = bestAttemptContent {
|
|
840
|
+
// Let Zixflow handle rich push and track delivery
|
|
841
|
+
MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
|
|
842
|
+
}
|
|
843
|
+
}
|
|
264
844
|
|
|
265
|
-
|
|
845
|
+
override func serviceExtensionTimeWillExpire() {
|
|
846
|
+
// Called when extension is about to be terminated
|
|
847
|
+
MessagingPush.shared.serviceExtensionTimeWillExpire()
|
|
266
848
|
|
|
267
|
-
|
|
268
|
-
|
|
849
|
+
if let contentHandler = contentHandler,
|
|
850
|
+
let bestAttemptContent = bestAttemptContent {
|
|
851
|
+
contentHandler(bestAttemptContent)
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
269
855
|
```
|
|
270
856
|
|
|
857
|
+
**Important:** Replace `"YOUR_API_KEY"` with your actual API key.
|
|
858
|
+
|
|
271
859
|
---
|
|
272
860
|
|
|
273
|
-
|
|
861
|
+
### Android Setup
|
|
274
862
|
|
|
275
|
-
|
|
863
|
+
Android push notifications use Firebase Cloud Messaging (FCM).
|
|
276
864
|
|
|
277
|
-
1
|
|
865
|
+
#### Step 1: Add Firebase to Your Project
|
|
278
866
|
|
|
279
|
-
|
|
280
|
-
|
|
867
|
+
1. Go to [Firebase Console](https://console.firebase.google.com/)
|
|
868
|
+
2. Add your Android app to Firebase project
|
|
869
|
+
3. Download `google-services.json`
|
|
870
|
+
4. Place `google-services.json` in `android/app/` directory
|
|
281
871
|
|
|
282
|
-
|
|
283
|
-
pod 'zixflow-reactnative/fcm', :path => '../node_modules/zixflow-reactnative'
|
|
872
|
+
#### Step 2: Configure Gradle
|
|
284
873
|
|
|
285
|
-
|
|
286
|
-
pod 'zixflow-reactnative/apn', :path => '../node_modules/zixflow-reactnative'
|
|
874
|
+
**Project-level `android/build.gradle`:**
|
|
287
875
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
876
|
+
```gradle
|
|
877
|
+
buildscript {
|
|
878
|
+
ext {
|
|
879
|
+
minSdkVersion = 24
|
|
880
|
+
compileSdkVersion = 34
|
|
881
|
+
targetSdkVersion = 34
|
|
882
|
+
}
|
|
291
883
|
|
|
292
|
-
|
|
884
|
+
dependencies {
|
|
885
|
+
classpath 'com.google.gms:google-services:4.4.2'
|
|
886
|
+
}
|
|
887
|
+
}
|
|
293
888
|
|
|
294
|
-
|
|
889
|
+
allprojects {
|
|
890
|
+
repositories {
|
|
891
|
+
google()
|
|
892
|
+
mavenCentral()
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
```
|
|
295
896
|
|
|
296
|
-
|
|
897
|
+
**App-level `android/app/build.gradle`:**
|
|
297
898
|
|
|
298
|
-
|
|
899
|
+
```gradle
|
|
900
|
+
apply plugin: 'com.android.application'
|
|
901
|
+
apply plugin: 'com.google.gms.google-services' // Add this line
|
|
299
902
|
|
|
300
|
-
|
|
903
|
+
android {
|
|
904
|
+
// ... existing configuration ...
|
|
905
|
+
}
|
|
301
906
|
|
|
302
|
-
|
|
303
|
-
|
|
907
|
+
dependencies {
|
|
908
|
+
// React Native auto-linking handles Zixflow dependencies
|
|
909
|
+
// ... your other dependencies ...
|
|
910
|
+
}
|
|
304
911
|
```
|
|
305
912
|
|
|
306
|
-
|
|
913
|
+
#### Step 3: Add Permissions
|
|
307
914
|
|
|
308
|
-
|
|
915
|
+
Add to `android/app/src/main/AndroidManifest.xml`:
|
|
309
916
|
|
|
310
|
-
|
|
917
|
+
```xml
|
|
918
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
311
919
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
| `cdpApiKey` | `string` | ✅ | Your Zixflow API key |
|
|
315
|
-
| `migrationSiteId` | `string` | ❌ | Site ID for migration from older SDKs |
|
|
316
|
-
| `region` | `ZixflowRegion` | ❌ | US or EU region (default: US) |
|
|
317
|
-
| `logLevel` | `ZixflowLogLevel` | ❌ | Logging verbosity (default: error) |
|
|
318
|
-
| `trackApplicationLifecycleEvents` | `boolean` | ❌ | Auto-track app lifecycle events |
|
|
319
|
-
| `inApp` | `object` | ❌ | In-app messaging configuration |
|
|
320
|
-
| `push` | `object` | ❌ | Push notification configuration |
|
|
920
|
+
<!-- Required for push notifications -->
|
|
921
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
321
922
|
|
|
322
|
-
|
|
923
|
+
<!-- Required for Android 13+ (API 33+) -->
|
|
924
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
925
|
+
|
|
926
|
+
<application>
|
|
927
|
+
<!-- Your app configuration -->
|
|
928
|
+
</application>
|
|
929
|
+
</manifest>
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
#### Step 4: Configure Notification Icon and Color (Optional)
|
|
323
933
|
|
|
324
|
-
|
|
934
|
+
Add to `android/app/src/main/AndroidManifest.xml` inside `<application>` tag:
|
|
325
935
|
|
|
326
|
-
|
|
936
|
+
```xml
|
|
937
|
+
<application>
|
|
938
|
+
<!-- Default notification icon (white, transparent background) -->
|
|
939
|
+
<meta-data
|
|
940
|
+
android:name="com.google.firebase.messaging.default_notification_icon"
|
|
941
|
+
android:resource="@drawable/ic_notification" />
|
|
327
942
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
ZixflowPushMessaging,
|
|
334
|
-
ZixflowLocation,
|
|
335
|
-
CustomAttributes,
|
|
336
|
-
IdentifyParams,
|
|
337
|
-
InAppMessage,
|
|
338
|
-
InboxMessage,
|
|
339
|
-
} from 'zixflow-reactnative';
|
|
943
|
+
<!-- Default notification color (accent color) -->
|
|
944
|
+
<meta-data
|
|
945
|
+
android:name="com.google.firebase.messaging.default_notification_color"
|
|
946
|
+
android:resource="@color/notification_color" />
|
|
947
|
+
</application>
|
|
340
948
|
```
|
|
341
949
|
|
|
342
950
|
---
|
|
343
951
|
|
|
344
|
-
|
|
952
|
+
### React Native Integration
|
|
345
953
|
|
|
346
|
-
|
|
954
|
+
#### Step 1: Initialize SDK
|
|
347
955
|
|
|
348
|
-
|
|
349
|
-
// In-app messaging
|
|
350
|
-
Zixflow.inAppMessaging.registerEventsListener(listener);
|
|
956
|
+
Initialize the Zixflow SDK in your `App.tsx`:
|
|
351
957
|
|
|
352
|
-
|
|
353
|
-
|
|
958
|
+
```typescript
|
|
959
|
+
import React, { useEffect } from 'react';
|
|
960
|
+
import { Zixflow, ZixflowConfig, ZixflowLogLevel } from 'zixflow-reactnative';
|
|
354
961
|
|
|
355
|
-
|
|
356
|
-
|
|
962
|
+
export default function App() {
|
|
963
|
+
useEffect(() => {
|
|
964
|
+
// Configure the SDK
|
|
965
|
+
const config: ZixflowConfig = {
|
|
966
|
+
apiKey: 'YOUR_API_KEY',
|
|
967
|
+
logLevel: ZixflowLogLevel.debug,
|
|
968
|
+
inApp: {
|
|
969
|
+
},
|
|
970
|
+
autoTrackDeviceAttributes: true,
|
|
971
|
+
trackApplicationLifecycleEvents: true,
|
|
972
|
+
};
|
|
973
|
+
|
|
974
|
+
// Initialize the SDK
|
|
975
|
+
Zixflow.initialize(config);
|
|
976
|
+
|
|
977
|
+
console.log('Zixflow SDK initialized');
|
|
978
|
+
}, []);
|
|
979
|
+
|
|
980
|
+
return (
|
|
981
|
+
// Your app UI
|
|
982
|
+
);
|
|
983
|
+
}
|
|
357
984
|
```
|
|
358
985
|
|
|
359
|
-
|
|
986
|
+
#### Step 2: Request Push Permission
|
|
987
|
+
|
|
988
|
+
Request permission to send push notifications:
|
|
989
|
+
|
|
990
|
+
```typescript
|
|
991
|
+
import React, { useState } from 'react';
|
|
992
|
+
import { Button, Alert } from 'react-native';
|
|
993
|
+
import { Zixflow, ZixflowPushPermissionStatus } from 'zixflow-reactnative';
|
|
994
|
+
|
|
995
|
+
export default function PushPermissionButton() {
|
|
996
|
+
const [permissionStatus, setPermissionStatus] = useState<ZixflowPushPermissionStatus | null>(null);
|
|
997
|
+
|
|
998
|
+
const requestPushPermission = async () => {
|
|
999
|
+
try {
|
|
1000
|
+
const permission = await Zixflow.pushMessaging.showPromptForPushNotifications({
|
|
1001
|
+
ios: {
|
|
1002
|
+
sound: true,
|
|
1003
|
+
badge: true,
|
|
1004
|
+
alert: true,
|
|
1005
|
+
},
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
setPermissionStatus(permission);
|
|
1009
|
+
|
|
1010
|
+
switch (permission) {
|
|
1011
|
+
case ZixflowPushPermissionStatus.Granted:
|
|
1012
|
+
Alert.alert('Success', 'Push notifications enabled!');
|
|
1013
|
+
console.log('Push notifications enabled');
|
|
1014
|
+
break;
|
|
1015
|
+
|
|
1016
|
+
case ZixflowPushPermissionStatus.Denied:
|
|
1017
|
+
Alert.alert('Denied', 'Push notification permission was denied');
|
|
1018
|
+
console.log('Push notifications denied');
|
|
1019
|
+
break;
|
|
1020
|
+
|
|
1021
|
+
case ZixflowPushPermissionStatus.NotDetermined:
|
|
1022
|
+
// iOS only: permission not yet asked
|
|
1023
|
+
console.log('Push notification permission not determined');
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
} catch (error) {
|
|
1027
|
+
console.error('Failed to request push permission:', error);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
360
1030
|
|
|
361
|
-
|
|
1031
|
+
return (
|
|
1032
|
+
<Button
|
|
1033
|
+
title="Enable Push Notifications"
|
|
1034
|
+
onPress={requestPushPermission}
|
|
1035
|
+
/>
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
```
|
|
362
1039
|
|
|
363
|
-
|
|
1040
|
+
**Permission Options (iOS)**:
|
|
364
1041
|
|
|
365
|
-
|
|
1042
|
+
| Option | Type | Description |
|
|
1043
|
+
|--------|------|-------------|
|
|
1044
|
+
| `sound` | boolean | Enable notification sounds |
|
|
1045
|
+
| `badge` | boolean | Enable app badge updates |
|
|
1046
|
+
| `alert` | boolean | Show notification alerts |
|
|
366
1047
|
|
|
367
|
-
|
|
368
|
-
- User identification
|
|
369
|
-
- Event tracking
|
|
370
|
-
- Push notifications
|
|
371
|
-
- In-app messaging
|
|
372
|
-
- Location tracking
|
|
373
|
-
- Inbox management
|
|
1048
|
+
#### Step 3: Check Permission Status
|
|
374
1049
|
|
|
375
|
-
|
|
1050
|
+
Check current push permission status:
|
|
376
1051
|
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
npm install
|
|
1052
|
+
```typescript
|
|
1053
|
+
import { Zixflow, ZixflowPushPermissionStatus } from 'zixflow-reactnative';
|
|
380
1054
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
1055
|
+
const checkPushPermission = async () => {
|
|
1056
|
+
try {
|
|
1057
|
+
const status = await Zixflow.pushMessaging.getPushPermissionStatus();
|
|
384
1058
|
|
|
385
|
-
|
|
386
|
-
|
|
1059
|
+
console.log('Push permission status:', status);
|
|
1060
|
+
|
|
1061
|
+
if (status === ZixflowPushPermissionStatus.Granted) {
|
|
1062
|
+
console.log('Push notifications are enabled');
|
|
1063
|
+
} else if (status === ZixflowPushPermissionStatus.Denied) {
|
|
1064
|
+
console.log('Push notifications are disabled');
|
|
1065
|
+
} else {
|
|
1066
|
+
console.log('Push permission not determined');
|
|
1067
|
+
}
|
|
1068
|
+
} catch (error) {
|
|
1069
|
+
console.error('Failed to get push permission status:', error);
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
387
1072
|
```
|
|
388
1073
|
|
|
389
|
-
|
|
1074
|
+
#### Step 4: Identify Users
|
|
390
1075
|
|
|
391
|
-
|
|
1076
|
+
**Critical**: Device tokens must be associated with a user before push notifications can be delivered.
|
|
392
1077
|
|
|
393
|
-
|
|
1078
|
+
```typescript
|
|
1079
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
394
1080
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
1081
|
+
// Identify user when they log in
|
|
1082
|
+
const handleLogin = async (userId: string, userEmail: string) => {
|
|
1083
|
+
try {
|
|
1084
|
+
// Identify user with Zixflow
|
|
1085
|
+
Zixflow.identify({
|
|
1086
|
+
userId: userId,
|
|
1087
|
+
traits: {
|
|
1088
|
+
email: userEmail,
|
|
1089
|
+
firstName: 'John',
|
|
1090
|
+
lastName: 'Doe',
|
|
1091
|
+
plan: 'premium',
|
|
1092
|
+
},
|
|
1093
|
+
});
|
|
398
1094
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
1095
|
+
console.log('User identified:', userId);
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
console.error('Failed to identify user:', error);
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
```
|
|
403
1101
|
|
|
404
|
-
**
|
|
405
|
-
-
|
|
406
|
-
-
|
|
407
|
-
-
|
|
1102
|
+
**Important Notes:**
|
|
1103
|
+
- When users start the app, they automatically generate a device token
|
|
1104
|
+
- 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
|
|
408
1107
|
|
|
409
|
-
|
|
1108
|
+
#### Step 5: Get Device Token
|
|
410
1109
|
|
|
411
|
-
|
|
1110
|
+
Retrieve the registered device token:
|
|
412
1111
|
|
|
413
|
-
|
|
1112
|
+
```typescript
|
|
1113
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
414
1114
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
1115
|
+
const getDeviceToken = async () => {
|
|
1116
|
+
try {
|
|
1117
|
+
const token = await Zixflow.pushMessaging.getRegisteredDeviceToken();
|
|
1118
|
+
console.log('Device token:', token);
|
|
1119
|
+
return token;
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
console.error('Failed to get device token:', error);
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
```
|
|
420
1126
|
|
|
421
1127
|
---
|
|
422
1128
|
|
|
423
|
-
|
|
1129
|
+
### Deep Links and Navigation
|
|
424
1130
|
|
|
425
|
-
|
|
1131
|
+
Handle deep links from push notifications:
|
|
426
1132
|
|
|
427
|
-
|
|
428
|
-
2. Follow our [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
429
|
-
3. Check out [DEVELOPMENT.md](DEVELOPMENT.md) for development guidelines
|
|
430
|
-
4. Open issues or pull requests on [GitHub](https://github.com/zixflow/zixflow-reactnative)
|
|
1133
|
+
#### Setup Deep Linking
|
|
431
1134
|
|
|
432
|
-
|
|
1135
|
+
**1. Configure Deep Links (iOS):**
|
|
1136
|
+
|
|
1137
|
+
Add to `ios/YourApp/Info.plist`:
|
|
433
1138
|
|
|
434
|
-
|
|
1139
|
+
```xml
|
|
1140
|
+
<key>CFBundleURLTypes</key>
|
|
1141
|
+
<array>
|
|
1142
|
+
<dict>
|
|
1143
|
+
<key>CFBundleURLSchemes</key>
|
|
1144
|
+
<array>
|
|
1145
|
+
<string>yourapp</string>
|
|
1146
|
+
</array>
|
|
1147
|
+
</dict>
|
|
1148
|
+
</array>
|
|
1149
|
+
```
|
|
435
1150
|
|
|
436
|
-
|
|
437
|
-
- 💬 [Community Forum](https://community.zixflow.com)
|
|
438
|
-
- 🐛 [Issue Tracker](https://github.com/zixflow/zixflow-reactnative/issues)
|
|
439
|
-
- 📧 Email: apps@zixflow.com
|
|
1151
|
+
**2. Configure Deep Links (Android):**
|
|
440
1152
|
|
|
441
|
-
|
|
1153
|
+
Add to `android/app/src/main/AndroidManifest.xml`:
|
|
442
1154
|
|
|
443
|
-
|
|
1155
|
+
```xml
|
|
1156
|
+
<activity android:name=".MainActivity">
|
|
1157
|
+
<!-- Existing intent filter -->
|
|
444
1158
|
|
|
445
|
-
|
|
1159
|
+
<!-- Deep link intent filter -->
|
|
1160
|
+
<intent-filter>
|
|
1161
|
+
<action android:name="android.intent.action.VIEW" />
|
|
1162
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
1163
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
446
1164
|
|
|
447
|
-
|
|
1165
|
+
<data
|
|
1166
|
+
android:scheme="yourapp"
|
|
1167
|
+
android:host="*" />
|
|
1168
|
+
</intent-filter>
|
|
1169
|
+
|
|
1170
|
+
<!-- Universal Links (optional) -->
|
|
1171
|
+
<intent-filter android:autoVerify="true">
|
|
1172
|
+
<action android:name="android.intent.action.VIEW" />
|
|
1173
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
1174
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
448
1175
|
|
|
449
|
-
|
|
1176
|
+
<data
|
|
1177
|
+
android:scheme="https"
|
|
1178
|
+
android:host="yourapp.com" />
|
|
1179
|
+
</intent-filter>
|
|
1180
|
+
</activity>
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
#### Handle Deep Links in React Native
|
|
1184
|
+
|
|
1185
|
+
Use React Navigation's linking configuration:
|
|
1186
|
+
|
|
1187
|
+
```typescript
|
|
1188
|
+
import React from 'react';
|
|
1189
|
+
import { NavigationContainer } from '@react-navigation/native';
|
|
1190
|
+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
1191
|
+
import { Linking } from 'react-native';
|
|
1192
|
+
|
|
1193
|
+
const Stack = createNativeStackNavigator();
|
|
1194
|
+
|
|
1195
|
+
const linking = {
|
|
1196
|
+
prefixes: ['yourapp://', 'https://yourapp.com'],
|
|
1197
|
+
config: {
|
|
1198
|
+
screens: {
|
|
1199
|
+
Home: 'home',
|
|
1200
|
+
Product: 'product/:id',
|
|
1201
|
+
Profile: 'profile',
|
|
1202
|
+
},
|
|
1203
|
+
},
|
|
1204
|
+
};
|
|
1205
|
+
|
|
1206
|
+
export default function App() {
|
|
1207
|
+
return (
|
|
1208
|
+
<NavigationContainer linking={linking}>
|
|
1209
|
+
<Stack.Navigator>
|
|
1210
|
+
<Stack.Screen name="Home" component={HomeScreen} />
|
|
1211
|
+
<Stack.Screen name="Product" component={ProductScreen} />
|
|
1212
|
+
<Stack.Screen name="Profile" component={ProfileScreen} />
|
|
1213
|
+
</Stack.Navigator>
|
|
1214
|
+
</NavigationContainer>
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
---
|
|
1220
|
+
|
|
1221
|
+
### Rich Push Notification Payloads
|
|
1222
|
+
|
|
1223
|
+
The Zixflow SDK automatically handles rich push notifications. Here's how to structure payloads:
|
|
1224
|
+
|
|
1225
|
+
#### iOS APNs Payload
|
|
1226
|
+
|
|
1227
|
+
```json
|
|
1228
|
+
{
|
|
1229
|
+
"aps": {
|
|
1230
|
+
"mutable-content": 1,
|
|
1231
|
+
"alert": {
|
|
1232
|
+
"title": "New Product Available",
|
|
1233
|
+
"body": "Check out our latest premium features"
|
|
1234
|
+
},
|
|
1235
|
+
"badge": 1,
|
|
1236
|
+
"sound": "default"
|
|
1237
|
+
},
|
|
1238
|
+
"Zixflow": {
|
|
1239
|
+
"push": {
|
|
1240
|
+
"link": "yourapp://product/123",
|
|
1241
|
+
"image": "https://example.com/product-image.jpg"
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
#### iOS FCM Payload
|
|
1248
|
+
|
|
1249
|
+
```json
|
|
1250
|
+
{
|
|
1251
|
+
"message": {
|
|
1252
|
+
"apns": {
|
|
1253
|
+
"payload": {
|
|
1254
|
+
"aps": {
|
|
1255
|
+
"mutable-content": 1,
|
|
1256
|
+
"alert": {
|
|
1257
|
+
"title": "Special Offer",
|
|
1258
|
+
"body": "Limited time discount!"
|
|
1259
|
+
}
|
|
1260
|
+
},
|
|
1261
|
+
"Zixflow": {
|
|
1262
|
+
"push": {
|
|
1263
|
+
"link": "https://yourapp.com/offers",
|
|
1264
|
+
"image": "https://example.com/offer.png"
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
},
|
|
1268
|
+
"headers": {
|
|
1269
|
+
"apns-priority": 10
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1276
|
+
#### Android FCM Payload
|
|
1277
|
+
|
|
1278
|
+
```json
|
|
1279
|
+
{
|
|
1280
|
+
"message": {
|
|
1281
|
+
"data": {
|
|
1282
|
+
"title": "Order Shipped",
|
|
1283
|
+
"body": "Your order is on the way!",
|
|
1284
|
+
"image": "https://example.com/shipping.jpg",
|
|
1285
|
+
"link": "yourapp://orders/456"
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
```
|
|
1290
|
+
|
|
1291
|
+
---
|
|
1292
|
+
|
|
1293
|
+
### Testing Push Notifications
|
|
1294
|
+
|
|
1295
|
+
#### 1. Verify Device Token Registration
|
|
1296
|
+
|
|
1297
|
+
Check if device token is registered:
|
|
1298
|
+
|
|
1299
|
+
```typescript
|
|
1300
|
+
const verifyPushSetup = async () => {
|
|
1301
|
+
try {
|
|
1302
|
+
const token = await Zixflow.pushMessaging.getRegisteredDeviceToken();
|
|
1303
|
+
const status = await Zixflow.pushMessaging.getPushPermissionStatus();
|
|
1304
|
+
|
|
1305
|
+
console.log('Device token:', token);
|
|
1306
|
+
console.log('Permission status:', status);
|
|
1307
|
+
|
|
1308
|
+
if (token && status === ZixflowPushPermissionStatus.Granted) {
|
|
1309
|
+
console.log('✓ Push notifications ready');
|
|
1310
|
+
} else {
|
|
1311
|
+
console.log('✗ Push setup incomplete');
|
|
1312
|
+
}
|
|
1313
|
+
} catch (error) {
|
|
1314
|
+
console.error('Push verification failed:', error);
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
```
|
|
1318
|
+
|
|
1319
|
+
#### 2. Enable Debug Logging
|
|
1320
|
+
|
|
1321
|
+
Set log level to debug during development:
|
|
1322
|
+
|
|
1323
|
+
```typescript
|
|
1324
|
+
const config: ZixflowConfig = {
|
|
1325
|
+
apiKey: 'YOUR_API_KEY',
|
|
1326
|
+
logLevel: ZixflowLogLevel.debug, // Verbose logging
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
Zixflow.initialize(config);
|
|
1330
|
+
```
|
|
1331
|
+
|
|
1332
|
+
#### 3. Test on Physical Devices
|
|
1333
|
+
|
|
1334
|
+
**iOS:**
|
|
1335
|
+
- Push notifications **do not work** on iOS Simulator
|
|
1336
|
+
- Must use physical iOS device
|
|
1337
|
+
- Ensure APNs certificate is configured in Zixflow dashboard
|
|
1338
|
+
|
|
1339
|
+
**Android:**
|
|
1340
|
+
- Emulator works if Google Play Services installed
|
|
1341
|
+
- Physical device always recommended
|
|
1342
|
+
- Ensure FCM Server Key is configured in Zixflow dashboard
|
|
1343
|
+
|
|
1344
|
+
#### 4. Send Test Push from Zixflow
|
|
1345
|
+
|
|
1346
|
+
1. Log into Zixflow dashboard
|
|
1347
|
+
2. Navigate to **Messaging** → **Push Notifications**
|
|
1348
|
+
3. Create test push notification
|
|
1349
|
+
4. Send to specific user (using `userId` from `identify()`)
|
|
1350
|
+
|
|
1351
|
+
---
|
|
1352
|
+
|
|
1353
|
+
### Troubleshooting
|
|
1354
|
+
|
|
1355
|
+
#### iOS Push Not Received
|
|
1356
|
+
|
|
1357
|
+
**Symptoms:** Push sent but not delivered on iOS
|
|
1358
|
+
|
|
1359
|
+
**Solutions:**
|
|
1360
|
+
1. Verify Push Notifications capability enabled in Xcode
|
|
1361
|
+
2. Check APNs certificate uploaded to Zixflow dashboard
|
|
1362
|
+
3. Ensure testing on physical device (not simulator)
|
|
1363
|
+
4. Verify user identified: `Zixflow.identify({ userId: ... })`
|
|
1364
|
+
5. Check permission granted: `getPushPermissionStatus()`
|
|
1365
|
+
6. Review logs for errors
|
|
1366
|
+
|
|
1367
|
+
#### Android Push Not Received
|
|
1368
|
+
|
|
1369
|
+
**Symptoms:** Push sent but not delivered on Android
|
|
1370
|
+
|
|
1371
|
+
**Solutions:**
|
|
1372
|
+
1. Verify `google-services.json` in `android/app/` directory
|
|
1373
|
+
2. Check FCM Server Key in Zixflow dashboard
|
|
1374
|
+
3. Ensure POST_NOTIFICATIONS permission granted (Android 13+)
|
|
1375
|
+
4. Verify Google Services plugin applied
|
|
1376
|
+
5. Check device token registered
|
|
1377
|
+
6. Review logs for errors
|
|
1378
|
+
|
|
1379
|
+
#### Rich Push Not Working (Images)
|
|
1380
|
+
|
|
1381
|
+
**Symptoms:** Images not loading in notifications
|
|
1382
|
+
|
|
1383
|
+
**iOS Solutions:**
|
|
1384
|
+
1. Ensure Notification Service Extension properly configured
|
|
1385
|
+
2. Verify extension has correct dependencies in Podfile
|
|
1386
|
+
3. Check App Groups configuration (if using)
|
|
1387
|
+
4. Verify image URL is accessible
|
|
1388
|
+
5. Check extension logs for errors
|
|
1389
|
+
|
|
1390
|
+
**Android Solutions:**
|
|
1391
|
+
1. Verify image URL is accessible from device
|
|
1392
|
+
2. Check internet connectivity
|
|
1393
|
+
3. Ensure image format is supported (JPEG, PNG, GIF)
|
|
1394
|
+
|
|
1395
|
+
#### Permission Denied
|
|
1396
|
+
|
|
1397
|
+
**Symptoms:** User denied push permission
|
|
1398
|
+
|
|
1399
|
+
**Solutions:**
|
|
1400
|
+
1. Explain value before requesting permission
|
|
1401
|
+
2. Guide users to Settings to enable manually
|
|
1402
|
+
3. Show in-app message explaining benefits
|
|
1403
|
+
4. Request permission at appropriate time (after user engagement)
|
|
1404
|
+
|
|
1405
|
+
#### Device Token Not Registered
|
|
1406
|
+
|
|
1407
|
+
**Symptoms:** `getRegisteredDeviceToken()` returns empty or fails
|
|
1408
|
+
|
|
1409
|
+
**Solutions:**
|
|
1410
|
+
1. Verify SDK initialized before calling
|
|
1411
|
+
2. Check permission granted
|
|
1412
|
+
3. Ensure identify() called to associate token
|
|
1413
|
+
4. Review native logs for errors
|
|
1414
|
+
5. Rebuild app and retry
|
|
1415
|
+
|
|
1416
|
+
---
|
|
1417
|
+
|
|
1418
|
+
### Best Practices
|
|
1419
|
+
|
|
1420
|
+
1. **Request permission thoughtfully** - Explain value before asking
|
|
1421
|
+
2. **Identify users immediately** after authentication
|
|
1422
|
+
3. **Test on physical devices** - Simulators have limitations
|
|
1423
|
+
4. **Use rich push** - Images increase engagement
|
|
1424
|
+
5. **Handle deep links** - Provide seamless navigation
|
|
1425
|
+
6. **Monitor metrics** - Track delivery and open rates
|
|
1426
|
+
7. **Enable debug logging** - During development only
|
|
1427
|
+
8. **Test both platforms** - iOS and Android behave differently
|
|
1428
|
+
9. **Clear identity on logout** - Call `clearIdentify()`
|
|
1429
|
+
10. **Keep credentials secure** - Never commit API keys to git
|
|
1430
|
+
|
|
1431
|
+
---
|
|
1432
|
+
|
|
1433
|
+
### Next Steps
|
|
1434
|
+
|
|
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
|
|
1438
|
+
|
|
1439
|
+
---
|
|
1440
|
+
|
|
1441
|
+
## In-App Messaging
|
|
1442
|
+
|
|
1443
|
+
### Event Listeners
|
|
1444
|
+
|
|
1445
|
+
Register event listeners to respond to in-app message events:
|
|
1446
|
+
|
|
1447
|
+
```typescript
|
|
1448
|
+
import { Zixflow, InAppMessageEvent, InAppMessageEventType } from 'zixflow-reactnative';
|
|
1449
|
+
import { useEffect } from 'react';
|
|
1450
|
+
|
|
1451
|
+
export default function App() {
|
|
1452
|
+
useEffect(() => {
|
|
1453
|
+
const inAppMessaging = Zixflow.inAppMessaging;
|
|
1454
|
+
|
|
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;
|
|
1460
|
+
|
|
1461
|
+
case InAppMessageEventType.messageDismissed:
|
|
1462
|
+
console.log('In-app message dismissed', event);
|
|
1463
|
+
break;
|
|
1464
|
+
|
|
1465
|
+
case InAppMessageEventType.messageActionTaken:
|
|
1466
|
+
console.log('Action taken on in-app message', event);
|
|
1467
|
+
handleMessageAction(event);
|
|
1468
|
+
break;
|
|
1469
|
+
|
|
1470
|
+
case InAppMessageEventType.errorWithMessage:
|
|
1471
|
+
console.error('Error with in-app message', event);
|
|
1472
|
+
break;
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
// Cleanup listener on unmount
|
|
1477
|
+
return () => {
|
|
1478
|
+
eventListener.remove();
|
|
1479
|
+
};
|
|
1480
|
+
}, []);
|
|
1481
|
+
|
|
1482
|
+
return (
|
|
1483
|
+
// Your app UI
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
### Message Events
|
|
1489
|
+
|
|
1490
|
+
The SDK provides the following in-app message event types:
|
|
1491
|
+
|
|
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 |
|
|
1498
|
+
|
|
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`)
|
|
1505
|
+
|
|
1506
|
+
### Dismissing Messages
|
|
1507
|
+
|
|
1508
|
+
Programmatically dismiss the current in-app message:
|
|
1509
|
+
|
|
1510
|
+
```typescript
|
|
1511
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1512
|
+
|
|
1513
|
+
const handleMessageAction = (event: InAppMessageEvent) => {
|
|
1514
|
+
if (event.actionValue === 'dismiss' || event.actionValue === 'close') {
|
|
1515
|
+
// Dismiss the message
|
|
1516
|
+
Zixflow.inAppMessaging.dismissMessage();
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
```
|
|
1520
|
+
|
|
1521
|
+
---
|
|
1522
|
+
|
|
1523
|
+
## Location Tracking
|
|
1524
|
+
|
|
1525
|
+
Enable location tracking to send location-based messages:
|
|
1526
|
+
|
|
1527
|
+
```typescript
|
|
1528
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1529
|
+
|
|
1530
|
+
// Location tracking is configured via the native SDK
|
|
1531
|
+
// Make sure to request location permissions in your app
|
|
1532
|
+
|
|
1533
|
+
// iOS: Add location permission keys to Info.plist
|
|
1534
|
+
// - NSLocationWhenInUseUsageDescription
|
|
1535
|
+
// - NSLocationAlwaysAndWhenInUseUsageDescription
|
|
1536
|
+
|
|
1537
|
+
// Android: Add location permissions to AndroidManifest.xml
|
|
1538
|
+
// - ACCESS_FINE_LOCATION
|
|
1539
|
+
// - ACCESS_COARSE_LOCATION
|
|
1540
|
+
```
|
|
1541
|
+
|
|
1542
|
+
Request location permissions using a library like `react-native-permissions`:
|
|
1543
|
+
|
|
1544
|
+
```typescript
|
|
1545
|
+
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions';
|
|
1546
|
+
import { Platform } from 'react-native';
|
|
1547
|
+
|
|
1548
|
+
const requestLocationPermission = async () => {
|
|
1549
|
+
const permission = Platform.select({
|
|
1550
|
+
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE,
|
|
1551
|
+
android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
|
|
1552
|
+
});
|
|
1553
|
+
|
|
1554
|
+
if (!permission) return;
|
|
1555
|
+
|
|
1556
|
+
const result = await request(permission);
|
|
1557
|
+
|
|
1558
|
+
if (result === RESULTS.GRANTED) {
|
|
1559
|
+
console.log('Location permission granted');
|
|
1560
|
+
}
|
|
1561
|
+
};
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
---
|
|
1565
|
+
|
|
1566
|
+
## Advanced Configuration
|
|
1567
|
+
|
|
1568
|
+
### Region Settings
|
|
1569
|
+
|
|
1570
|
+
Configure the data center region for data residency:
|
|
1571
|
+
|
|
1572
|
+
```typescript
|
|
1573
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1574
|
+
|
|
1575
|
+
const config = {
|
|
1576
|
+
apiKey: 'YOUR_API_KEY',
|
|
1577
|
+
// or
|
|
1578
|
+
};
|
|
1579
|
+
|
|
1580
|
+
Zixflow.initialize(config);
|
|
1581
|
+
```
|
|
1582
|
+
|
|
1583
|
+
**Available regions**:
|
|
1584
|
+
- `` - United States data center
|
|
1585
|
+
- `` - European Union data center
|
|
1586
|
+
|
|
1587
|
+
### Log Levels
|
|
1588
|
+
|
|
1589
|
+
Control SDK logging for debugging:
|
|
1590
|
+
|
|
1591
|
+
```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);
|
|
1600
|
+
```
|
|
1601
|
+
|
|
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)
|
|
1607
|
+
|
|
1608
|
+
### Auto-Tracking Options
|
|
1609
|
+
|
|
1610
|
+
Configure automatic tracking features:
|
|
1611
|
+
|
|
1612
|
+
```typescript
|
|
1613
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1614
|
+
|
|
1615
|
+
const config = {
|
|
1616
|
+
apiKey: 'YOUR_API_KEY',
|
|
1617
|
+
|
|
1618
|
+
// Automatically track device attributes (OS, model, app version)
|
|
1619
|
+
autoTrackDeviceAttributes: true,
|
|
1620
|
+
|
|
1621
|
+
// Automatically track app lifecycle events (open, close, background)
|
|
1622
|
+
trackApplicationLifecycleEvents: true,
|
|
1623
|
+
|
|
1624
|
+
// Automatically track screens (requires integration)
|
|
1625
|
+
autoTrackScreenViews: true,
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1628
|
+
Zixflow.initialize(config);
|
|
1629
|
+
```
|
|
1630
|
+
|
|
1631
|
+
### Custom API Hosts
|
|
1632
|
+
|
|
1633
|
+
Override API endpoints for testing or custom infrastructure:
|
|
1634
|
+
|
|
1635
|
+
```typescript
|
|
1636
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1637
|
+
|
|
1638
|
+
const config = {
|
|
1639
|
+
apiKey: 'YOUR_API_KEY',
|
|
1640
|
+
|
|
1641
|
+
// Custom tracking API host
|
|
1642
|
+
trackingApiUrl: 'https://custom-track.zixflow.com',
|
|
1643
|
+
|
|
1644
|
+
// Custom in-app messaging API host
|
|
1645
|
+
inApp: {
|
|
1646
|
+
// Override in-app messaging API endpoint if needed
|
|
1647
|
+
},
|
|
1648
|
+
};
|
|
1649
|
+
|
|
1650
|
+
Zixflow.initialize(config);
|
|
1651
|
+
```
|
|
1652
|
+
|
|
1653
|
+
---
|
|
1654
|
+
|
|
1655
|
+
## Troubleshooting
|
|
1656
|
+
|
|
1657
|
+
### Installation Issues
|
|
1658
|
+
|
|
1659
|
+
**Issue**: `npm install` fails with dependency conflicts
|
|
1660
|
+
|
|
1661
|
+
**Solution**: Use `--legacy-peer-deps` flag:
|
|
1662
|
+
```bash
|
|
1663
|
+
npm install zixflow-reactnative --legacy-peer-deps
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1666
|
+
Or with Yarn:
|
|
1667
|
+
```bash
|
|
1668
|
+
yarn add zixflow-reactnative --legacy-peer-deps
|
|
1669
|
+
```
|
|
1670
|
+
|
|
1671
|
+
---
|
|
1672
|
+
|
|
1673
|
+
**Issue**: Auto-linking fails after installation
|
|
1674
|
+
|
|
1675
|
+
**Solution**: Try manual linking:
|
|
1676
|
+
|
|
1677
|
+
1. Clean the build:
|
|
1678
|
+
```bash
|
|
1679
|
+
cd android && ./gradlew clean && cd ..
|
|
1680
|
+
cd ios && rm -rf Pods && pod install && cd ..
|
|
1681
|
+
```
|
|
1682
|
+
|
|
1683
|
+
2. Rebuild the app:
|
|
1684
|
+
```bash
|
|
1685
|
+
npx react-native run-ios
|
|
1686
|
+
npx react-native run-android
|
|
1687
|
+
```
|
|
1688
|
+
|
|
1689
|
+
### iOS Build Errors
|
|
1690
|
+
|
|
1691
|
+
**Issue**: `Module 'Zixflow' not found`
|
|
1692
|
+
|
|
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
|
|
1697
|
+
|
|
1698
|
+
---
|
|
1699
|
+
|
|
1700
|
+
**Issue**: Swift compiler errors in native modules
|
|
1701
|
+
|
|
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 ..`
|
|
1706
|
+
|
|
1707
|
+
---
|
|
1708
|
+
|
|
1709
|
+
**Issue**: Notification Service Extension not working
|
|
1710
|
+
|
|
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
|
|
1716
|
+
|
|
1717
|
+
### Android Build Errors
|
|
1718
|
+
|
|
1719
|
+
**Issue**: `Cannot find symbol class Zixflow`
|
|
1720
|
+
|
|
1721
|
+
**Solution**:
|
|
1722
|
+
1. Clean Gradle cache:
|
|
1723
|
+
```bash
|
|
1724
|
+
cd android && ./gradlew clean && cd ..
|
|
1725
|
+
```
|
|
1726
|
+
|
|
1727
|
+
2. Rebuild the app:
|
|
1728
|
+
```bash
|
|
1729
|
+
npx react-native run-android
|
|
1730
|
+
```
|
|
1731
|
+
|
|
1732
|
+
---
|
|
1733
|
+
|
|
1734
|
+
**Issue**: Duplicate class errors with Firebase
|
|
1735
|
+
|
|
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
|
|
1742
|
+
```
|
|
1743
|
+
|
|
1744
|
+
---
|
|
1745
|
+
|
|
1746
|
+
**Issue**: Minimum SDK version error
|
|
1747
|
+
|
|
1748
|
+
**Solution**: Update `android/build.gradle`:
|
|
1749
|
+
```gradle
|
|
1750
|
+
ext {
|
|
1751
|
+
minSdkVersion = 24
|
|
1752
|
+
}
|
|
1753
|
+
```
|
|
1754
|
+
|
|
1755
|
+
### Push Notification Issues
|
|
1756
|
+
|
|
1757
|
+
**Issue**: Push notifications not received on iOS
|
|
1758
|
+
|
|
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)
|
|
1765
|
+
|
|
1766
|
+
---
|
|
1767
|
+
|
|
1768
|
+
**Issue**: Push notifications not received on Android
|
|
1769
|
+
|
|
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+)
|
|
1776
|
+
|
|
1777
|
+
---
|
|
1778
|
+
|
|
1779
|
+
**Issue**: Rich push notifications (images) not working
|
|
1780
|
+
|
|
1781
|
+
**Solution**: Ensure Notification Service Extension is properly configured on iOS (see [Notification Service Extension](#notification-service-extension))
|
|
1782
|
+
|
|
1783
|
+
### In-App Message Issues
|
|
1784
|
+
|
|
1785
|
+
**Issue**: In-app messages not displaying
|
|
1786
|
+
|
|
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
|
|
1793
|
+
|
|
1794
|
+
---
|
|
1795
|
+
|
|
1796
|
+
**Issue**: In-app message events not firing
|
|
1797
|
+
|
|
1798
|
+
**Solution**: Ensure event listener is registered before messages are triggered:
|
|
1799
|
+
```typescript
|
|
1800
|
+
useEffect(() => {
|
|
1801
|
+
const listener = Zixflow.inAppMessaging.registerEventsListener((event) => {
|
|
1802
|
+
console.log('In-app event:', event);
|
|
1803
|
+
});
|
|
1804
|
+
|
|
1805
|
+
return () => listener.remove();
|
|
1806
|
+
}, []);
|
|
1807
|
+
```
|
|
1808
|
+
|
|
1809
|
+
---
|
|
1810
|
+
|
|
1811
|
+
## Example Applications
|
|
1812
|
+
|
|
1813
|
+
The Zixflow React Native SDK includes example applications demonstrating best practices:
|
|
1814
|
+
|
|
1815
|
+
### Sample App (APNs)
|
|
1816
|
+
|
|
1817
|
+
Location: `example/`
|
|
1818
|
+
|
|
1819
|
+
**Features**:
|
|
1820
|
+
- User identification and logout
|
|
1821
|
+
- Event tracking
|
|
1822
|
+
- Screen tracking with React Navigation
|
|
1823
|
+
- Push notifications with APNs
|
|
1824
|
+
- In-app messaging with event listeners
|
|
1825
|
+
- Profile and device attributes
|
|
1826
|
+
|
|
1827
|
+
**Running the example**:
|
|
1828
|
+
|
|
1829
|
+
```bash
|
|
1830
|
+
# Install dependencies
|
|
1831
|
+
cd example
|
|
1832
|
+
npm install
|
|
1833
|
+
|
|
1834
|
+
# iOS
|
|
1835
|
+
cd ios && pod install && cd ..
|
|
1836
|
+
npx react-native run-ios
|
|
1837
|
+
|
|
1838
|
+
# Android
|
|
1839
|
+
npx react-native run-android
|
|
1840
|
+
```
|
|
1841
|
+
|
|
1842
|
+
---
|
|
1843
|
+
|
|
1844
|
+
## API Reference
|
|
1845
|
+
|
|
1846
|
+
### Core SDK
|
|
1847
|
+
|
|
1848
|
+
#### `Zixflow.initialize(config: ZixflowConfig): void`
|
|
1849
|
+
|
|
1850
|
+
Initialize the SDK with configuration.
|
|
1851
|
+
|
|
1852
|
+
```typescript
|
|
1853
|
+
Zixflow.initialize({
|
|
1854
|
+
apiKey: 'YOUR_API_KEY',
|
|
1855
|
+
});
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
#### `Zixflow.identify(params: { userId: string; traits?: object }): void`
|
|
1859
|
+
|
|
1860
|
+
Identify a user with optional traits.
|
|
1861
|
+
|
|
1862
|
+
```typescript
|
|
1863
|
+
Zixflow.identify({
|
|
1864
|
+
userId: 'user-123',
|
|
1865
|
+
traits: { email: 'user@example.com' }
|
|
1866
|
+
});
|
|
1867
|
+
```
|
|
1868
|
+
|
|
1869
|
+
#### `Zixflow.clearIdentify(): void`
|
|
1870
|
+
|
|
1871
|
+
Clear the current user's identity.
|
|
1872
|
+
|
|
1873
|
+
```typescript
|
|
1874
|
+
Zixflow.clearIdentify();
|
|
1875
|
+
```
|
|
1876
|
+
|
|
1877
|
+
#### `Zixflow.track(name: string, properties?: object | Map<string, any>): void`
|
|
1878
|
+
|
|
1879
|
+
Track a custom event.
|
|
1880
|
+
|
|
1881
|
+
```typescript
|
|
1882
|
+
Zixflow.track('button_clicked', { button_name: 'signup' });
|
|
1883
|
+
```
|
|
1884
|
+
|
|
1885
|
+
#### `Zixflow.screen(name: string, properties?: object): void`
|
|
1886
|
+
|
|
1887
|
+
Track a screen view.
|
|
1888
|
+
|
|
1889
|
+
```typescript
|
|
1890
|
+
Zixflow.screen('HomeScreen');
|
|
1891
|
+
```
|
|
1892
|
+
|
|
1893
|
+
#### `Zixflow.setProfileAttributes(attributes: object): void`
|
|
1894
|
+
|
|
1895
|
+
Set attributes on the user profile.
|
|
1896
|
+
|
|
1897
|
+
```typescript
|
|
1898
|
+
Zixflow.setProfileAttributes({ plan: 'premium' });
|
|
1899
|
+
```
|
|
1900
|
+
|
|
1901
|
+
#### `Zixflow.setDeviceAttributes(attributes: object): void`
|
|
1902
|
+
|
|
1903
|
+
Set attributes on the current device.
|
|
1904
|
+
|
|
1905
|
+
```typescript
|
|
1906
|
+
Zixflow.setDeviceAttributes({ app_version: '2.0.0' });
|
|
1907
|
+
```
|
|
1908
|
+
|
|
1909
|
+
### Push Messaging
|
|
1910
|
+
|
|
1911
|
+
#### `Zixflow.pushMessaging.showPromptForPushNotifications(options): Promise<ZixflowPushPermissionStatus>`
|
|
1912
|
+
|
|
1913
|
+
Request push notification permission.
|
|
1914
|
+
|
|
1915
|
+
```typescript
|
|
1916
|
+
const status = await Zixflow.pushMessaging.showPromptForPushNotifications({
|
|
1917
|
+
ios: { sound: true, badge: true }
|
|
1918
|
+
});
|
|
1919
|
+
```
|
|
1920
|
+
|
|
1921
|
+
### In-App Messaging
|
|
1922
|
+
|
|
1923
|
+
#### `Zixflow.inAppMessaging.registerEventsListener(callback): EventSubscription`
|
|
1924
|
+
|
|
1925
|
+
Register a listener for in-app message events.
|
|
1926
|
+
|
|
1927
|
+
```typescript
|
|
1928
|
+
const listener = Zixflow.inAppMessaging.registerEventsListener((event) => {
|
|
1929
|
+
console.log('In-app event:', event);
|
|
1930
|
+
});
|
|
1931
|
+
|
|
1932
|
+
// Remove listener
|
|
1933
|
+
listener.remove();
|
|
1934
|
+
```
|
|
1935
|
+
|
|
1936
|
+
#### `Zixflow.inAppMessaging.dismissMessage(): void`
|
|
1937
|
+
|
|
1938
|
+
Dismiss the currently displayed in-app message.
|
|
1939
|
+
|
|
1940
|
+
```typescript
|
|
1941
|
+
Zixflow.inAppMessaging.dismissMessage();
|
|
1942
|
+
```
|
|
1943
|
+
|
|
1944
|
+
### Types
|
|
1945
|
+
|
|
1946
|
+
#### `ZixflowConfig`
|
|
1947
|
+
|
|
1948
|
+
Configuration object for SDK initialization.
|
|
1949
|
+
|
|
1950
|
+
```typescript
|
|
1951
|
+
interface ZixflowConfig {
|
|
1952
|
+
apiKey: string;
|
|
1953
|
+
region?: Region;
|
|
1954
|
+
logLevel?: ZixflowLogLevel;
|
|
1955
|
+
inApp?: {
|
|
1956
|
+
};
|
|
1957
|
+
autoTrackDeviceAttributes?: boolean;
|
|
1958
|
+
trackApplicationLifecycleEvents?: boolean;
|
|
1959
|
+
autoTrackScreenViews?: boolean;
|
|
1960
|
+
trackingApiUrl?: string;
|
|
1961
|
+
}
|
|
1962
|
+
```
|
|
1963
|
+
|
|
1964
|
+
#### `Region`
|
|
1965
|
+
|
|
1966
|
+
Data center region enum.
|
|
1967
|
+
|
|
1968
|
+
```typescript
|
|
1969
|
+
enum Region {
|
|
1970
|
+
US = 'US',
|
|
1971
|
+
EU = 'EU'
|
|
1972
|
+
}
|
|
1973
|
+
```
|
|
1974
|
+
|
|
1975
|
+
#### `ZixflowLogLevel`
|
|
1976
|
+
|
|
1977
|
+
Log level enum.
|
|
1978
|
+
|
|
1979
|
+
```typescript
|
|
1980
|
+
enum ZixflowLogLevel {
|
|
1981
|
+
none = 'none',
|
|
1982
|
+
error = 'error',
|
|
1983
|
+
info = 'info',
|
|
1984
|
+
debug = 'debug'
|
|
1985
|
+
}
|
|
1986
|
+
```
|
|
1987
|
+
|
|
1988
|
+
#### `ZixflowPushPermissionStatus`
|
|
1989
|
+
|
|
1990
|
+
Push notification permission status.
|
|
1991
|
+
|
|
1992
|
+
```typescript
|
|
1993
|
+
enum ZixflowPushPermissionStatus {
|
|
1994
|
+
Granted = 'granted',
|
|
1995
|
+
Denied = 'denied',
|
|
1996
|
+
NotDetermined = 'notDetermined'
|
|
1997
|
+
}
|
|
1998
|
+
```
|
|
1999
|
+
|
|
2000
|
+
#### `InAppMessageEventType`
|
|
2001
|
+
|
|
2002
|
+
In-app message event types.
|
|
2003
|
+
|
|
2004
|
+
```typescript
|
|
2005
|
+
enum InAppMessageEventType {
|
|
2006
|
+
messageShown = 'messageShown',
|
|
2007
|
+
messageDismissed = 'messageDismissed',
|
|
2008
|
+
messageActionTaken = 'messageActionTaken',
|
|
2009
|
+
errorWithMessage = 'errorWithMessage'
|
|
2010
|
+
}
|
|
2011
|
+
```
|
|
2012
|
+
|
|
2013
|
+
#### `InAppMessageEvent`
|
|
2014
|
+
|
|
2015
|
+
In-app message event object.
|
|
2016
|
+
|
|
2017
|
+
```typescript
|
|
2018
|
+
interface InAppMessageEvent {
|
|
2019
|
+
eventType: InAppMessageEventType;
|
|
2020
|
+
deliveryId?: string;
|
|
2021
|
+
messageId?: string;
|
|
2022
|
+
actionName?: string;
|
|
2023
|
+
actionValue?: string;
|
|
2024
|
+
}
|
|
2025
|
+
```
|
|
2026
|
+
|
|
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
|
+
---
|
|
450
2048
|
|
|
451
|
-
|
|
2049
|
+
**Need help?** Contact our support team at support@zixflow.com or open an issue on GitHub.
|