@mparticle/web-sdk 3.24.0 → 3.26.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.
@@ -5,6 +5,7 @@ export interface IRoktLauncherOptions extends Dictionary<any> {
5
5
  noDeviceID?: boolean;
6
6
  noFunctional?: boolean;
7
7
  noTargeting?: boolean;
8
+ doNotShareOrSell?: boolean;
8
9
  sessionId?: string;
9
10
  sessionToken?: string;
10
11
  }
@@ -23,11 +23,12 @@ import { PARTNER_MODULE_IDS } from "./cookieSyncManager";
23
23
  import IntegrationCapture from "./integrationCapture";
24
24
  import Constants from "./constants";
25
25
  import { subscribeToRouteChange } from "./routeChangeMonitor";
26
- import type { CheckoutIntentKind, CheckoutIntentSource } from "./buttonTracking/checkoutIntent";
26
+ import type { CheckoutIntentKind, CheckoutIntentSource, PaymentFrameFamily } from "./buttonTracking/checkoutIntent";
27
27
 
28
28
  const PASSBACK_CONVERSION_TRACKING_ID = 'passbackconversiontrackingid';
29
- // One signal per kind (commit, wallet, checkout_step, frame and cart), so a new kind never evicts another.
30
- const CHECKOUT_INTENT_BUFFER_LIMIT = 5;
29
+ // One signal per kind (commit, wallet, checkout_step, frame and cart), with an
30
+ // add-to-cart click apart from a cart open, so a new one never evicts another.
31
+ const CHECKOUT_INTENT_BUFFER_LIMIT = 6;
31
32
  const CHECKOUT_INTENT_MAX_AGE_MS = 30000;
32
33
 
33
34
  type AttributeTargetUser = Pick<IMParticleUser, 'getUserIdentities' | 'setUserAttributes'>;
@@ -83,6 +84,19 @@ export interface ICheckoutIntentSignal {
83
84
  t: number;
84
85
  source?: CheckoutIntentSource;
85
86
  pathname?: string;
87
+ // On a cart click that puts something in the cart. Older kits ignore it.
88
+ adds?: true;
89
+ }
90
+
91
+ // What a kit receives when the shopper picks a payment method: the names of a
92
+ // payment radio's option, masked like a label, or the payment family of a
93
+ // frame the shopper moved into. It is handed over in memory only: the kit
94
+ // keeps the family it reads and nothing of the names.
95
+ export interface IPaymentPickSignal {
96
+ t: number;
97
+ pathname: string;
98
+ names?: readonly string[];
99
+ family?: PaymentFrameFamily;
86
100
  }
87
101
 
