@magicpixel/rn-mp-client-sdk 0.11.0 → 1.12.1
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/lib/commonjs/common/app-types.js.map +1 -1
- package/lib/commonjs/common/constants.js +5 -26
- package/lib/commonjs/common/constants.js.map +1 -1
- package/lib/commonjs/common/data-store.js +36 -117
- package/lib/commonjs/common/data-store.js.map +1 -1
- package/lib/commonjs/common/event-bus.js +3 -10
- package/lib/commonjs/common/event-bus.js.map +1 -1
- package/lib/commonjs/common/logger.js +22 -14
- package/lib/commonjs/common/logger.js.map +1 -1
- package/lib/commonjs/common/network-service.js +6 -21
- package/lib/commonjs/common/network-service.js.map +1 -1
- package/lib/commonjs/common/reporter.js +8 -31
- package/lib/commonjs/common/reporter.js.map +1 -1
- package/lib/commonjs/common/utils.js +64 -65
- package/lib/commonjs/common/utils.js.map +1 -1
- package/lib/commonjs/coverage/lcov-report/block-navigation.js +6 -19
- package/lib/commonjs/coverage/lcov-report/block-navigation.js.map +1 -1
- package/lib/commonjs/coverage/lcov-report/prettify.js +2 -182
- package/lib/commonjs/coverage/lcov-report/prettify.js.map +1 -1
- package/lib/commonjs/coverage/lcov-report/sorter.js +64 -94
- package/lib/commonjs/coverage/lcov-report/sorter.js.map +1 -1
- package/lib/commonjs/eedl/eedl.js +207 -84
- package/lib/commonjs/eedl/eedl.js.map +1 -1
- package/lib/commonjs/index.js +105 -94
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/geo-api-response.js +2 -0
- package/lib/commonjs/models/geo-api-response.js.map +1 -0
- package/lib/commonjs/models/mp-client-sdk.js +3 -11
- package/lib/commonjs/models/mp-client-sdk.js.map +1 -1
- package/lib/commonjs/processors/data-element.processor.js +85 -80
- package/lib/commonjs/processors/data-element.processor.js.map +1 -1
- package/lib/commonjs/processors/geo-location.processor.js +70 -0
- package/lib/commonjs/processors/geo-location.processor.js.map +1 -0
- package/lib/commonjs/processors/qc.processor.js +2 -25
- package/lib/commonjs/processors/qc.processor.js.map +1 -1
- package/lib/commonjs/processors/tag.processor.js +17 -86
- package/lib/commonjs/processors/tag.processor.js.map +1 -1
- package/lib/commonjs/processors/trans-function.processor.js +5 -23
- package/lib/commonjs/processors/trans-function.processor.js.map +1 -1
- package/lib/commonjs/processors/visit-id.processor.js +4 -50
- package/lib/commonjs/processors/visit-id.processor.js.map +1 -1
- package/lib/module/common/app-types.js.map +1 -1
- package/lib/module/common/constants.js +4 -22
- package/lib/module/common/constants.js.map +1 -1
- package/lib/module/common/data-store.js +35 -108
- package/lib/module/common/data-store.js.map +1 -1
- package/lib/module/common/event-bus.js +3 -6
- package/lib/module/common/event-bus.js.map +1 -1
- package/lib/module/common/logger.js +22 -12
- package/lib/module/common/logger.js.map +1 -1
- package/lib/module/common/network-service.js +6 -11
- package/lib/module/common/network-service.js.map +1 -1
- package/lib/module/common/reporter.js +8 -19
- package/lib/module/common/reporter.js.map +1 -1
- package/lib/module/common/utils.js +63 -56
- package/lib/module/common/utils.js.map +1 -1
- package/lib/module/coverage/lcov-report/block-navigation.js +6 -19
- package/lib/module/coverage/lcov-report/block-navigation.js.map +1 -1
- package/lib/module/coverage/lcov-report/prettify.js +2 -182
- package/lib/module/coverage/lcov-report/prettify.js.map +1 -1
- package/lib/module/coverage/lcov-report/sorter.js +64 -94
- package/lib/module/coverage/lcov-report/sorter.js.map +1 -1
- package/lib/module/eedl/eedl.js +206 -76
- package/lib/module/eedl/eedl.js.map +1 -1
- package/lib/module/index.js +103 -57
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/geo-api-response.js +2 -0
- package/lib/module/models/geo-api-response.js.map +1 -0
- package/lib/module/models/mp-client-sdk.js +0 -5
- package/lib/module/models/mp-client-sdk.js.map +1 -1
- package/lib/module/processors/data-element.processor.js +82 -71
- package/lib/module/processors/data-element.processor.js.map +1 -1
- package/lib/module/processors/geo-location.processor.js +63 -0
- package/lib/module/processors/geo-location.processor.js.map +1 -0
- package/lib/module/processors/qc.processor.js +2 -11
- package/lib/module/processors/qc.processor.js.map +1 -1
- package/lib/module/processors/tag.processor.js +17 -57
- package/lib/module/processors/tag.processor.js.map +1 -1
- package/lib/module/processors/trans-function.processor.js +5 -12
- package/lib/module/processors/trans-function.processor.js.map +1 -1
- package/lib/module/processors/visit-id.processor.js +4 -27
- package/lib/module/processors/visit-id.processor.js.map +1 -1
- package/lib/typescript/common/app-types.d.ts +4 -0
- package/lib/typescript/common/constants.d.ts +1 -0
- package/lib/typescript/common/data-store.d.ts +8 -0
- package/lib/typescript/common/logger.d.ts +5 -0
- package/lib/typescript/common/utils.d.ts +19 -0
- package/lib/typescript/eedl/eedl.d.ts +16 -5
- package/lib/typescript/index.d.ts +53 -0
- package/lib/typescript/models/geo-api-response.d.ts +12 -0
- package/lib/typescript/processors/data-element.processor.d.ts +10 -1
- package/lib/typescript/processors/geo-location.processor.d.ts +10 -0
- package/package.json +25 -10
- package/src/common/app-types.ts +4 -0
- package/src/common/constants.ts +2 -0
- package/src/common/data-store.ts +38 -0
- package/src/common/logger.ts +19 -3
- package/src/common/network-service.ts +2 -0
- package/src/common/utils.ts +58 -0
- package/src/eedl/eedl.ts +241 -18
- package/src/index.tsx +99 -3
- package/src/models/geo-api-response.ts +13 -0
- package/src/processors/data-element.processor.ts +140 -70
- package/src/processors/geo-location.processor.ts +91 -0
package/src/common/utils.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { flatten, unflatten } from 'flat';
|
|
|
10
10
|
import { EventBus } from './event-bus';
|
|
11
11
|
import { Dimensions, ScaledSize } from 'react-native';
|
|
12
12
|
import { URL } from 'react-native-url-polyfill';
|
|
13
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
13
14
|
|
|
14
15
|
export class Utils {
|
|
15
16
|
static triggerEvent(eventName: string, payload: any): void {
|
|
@@ -207,6 +208,63 @@ export class Utils {
|
|
|
207
208
|
return Constants.LARGE_RANDOM_POOL();
|
|
208
209
|
}
|
|
209
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Make HTTP GET request - React Native implementation
|
|
213
|
+
* @param url URL to fetch
|
|
214
|
+
* @returns Promise with response data
|
|
215
|
+
*/
|
|
216
|
+
static async getHttp<T>(url: string): Promise<T> {
|
|
217
|
+
try {
|
|
218
|
+
const response = await fetch(url, {
|
|
219
|
+
method: 'GET',
|
|
220
|
+
headers: {
|
|
221
|
+
'Content-Type': 'application/json',
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
if (!response.ok) {
|
|
226
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return await response.json();
|
|
230
|
+
} catch (error) {
|
|
231
|
+
Logger.logError('HTTP GET request failed:', error);
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Get value from AsyncStorage (React Native equivalent of sessionStorage)
|
|
238
|
+
* @param key Storage key
|
|
239
|
+
* @param defaultValue Default value if key not found
|
|
240
|
+
* @returns Promise with stored value or default
|
|
241
|
+
*/
|
|
242
|
+
static async getValueFromAsyncStorage<T>(
|
|
243
|
+
key: string,
|
|
244
|
+
defaultValue: T
|
|
245
|
+
): Promise<T> {
|
|
246
|
+
try {
|
|
247
|
+
const value = await AsyncStorage.getItem(key);
|
|
248
|
+
return value ? JSON.parse(value) : defaultValue;
|
|
249
|
+
} catch (error) {
|
|
250
|
+
Logger.logError('Error getting value from AsyncStorage:', error);
|
|
251
|
+
return defaultValue;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Set value to AsyncStorage (React Native equivalent of sessionStorage)
|
|
257
|
+
* @param key Storage key
|
|
258
|
+
* @param value Value to store
|
|
259
|
+
*/
|
|
260
|
+
static async setValueToAsyncStorage(key: string, value: any): Promise<void> {
|
|
261
|
+
try {
|
|
262
|
+
await AsyncStorage.setItem(key, JSON.stringify(value));
|
|
263
|
+
} catch (error) {
|
|
264
|
+
Logger.logError('Error setting value to AsyncStorage:', error);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
210
268
|
static getSimpleDebugId(prefix?: string): string {
|
|
211
269
|
return `${prefix ?? ''}${this.randomNumber(100000000, 99999999999)}`;
|
|
212
270
|
}
|
package/src/eedl/eedl.ts
CHANGED
|
@@ -1,22 +1,39 @@
|
|
|
1
1
|
import { Utils } from '../common/utils';
|
|
2
2
|
import type { EventProcessorFn, MapLike, TypedAny } from '../common/app-types';
|
|
3
3
|
import { Logger } from '../common/logger';
|
|
4
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
5
|
+
import { customAlphabet } from 'nanoid/non-secure';
|
|
6
|
+
|
|
7
|
+
const eventsToPersist: Record<string, string> = {
|
|
8
|
+
user_info: '_mpPendingUserInfo',
|
|
9
|
+
mp_purchase: '_mpPendingPurchase',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// UUID v4 generator for React Native
|
|
13
|
+
const getUUIDV4 = customAlphabet(
|
|
14
|
+
'1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
|
15
|
+
36
|
|
16
|
+
);
|
|
4
17
|
|
|
5
18
|
export class MpDataLayerHelper {
|
|
6
19
|
isReady = false;
|
|
7
20
|
_masterDataLayer: MapLike = {};
|
|
21
|
+
_persistedVars: MapLike = {};
|
|
8
22
|
eventProcessors: Record<string, any> = {};
|
|
9
23
|
stateTracker: Array<any> = [];
|
|
10
24
|
dlInitEvent: string;
|
|
11
25
|
receivedInitialEvent = false;
|
|
12
26
|
eventQueue: Array<any> = [];
|
|
27
|
+
private isEntryPoint = 0;
|
|
13
28
|
|
|
14
29
|
constructor(
|
|
15
30
|
private readonly dlEventName: string,
|
|
16
31
|
private readonly dlInitMode: string,
|
|
17
|
-
dlInitEvent: string
|
|
32
|
+
dlInitEvent: string,
|
|
33
|
+
private readonly storageKeyName: string = '_mpdls'
|
|
18
34
|
) {
|
|
19
35
|
this.dlInitEvent = dlInitEvent;
|
|
36
|
+
this.resetEntryPointInfo();
|
|
20
37
|
|
|
21
38
|
if (this.dlInitMode !== 'manual') {
|
|
22
39
|
this.isReady = true;
|
|
@@ -27,7 +44,9 @@ export class MpDataLayerHelper {
|
|
|
27
44
|
}
|
|
28
45
|
}
|
|
29
46
|
|
|
30
|
-
init(
|
|
47
|
+
async init(
|
|
48
|
+
globalEventListeners: Record<string, EventProcessorFn>
|
|
49
|
+
): Promise<void> {
|
|
31
50
|
// register any global event listeners passed through to the init command
|
|
32
51
|
const globalEventListenerKeys = Object.keys(globalEventListeners || {});
|
|
33
52
|
if (globalEventListenerKeys?.length > 0) {
|
|
@@ -37,13 +56,34 @@ export class MpDataLayerHelper {
|
|
|
37
56
|
}
|
|
38
57
|
}
|
|
39
58
|
}
|
|
59
|
+
|
|
60
|
+
// Load persisted events from AsyncStorage
|
|
61
|
+
for (const key of Object.keys(eventsToPersist)) {
|
|
62
|
+
try {
|
|
63
|
+
const persistedEvent = await AsyncStorage.getItem(eventsToPersist[key]);
|
|
64
|
+
if (persistedEvent) {
|
|
65
|
+
const event: { eventName: string; eventPayload: any } =
|
|
66
|
+
JSON.parse(persistedEvent);
|
|
67
|
+
this.pushEvent(event.eventName, event.eventPayload);
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
Logger.logError('Error parsing persisted event', err);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
40
73
|
}
|
|
41
74
|
|
|
42
75
|
pushEvent(eventName: string, payload: MapLike): void {
|
|
43
76
|
Logger.logDbg('EV Push Event:: ', JSON.stringify(payload));
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
77
|
+
if (
|
|
78
|
+
eventName === 'set' ||
|
|
79
|
+
eventName === 'persist' ||
|
|
80
|
+
eventName === 'clear' ||
|
|
81
|
+
eventName === 'user_info'
|
|
82
|
+
) {
|
|
83
|
+
// process regardless - fire and forget for async operations
|
|
84
|
+
this.processQItems(eventName, payload).catch((err) =>
|
|
85
|
+
Logger.logError('Error processing event', err)
|
|
86
|
+
);
|
|
47
87
|
} else {
|
|
48
88
|
if (!this.receivedInitialEvent) {
|
|
49
89
|
// set only if this is not true already
|
|
@@ -55,17 +95,28 @@ export class MpDataLayerHelper {
|
|
|
55
95
|
} else if (!this.isReady) {
|
|
56
96
|
this.eventQueue.push([eventName, payload]);
|
|
57
97
|
} else {
|
|
58
|
-
|
|
98
|
+
// fire and forget for async operations
|
|
99
|
+
this.processQItems(eventName, payload).catch((err) =>
|
|
100
|
+
Logger.logError('Error processing event', err)
|
|
101
|
+
);
|
|
59
102
|
}
|
|
60
103
|
}
|
|
61
104
|
}
|
|
62
105
|
|
|
63
|
-
processQItems(eventName: string, payload: MapLike): void {
|
|
106
|
+
async processQItems(eventName: string, payload: MapLike): Promise<void> {
|
|
64
107
|
try {
|
|
65
108
|
if (eventName === 'set') {
|
|
66
109
|
this.setDl(payload);
|
|
110
|
+
} else if (eventName === 'persist') {
|
|
111
|
+
await this.storeData(payload?.key, payload?.value);
|
|
112
|
+
} else if (eventName === 'clear') {
|
|
113
|
+
if (Array.isArray(payload) && payload.length > 0) {
|
|
114
|
+
await this.deleteData(payload as string[]);
|
|
115
|
+
}
|
|
116
|
+
} else if (eventName === 'user_info') {
|
|
117
|
+
this.setUserData(payload);
|
|
67
118
|
} else {
|
|
68
|
-
this.eventProcessor(eventName, payload);
|
|
119
|
+
await this.eventProcessor(eventName, payload);
|
|
69
120
|
}
|
|
70
121
|
/* Make sure nothing is written below this line. If you do so, remember to return on error conditions above */
|
|
71
122
|
} catch (err) {
|
|
@@ -89,19 +140,166 @@ export class MpDataLayerHelper {
|
|
|
89
140
|
return this._masterDataLayer;
|
|
90
141
|
}
|
|
91
142
|
|
|
143
|
+
private setUserData(payload: {
|
|
144
|
+
pid?: string;
|
|
145
|
+
email?: string;
|
|
146
|
+
phone?: string;
|
|
147
|
+
country?: string;
|
|
148
|
+
city?: string;
|
|
149
|
+
state?: string;
|
|
150
|
+
fName?: string;
|
|
151
|
+
lName?: string;
|
|
152
|
+
zip?: string;
|
|
153
|
+
}): void {
|
|
154
|
+
if (
|
|
155
|
+
payload?.zip &&
|
|
156
|
+
payload?.zip?.length > 0 &&
|
|
157
|
+
payload?.zip?.indexOf('-') > -1
|
|
158
|
+
) {
|
|
159
|
+
payload.zip = payload.zip.split('-')[0].trim();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const uif: any = {};
|
|
163
|
+
this._persistedVars = this._persistedVars || {};
|
|
164
|
+
this._persistedVars.uif = this._persistedVars.uif || {};
|
|
165
|
+
|
|
166
|
+
if (payload.pid) {
|
|
167
|
+
this._persistedVars.uif.user_pid = payload.pid;
|
|
168
|
+
uif.pid = payload.pid;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (payload.email) {
|
|
172
|
+
this._persistedVars.uif.user_email = payload.email;
|
|
173
|
+
uif.e = payload.email;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (payload.phone) {
|
|
177
|
+
this._persistedVars.uif.user_phone = payload.phone;
|
|
178
|
+
uif.p = payload.phone;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (payload.country) {
|
|
182
|
+
this._persistedVars.uif.user_country = payload.country;
|
|
183
|
+
uif.cy = payload.country;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (payload.city) {
|
|
187
|
+
this._persistedVars.uif.user_city = payload.city;
|
|
188
|
+
uif.ct = payload.city;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (payload.state) {
|
|
192
|
+
this._persistedVars.uif.user_state = payload.state;
|
|
193
|
+
uif.st = payload.state;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (payload.fName) {
|
|
197
|
+
this._persistedVars.uif.fn = payload.fName;
|
|
198
|
+
uif.fn = payload.fName;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (payload.lName) {
|
|
202
|
+
this._persistedVars.uif.ln = payload.lName;
|
|
203
|
+
uif.ln = payload.lName;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (payload.zip) {
|
|
207
|
+
this._persistedVars.uif.zip_code = payload.zip;
|
|
208
|
+
uif.z = payload.zip;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (Object.keys(uif).length > 0) {
|
|
212
|
+
this.storeData('uif', uif);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private async deleteData(chips: string[]): Promise<void> {
|
|
217
|
+
const fullData = await this.getFullData();
|
|
218
|
+
for (const chip of chips) {
|
|
219
|
+
if (typeof chip === 'string') {
|
|
220
|
+
delete fullData[chip];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
await this.storeFullData(fullData);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private async storeData(chip: string, value: any): Promise<void> {
|
|
227
|
+
if (typeof chip !== 'undefined' && typeof value !== 'undefined') {
|
|
228
|
+
const fullData = await this.getFullData();
|
|
229
|
+
fullData[chip] = value;
|
|
230
|
+
await this.storeFullData(fullData);
|
|
231
|
+
this._persistedVars[chip] = value;
|
|
232
|
+
} else {
|
|
233
|
+
Logger.logError('Both key and value are required for persisting data');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private async reloadPersistedVars(): Promise<void> {
|
|
238
|
+
this._persistedVars = await this.getFullData();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
private async getFullData(): Promise<MapLike> {
|
|
242
|
+
try {
|
|
243
|
+
const storedData = await AsyncStorage.getItem(this.storageKeyName);
|
|
244
|
+
if (storedData) {
|
|
245
|
+
return JSON.parse(storedData);
|
|
246
|
+
}
|
|
247
|
+
} catch (err) {
|
|
248
|
+
Logger.logError('Error reloading persisted variables', err);
|
|
249
|
+
}
|
|
250
|
+
return {};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private async storeFullData(fullData: MapLike): Promise<void> {
|
|
254
|
+
this._persistedVars = fullData;
|
|
255
|
+
try {
|
|
256
|
+
await AsyncStorage.setItem(this.storageKeyName, JSON.stringify(fullData));
|
|
257
|
+
} catch (err) {
|
|
258
|
+
Logger.logError('Error storing data', err);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// private async getStoredData<T = any>(chip: string, defValue: T): Promise<T> {
|
|
263
|
+
// let value: T;
|
|
264
|
+
// try {
|
|
265
|
+
// const storedData = await AsyncStorage.getItem(this.storageKeyName);
|
|
266
|
+
// if (storedData) {
|
|
267
|
+
// const parsedData = JSON.parse(storedData);
|
|
268
|
+
// value = parsedData[chip];
|
|
269
|
+
// }
|
|
270
|
+
// } catch (err) {
|
|
271
|
+
// Logger.logError('Error parsing stored data', err);
|
|
272
|
+
// }
|
|
273
|
+
// return value ?? defValue;
|
|
274
|
+
// }
|
|
275
|
+
|
|
92
276
|
/**
|
|
93
277
|
* Private event processor. Idea is that whenever an event is detected, we create a copy of the master data layer,
|
|
94
278
|
* add the event variables, and trigger the event requested when initializing the data layer helper
|
|
95
279
|
* @param eventName
|
|
96
280
|
* @param model
|
|
97
281
|
*/
|
|
98
|
-
eventProcessor(
|
|
282
|
+
async eventProcessor(
|
|
283
|
+
eventName: string,
|
|
284
|
+
model: TypedAny | undefined
|
|
285
|
+
): Promise<void> {
|
|
286
|
+
model = model ?? {};
|
|
287
|
+
|
|
99
288
|
/**
|
|
100
289
|
* The following If block clears the data layer when the initial event is received.
|
|
101
290
|
* This is done to prevent value carry overs from one page to another in single page apps
|
|
102
291
|
*/
|
|
103
292
|
if (eventName === 'reset' || eventName === this.dlInitEvent) {
|
|
104
293
|
this.reset();
|
|
294
|
+
|
|
295
|
+
// add an init event based uuid to the core data model
|
|
296
|
+
model['page_load_uid'] = getUUIDV4();
|
|
297
|
+
model['is_entry_point'] = this.getIsEntryPointValue();
|
|
298
|
+
if (model['is_entry_point'] === 1) {
|
|
299
|
+
// Note: In React Native, we don't have document.referrer, so we'll use a placeholder
|
|
300
|
+
model['entry_point_referrer'] = '';
|
|
301
|
+
}
|
|
302
|
+
|
|
105
303
|
this.setDl(model);
|
|
106
304
|
model = undefined;
|
|
107
305
|
}
|
|
@@ -114,6 +312,11 @@ export class MpDataLayerHelper {
|
|
|
114
312
|
model = {};
|
|
115
313
|
}
|
|
116
314
|
|
|
315
|
+
await this.reloadPersistedVars();
|
|
316
|
+
|
|
317
|
+
// get persisted values and add them into the event model
|
|
318
|
+
model['p'] = this._persistedVars ?? {};
|
|
319
|
+
|
|
117
320
|
// generate a unique id for each event automatically
|
|
118
321
|
model['ev._id'] = Utils.getUniqueID();
|
|
119
322
|
|
|
@@ -122,17 +325,21 @@ export class MpDataLayerHelper {
|
|
|
122
325
|
|
|
123
326
|
model['ev._eventName'] = eventName;
|
|
124
327
|
|
|
328
|
+
model['ev._persistKey'] = eventsToPersist[eventName] || null;
|
|
329
|
+
|
|
125
330
|
model = Utils.flattenObject(model);
|
|
126
331
|
|
|
127
332
|
// create a clone of master data layer and merge event model to it
|
|
128
333
|
const _clone = Object.assign({}, this._masterDataLayer, model);
|
|
129
334
|
const eventTs = Date.now();
|
|
130
335
|
|
|
131
|
-
const eventPayload =
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
336
|
+
const eventPayload = JSON.parse(
|
|
337
|
+
JSON.stringify({
|
|
338
|
+
eventName: eventName,
|
|
339
|
+
eventTs: eventTs,
|
|
340
|
+
model: _clone,
|
|
341
|
+
})
|
|
342
|
+
);
|
|
136
343
|
|
|
137
344
|
// add to state tracker
|
|
138
345
|
this.stateTracker.push(eventPayload);
|
|
@@ -202,7 +409,9 @@ export class MpDataLayerHelper {
|
|
|
202
409
|
// drain queue only if the initial configured event has been received,
|
|
203
410
|
// otherwise mark isReady but dont drain the queue. queue will be drained first when the init
|
|
204
411
|
// event is received
|
|
205
|
-
this.drainQueue()
|
|
412
|
+
this.drainQueue().catch((err) =>
|
|
413
|
+
Logger.logError('Error draining queue', err)
|
|
414
|
+
);
|
|
206
415
|
} else {
|
|
207
416
|
Logger.logDbg(
|
|
208
417
|
`Initial event (${this.dlInitEvent}) NOT received. Events will be queued`
|
|
@@ -210,7 +419,7 @@ export class MpDataLayerHelper {
|
|
|
210
419
|
}
|
|
211
420
|
}
|
|
212
421
|
|
|
213
|
-
drainQueue(): void {
|
|
422
|
+
async drainQueue(): Promise<void> {
|
|
214
423
|
Logger.logDbg('drainQueue...');
|
|
215
424
|
// create a copy of the array
|
|
216
425
|
const _temp = [...this.eventQueue];
|
|
@@ -222,7 +431,7 @@ export class MpDataLayerHelper {
|
|
|
222
431
|
);
|
|
223
432
|
if (initialEventObjectIndex > -1) {
|
|
224
433
|
// splice and execute it
|
|
225
|
-
this.processQItems(
|
|
434
|
+
await this.processQItems(
|
|
226
435
|
_temp[initialEventObjectIndex][0],
|
|
227
436
|
_temp[initialEventObjectIndex][1]
|
|
228
437
|
);
|
|
@@ -230,7 +439,21 @@ export class MpDataLayerHelper {
|
|
|
230
439
|
}
|
|
231
440
|
// continue with other items
|
|
232
441
|
for (const item of _temp) {
|
|
233
|
-
this.processQItems(item[0], item[1]);
|
|
442
|
+
await this.processQItems(item[0], item[1]);
|
|
234
443
|
}
|
|
235
444
|
}
|
|
445
|
+
|
|
446
|
+
getIsEntryPointValue(): number {
|
|
447
|
+
// In React Native, we'll use a simple approach for entry point tracking
|
|
448
|
+
// This could be enhanced with proper session storage implementation
|
|
449
|
+
const currentValue = this.isEntryPoint;
|
|
450
|
+
this.isEntryPoint = 0; // Reset after first use
|
|
451
|
+
return currentValue;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
resetEntryPointInfo(): void {
|
|
455
|
+
// In React Native, we'll default to entry point = 1 for the first session
|
|
456
|
+
// This could be enhanced with proper referrer tracking if needed
|
|
457
|
+
this.isEntryPoint = 1;
|
|
458
|
+
}
|
|
236
459
|
}
|
package/src/index.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import { QcProcessor } from './processors/qc.processor';
|
|
|
16
16
|
import { NetworkService } from './common/network-service';
|
|
17
17
|
import { EventBus } from './common/event-bus';
|
|
18
18
|
import { VisitIdProcessor } from './processors/visit-id.processor';
|
|
19
|
+
import { GeoLocationProcessor } from './processors/geo-location.processor';
|
|
19
20
|
|
|
20
21
|
const DL_INIT_EVENT = 'page_load';
|
|
21
22
|
|
|
@@ -23,7 +24,8 @@ class MagicPixelImpl {
|
|
|
23
24
|
private static dl: MpDataLayerHelper = new MpDataLayerHelper(
|
|
24
25
|
'mpDlEvent',
|
|
25
26
|
'manual',
|
|
26
|
-
DL_INIT_EVENT
|
|
27
|
+
DL_INIT_EVENT,
|
|
28
|
+
'_mpRnDataLayer'
|
|
27
29
|
);
|
|
28
30
|
private static customerInfo: AppCustomerInfo;
|
|
29
31
|
private static customerIdentifiers: MapLike = {};
|
|
@@ -33,6 +35,7 @@ class MagicPixelImpl {
|
|
|
33
35
|
private static firstAppLaunch = true;
|
|
34
36
|
|
|
35
37
|
static async init(options: SdkInitOptions): Promise<void> {
|
|
38
|
+
Logger.setLogLevel(options.logLevel ?? 'none');
|
|
36
39
|
await NetworkService.refreshClientSdkJson(options);
|
|
37
40
|
|
|
38
41
|
if (!DataStore.isDataStoreReady()) {
|
|
@@ -59,6 +62,16 @@ class MagicPixelImpl {
|
|
|
59
62
|
Logger.logDbg('No facebook client id found. not setting');
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
// Initialize EEDL with any global event listeners
|
|
66
|
+
await this.dl.init({});
|
|
67
|
+
|
|
68
|
+
// Make geo location API call after initialization
|
|
69
|
+
try {
|
|
70
|
+
await GeoLocationProcessor.makeGeoLocationApiCall();
|
|
71
|
+
} catch (err) {
|
|
72
|
+
Logger.logError('Error making geo location API call:', err);
|
|
73
|
+
}
|
|
74
|
+
|
|
62
75
|
MagicPixelEventBus.on('mpDlEvent', async (evtName, payload) => {
|
|
63
76
|
Logger.logDbg('mpDlEvent:: ', evtName, JSON.stringify(payload));
|
|
64
77
|
const eventName: string = payload.eventName;
|
|
@@ -280,7 +293,7 @@ class MagicPixelImpl {
|
|
|
280
293
|
DataStore.getSSTDownStream(),
|
|
281
294
|
evtName,
|
|
282
295
|
evtId
|
|
283
|
-
).catch((err
|
|
296
|
+
).catch((err) => {
|
|
284
297
|
Reporter.reportError('l::postSST', err);
|
|
285
298
|
});
|
|
286
299
|
}
|
|
@@ -325,7 +338,10 @@ class MagicPixelImpl {
|
|
|
325
338
|
static recordPageLoad(pageLoadInfo: AppPageLoad): void {
|
|
326
339
|
pageLoadInfo.is_entry = this.firstAppLaunch ? 1 : 0;
|
|
327
340
|
|
|
328
|
-
|
|
341
|
+
// Use stored deepLinkUrl if it exists AND either:
|
|
342
|
+
// - deep_link_url wasn't provided in pageLoadInfo, OR
|
|
343
|
+
// - deep_link_url is empty/falsy (defensive programming for developer mistakes)
|
|
344
|
+
if (this.deepLinkUrl && !pageLoadInfo.deep_link_url) {
|
|
329
345
|
pageLoadInfo.deep_link_url = this.deepLinkUrl;
|
|
330
346
|
}
|
|
331
347
|
|
|
@@ -361,6 +377,86 @@ class MagicPixelImpl {
|
|
|
361
377
|
this.deepLinkUrl = undefined;
|
|
362
378
|
this.firstAppLaunch = false;
|
|
363
379
|
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Set user information for tracking
|
|
383
|
+
* @param userInfo User information object
|
|
384
|
+
*/
|
|
385
|
+
static setUserInfo(userInfo: {
|
|
386
|
+
pid?: string;
|
|
387
|
+
email?: string;
|
|
388
|
+
phone?: string;
|
|
389
|
+
country?: string;
|
|
390
|
+
city?: string;
|
|
391
|
+
state?: string;
|
|
392
|
+
fName?: string;
|
|
393
|
+
lName?: string;
|
|
394
|
+
zip?: string;
|
|
395
|
+
}): void {
|
|
396
|
+
this.dl.pushEvent('user_info', userInfo);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Persist custom data to storage
|
|
401
|
+
* @param key Storage key
|
|
402
|
+
* @param value Value to store
|
|
403
|
+
*/
|
|
404
|
+
static persistData(key: string, value: any): void {
|
|
405
|
+
this.dl.pushEvent('persist', { key, value });
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Clear specific persisted data
|
|
410
|
+
* @param keys Array of keys to clear
|
|
411
|
+
*/
|
|
412
|
+
static clearPersistedData(keys: string[]): void {
|
|
413
|
+
this.dl.pushEvent('clear', keys);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Set data layer variables
|
|
418
|
+
* @param data Data to set in the data layer
|
|
419
|
+
*/
|
|
420
|
+
static setDataLayer(data: MapLike): void {
|
|
421
|
+
this.dl.pushEvent('set', data);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Register a custom event processor
|
|
426
|
+
* @param eventType Event type to listen for
|
|
427
|
+
* @param processor Function to process the event
|
|
428
|
+
*/
|
|
429
|
+
static registerEventProcessor(
|
|
430
|
+
eventType: string,
|
|
431
|
+
processor: (payload: any) => void
|
|
432
|
+
): void {
|
|
433
|
+
this.dl.registerProcessor(eventType, processor);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Get current data layer state
|
|
438
|
+
* @returns Current data layer object
|
|
439
|
+
*/
|
|
440
|
+
static getDataLayer(): MapLike {
|
|
441
|
+
return this.dl.getDl();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Get event state tracker
|
|
446
|
+
* @returns Array of all tracked events
|
|
447
|
+
*/
|
|
448
|
+
static getEventState(): any[] {
|
|
449
|
+
return this.dl.getState();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Check if a specific event has happened
|
|
454
|
+
* @param eventName Event name to check
|
|
455
|
+
* @returns True if event has occurred
|
|
456
|
+
*/
|
|
457
|
+
static hasEventHappened(eventName: string): boolean {
|
|
458
|
+
return this.dl.hasEventHappened(eventName);
|
|
459
|
+
}
|
|
364
460
|
}
|
|
365
461
|
|
|
366
462
|
export const MagicPixelEventBus = EventBus;
|