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 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.url) {
90
- showInAppMessage(remoteMessage.data, openedInAppWebViewCount);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "notifly-sdk",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/constant.js CHANGED
@@ -1,4 +1,4 @@
1
- export const SDK_VERSION = '2.1.1';
1
+ export const SDK_VERSION = '2.2.4';
2
2
 
3
3
  export const NAMESPACE = {
4
4
  'EVENTID': '830b5f7b-e392-43db-a17b-d835f0bcab2b',
@@ -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 = JSON.parse(data.modal_properties || '{}');
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 openAppEventParams = {
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', openAppEventParams, null, true);
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
+ }