88
102
  export interface IRoktKitSettings {
@@ -109,6 +123,8 @@ export interface IRoktKit {
109
123
  onRouteChange?: () => void;
110
124
  // Set by the kit only when it wants checkout intent signals.
111
125
  onCheckoutIntent?: (signal: ICheckoutIntentSignal) => void;
126
+ // Set by the kit only when it wants payment picks.
127
+ onPaymentPick?: (signal: IPaymentPickSignal) => void;
112
128
  launcherOptions?: Dictionary<any>;
113
129
  settings?: IRoktKitSettings;
114
130
  integrationName?: string;
@@ -315,6 +331,18 @@ export default class RoktManager {
315
331
  this.autoButtonClicksForwarded = forwarded;
316
332
  }
317
333
 
334
+ // noTargeting (which noDeviceId implies), doNotShareOrSell or Global Privacy
335
+ // Control. Unlike noFunctional, these also stop auto button and link clicks
336
+ // from being logged.
337
+ public hasTargetingOptOut(): boolean {
338
+ const options = this.launcherOptions || {};
339
+ if (options.noTargeting || options.doNotShareOrSell) {
340
+ return true;
341
+ }
342
+ const nav = typeof navigator === 'undefined' ? undefined : (navigator as Navigator & { globalPrivacyControl?: boolean });
343
+ return !!nav && nav.globalPrivacyControl === true;
344
+ }
345
+
318
346
  // Checkout intent is off unless the flag is on, and under opt-out, any Rokt
319
347
  // privacy launcher option, Global Privacy Control, or a Rokt connection that
320
348
  // does not receive auto button clicks.
@@ -328,12 +356,7 @@ export default class RoktManager {
328
356
  ) {
329
357
  return true;
330
358
  }
331
- const options = this.launcherOptions || {};
332
- if (options.noFunctional || options.noTargeting || options.doNotShareOrSell) {
333
- return true;
334
- }
335
- const nav = typeof navigator === 'undefined' ? undefined : (navigator as Navigator & { globalPrivacyControl?: boolean });
336
- return !!nav && nav.globalPrivacyControl === true;
359
+ return !!this.launcherOptions?.noFunctional || this.hasTargetingOptOut();
337
360
  }
338
361
 
339
362
  // True when the kit can wait for the shopper's confirm click: signals are not
@@ -355,8 +378,14 @@ export default class RoktManager {
355
378
 
356
379
  const kit = this.kit;
357
380
  if (!kit) {
381
+ // One per kind, with an add-to-cart click kept apart from a
382
+ // click that opens the cart.
358
383
  this.pendingCheckoutIntents = this.pendingCheckoutIntents
359
- .filter(pending => pending.signal.kind !== signal.kind)
384
+ .filter(
385
+ pending =>
386
+ pending.signal.kind !== signal.kind ||
387
+ !!pending.signal.adds !== !!signal.adds
388
+ )
360
389
  .concat({ signal, pathname })
361
390
  .slice(-CHECKOUT_INTENT_BUFFER_LIMIT);
362
391
  return;
@@ -377,6 +406,26 @@ export default class RoktManager {
377
406
  this.pendingCheckoutIntents = [];
378
407
  }
379
408
 
409
+ // Under the same gates as checkout intent. A pick made before a kit
410
+ // attaches is not kept: the shopper is still choosing, and the next pick
411
+ // replaces it.
412
+ public notifyPaymentPick(signal: IPaymentPickSignal): void {
413
+ if (this.isCheckoutIntentSuppressed()) {
414
+ return;
415
+ }
416
+
417
+ const kit = this.kit;
418
+ try {
419
+ if (kit && isFunction(kit.onPaymentPick)) {
420
+ kit.onPaymentPick(signal);
421
+ }
422
+ } catch (e) {
423
+ this.logger?.error(
424
+ `RoktManager: Error in onPaymentPick: ${getErrorMessage(e)}`
425
+ );
426
+ }
427
+ }
428
+
380
429
  // Replays recent buffered signals raised on the current page, oldest first.
381
430
  private flushCheckoutIntents(): void {
382
431
  const pending = this.pendingCheckoutIntents;
package/src/store.ts CHANGED
@@ -159,6 +159,7 @@ export interface IFeatureFlags {
159
159
  astBackgroundEvents?: boolean;
160
160
  autoLogPageView?: boolean;
161
161
  autoButtonTracking?: boolean;
162
+ autoLinkTracking?: boolean;
162
163
  }
163
164
 
164
165
  // Temporary Interface until Store can be refactored as a class
@@ -793,6 +794,7 @@ export function processFlags(config: SDKInitConfig): IFeatureFlags {
793
794
  AstBackgroundEvents,
794
795
  AutoLogPageView,
795
796
  AutoButtonTracking,
797
+ AutoLinkTracking,
796
798
  } = Constants.FeatureFlags;
797
799
 
798
800
  if (!config.flags) {
@@ -815,6 +817,7 @@ export function processFlags(config: SDKInitConfig): IFeatureFlags {
815
817
  flags[AstBackgroundEvents] = config.flags[AstBackgroundEvents] === 'True';
816
818
  flags[AutoLogPageView] = config.flags[AutoLogPageView] === 'True';
817
819
  flags[AutoButtonTracking] = config.flags[AutoButtonTracking] === 'True';
820
+ flags[AutoLinkTracking] = config.flags[AutoLinkTracking] === 'True';
818
821
  return flags;
819
822
  }
820
823