@mparticle/web-sdk 2.79.2 → 2.80.0

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.
@@ -30,7 +30,9 @@ import Persistence from './persistence';
30
30
  import Events from './events';
31
31
  import Forwarders from './forwarders';
32
32
  import ServerModel, { IServerModel } from './serverModel';
33
- import ForwardingStatsUploader from './forwardingStatsUploader';
33
+ import ForwardingStatsUploader, {
34
+ IForwardingStatsUploader,
35
+ } from './forwardingStatsUploader';
34
36
  import Identity from './identity';
35
37
  import Consent, { IConsent } from './consent';
36
38
  import KitBlocker from './kitBlocking';
@@ -57,7 +59,12 @@ import { LoggingDispatcher } from './reporting/loggingDispatcher';
57
59
  import { IErrorReportingService, ILoggingService } from './reporting/types';
58
60
  import { logDeprecatedMethodUsage } from './reporting/deprecatedMethodLogger';
59
61
  import { normalizeRoktLauncherOptions } from './roktLauncherOptions';
60
- import { PageViewTracker } from './pageViewTracker';
62
+ import {
63
+ hasInitialPageViewFired,
64
+ markInitialPageViewFired,
65
+ PageViewTracker,
66
+ resetPageViewTracking,
67
+ } from './pageViewTracker';
61
68
 
