notifly-sdk 2.1.2 → 2.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.
- package/index.js +69 -5
- package/package.json +1 -1
- package/src/constant.js +1 -1
- package/src/in_app_message.js +5 -2
- package/src/utils.js +33 -5
package/index.js
CHANGED
|
@@ -4,13 +4,71 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
|
4
4
|
import messaging from '@react-native-firebase/messaging';
|
|
5
5
|
import logEvent from './src/log_event';
|
|
6
6
|
import { setUserProperties, removeUserId } from './src/user';
|
|
7
|
-
import { clickHandler, sessionStart } from './src/utils';
|
|
7
|
+
import { base64Decode, clickHandler, sessionStart } from './src/utils';
|
|
8
8
|
import { showInAppMessage } from './src/in_app_message';
|
|
9
|
-
|
|
9
|
+
let isSetBackgroundHandler = false;
|
|
10
10
|
exports.trackEvent = logEvent;
|
|
11
11
|
exports.setUserProperties = setUserProperties;
|
|
12
12
|
exports.clickHandler = clickHandler;
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Sets the background message handler for the Notifly SDK.
|
|
16
|
+
* This method should be called in the index.js file of your app.
|
|
17
|
+
* Should be used when you don't have a custom background message handler.
|
|
18
|
+
* @returns {Promise<void>} - A promise that resolves when the background message handler is set.
|
|
19
|
+
* @example
|
|
20
|
+
* setNotiflyBackgroundMessageHandler();
|
|
21
|
+
*/
|
|
22
|
+
async function setNotiflyBackgroundMessageHandler() {
|
|
23
|
+
messaging().setBackgroundMessageHandler(notiflyBackgroundHandler);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The background message handler for the Notifly SDK.
|
|
28
|
+
* This method should be called in the index.js file of your app.
|
|
29
|
+
* Should be used when you have a custom background message handler.
|
|
30
|
+
* @param {Object} remoteMessage - The remote message to handle.
|
|
31
|
+
* @returns {Promise<void>} - A promise that resolves when the background message handler is set.
|
|
32
|
+
* @example
|
|
33
|
+
* messaging().setBackgroundMessageHandler(async remoteMessage => {
|
|
34
|
+
console.log('Existing handler: Background message received:', remoteMessage);
|
|
35
|
+
await notiflyBackgroundHandler(remoteMessage);
|
|
36
|
+
});
|
|
37
|
+
*/
|
|
38
|
+
async function notiflyBackgroundHandler(remoteMessage) {
|
|
39
|
+
if (!remoteMessage.notification) {
|
|
40
|
+
return; // TODO(minyong): Discuss if we should log only when notifly_message_type is push-notitification.
|
|
41
|
+
}
|
|
42
|
+
if (!isSetBackgroundHandler) {
|
|
43
|
+
await logEvent(
|
|
44
|
+
'push_delivered',
|
|
45
|
+
{
|
|
46
|
+
type: 'message_event',
|
|
47
|
+
channel: 'push-notification',
|
|
48
|
+
campaign_id: remoteMessage?.data?.campaign_id,
|
|
49
|
+
notifly_message_id: remoteMessage?.data?.notifly_message_id,
|
|
50
|
+
status: 'quit',
|
|
51
|
+
},
|
|
52
|
+
null,
|
|
53
|
+
true,
|
|
54
|
+
);
|
|
55
|
+
isSetBackgroundHandler = true;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
await logEvent(
|
|
59
|
+
'push_delivered',
|
|
60
|
+
{
|
|
61
|
+
type: 'message_event',
|
|
62
|
+
channel: 'push-notification',
|
|
63
|
+
campaign_id: remoteMessage?.data?.campaign_id,
|
|
64
|
+
notifly_message_id: remoteMessage.data?.notifly_message_id,
|
|
65
|
+
status: 'background',
|
|
66
|
+
},
|
|
67
|
+
null,
|
|
68
|
+
true,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
14
72
|
/**
|
|
15
73
|
* Sets the external user ID for the user.
|
|
16
74
|
*
|
|
@@ -52,7 +110,6 @@ exports.setUserId = async function (userID) {
|
|
|
52
110
|
exports.initialize = async function (prjId, userName, password, useCustomClickHandler = false) {
|
|
53
111
|
try {
|
|
54
112
|
await messaging().requestPermission();
|
|
55
|
-
|
|
56
113
|
// in-app-message
|
|
57
114
|
const openedInAppWebViewCount = { count: 0 };
|
|
58
115
|
messaging().onMessage((remoteMessage) => {
|
|
@@ -72,6 +129,7 @@ exports.initialize = async function (prjId, userName, password, useCustomClickHa
|
|
|
72
129
|
}
|
|
73
130
|
|
|
74
131
|
messaging().getToken();
|
|
132
|
+
messaging().setDeliveryMetricsExportToBigQuery(true);
|
|
75
133
|
|
|
76
134
|
await Promise.all([
|
|
77
135
|
AsyncStorage.setItem('notiflyProjectId', prjId),
|
|
@@ -86,8 +144,10 @@ exports.initialize = async function (prjId, userName, password, useCustomClickHa
|
|
|
86
144
|
|
|
87
145
|
async function handleInAppMessage(remoteMessage, openedInAppWebViewCount) {
|
|
88
146
|
try {
|
|
89
|
-
if (remoteMessage.data?.notifly_message_type === 'in-app-message' && remoteMessage.data
|
|
90
|
-
|
|
147
|
+
if (remoteMessage.data?.notifly_message_type === 'in-app-message' && remoteMessage.data?.notifly_in_app_message_data) {
|
|
148
|
+
const decodedJsonString = base64Decode(remoteMessage.data?.notifly_in_app_message_data);
|
|
149
|
+
const notiflyInAppMessageData = JSON.parse(decodedJsonString);
|
|
150
|
+
showInAppMessage(notiflyInAppMessageData, openedInAppWebViewCount);
|
|
91
151
|
}
|
|
92
152
|
} catch (err) {
|
|
93
153
|
console.warn('[Notifly] In-app message handling failed:', err);
|
|
@@ -106,6 +166,7 @@ async function handleNotificationOpened(remoteMessage) {
|
|
|
106
166
|
type: 'message_event',
|
|
107
167
|
channel: 'push-notification',
|
|
108
168
|
campaign_id: remoteMessage.data.campaign_id,
|
|
169
|
+
notifly_message_id: remoteMessage.data?.notifly_message_id,
|
|
109
170
|
status: 'background',
|
|
110
171
|
},
|
|
111
172
|
null,
|
|
@@ -115,3 +176,6 @@ async function handleNotificationOpened(remoteMessage) {
|
|
|
115
176
|
console.warn('[Notifly] Notification opened handling failed:', err);
|
|
116
177
|
}
|
|
117
178
|
}
|
|
179
|
+
|
|
180
|
+
exports.setNotiflyBackgroundMessageHandler = setNotiflyBackgroundMessageHandler;
|
|
181
|
+
exports.notiflyBackgroundHandler = notiflyBackgroundHandler;
|
package/package.json
CHANGED
package/src/constant.js
CHANGED
package/src/in_app_message.js
CHANGED
|
@@ -25,7 +25,7 @@ export async function showInAppMessage(data, openedInAppWebViewCount) {
|
|
|
25
25
|
if (!(data?.url && data?.modal_properties)) {
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
|
-
const modalProperties =
|
|
28
|
+
const modalProperties = data.modal_properties || {};
|
|
29
29
|
const screenWidth = Dimensions.get('window').width;
|
|
30
30
|
const screenHeight = Dimensions.get('window').height;
|
|
31
31
|
const webViewProps = _translateWebviewProps(modalProperties, screenWidth, screenHeight);
|
|
@@ -54,6 +54,7 @@ export async function showInAppMessage(data, openedInAppWebViewCount) {
|
|
|
54
54
|
channel: 'in-app-message',
|
|
55
55
|
button_name: message.button_name,
|
|
56
56
|
campaign_id: data.campaign_id,
|
|
57
|
+
notifly_message_id: data.notifly_message_id,
|
|
57
58
|
},
|
|
58
59
|
null,
|
|
59
60
|
true
|
|
@@ -66,6 +67,7 @@ export async function showInAppMessage(data, openedInAppWebViewCount) {
|
|
|
66
67
|
channel: 'in-app-message',
|
|
67
68
|
button_name: message.button_name,
|
|
68
69
|
campaign_id: data.campaign_id,
|
|
70
|
+
notifly_message_id: data.notifly_message_id,
|
|
69
71
|
},
|
|
70
72
|
null,
|
|
71
73
|
true
|
|
@@ -85,6 +87,7 @@ export async function showInAppMessage(data, openedInAppWebViewCount) {
|
|
|
85
87
|
channel: 'in-app-message',
|
|
86
88
|
button_name: message.button_name,
|
|
87
89
|
campaign_id: data.campaign_id,
|
|
90
|
+
notifly_message_id: data.notifly_message_id,
|
|
88
91
|
},
|
|
89
92
|
null,
|
|
90
93
|
true
|
|
@@ -101,7 +104,7 @@ export async function showInAppMessage(data, openedInAppWebViewCount) {
|
|
|
101
104
|
openedInAppWebViewCount.count = openedInAppWebViewCount.count + 1;
|
|
102
105
|
logEvent(
|
|
103
106
|
'in_app_message_show',
|
|
104
|
-
{ type: 'message_event', channel: 'in-app-message', campaign_id: data.campaign_id },
|
|
107
|
+
{ type: 'message_event', channel: 'in-app-message', campaign_id: data.campaign_id, notifly_message_id: data.notifly_message_id },
|
|
105
108
|
null,
|
|
106
109
|
true
|
|
107
110
|
); // logging in app messaging delivered
|
package/src/utils.js
CHANGED
|
@@ -51,15 +51,17 @@ export async function sessionStart() {
|
|
|
51
51
|
const brandPromise = rnDeviceInfo.getBrand();
|
|
52
52
|
const modelPromise = rnDeviceInfo.getModel();
|
|
53
53
|
const userAgentPromise = rnDeviceInfo.getUserAgent();
|
|
54
|
+
const notifAuthStatusPromise = messaging().hasPermission();
|
|
54
55
|
|
|
55
|
-
const [deviceModel, deviceBrand, apiLevel, userAgent] = await Promise.all([
|
|
56
|
+
const [deviceModel, deviceBrand, apiLevel, userAgent, notifAuthStatus] = await Promise.all([
|
|
56
57
|
modelPromise,
|
|
57
58
|
brandPromise,
|
|
58
59
|
apiLevelPromise,
|
|
59
60
|
userAgentPromise,
|
|
61
|
+
notifAuthStatusPromise,
|
|
60
62
|
]);
|
|
61
63
|
|
|
62
|
-
const
|
|
64
|
+
const sessionStartEventParams = {
|
|
63
65
|
platform,
|
|
64
66
|
type: 'session_start_event',
|
|
65
67
|
device_model: deviceModel,
|
|
@@ -68,8 +70,9 @@ export async function sessionStart() {
|
|
|
68
70
|
api_level: apiLevel,
|
|
69
71
|
user_agent: userAgent,
|
|
70
72
|
},
|
|
73
|
+
notif_auth_status: notifAuthStatus,
|
|
71
74
|
};
|
|
72
|
-
await logEvent('session_start',
|
|
75
|
+
await logEvent('session_start', sessionStartEventParams, null, true);
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
/**
|
|
@@ -97,14 +100,14 @@ export async function clickHandler(remoteMessage) {
|
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
try {
|
|
100
|
-
const { data: { link, campaign_id } = {} } = remoteMessage;
|
|
103
|
+
const { data: { link, campaign_id, notifly_message_id } = {} } = remoteMessage;
|
|
101
104
|
|
|
102
105
|
if (link) {
|
|
103
106
|
Linking.openURL(link);
|
|
104
107
|
}
|
|
105
108
|
await logEvent(
|
|
106
109
|
'push_click',
|
|
107
|
-
{ channel: 'push-notification', type: 'message_event', campaign_id, status: 'quit' },
|
|
110
|
+
{ channel: 'push-notification', type: 'message_event', campaign_id, notifly_message_id, status: 'quit' },
|
|
108
111
|
null,
|
|
109
112
|
true
|
|
110
113
|
);
|
|
@@ -112,3 +115,28 @@ export async function clickHandler(remoteMessage) {
|
|
|
112
115
|
console.warn('[Notifly] custom click handler registration failed.');
|
|
113
116
|
}
|
|
114
117
|
}
|
|
118
|
+
|
|
119
|
+
// React Native does not support Buffer out of the box, so we need to implement our own base64 decoder.
|
|
120
|
+
export function base64Decode(input) {
|
|
121
|
+
const chars =
|
|
122
|
+
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
123
|
+
let str = '';
|
|
124
|
+
let output = '';
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < input.length; i += 4) {
|
|
127
|
+
const encoded1 = chars.indexOf(input[i]);
|
|
128
|
+
const encoded2 = chars.indexOf(input[i + 1]);
|
|
129
|
+
const encoded3 = chars.indexOf(input[i + 2]);
|
|
130
|
+
const encoded4 = chars.indexOf(input[i + 3]);
|
|
131
|
+
|
|
132
|
+
const decoded1 = (encoded1 << 2) | (encoded2 >> 4);
|
|
133
|
+
const decoded2 = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
|
134
|
+
const decoded3 = ((encoded3 & 3) << 6) | encoded4;
|
|
135
|
+
|
|
136
|
+
output += String.fromCharCode(decoded1);
|
|
137
|
+
if (encoded3 !== 64) output += String.fromCharCode(decoded2);
|
|
138
|
+
if (encoded4 !== 64) output += String.fromCharCode(decoded3);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return output;
|
|
142
|
+
}
|