@mparticle/web-sdk 3.23.0 → 3.25.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.
- package/dist/mparticle.common.js +1 -1688
- package/dist/mparticle.esm.js +1 -1688
- package/dist/mparticle.js +1015 -253
- package/dist/types/src/buttonTracking/buttonClickEvent.d.ts +7 -0
- package/dist/types/src/buttonTracking/buttonDescription.d.ts +10 -3
- package/dist/types/src/buttonTracking/buttonTracker.d.ts +8 -0
- package/dist/types/src/buttonTracking/checkoutIntent.d.ts +8 -3
- package/dist/types/src/buttonTracking/controls.d.ts +8 -4
- package/dist/types/src/buttonTracking/labelMasking.d.ts +1 -0
- package/dist/types/src/configAPIClient.d.ts +1 -0
- package/dist/types/src/constants.d.ts +1 -0
- package/dist/types/src/cookieConsentManager.d.ts +17 -3
- package/dist/types/src/forwarder-utils.d.ts +3 -0
- package/dist/types/src/pageViewTracker.d.ts +19 -3
- package/dist/types/src/roktLauncherOptions.d.ts +1 -0
- package/dist/types/src/roktManager.d.ts +13 -2
- package/dist/types/src/sdkRuntimeModels.d.ts +1 -0
- package/dist/types/src/store.d.ts +3 -0
- package/package.json +21 -14
- package/src/buttonTracking/buttonClickEvent.ts +126 -8
- package/src/buttonTracking/buttonDescription.ts +336 -53
- package/src/buttonTracking/buttonTracker.ts +231 -19
- package/src/buttonTracking/checkoutIntent.ts +117 -23
- package/src/buttonTracking/controls.ts +169 -55
- package/src/buttonTracking/labelMasking.ts +4 -1
- package/src/configAPIClient.ts +1 -0
- package/src/constants.ts +1 -0
- package/src/cookieConsentManager.ts +23 -3
- package/src/cookieSyncManager.ts +11 -3
- package/src/events.ts +9 -3
- package/src/forwarder-utils.ts +38 -0
- package/src/forwarders.ts +2 -28
- package/src/mp-instance.ts +41 -7
- package/src/pageUrl.ts +43 -2
- package/src/pageViewTracker.ts +193 -111
- package/src/roktLauncherOptions.ts +1 -0
- package/src/roktManager.ts +66 -11
- package/src/sdkRuntimeModels.ts +1 -0
- package/src/store.ts +17 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { IKitFilterSettings } from '../configAPIClient';
|
|
2
|
+
import type KitBlocker from '../kitBlocking';
|
|
1
3
|
import { BaseEvent } from '../sdkRuntimeModels';
|
|
2
4
|
import { IButtonClick } from './buttonDescription';
|
|
3
5
|
export declare const AUTO_BUTTON_ATTRIBUTE = "is_auto_button_click";
|
|
4
6
|
export declare const BUTTON_CLICK_EVENT_NAME = "Auto Button Click";
|
|
7
|
+
export declare const AUTO_LINK_ATTRIBUTE = "is_auto_link_click";
|
|
8
|
+
export declare const LINK_CLICK_EVENT_NAME = "Auto Link Click";
|
|
5
9
|
export declare const buildButtonClickEvent: (click: IButtonClick, pathname: string) => BaseEvent;
|
|
10
|
+
export declare const buildLinkClickEvent: (click: IButtonClick, pathname: string) => BaseEvent;
|
|
11
|
+
export type ButtonClickBlocker = 'data plan' | 'forwarding rule' | 'event name filter' | 'event type filter';
|
|
12
|
+
export declare const getButtonClickBlocker: (forwarder: IKitFilterSettings, kitBlocker?: KitBlocker, link?: boolean) => ButtonClickBlocker | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type ButtonElementKind = 'button' | 'input' | 'role' | 'wallet' | 'link';
|
|
2
|
-
export type LinkType = 'same_page' | 'outbound' | 'download';
|
|
3
|
-
export type ButtonLabelSource = 'labelledby' | 'aria' | 'text' | '
|
|
2
|
+
export type LinkType = 'same_page' | 'internal' | 'outbound' | 'download';
|
|
3
|
+
export type ButtonLabelSource = 'labelledby' | 'aria' | 'text' | 'alt' | 'title' | 'value' | 'none';
|
|
4
4
|
export interface IButtonClick {
|
|
5
5
|
label?: string;
|
|
6
6
|
labelSource: ButtonLabelSource;
|
|
@@ -18,4 +18,11 @@ export interface IButtonClick {
|
|
|
18
18
|
fileExtension?: string;
|
|
19
19
|
checked?: boolean;
|
|
20
20
|
}
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function isLinkClick(click: IButtonClick): boolean;
|
|
22
|
+
export declare function describeButtonClick(control: Element, path?: Array<EventTarget | null>): IButtonClick | undefined;
|
|
23
|
+
export interface IPaymentChoice {
|
|
24
|
+
radio: Element;
|
|
25
|
+
names: string[];
|
|
26
|
+
}
|
|
27
|
+
export declare function describePaymentChoice(control: Element, path?: Array<EventTarget | null>): IPaymentChoice | undefined;
|
|
28
|
+
export declare function isPicked(radio: Element): boolean;
|
|
@@ -2,6 +2,8 @@ import { IMParticleWebSDKInstance } from '../mp-instance';
|
|
|
2
2
|
export declare const WIN_BTN_KEY = "__mpBtn__";
|
|
3
3
|
export interface IButtonTrackerOptions {
|
|
4
4
|
hasRoktKit: boolean;
|
|
5
|
+
logButtons: boolean;
|
|
6
|
+
logLinks: boolean;
|
|
5
7
|
}
|
|
6
8
|
export declare const getActiveButtonTracker: () => ButtonTracker | undefined;
|
|
7
9
|
export declare const resetButtonTracking: () => void;
|
|
@@ -9,8 +11,11 @@ export declare class ButtonTracker {
|
|
|
9
11
|
private readonly mpInstance;
|
|
10
12
|
private active;
|
|
11
13
|
private hasRoktKit;
|
|
14
|
+
private logButtons;
|
|
15
|
+
private logLinks;
|
|
12
16
|
private generation;
|
|
13
17
|
private lastCommitClick;
|
|
18
|
+
private lastClick;
|
|
14
19
|
private lastSent;
|
|
15
20
|
private pagePath;
|
|
16
21
|
private pageEvents;
|
|
@@ -21,6 +26,7 @@ export declare class ButtonTracker {
|
|
|
21
26
|
constructor(mpInstance: IMParticleWebSDKInstance);
|
|
22
27
|
get isActive(): boolean;
|
|
23
28
|
init(options: IButtonTrackerOptions): void;
|
|
29
|
+
onApplePayBegin(): void;
|
|
24
30
|
teardown(): void;
|
|
25
31
|
clearPending(): void;
|
|
26
32
|
private reset;
|
|
@@ -35,7 +41,9 @@ export declare class ButtonTracker {
|
|
|
35
41
|
private uploadNow;
|
|
36
42
|
private cancelUpload;
|
|
37
43
|
private emit;
|
|
44
|
+
private pickPayment;
|
|
38
45
|
private eventsEnabled;
|
|
46
|
+
private hasTargetingOptOut;
|
|
39
47
|
private isKitSuppressed;
|
|
40
48
|
private log;
|
|
41
49
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
export type CheckoutIntentKind = 'commit' | 'wallet' | 'checkout_step' | 'frame';
|
|
2
|
-
export type
|
|
1
|
+
export type CheckoutIntentKind = 'commit' | 'wallet' | 'checkout_step' | 'frame' | 'cart';
|
|
2
|
+
export type PaymentFrameFamily = 'apple_pay' | 'google_pay' | 'amazon_pay' | 'shop_pay' | 'card';
|
|
3
|
+
export type CheckoutIntentSource = 'vendor' | 'label' | 'brand' | 'frame' | 'submit' | 'name' | 'api';
|
|
3
4
|
export interface ICheckoutIntent {
|
|
4
5
|
kind: Exclude<CheckoutIntentKind, 'frame'>;
|
|
5
6
|
source: CheckoutIntentSource;
|
|
6
7
|
}
|
|
7
8
|
export declare function classifyIntent(control: Element, pathname: string): ICheckoutIntent | undefined;
|
|
8
9
|
export declare function classifyIntentControl(control: Element, pathname: string): Exclude<CheckoutIntentKind, 'frame'> | undefined;
|
|
9
|
-
export
|
|
10
|
+
export interface IPaymentFrame {
|
|
11
|
+
kind: 'wallet' | 'frame';
|
|
12
|
+
family?: PaymentFrameFamily;
|
|
13
|
+
}
|
|
14
|
+
export declare function classifyPaymentFrame(target: EventTarget | null, win: Window): IPaymentFrame | undefined;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
export declare const CONTROL_SELECTOR = "button, input[type=\"submit\"], input[type=\"button\"], input[type=\"image\"], [role=\"button\"]";
|
|
2
|
+
export declare function someComposedAncestor(element: Element, test: (node: Element) => boolean, until?: Element): boolean;
|
|
2
3
|
export declare function hasComposedAncestor(element: Element, selector: string): boolean;
|
|
3
4
|
export declare function isRoktElement(element: Element): boolean;
|
|
4
5
|
export declare function vendorButtonKind(control: Element): 'wallet' | 'checkout_step' | 'none' | undefined;
|
|
6
|
+
export declare function nameWords(value: string | null): string;
|
|
7
|
+
export declare function isWalletNamed(element: Element): boolean;
|
|
5
8
|
export declare function isWalletElement(element: Element): boolean;
|
|
6
|
-
export declare function isQuietIntentControl(control: Element, isVendorWallet: boolean): boolean;
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function isQuietIntentControl(control: Element, isVendorWallet: boolean, isCart?: boolean): boolean;
|
|
10
|
+
export declare function isWalletNamedControl(element: Element): boolean;
|
|
11
|
+
export declare function isExcludedPath(path: Array<EventTarget | null>): boolean;
|
|
12
|
+
export declare function findControl(path: Array<EventTarget | null>, included?: boolean): Element | undefined;
|
|
13
|
+
export declare function isUnsafeTextSource(element: Element, own?: Element): boolean;
|
|
@@ -163,6 +163,7 @@ declare const Constants: {
|
|
|
163
163
|
readonly AstBackgroundEvents: "astBackgroundEvents";
|
|
164
164
|
readonly AutoLogPageView: "autoLogPageView";
|
|
165
165
|
readonly AutoButtonTracking: "autoButtonTracking";
|
|
166
|
+
readonly AutoLinkTracking: "autoLinkTracking";
|
|
166
167
|
};
|
|
167
168
|
readonly DefaultInstance: "default_instance";
|
|
168
169
|
readonly CCPAPurpose: "data_sale_opt_out";
|
|
@@ -15,6 +15,11 @@ export interface ICookieConsentFlags {
|
|
|
15
15
|
* Default: false (targeting is allowed)
|
|
16
16
|
*/
|
|
17
17
|
noTargeting: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* When true, indicates the user has opted out of the sale or sharing of their data.
|
|
20
|
+
* Default: false (sharing is allowed)
|
|
21
|
+
*/
|
|
22
|
+
doNotShareOrSell?: boolean;
|
|
18
23
|
}
|
|
19
24
|
export interface ICookieConsentManager {
|
|
20
25
|
/**
|
|
@@ -25,6 +30,10 @@ export interface ICookieConsentManager {
|
|
|
25
30
|
* Functional tracking is allowed when noFunctional is false (default)
|
|
26
31
|
*/
|
|
27
32
|
getNoFunctional: () => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Sharing is allowed when doNotShareOrSell is false (default)
|
|
35
|
+
*/
|
|
36
|
+
getDoNotShareOrSell: () => boolean;
|
|
28
37
|
/**
|
|
29
38
|
* Syncs the $NoTargeting user attribute based on the current noTargeting flag.
|
|
30
39
|
* Sets the attribute when noTargeting is true, removes it when false.
|
|
@@ -32,12 +41,12 @@ export interface ICookieConsentManager {
|
|
|
32
41
|
syncNoTargetingAttribute: (user: IMParticleUser | null) => void;
|
|
33
42
|
}
|
|
34
43
|
/**
|
|
35
|
-
* CookieConsentManager handles storage and access of consent flags (noFunctional, noTargeting
|
|
36
|
-
* that are passed via launcherOptions during SDK initialization.
|
|
44
|
+
* CookieConsentManager handles storage and access of consent flags (noFunctional, noTargeting,
|
|
45
|
+
* doNotShareOrSell) that are passed via launcherOptions during SDK initialization.
|
|
37
46
|
*
|
|
38
47
|
* These flags allow Rokt integration to respect user privacy choices.
|
|
39
48
|
*
|
|
40
|
-
* Default behavior:
|
|
49
|
+
* Default behavior: All flags default to false, meaning all features are allowed
|
|
41
50
|
* unless explicitly opted out by the user.
|
|
42
51
|
*/
|
|
43
52
|
export default class CookieConsentManager implements ICookieConsentManager {
|
|
@@ -53,5 +62,10 @@ export default class CookieConsentManager implements ICookieConsentManager {
|
|
|
53
62
|
* Functional tracking is allowed when noFunctional is false (default).
|
|
54
63
|
*/
|
|
55
64
|
getNoFunctional(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Returns true if the user has opted out of the sale or sharing of their data.
|
|
67
|
+
* Sharing is allowed when doNotShareOrSell is false (default).
|
|
68
|
+
*/
|
|
69
|
+
getDoNotShareOrSell(): boolean;
|
|
56
70
|
syncNoTargetingAttribute(user: IMParticleUser | null): void;
|
|
57
71
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as EventsApi from '@mparticle/event-models';
|
|
2
2
|
import { IKitFilterSettings } from './configAPIClient';
|
|
3
|
+
import type { SDKEvent } from './sdkRuntimeModels';
|
|
4
|
+
import type KitBlocker from './kitBlocking';
|
|
3
5
|
type ForwarderFilterConfig = Pick<IKitFilterSettings, 'eventNameFilters' | 'eventTypeFilters' | 'screenNameFilters' | 'screenAttributeFilters' | 'attributeFilters' | 'userIdentityFilters' | 'filteringEventAttributeValue'>;
|
|
4
6
|
export declare function isBlockedByForwardingRule(messageType: number, attributes: Record<string, unknown> | null, forwarder: ForwarderFilterConfig): boolean;
|
|
5
7
|
export declare function isBlockedByEventFilter(messageType: number, hashedEventName: number, hashedEventType: number, forwarder: ForwarderFilterConfig): boolean;
|
|
8
|
+
export declare function isEventForwarded(event: SDKEvent, forwarder: ForwarderFilterConfig, kitBlocker?: KitBlocker): boolean;
|
|
6
9
|
export declare function filterEventAttributes(messageType: number, eventCategory: number, eventName: string, attributes: Record<string, unknown> | null, forwarder: ForwarderFilterConfig): Record<string, unknown> | null;
|
|
7
10
|
export declare function filterUserIdentities(userIdentities: Array<{
|
|
8
11
|
Type: number;
|
|
@@ -3,11 +3,23 @@ import { BaseEvent } from './sdkRuntimeModels';
|
|
|
3
3
|
import { Dictionary } from './utils';
|
|
4
4
|
export declare const WIN_APV_KEY = "__mpApv__";
|
|
5
5
|
export declare const ALLOWED_QUERY_PARAMS: string[];
|
|
6
|
+
export declare const AUTO_PAGE_VIEW_ATTRIBUTE = "is_auto_page_view";
|
|
7
|
+
export declare const MAX_CUSTOM_QUERY_PARAMS = 25;
|
|
8
|
+
export interface IQueryParamAllowlist {
|
|
9
|
+
allowed: string[];
|
|
10
|
+
rejectedPositions: number[];
|
|
11
|
+
overLimit: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const MAX_CUSTOM_QUERY_PARAM_VALUE_LENGTH = 512;
|
|
14
|
+
export interface ICapturedParam {
|
|
15
|
+
name: string;
|
|
16
|
+
value: string;
|
|
17
|
+
}
|
|
6
18
|
export declare const ALLOWED_QUERY_PARAM_PREFIXES: string[];
|
|
7
19
|
export declare const isAllowedQueryParam: (name: string) => boolean;
|
|
8
20
|
interface IPageSnapshot {
|
|
9
21
|
path: string;
|
|
10
|
-
params:
|
|
22
|
+
params: ICapturedParam[];
|
|
11
23
|
}
|
|
12
24
|
interface IPageViewData extends IPageSnapshot {
|
|
13
25
|
hostname: string;
|
|
@@ -17,8 +29,10 @@ interface IPageViewData extends IPageSnapshot {
|
|
|
17
29
|
export interface IPageViewOptions {
|
|
18
30
|
isAutoPageView?: boolean;
|
|
19
31
|
}
|
|
20
|
-
export declare const
|
|
21
|
-
export declare const
|
|
32
|
+
export declare const parseQueryParamAllowlist: (configured: unknown) => IQueryParamAllowlist;
|
|
33
|
+
export declare const effectiveAllowlist: (extras?: string[]) => string[];
|
|
34
|
+
export declare const allowedQueryParams: (href: string, extras?: string[]) => ICapturedParam[];
|
|
35
|
+
export declare const paramsToAttributes: (params: ICapturedParam[]) => Dictionary<string>;
|
|
22
36
|
export declare const autoPageViewAttribute: (isAutoPageView?: boolean) => Dictionary<boolean>;
|
|
23
37
|
export declare const pageKey: (page: IPageSnapshot) => string;
|
|
24
38
|
export declare const isNewPage: (lastKey: string | null, candidateKey: string) => boolean;
|
|
@@ -31,6 +45,7 @@ export declare class PageViewTracker {
|
|
|
31
45
|
private readonly mpInstance;
|
|
32
46
|
private lastPage;
|
|
33
47
|
private active;
|
|
48
|
+
private customQueryParams;
|
|
34
49
|
private pendingNavigations;
|
|
35
50
|
private undoHistoryPatch;
|
|
36
51
|
private readonly isAutoPageView;
|
|
@@ -38,6 +53,7 @@ export declare class PageViewTracker {
|
|
|
38
53
|
get isActive(): boolean;
|
|
39
54
|
init(): void;
|
|
40
55
|
teardown(): void;
|
|
56
|
+
private readCustomQueryParams;
|
|
41
57
|
private retire;
|
|
42
58
|
private takePendingNavigations;
|
|
43
59
|
private safeHandleNavigation;
|
|
@@ -9,7 +9,7 @@ import { MPID } from "@mparticle/web-sdk";
|
|
|
9
9
|
import { IErrorReportingService, ILoggingService } from "./reporting/types";
|
|
10
10
|
import { IRoktLauncherOptions } from "./roktLauncherOptions";
|
|
11
11
|
import IntegrationCapture from "./integrationCapture";
|
|
12
|
-
import type { CheckoutIntentKind, CheckoutIntentSource } from "./buttonTracking/checkoutIntent";
|
|
12
|
+
import type { CheckoutIntentKind, CheckoutIntentSource, PaymentFrameFamily } from "./buttonTracking/checkoutIntent";
|
|
13
13
|
export type RoktAttributeValueArray = Array<string | number | boolean>;
|
|
14
14
|
export type RoktAttributeValueType = string | number | boolean | undefined | null;
|
|
15
15
|
export type RoktAttributeValue = RoktAttributeValueType | RoktAttributeValueArray;
|
|
@@ -50,6 +50,12 @@ export interface ICheckoutIntentSignal {
|
|
|
50
50
|
source?: CheckoutIntentSource;
|
|
51
51
|
pathname?: string;
|
|
52
52
|
}
|
|
53
|
+
export interface IPaymentPickSignal {
|
|
54
|
+
t: number;
|
|
55
|
+
pathname: string;
|
|
56
|
+
names?: readonly string[];
|
|
57
|
+
family?: PaymentFrameFamily;
|
|
58
|
+
}
|
|
53
59
|
export interface IRoktKitSettings {
|
|
54
60
|
accountId?: string;
|
|
55
61
|
placementAttributesMapping?: string;
|
|
@@ -68,6 +74,7 @@ export interface IRoktKit {
|
|
|
68
74
|
terminate?: () => Promise<void>;
|
|
69
75
|
onRouteChange?: () => void;
|
|
70
76
|
onCheckoutIntent?: (signal: ICheckoutIntentSignal) => void;
|
|
77
|
+
onPaymentPick?: (signal: IPaymentPickSignal) => void;
|
|
71
78
|
launcherOptions?: Dictionary<any>;
|
|
72
79
|
settings?: IRoktKitSettings;
|
|
73
80
|
integrationName?: string;
|
|
@@ -102,6 +109,7 @@ export default class RoktManager {
|
|
|
102
109
|
private isShoppableAdsLoaded;
|
|
103
110
|
private stopRouteChangeWatch;
|
|
104
111
|
private pendingCheckoutIntents;
|
|
112
|
+
private autoButtonClicksForwarded;
|
|
105
113
|
constructor(instanceName?: string);
|
|
106
114
|
/**
|
|
107
115
|
* Sets a callback to be invoked when RoktManager becomes ready
|
|
@@ -127,12 +135,15 @@ export default class RoktManager {
|
|
|
127
135
|
attachKit(kit: IRoktKit): void;
|
|
128
136
|
private watchRouteChanges;
|
|
129
137
|
private notifyRouteChange;
|
|
138
|
+
setAutoButtonClicksForwarded(forwarded: boolean): void;
|
|
139
|
+
hasTargetingOptOut(): boolean;
|
|
130
140
|
isCheckoutIntentSuppressed(): boolean;
|
|
131
141
|
isCheckoutIntentLive(): boolean;
|
|
132
142
|
notifyCheckoutIntent(signal: ICheckoutIntentSignal, pathname?: string): void;
|
|
133
143
|
discardCheckoutIntents(): void;
|
|
144
|
+
notifyPaymentPick(signal: IPaymentPickSignal): void;
|
|
134
145
|
private flushCheckoutIntents;
|
|
135
|
-
|
|
146
|
+
isAutoLogPageViewEnabled(): boolean;
|
|
136
147
|
/**
|
|
137
148
|
* Renders ads based on the options provided
|
|
138
149
|
*
|
|
@@ -223,6 +223,7 @@ export interface SDKInitConfig extends Omit<MPConfiguration, 'dataPlan' | 'logLe
|
|
|
223
223
|
dataPlanOptions?: KitBlockerOptions;
|
|
224
224
|
flags?: Dictionary;
|
|
225
225
|
pixelConfigs?: IPixelConfiguration[];
|
|
226
|
+
autoLogPageViewQueryParams?: string;
|
|
226
227
|
aliasMaxWindow?: number;
|
|
227
228
|
deviceId?: string;
|
|
228
229
|
forceHttps?: boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Batch } from '@mparticle/event-models';
|
|
2
2
|
import { MPID, IdentifyRequest, SDKEventCustomFlags, ConsentState, UserIdentities } from '@mparticle/web-sdk';
|
|
3
3
|
import { IKitConfigs } from './configAPIClient';
|
|
4
|
+
import { IQueryParamAllowlist } from './pageViewTracker';
|
|
4
5
|
import { DataPlanResult, KitBlockerOptions, LogLevelType, SDKDataPlan, SDKEvent, SDKGeoLocation, SDKInitConfig, SDKProduct } from './sdkRuntimeModels';
|
|
5
6
|
import { Dictionary, AttributeValue } from './utils';
|
|
6
7
|
import { SDKConsentState } from './consent';
|
|
@@ -25,6 +26,7 @@ export interface SDKConfig {
|
|
|
25
26
|
appVersion?: string;
|
|
26
27
|
package?: string;
|
|
27
28
|
flags?: IFeatureFlags;
|
|
29
|
+
autoLogPageViewQueryParams?: IQueryParamAllowlist;
|
|
28
30
|
kitConfigs: IKitConfigs[];
|
|
29
31
|
kits: Dictionary<UnregisteredKit>;
|
|
30
32
|
logLevel?: LogLevelType;
|
|
@@ -80,6 +82,7 @@ export interface IFeatureFlags {
|
|
|
80
82
|
astBackgroundEvents?: boolean;
|
|
81
83
|
autoLogPageView?: boolean;
|
|
82
84
|
autoButtonTracking?: boolean;
|
|
85
|
+
autoLinkTracking?: boolean;
|
|
83
86
|
}
|
|
84
87
|
export interface IStore {
|
|
85
88
|
isEnabled: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mparticle/web-sdk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.0",
|
|
4
4
|
"description": "mParticle core SDK for web applications",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -101,20 +101,18 @@
|
|
|
101
101
|
"lint"
|
|
102
102
|
],
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@babel/core": "^
|
|
105
|
-
"@babel/
|
|
106
|
-
"@babel/
|
|
107
|
-
"@babel/
|
|
108
|
-
"@babel/
|
|
109
|
-
"@babel/plugin-transform-runtime": "^7.6.0",
|
|
110
|
-
"@babel/preset-env": "^7.6.0",
|
|
111
|
-
"@babel/preset-typescript": "^7.6.0",
|
|
104
|
+
"@babel/core": "^8.0.7",
|
|
105
|
+
"@babel/plugin-transform-runtime": "^8.0.6",
|
|
106
|
+
"@babel/preset-env": "^8.0.7",
|
|
107
|
+
"@babel/preset-typescript": "^8.0.7",
|
|
108
|
+
"@babel/runtime": "^8.0.7",
|
|
112
109
|
"@mparticle/data-planning-models": "^0.1.0",
|
|
113
110
|
"@mparticle/event-models": "^1.3.1",
|
|
114
|
-
"@rollup/plugin-babel": "
|
|
111
|
+
"@rollup/plugin-babel": "^7.1.0",
|
|
115
112
|
"@rollup/plugin-commonjs": "25.0.4",
|
|
116
113
|
"@rollup/plugin-json": "^5.0.2",
|
|
117
114
|
"@rollup/plugin-node-resolve": "15.2.1",
|
|
115
|
+
"@rollup/plugin-terser": "^1.0.1",
|
|
118
116
|
"@rollup/plugin-typescript": "^11.1.0",
|
|
119
117
|
"@semantic-release/changelog": "^6.0.3",
|
|
120
118
|
"@semantic-release/exec": "^6.0.3",
|
|
@@ -126,7 +124,7 @@
|
|
|
126
124
|
"@types/mocha": "^9.0.0",
|
|
127
125
|
"@types/mparticle__web-sdk": "^2.66.0",
|
|
128
126
|
"@types/node": "^20.1.0",
|
|
129
|
-
"babel-
|
|
127
|
+
"babel-plugin-polyfill-corejs3": "^1.0.0",
|
|
130
128
|
"browser-sync": "^2.26.3",
|
|
131
129
|
"browserify": "^17.0.0",
|
|
132
130
|
"chai": "^4.2.0",
|
|
@@ -159,7 +157,7 @@
|
|
|
159
157
|
"shelljs": "^0.8.4",
|
|
160
158
|
"should": "^7.1.0",
|
|
161
159
|
"sinon": "^16.1.3",
|
|
162
|
-
"ts-jest": "^29.
|
|
160
|
+
"ts-jest": "^29.4.15",
|
|
163
161
|
"tslib": "^2.1.0",
|
|
164
162
|
"typescript": "^5.0.2",
|
|
165
163
|
"uglify-js": "^3.4.9",
|
|
@@ -169,7 +167,16 @@
|
|
|
169
167
|
"peerDependencies": {
|
|
170
168
|
"@mparticle/event-models": "^1.3.1"
|
|
171
169
|
},
|
|
172
|
-
"
|
|
173
|
-
"@babel
|
|
170
|
+
"overrides": {
|
|
171
|
+
"@rollup/plugin-babel": {
|
|
172
|
+
"@babel/core": "$@babel/core"
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"devEngines": {
|
|
176
|
+
"runtime": {
|
|
177
|
+
"name": "node",
|
|
178
|
+
"version": "^22.18.0 || >=24.11.0",
|
|
179
|
+
"onFail": "warn"
|
|
180
|
+
}
|
|
174
181
|
}
|
|
175
182
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IKitFilterSettings } from '../configAPIClient';
|
|
2
|
+
import { isEventForwarded } from '../forwarder-utils';
|
|
3
|
+
import type KitBlocker from '../kitBlocking';
|
|
4
|
+
import KitFilterHelper from '../kitFilterHelper';
|
|
5
|
+
import { BaseEvent, SDKEvent } from '../sdkRuntimeModels';
|
|
2
6
|
import { EventType, MessageType } from '../types';
|
|
3
7
|
import { IButtonClick } from './buttonDescription';
|
|
4
8
|
|
|
@@ -8,22 +12,25 @@ export const AUTO_BUTTON_ATTRIBUTE = 'is_auto_button_click';
|
|
|
8
12
|
// Specific enough not to merge with a customer's own 'Button Click' event.
|
|
9
13
|
export const BUTTON_CLICK_EVENT_NAME = 'Auto Button Click';
|
|
10
14
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export const
|
|
15
|
+
// Marks an automatically logged click on a link that leaves the page.
|
|
16
|
+
export const AUTO_LINK_ATTRIBUTE = 'is_auto_link_click';
|
|
17
|
+
|
|
18
|
+
export const LINK_CLICK_EVENT_NAME = 'Auto Link Click';
|
|
19
|
+
|
|
20
|
+
// The attributes both click events carry, with the page fields that auto page
|
|
21
|
+
// views carry. No intent: classifying clicks is left to whoever reads the data.
|
|
22
|
+
const clickAttributes = (
|
|
15
23
|
click: IButtonClick,
|
|
16
24
|
pathname: string
|
|
17
|
-
):
|
|
25
|
+
): { [key: string]: string | boolean } => {
|
|
18
26
|
const data: { [key: string]: string | boolean } = {
|
|
19
27
|
label_source: click.labelSource,
|
|
20
28
|
element: click.element,
|
|
21
29
|
type: click.type,
|
|
22
30
|
path: pathname,
|
|
23
31
|
hostname: window.location.hostname,
|
|
24
|
-
[AUTO_BUTTON_ATTRIBUTE]: true,
|
|
25
32
|
};
|
|
26
|
-
// Optional fields are left out when the
|
|
33
|
+
// Optional fields are left out when the control has no safe value for them.
|
|
27
34
|
const optional: { [key: string]: string | undefined } = {
|
|
28
35
|
label: click.label,
|
|
29
36
|
aria_label: click.ariaLabel,
|
|
@@ -45,6 +52,16 @@ export const buildButtonClickEvent = (
|
|
|
45
52
|
if (click.checked !== undefined) {
|
|
46
53
|
data.checked = click.checked;
|
|
47
54
|
}
|
|
55
|
+
return data;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// One custom event per button click, logged like logLink() with the auto marker.
|
|
59
|
+
export const buildButtonClickEvent = (
|
|
60
|
+
click: IButtonClick,
|
|
61
|
+
pathname: string
|
|
62
|
+
): BaseEvent => {
|
|
63
|
+
const data = clickAttributes(click, pathname);
|
|
64
|
+
data[AUTO_BUTTON_ATTRIBUTE] = true;
|
|
48
65
|
return {
|
|
49
66
|
messageType: MessageType.PageEvent,
|
|
50
67
|
name: BUTTON_CLICK_EVENT_NAME,
|
|
@@ -52,3 +69,104 @@ export const buildButtonClickEvent = (
|
|
|
52
69
|
eventType: EventType.Other,
|
|
53
70
|
};
|
|
54
71
|
};
|
|
72
|
+
|
|
73
|
+
// One custom event per click on a link that leaves the page. Typed Other, not
|
|
74
|
+
// Navigation, so no kit reads it as a page change. A plain link to another page
|
|
75
|
+
// of the site goes without its text, which can name the shopper ("Hi, Jane");
|
|
76
|
+
// a button or wallet acting as a link keeps its name.
|
|
77
|
+
export const buildLinkClickEvent = (
|
|
78
|
+
click: IButtonClick,
|
|
79
|
+
pathname: string
|
|
80
|
+
): BaseEvent => {
|
|
81
|
+
const data = clickAttributes(
|
|
82
|
+
click.linkType === 'internal' && click.element === 'link'
|
|
83
|
+
? {
|
|
84
|
+
...click,
|
|
85
|
+
label: undefined,
|
|
86
|
+
labelSource: 'none',
|
|
87
|
+
ariaLabel: undefined,
|
|
88
|
+
}
|
|
89
|
+
: click,
|
|
90
|
+
pathname
|
|
91
|
+
);
|
|
92
|
+
data[AUTO_LINK_ATTRIBUTE] = true;
|
|
93
|
+
return {
|
|
94
|
+
messageType: MessageType.PageEvent,
|
|
95
|
+
name: LINK_CLICK_EVENT_NAME,
|
|
96
|
+
data,
|
|
97
|
+
eventType: EventType.Other,
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Every attribute buildButtonClickEvent can set apart from the marker and the
|
|
102
|
+
// hostname, which is the same on every click on this page. A spec checks the
|
|
103
|
+
// two stay in step.
|
|
104
|
+
const CLICK_ATTRIBUTES = [
|
|
105
|
+
'label_source',
|
|
106
|
+
'element',
|
|
107
|
+
'type',
|
|
108
|
+
'path',
|
|
109
|
+
'label',
|
|
110
|
+
'aria_label',
|
|
111
|
+
'icon',
|
|
112
|
+
'element_id',
|
|
113
|
+
'element_name',
|
|
114
|
+
'test_id',
|
|
115
|
+
'controls',
|
|
116
|
+
'form',
|
|
117
|
+
'link_type',
|
|
118
|
+
'link_domain',
|
|
119
|
+
'file_extension',
|
|
120
|
+
'checked',
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
export type ButtonClickBlocker =
|
|
124
|
+
| 'data plan'
|
|
125
|
+
| 'forwarding rule'
|
|
126
|
+
| 'event name filter'
|
|
127
|
+
| 'event type filter';
|
|
128
|
+
|
|
129
|
+
// Which check keeps some or all auto button clicks, or auto link clicks with
|
|
130
|
+
// `link`, from a kit, or undefined when the kit receives every one. A forwarding
|
|
131
|
+
// rule on an attribute whose value differs between clicks lets some through and
|
|
132
|
+
// not others. Each other check goes through isEventForwarded on its own, so
|
|
133
|
+
// together they decide as it does for each click.
|
|
134
|
+
export const getButtonClickBlocker = (
|
|
135
|
+
forwarder: IKitFilterSettings,
|
|
136
|
+
kitBlocker?: KitBlocker,
|
|
137
|
+
link = false
|
|
138
|
+
): ButtonClickBlocker | undefined => {
|
|
139
|
+
const rule = forwarder.filteringEventAttributeValue;
|
|
140
|
+
if (
|
|
141
|
+
rule &&
|
|
142
|
+
rule.eventAttributeValue &&
|
|
143
|
+
CLICK_ATTRIBUTES.some(
|
|
144
|
+
name =>
|
|
145
|
+
KitFilterHelper.hashAttributeConditionalForwarding(name) ===
|
|
146
|
+
rule.eventAttributeName
|
|
147
|
+
)
|
|
148
|
+
) {
|
|
149
|
+
return 'forwarding rule';
|
|
150
|
+
}
|
|
151
|
+
const attributes: { [key: string]: string | boolean } = {
|
|
152
|
+
hostname: window.location.hostname,
|
|
153
|
+
};
|
|
154
|
+
attributes[link ? AUTO_LINK_ATTRIBUTE : AUTO_BUTTON_ATTRIBUTE] = true;
|
|
155
|
+
const click = ({
|
|
156
|
+
EventName: link ? LINK_CLICK_EVENT_NAME : BUTTON_CLICK_EVENT_NAME,
|
|
157
|
+
EventCategory: EventType.Other,
|
|
158
|
+
EventDataType: MessageType.PageEvent,
|
|
159
|
+
EventAttributes: attributes,
|
|
160
|
+
} as unknown) as SDKEvent;
|
|
161
|
+
const checks: Array<[ButtonClickBlocker, Partial<IKitFilterSettings>]> = [
|
|
162
|
+
['data plan', {}],
|
|
163
|
+
['forwarding rule', { filteringEventAttributeValue: rule }],
|
|
164
|
+
['event name filter', { eventNameFilters: forwarder.eventNameFilters }],
|
|
165
|
+
['event type filter', { eventTypeFilters: forwarder.eventTypeFilters }],
|
|
166
|
+
];
|
|
167
|
+
const failed = checks.find(
|
|
168
|
+
([, filters]) =>
|
|
169
|
+
!isEventForwarded(click, filters as IKitFilterSettings, kitBlocker)
|
|
170
|
+
);
|
|
171
|
+
return failed ? failed[0] : undefined;
|
|
172
|
+
};
|