62
69
  export interface IErrorLogMessage {
63
70
  message?: string;
@@ -82,7 +89,7 @@ export interface IMParticleWebSDKInstance extends MParticleWebSDK {
82
89
  _Ecommerce: IECommerce;
83
90
  _Events: IEvents;
84
91
  _Forwarders: any; // https://go.mparticle.com/work/SQDSDKS-5767
85
- _ForwardingStatsUploader: ForwardingStatsUploader;
92
+ _ForwardingStatsUploader: IForwardingStatsUploader;
86
93
  _Helpers: SDKHelpersApi;
87
94
  _Identity: IIdentity;
88
95
  _IdentityAPIClient: typeof IdentityAPIClient;
@@ -105,6 +112,7 @@ export interface IMParticleWebSDKInstance extends MParticleWebSDK {
105
112
  captureTiming(metricName: string);
106
113
  processQueueOnIdentityFailure?: () => void;
107
114
  processQueueOnNoFunctional?: () => void;
115
+ uiwebviewBridgeName?: string;
108
116
  }
109
117
 
110
118
  const { Messages, HTTPCodes, FeatureFlags, CaptureIntegrationSpecificIdsV2Modes } = Constants;
@@ -298,12 +306,8 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan
298
306
  );
299
307
  instance._Events.stopTracking();
300
308
 
301
- const instanceTracker = instance._PageViewTracker;
302
- if (instanceTracker) {
303
- instanceTracker.teardown();
304
- instance._PageViewTracker = undefined;
305
- }
306
- PageViewTracker.resetWindowState(instanceTracker);
309
+ resetPageViewTracking();
310
+ instance._PageViewTracker = undefined;
307
311
 
308
312
  if (!keepPersistence) {
309
313
  instance._Persistence.resetPersistence();
@@ -1593,32 +1597,30 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
1593
1597
  mpInstance._SessionManager.initialize();
1594
1598
  mpInstance._Events.logAST();
1595
1599
 
1596
- // Note: APV uses window-level singletons (WIN_TRACKER_KEY, WIN_INIT_PV_KEY)
1597
- // that assume a single active SDK instance. Multiple-instance support is
1598
- // out of scope
1600
+ // Note: APV state (the active tracker and the initial-page-view flag) is
1601
+ // window-scoped and assumes a single active SDK instance. Multiple-instance
1602
+ // support is out of scope.
1599
1603
  if (getFeatureFlag(AutoLogPageView)) {
1600
1604
  if (!mpInstance._PageViewTracker) {
1601
1605
  mpInstance.Logger.verbose(
1602
1606
  'mParticle APV: [sdk-init] creating new PageViewTracker for this instance'
1603
1607
  );
1604
1608
  mpInstance._PageViewTracker = new PageViewTracker(mpInstance);
1609
+ }
1605
1610
 
1606
- // Fire the initial page view once per page load (hard navigation).
1607
- // The flag survives module re-evaluation so repeated init() calls
1608
- // from SPA re-renders don't fire duplicate logPageView() events.
1609
- if (PageViewTracker.hasInitialPageViewFired()) {
1610
- mpInstance.Logger.verbose(
1611
- 'mParticle APV: [sdk-init] initial page view already logged this page load, skipping'
1612
- );
1613
- } else {
1614
- PageViewTracker.markInitialPageViewFired();
1615
- mpInstance._Events.logPageView();
1616
- }
1617
- } else {
1611
+ // The initial page view fires once per hard page load, not once per
1612
+ // init(): the window flag survives the module re-evaluation Next.js
1613
+ // performs on every SPA navigation, so repeated init() calls from SPA
1614
+ // re-renders don't fire duplicate logPageView() events.
1615
+ if (hasInitialPageViewFired()) {
1618
1616
  mpInstance.Logger.verbose(
1619
- 'mParticle APV: [sdk-init] tracker already on this instance, skipping logPageView'
1617
+ 'mParticle APV: [sdk-init] initial page view already logged this page load, skipping'
1620
1618
  );
1619
+ } else {
1620
+ markInitialPageViewFired();
1621
+ mpInstance._Events.logPageView();
1621
1622
  }
1623
+
1622
1624
  mpInstance._PageViewTracker.init();
1623
1625
  } else if (mpInstance._PageViewTracker) {
1624
1626
  // AutoLogPageView was disabled on re-init: tear down the active tracker
@@ -1,3 +1,23 @@
1
+ export interface IWKScriptMessageHandler {
2
+ postMessage(message: string): void;
3
+ }
4
+
5
+ export interface IAndroidNativeBridge {
6
+ [methodName: string]: ((payload?: string) => void) | undefined;
7
+ }
8
+
9
+ declare global {
10
+ interface Window {
11
+ webkit?: {
12
+ messageHandlers?: Record<
13
+ string,
14
+ IWKScriptMessageHandler | undefined
15
+ >;
16
+ };
17
+ mParticleAndroid?: IAndroidNativeBridge;
18
+ }
19
+ }
20
+
1
21
  export interface INativeSdkHelpers {
2
22
  initializeSessionAttributes: (apiKey: string) => void;
3
23
  isBridgeV2Available: (bridgeName: string) => boolean;
@@ -9,5 +29,5 @@ export interface INativeSdkHelpers {
9
29
  sendToNative: (path: string, value?: string) => void;
10
30
  sendViaBridgeV1: (path: string, value: string) => void;
11
31
  sendViaIframeToIOS: (path: string, value: string) => void;
12
- sendViaBridgeV2: (path: string, value: string, requiredWebviewBridgeName: boolean) => void;
32
+ sendViaBridgeV2: (path: string, value: string, requiredWebviewBridgeName: string) => void;
13
33
  }
@@ -1,13 +1,40 @@
1
1
  import Constants from './constants';
2
+ import { IMParticleWebSDKInstance } from './mp-instance';
3
+ import {
4
+ IAndroidNativeBridge,
5
+ INativeSdkHelpers,
6
+ } from './nativeSdkHelpers.interfaces';
2
7
 
3
- var Messages = Constants.Messages;
8
+ const Messages = Constants.Messages;
4
9
 
5
- var androidBridgeNameBase = 'mParticleAndroid';
6
- var iosBridgeNameBase = 'mParticle';
10
+ const androidBridgeNameBase = 'mParticleAndroid';
11
+ const iosBridgeNameBase = 'mParticle';
7
12
 
8
- export default function NativeSdkHelpers(mpInstance) {
9
- var self = this;
10
- this.initializeSessionAttributes = function(apiKey) {
13
+ function getAndroidBridge(name: string): IAndroidNativeBridge | undefined {
14
+ if (!Object.prototype.hasOwnProperty.call(window, name)) {
15
+ return undefined;
16
+ }
17
+
18
+ return (window as unknown as Record<string, IAndroidNativeBridge | undefined>)[
19
+ name
20
+ ];
21
+ }
22
+
23
+ function getInstanceNamedValue(
24
+ instance: IMParticleWebSDKInstance,
25
+ name: string
26
+ ): unknown {
27
+ return (instance as IMParticleWebSDKInstance & Record<string, unknown>)[
28
+ name
29
+ ];
30
+ }
31
+
32
+ export default function NativeSdkHelpers(
33
+ this: INativeSdkHelpers,
34
+ mpInstance: IMParticleWebSDKInstance
35
+ ): void {
36
+ const self = this;
37
+ this.initializeSessionAttributes = function(apiKey: string): void {
11
38
  const { SetSessionAttribute } = Constants.NativeSdkPaths;
12
39
  const env = JSON.stringify({
13
40
  key: '$src_env',
@@ -25,20 +52,16 @@ export default function NativeSdkHelpers(mpInstance) {
25
52
  }
26
53
  };
27
54
 
28
- this.isBridgeV2Available = function(bridgeName) {
55
+ this.isBridgeV2Available = function(bridgeName: string): boolean {
29
56
  if (!bridgeName) {
30
57
  return false;
31
58
  }
32
- var androidBridgeName =
59
+ const androidBridgeName =
33
60
  androidBridgeNameBase + '_' + bridgeName + '_v2';
34
- var iosBridgeName = iosBridgeNameBase + '_' + bridgeName + '_v2';
61
+ const iosBridgeName = iosBridgeNameBase + '_' + bridgeName + '_v2';
35
62
 
36
63
  // iOS v2 bridge
37
- if (
38
- window.webkit &&
39
- window.webkit.messageHandlers &&
40
- window.webkit.messageHandlers.hasOwnProperty(iosBridgeName)
41
- ) {
64
+ if (window.webkit?.messageHandlers?.hasOwnProperty(iosBridgeName)) {
42
65
  return true;
43
66
  }
44
67
  // other iOS v2 bridge
@@ -58,9 +81,9 @@ export default function NativeSdkHelpers(mpInstance) {
58
81
  };
59
82
 
60
83
  this.isWebviewEnabled = function(
61
- requiredWebviewBridgeName,
62
- minWebviewBridgeVersion
63
- ) {
84
+ requiredWebviewBridgeName: string,
85
+ minWebviewBridgeVersion: number
86
+ ): boolean {
64
87
  mpInstance._Store.bridgeV2Available = self.isBridgeV2Available(
65
88
  requiredWebviewBridgeName
66
89
  );
@@ -92,7 +115,7 @@ export default function NativeSdkHelpers(mpInstance) {
92
115
  return false;
93
116
  };
94
117
 
95
- this.isBridgeV1Available = function() {
118
+ this.isBridgeV1Available = function(): boolean {
96
119
  if (
97
120
  mpInstance._Store.SDKConfig.useNativeSdk ||
98
121
  window.mParticleAndroid ||
@@ -104,7 +127,7 @@ export default function NativeSdkHelpers(mpInstance) {
104
127
  return false;
105
128
  };
106
129
 
107
- this.sendToNative = function(path, value) {
130
+ this.sendToNative = function(path: string, value?: string): void {
108
131
  if (
109
132
  mpInstance._Store.bridgeV2Available &&
110
133
  mpInstance._Store.SDKConfig.minWebviewBridgeVersion === 2
@@ -136,7 +159,7 @@ export default function NativeSdkHelpers(mpInstance) {
136
159
  }
137
160
  };
138
161
 
139
- this.sendViaBridgeV1 = function(path, value) {
162
+ this.sendViaBridgeV1 = function(path: string, value: string): void {
140
163
  if (
141
164
  window.mParticleAndroid &&
142
165
  window.mParticleAndroid.hasOwnProperty(path)
@@ -153,8 +176,8 @@ export default function NativeSdkHelpers(mpInstance) {
153
176
  }
154
177
  };
155
178
 
156
- this.sendViaIframeToIOS = function(path, value) {
157
- var iframe = document.createElement('IFRAME');
179
+ this.sendViaIframeToIOS = function(path: string, value: string): void {
180
+ const iframe = document.createElement('IFRAME');
158
181
  iframe.setAttribute(
159
182
  'src',
160
183
  'mp-sdk://' + path + '/' + encodeURIComponent(value)
@@ -163,30 +186,32 @@ export default function NativeSdkHelpers(mpInstance) {
163
186
  iframe.parentNode.removeChild(iframe);
164
187
  };
165
188
 
166
- this.sendViaBridgeV2 = function(path, value, requiredWebviewBridgeName) {
189
+ this.sendViaBridgeV2 = function(
190
+ path: string,
191
+ value: string,
192
+ requiredWebviewBridgeName: string
193
+ ): void {
167
194
  if (!requiredWebviewBridgeName) {
168
195
  return;
169
196
  }
170
197
 
171
- var androidBridgeName =
198
+ const androidBridgeName =
172
199
  androidBridgeNameBase + '_' + requiredWebviewBridgeName + '_v2',
173
- androidBridge = window[androidBridgeName],
200
+ androidBridge = getAndroidBridge(androidBridgeName),
174
201
  iosBridgeName =
175
- iosBridgeNameBase + '_' + requiredWebviewBridgeName + '_v2',
176
- iOSBridgeMessageHandler,
177
- iOSBridgeNonMessageHandler;
202
+ iosBridgeNameBase + '_' + requiredWebviewBridgeName + '_v2';
203
+ let iOSBridgeMessageHandler, iOSBridgeNonMessageHandler;
178
204
 
179
- if (
180
- window.webkit &&
181
- window.webkit.messageHandlers &&
182
- window.webkit.messageHandlers[iosBridgeName]
183
- ) {
205
+ if (window.webkit?.messageHandlers?.[iosBridgeName]) {
184
206
  iOSBridgeMessageHandler =
185
207
  window.webkit.messageHandlers[iosBridgeName];
186
208
  }
187
209
 
188
210
  if (mpInstance.uiwebviewBridgeName === iosBridgeName) {
189
- iOSBridgeNonMessageHandler = mpInstance[iosBridgeName];
211
+ iOSBridgeNonMessageHandler = getInstanceNamedValue(
212
+ mpInstance,
213
+ iosBridgeName
214
+ );
190
215
  }
191
216
 
192
217
  if (androidBridge && androidBridge.hasOwnProperty(path)) {