@mparticle/web-sdk 2.31.1 → 2.32.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/dist/mparticle.common.js +29 -43
- package/dist/mparticle.esm.js +29 -43
- package/dist/mparticle.js +152 -130
- package/package.json +1 -1
- package/src/aliasRequestApiClient.ts +2 -1
- package/src/configAPIClient.ts +2 -12
- package/src/consent.ts +4 -0
- package/src/cookieSyncManager.ts +162 -0
- package/src/identity.js +1 -5
- package/src/identityApiClient.interfaces.ts +44 -0
- package/src/integrationCapture.ts +77 -12
- package/src/nativeSdkHelpers.interfaces.ts +13 -0
- package/src/persistence.interfaces.ts +3 -4
- package/src/sdkRuntimeModels.ts +5 -1
- package/src/sdkToEventsApiConverter.ts +37 -3
- package/src/store.ts +3 -3
- package/src/utils.ts +25 -0
- package/src/cookieSyncManager.js +0 -197
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { IdentityApiData, MPID, UserIdentities } from '@mparticle/web-sdk';
|
|
2
|
+
import {
|
|
3
|
+
IdentityCallback,
|
|
4
|
+
IIdentityResponse,
|
|
5
|
+
} from './identity-user-interfaces';
|
|
6
|
+
import {
|
|
7
|
+
IAliasRequest,
|
|
8
|
+
IAliasCallback,
|
|
9
|
+
IIdentityRequest,
|
|
10
|
+
IdentityAPIMethod,
|
|
11
|
+
IIdentity,
|
|
12
|
+
} from './identity.interfaces';
|
|
13
|
+
import { MParticleWebSDK } from './sdkRuntimeModels';
|
|
14
|
+
|
|
15
|
+
export interface IIdentityApiClient {
|
|
16
|
+
sendAliasRequest: (
|
|
17
|
+
aliasRequest: IAliasRequest,
|
|
18
|
+
aliasCallback: IAliasCallback
|
|
19
|
+
) => Promise<void>;
|
|
20
|
+
sendIdentityRequest: (
|
|
21
|
+
identityApiRequest: IIdentityRequest,
|
|
22
|
+
method: IdentityAPIMethod,
|
|
23
|
+
callback: IdentityCallback,
|
|
24
|
+
originalIdentityApiData: IdentityApiData,
|
|
25
|
+
parseIdentityResponse: IIdentity['parseIdentityResponse'],
|
|
26
|
+
mpid: MPID,
|
|
27
|
+
knownIdentities: UserIdentities
|
|
28
|
+
) => Promise<void>;
|
|
29
|
+
getUploadUrl: (method: IdentityAPIMethod, mpid: MPID) => string;
|
|
30
|
+
getIdentityResponseFromFetch: (
|
|
31
|
+
response: Response,
|
|
32
|
+
responseBody: string
|
|
33
|
+
) => IIdentityResponse;
|
|
34
|
+
getIdentityResponseFromXHR: (response: Response) => IIdentityResponse;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// https://go.mparticle.com/work/SQDSDKS-6568
|
|
38
|
+
// https://go.mparticle.com/work/SQDSDKS-6679
|
|
39
|
+
// Combine with `sendIdentityRequest` above once module is fully migrated
|
|
40
|
+
export type IIdentityApiClientSendAliasRequest = (
|
|
41
|
+
mpInstance: MParticleWebSDK,
|
|
42
|
+
aliasRequest: IAliasRequest,
|
|
43
|
+
aliasCallback: IAliasCallback
|
|
44
|
+
) => Promise<void>;
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getCookies,
|
|
6
6
|
getHref,
|
|
7
7
|
isEmpty,
|
|
8
|
+
valueof,
|
|
8
9
|
} from './utils';
|
|
9
10
|
|
|
10
11
|
export interface IntegrationCaptureProcessorFunction {
|
|
@@ -48,11 +49,24 @@ export const facebookClickIdProcessor: IntegrationCaptureProcessorFunction = (
|
|
|
48
49
|
|
|
49
50
|
return `fb.${subdomainIndex}.${_timestamp}.${clickId}`;
|
|
50
51
|
};
|
|
52
|
+
|
|
53
|
+
// Integration outputs are used to determine how click ids are used within the SDK
|
|
54
|
+
// CUSTOM_FLAGS are sent out when an Event is created via ServerModel.createEventObject
|
|
55
|
+
// PARTNER_IDENTITIES are sent out in a Batch when a group of events are converted to a Batch
|
|
56
|
+
|
|
57
|
+
const IntegrationOutputs = {
|
|
58
|
+
CUSTOM_FLAGS: 'custom_flags',
|
|
59
|
+
PARTNER_IDENTITIES: 'partner_identities',
|
|
60
|
+
} as const;
|
|
61
|
+
|
|
62
|
+
interface IntegrationMappingItem {
|
|
63
|
+
mappedKey: string;
|
|
64
|
+
output: valueof<typeof IntegrationOutputs>;
|
|
65
|
+
processor?: IntegrationCaptureProcessorFunction;
|
|
66
|
+
}
|
|
67
|
+
|
|
51
68
|
interface IntegrationIdMapping {
|
|
52
|
-
[key: string]:
|
|
53
|
-
mappedKey: string;
|
|
54
|
-
processor?: IntegrationCaptureProcessorFunction;
|
|
55
|
-
};
|
|
69
|
+
[key: string]: IntegrationMappingItem;
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
const integrationMapping: IntegrationIdMapping = {
|
|
@@ -60,33 +74,54 @@ const integrationMapping: IntegrationIdMapping = {
|
|
|
60
74
|
fbclid: {
|
|
61
75
|
mappedKey: 'Facebook.ClickId',
|
|
62
76
|
processor: facebookClickIdProcessor,
|
|
77
|
+
output: IntegrationOutputs.CUSTOM_FLAGS,
|
|
63
78
|
},
|
|
64
79
|
_fbp: {
|
|
65
80
|
mappedKey: 'Facebook.BrowserId',
|
|
81
|
+
output: IntegrationOutputs.CUSTOM_FLAGS,
|
|
66
82
|
},
|
|
67
83
|
_fbc: {
|
|
68
84
|
mappedKey: 'Facebook.ClickId',
|
|
85
|
+
output: IntegrationOutputs.CUSTOM_FLAGS,
|
|
69
86
|
},
|
|
70
87
|
|
|
71
88
|
// Google
|
|
72
89
|
gclid: {
|
|
73
90
|
mappedKey: 'GoogleEnhancedConversions.Gclid',
|
|
91
|
+
output: IntegrationOutputs.CUSTOM_FLAGS,
|
|
74
92
|
},
|
|
75
93
|
gbraid: {
|
|
76
94
|
mappedKey: 'GoogleEnhancedConversions.Gbraid',
|
|
95
|
+
output: IntegrationOutputs.CUSTOM_FLAGS,
|
|
77
96
|
},
|
|
78
97
|
wbraid: {
|
|
79
98
|
mappedKey: 'GoogleEnhancedConversions.Wbraid',
|
|
99
|
+
output: IntegrationOutputs.CUSTOM_FLAGS,
|
|
80
100
|
},
|
|
81
101
|
|
|
102
|
+
// TIKTOK
|
|
103
|
+
ttclid: {
|
|
104
|
+
mappedKey: 'TikTok.Callback',
|
|
105
|
+
output: IntegrationOutputs.CUSTOM_FLAGS,
|
|
106
|
+
},
|
|
107
|
+
_ttp: {
|
|
108
|
+
mappedKey: 'tiktok_cookie_id',
|
|
109
|
+
output: IntegrationOutputs.PARTNER_IDENTITIES,
|
|
110
|
+
},
|
|
82
111
|
};
|
|
83
112
|
|
|
84
113
|
export default class IntegrationCapture {
|
|
85
114
|
public clickIds: Dictionary<string>;
|
|
86
115
|
public readonly initialTimestamp: number;
|
|
116
|
+
public readonly filteredPartnerIdentityMappings: IntegrationIdMapping;
|
|
117
|
+
public readonly filteredCustomFlagMappings: IntegrationIdMapping;
|
|
87
118
|
|
|
88
119
|
constructor() {
|
|
89
120
|
this.initialTimestamp = Date.now();
|
|
121
|
+
|
|
122
|
+
// Cache filtered mappings for faster access
|
|
123
|
+
this.filteredPartnerIdentityMappings = this.filterMappings(IntegrationOutputs.PARTNER_IDENTITIES);
|
|
124
|
+
this.filteredCustomFlagMappings = this.filterMappings(IntegrationOutputs.CUSTOM_FLAGS);
|
|
90
125
|
}
|
|
91
126
|
|
|
92
127
|
/**
|
|
@@ -134,22 +169,42 @@ export default class IntegrationCapture {
|
|
|
134
169
|
* @returns {SDKEventCustomFlags} The custom flags.
|
|
135
170
|
*/
|
|
136
171
|
public getClickIdsAsCustomFlags(): SDKEventCustomFlags {
|
|
137
|
-
|
|
172
|
+
return this.getClickIds(this.clickIds, this.filteredCustomFlagMappings);
|
|
173
|
+
}
|
|
138
174
|
|
|
139
|
-
|
|
140
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Returns only the `partner_identities` mapped integration output.
|
|
177
|
+
* @returns {Dictionary<string>} The partner identities.
|
|
178
|
+
*/
|
|
179
|
+
public getClickIdsAsPartnerIdentities(): Dictionary<string> {
|
|
180
|
+
return this.getClickIds(this.clickIds, this.filteredPartnerIdentityMappings);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private getClickIds(
|
|
184
|
+
clickIds: Dictionary<string>,
|
|
185
|
+
mappingList: IntegrationIdMapping
|
|
186
|
+
): Dictionary<string> {
|
|
187
|
+
const mappedClickIds: Dictionary<string> = {};
|
|
188
|
+
|
|
189
|
+
if (!clickIds) {
|
|
190
|
+
return mappedClickIds;
|
|
141
191
|
}
|
|
142
192
|
|
|
143
|
-
for (const [key, value] of Object.entries(
|
|
144
|
-
const mappedKey =
|
|
193
|
+
for (const [key, value] of Object.entries(clickIds)) {
|
|
194
|
+
const mappedKey = mappingList[key]?.mappedKey;
|
|
145
195
|
if (!isEmpty(mappedKey)) {
|
|
146
|
-
|
|
196
|
+
mappedClickIds[mappedKey] = value;
|
|
147
197
|
}
|
|
148
198
|
}
|
|
149
|
-
|
|
199
|
+
|
|
200
|
+
return mappedClickIds;
|
|
150
201
|
}
|
|
151
202
|
|
|
152
|
-
private applyProcessors(
|
|
203
|
+
private applyProcessors(
|
|
204
|
+
clickIds: Dictionary<string>,
|
|
205
|
+
url?: string,
|
|
206
|
+
timestamp?: number
|
|
207
|
+
): Dictionary<string> {
|
|
153
208
|
const processedClickIds: Dictionary<string> = {};
|
|
154
209
|
|
|
155
210
|
for (const [key, value] of Object.entries(clickIds)) {
|
|
@@ -163,4 +218,14 @@ export default class IntegrationCapture {
|
|
|
163
218
|
|
|
164
219
|
return processedClickIds;
|
|
165
220
|
}
|
|
221
|
+
|
|
222
|
+
private filterMappings(
|
|
223
|
+
outputType: valueof<typeof IntegrationOutputs>
|
|
224
|
+
): IntegrationIdMapping {
|
|
225
|
+
return Object.fromEntries(
|
|
226
|
+
Object.entries(integrationMapping).filter(
|
|
227
|
+
([, value]) => value.output === outputType
|
|
228
|
+
)
|
|
229
|
+
);
|
|
230
|
+
}
|
|
166
231
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface INativeSdkHelpers {
|
|
2
|
+
initializeSessionAttributes: (apiKey: string) => void;
|
|
3
|
+
isBridgeV2Available: (bridgeName: string) => boolean;
|
|
4
|
+
isWebviewEnabled: (
|
|
5
|
+
requiredWebviewBridgeName: string,
|
|
6
|
+
minWebviewBridgeVersion: number
|
|
7
|
+
) => boolean;
|
|
8
|
+
isBridgeV1Available: () => boolean;
|
|
9
|
+
sendToNative: (path: string, value: string) => void;
|
|
10
|
+
sendViaBridgeV1: (path: string, value: string) => void;
|
|
11
|
+
sendViaIframeToIOS: (path: string, value: string) => void;
|
|
12
|
+
sendViaBridgeV2: (path: string, value: string, requiredWebviewBridgeName: boolean) => void;
|
|
13
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { Dictionary } from './utils';
|
|
15
15
|
import { IMinifiedConsentJSONObject } from './consent';
|
|
16
16
|
import { UserAttributes } from './identity-user-interfaces';
|
|
17
|
+
import { CookieSyncDates } from './cookieSyncManager';
|
|
17
18
|
|
|
18
19
|
export type UploadsTable = Dictionary<any>;
|
|
19
20
|
export interface iForwardingStatsBatches {
|
|
@@ -79,10 +80,8 @@ export interface IPersistenceMinified extends Dictionary {
|
|
|
79
80
|
// };
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
export type CookieSyncDate = Dictionary<number>;
|
|
83
|
-
|
|
84
83
|
export interface IUserPersistenceMinified extends Dictionary {
|
|
85
|
-
csd:
|
|
84
|
+
csd: CookieSyncDates; // list of timestamps for last cookie sync per module
|
|
86
85
|
con: IMinifiedConsentJSONObject; // Consent State
|
|
87
86
|
ui: UserIdentities; // User Identities
|
|
88
87
|
ua: UserAttributes; // User Attributes
|
|
@@ -121,7 +120,7 @@ export interface IPersistence {
|
|
|
121
120
|
getDomain(doc: string, locationHostname: string): string;
|
|
122
121
|
getCartProducts(mpid: MPID): Product[];
|
|
123
122
|
setCartProducts(allProducts: Product[]): void;
|
|
124
|
-
saveUserCookieSyncDatesToPersistence(mpid: MPID, csd:
|
|
123
|
+
saveUserCookieSyncDatesToPersistence(mpid: MPID, csd: CookieSyncDates): void;
|
|
125
124
|
savePersistence(persistance: IPersistenceMinified): void;
|
|
126
125
|
getPersistence(): IPersistenceMinified;
|
|
127
126
|
getFirstSeenTime(mpid: MPID): string | null;
|
package/src/sdkRuntimeModels.ts
CHANGED
|
@@ -31,6 +31,8 @@ import {
|
|
|
31
31
|
} from './identity-user-interfaces';
|
|
32
32
|
import { IIdentityType } from './types.interfaces';
|
|
33
33
|
import IntegrationCapture from './integrationCapture';
|
|
34
|
+
import { INativeSdkHelpers } from './nativeSdkHelpers.interfaces';
|
|
35
|
+
import { ICookieSyncManager, IPixelConfiguration } from './cookieSyncManager';
|
|
34
36
|
|
|
35
37
|
// TODO: Resolve this with version in @mparticle/web-sdk
|
|
36
38
|
export type SDKEventCustomFlags = Dictionary<any>;
|
|
@@ -158,6 +160,7 @@ export interface MParticleWebSDK {
|
|
|
158
160
|
Logger: SDKLoggerApi;
|
|
159
161
|
MPSideloadedKit: IMPSideloadedKit;
|
|
160
162
|
_APIClient: any; // TODO: Set up API Client
|
|
163
|
+
_CookieSyncManager: ICookieSyncManager;
|
|
161
164
|
_Store: IStore;
|
|
162
165
|
_Forwarders: any;
|
|
163
166
|
_Helpers: SDKHelpersApi;
|
|
@@ -167,7 +170,7 @@ export interface MParticleWebSDK {
|
|
|
167
170
|
_SessionManager: ISessionManager;
|
|
168
171
|
_Consent: SDKConsentApi;
|
|
169
172
|
Consent: SDKConsentApi;
|
|
170
|
-
_NativeSdkHelpers:
|
|
173
|
+
_NativeSdkHelpers: INativeSdkHelpers;
|
|
171
174
|
_Persistence: IPersistence;
|
|
172
175
|
_preInit: any; // TODO: Set up API
|
|
173
176
|
_instances?: Dictionary<MParticleWebSDK>;
|
|
@@ -228,6 +231,7 @@ export interface SDKInitConfig
|
|
|
228
231
|
sideloadedKits?: MPForwarder[];
|
|
229
232
|
dataPlanOptions?: KitBlockerOptions;
|
|
230
233
|
flags?: Dictionary;
|
|
234
|
+
pixelConfigs?: IPixelConfiguration[];
|
|
231
235
|
|
|
232
236
|
aliasMaxWindow?: number;
|
|
233
237
|
deviceId?: string;
|
|
@@ -13,15 +13,30 @@ import {
|
|
|
13
13
|
SDKCCPAConsentState,
|
|
14
14
|
} from './consent';
|
|
15
15
|
import Types from './types';
|
|
16
|
-
import { isEmpty } from './utils';
|
|
16
|
+
import { Dictionary, isEmpty } from './utils';
|
|
17
17
|
import { ISDKUserIdentity } from './identity-user-interfaces';
|
|
18
18
|
import { SDKIdentityTypeEnum } from './identity.interfaces';
|
|
19
|
+
import Constants from './constants';
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
FeatureFlags
|
|
23
|
+
} = Constants;
|
|
24
|
+
const {
|
|
25
|
+
CaptureIntegrationSpecificIds
|
|
26
|
+
} = FeatureFlags;
|
|
27
|
+
|
|
28
|
+
type PartnerIdentities = Dictionary<string>;
|
|
29
|
+
|
|
30
|
+
// https://go.mparticle.com/work/SQDSDKS-6964
|
|
31
|
+
interface Batch extends EventsApi.Batch {
|
|
32
|
+
partner_identities?: PartnerIdentities;
|
|
33
|
+
}
|
|
19
34
|
|
|
20
35
|
export function convertEvents(
|
|
21
36
|
mpid: string,
|
|
22
37
|
sdkEvents: SDKEvent[],
|
|
23
38
|
mpInstance: MParticleWebSDK
|
|
24
|
-
):
|
|
39
|
+
): Batch | null {
|
|
25
40
|
if (!mpid) {
|
|
26
41
|
return null;
|
|
27
42
|
}
|
|
@@ -29,6 +44,16 @@ export function convertEvents(
|
|
|
29
44
|
return null;
|
|
30
45
|
}
|
|
31
46
|
|
|
47
|
+
const {
|
|
48
|
+
_IntegrationCapture,
|
|
49
|
+
_Helpers,
|
|
50
|
+
} = mpInstance
|
|
51
|
+
|
|
52
|
+
const {
|
|
53
|
+
getFeatureFlag,
|
|
54
|
+
} = _Helpers;
|
|
55
|
+
|
|
56
|
+
|
|
32
57
|
const user = mpInstance.Identity.getCurrentUser();
|
|
33
58
|
|
|
34
59
|
const uploadEvents: EventsApi.BaseEvent[] = [];
|
|
@@ -56,7 +81,7 @@ export function convertEvents(
|
|
|
56
81
|
currentConsentState = user.getConsentState();
|
|
57
82
|
}
|
|
58
83
|
|
|
59
|
-
const upload:
|
|
84
|
+
const upload: Batch = {
|
|
60
85
|
source_request_id: mpInstance._Helpers.generateUniqueId(),
|
|
61
86
|
mpid,
|
|
62
87
|
timestamp_unixtime_ms: new Date().getTime(),
|
|
@@ -102,6 +127,15 @@ export function convertEvents(
|
|
|
102
127
|
},
|
|
103
128
|
};
|
|
104
129
|
}
|
|
130
|
+
|
|
131
|
+
const isIntegrationCaptureEnabled: boolean = getFeatureFlag && Boolean(getFeatureFlag(CaptureIntegrationSpecificIds));
|
|
132
|
+
if (isIntegrationCaptureEnabled) {
|
|
133
|
+
const capturedPartnerIdentities: PartnerIdentities = _IntegrationCapture?.getClickIdsAsPartnerIdentities();
|
|
134
|
+
if (!isEmpty(capturedPartnerIdentities)) {
|
|
135
|
+
upload.partner_identities = capturedPartnerIdentities;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
105
139
|
return upload;
|
|
106
140
|
}
|
|
107
141
|
|
package/src/store.ts
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
IGlobalStoreV2MinifiedKeys,
|
|
38
38
|
IPersistenceMinified,
|
|
39
39
|
} from './persistence.interfaces';
|
|
40
|
+
import { CookieSyncDates, IPixelConfiguration } from './cookieSyncManager';
|
|
40
41
|
|
|
41
42
|
// This represents the runtime configuration of the SDK AFTER
|
|
42
43
|
// initialization has been complete and all settings and
|
|
@@ -118,7 +119,6 @@ function createSDKConfig(config: SDKInitConfig): SDKConfig {
|
|
|
118
119
|
|
|
119
120
|
// TODO: Placeholder Types to be filled in as we migrate more modules
|
|
120
121
|
// to TypeScript
|
|
121
|
-
export type PixelConfiguration = Dictionary;
|
|
122
122
|
export type ServerSettings = Dictionary;
|
|
123
123
|
export type SessionAttributes = Dictionary;
|
|
124
124
|
export type IntegrationAttributes = Dictionary<Dictionary<string>>;
|
|
@@ -168,7 +168,7 @@ export interface IStore {
|
|
|
168
168
|
identifyCalled: boolean;
|
|
169
169
|
isLoggedIn: boolean;
|
|
170
170
|
sideloadedKitsCount?: number;
|
|
171
|
-
cookieSyncDates:
|
|
171
|
+
cookieSyncDates: CookieSyncDates;
|
|
172
172
|
integrationAttributes: IntegrationAttributes;
|
|
173
173
|
requireDelay: boolean;
|
|
174
174
|
isLocalStorageAvailable: boolean | null;
|
|
@@ -178,7 +178,7 @@ export interface IStore {
|
|
|
178
178
|
kits: Dictionary<MPForwarder>;
|
|
179
179
|
sideloadedKits: MPForwarder[];
|
|
180
180
|
configuredForwarders: MPForwarder[];
|
|
181
|
-
pixelConfigurations:
|
|
181
|
+
pixelConfigurations: IPixelConfiguration[];
|
|
182
182
|
integrationDelayTimeoutStart: number; // UNIX Timestamp
|
|
183
183
|
webviewBridgeEnabled?: boolean;
|
|
184
184
|
wrapperSDKInfo: WrapperSDKInfo;
|
package/src/utils.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MPID } from '@mparticle/web-sdk';
|
|
1
2
|
import Constants from './constants';
|
|
2
3
|
|
|
3
4
|
const { Messages } = Constants;
|
|
@@ -175,6 +176,27 @@ const replaceApostrophesWithQuotes = (value: string): string =>
|
|
|
175
176
|
const replaceQuotesWithApostrophes = (value: string): string =>
|
|
176
177
|
value.replace(/\"/g, "'");
|
|
177
178
|
|
|
179
|
+
const replaceMPID = (value: string, mpid: MPID): string => value.replace('%%mpid%%', mpid);
|
|
180
|
+
|
|
181
|
+
const replaceAmpWithAmpersand = (value: string): string => value.replace(/&/g, '&');
|
|
182
|
+
|
|
183
|
+
const createCookieSyncUrl = (
|
|
184
|
+
mpid: MPID,
|
|
185
|
+
pixelUrl: string,
|
|
186
|
+
redirectUrl?: string
|
|
187
|
+
): string => {
|
|
188
|
+
const modifiedPixelUrl = replaceAmpWithAmpersand(pixelUrl);
|
|
189
|
+
const modifiedDirectUrl = redirectUrl
|
|
190
|
+
? replaceAmpWithAmpersand(redirectUrl)
|
|
191
|
+
: null;
|
|
192
|
+
|
|
193
|
+
const url = replaceMPID(modifiedPixelUrl, mpid);
|
|
194
|
+
const redirect = modifiedDirectUrl
|
|
195
|
+
? replaceMPID(modifiedDirectUrl, mpid)
|
|
196
|
+
: '';
|
|
197
|
+
return url + encodeURIComponent(redirect);
|
|
198
|
+
};
|
|
199
|
+
|
|
178
200
|
// FIXME: REFACTOR for V3
|
|
179
201
|
// only used in store.js to sanitize server-side formatting of
|
|
180
202
|
// booleans when checking for `isDevelopmentMode`
|
|
@@ -336,6 +358,7 @@ const getHref = (): string => {
|
|
|
336
358
|
export {
|
|
337
359
|
createCookieString,
|
|
338
360
|
revertCookieString,
|
|
361
|
+
createCookieSyncUrl,
|
|
339
362
|
valueof,
|
|
340
363
|
converted,
|
|
341
364
|
decoded,
|
|
@@ -366,4 +389,6 @@ export {
|
|
|
366
389
|
queryStringParser,
|
|
367
390
|
getCookies,
|
|
368
391
|
getHref,
|
|
392
|
+
replaceMPID,
|
|
393
|
+
replaceAmpWithAmpersand,
|
|
369
394
|
};
|
package/src/cookieSyncManager.js
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import Constants from './constants';
|
|
2
|
-
|
|
3
|
-
var Messages = Constants.Messages;
|
|
4
|
-
|
|
5
|
-
export default function cookieSyncManager(mpInstance) {
|
|
6
|
-
var self = this;
|
|
7
|
-
|
|
8
|
-
// Public
|
|
9
|
-
this.attemptCookieSync = function(previousMPID, mpid, mpidIsNotInCookies) {
|
|
10
|
-
// TODO: These should move inside the for loop
|
|
11
|
-
var pixelConfig,
|
|
12
|
-
lastSyncDateForModule,
|
|
13
|
-
url,
|
|
14
|
-
redirect,
|
|
15
|
-
urlWithRedirect,
|
|
16
|
-
requiresConsent;
|
|
17
|
-
|
|
18
|
-
// TODO: Make this exit quicker instead of nested
|
|
19
|
-
if (mpid && !mpInstance._Store.webviewBridgeEnabled) {
|
|
20
|
-
mpInstance._Store.pixelConfigurations.forEach(function(
|
|
21
|
-
pixelSettings
|
|
22
|
-
) {
|
|
23
|
-
// set requiresConsent to false to start each additional pixel configuration
|
|
24
|
-
// set to true only if filteringConsenRuleValues.values.length exists
|
|
25
|
-
requiresConsent = false;
|
|
26
|
-
|
|
27
|
-
// TODO: Replace with isEmpty
|
|
28
|
-
if (
|
|
29
|
-
pixelSettings.filteringConsentRuleValues &&
|
|
30
|
-
pixelSettings.filteringConsentRuleValues.values &&
|
|
31
|
-
pixelSettings.filteringConsentRuleValues.values.length
|
|
32
|
-
) {
|
|
33
|
-
requiresConsent = true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
pixelConfig = {
|
|
37
|
-
// Kit Module ID
|
|
38
|
-
moduleId: pixelSettings.moduleId,
|
|
39
|
-
|
|
40
|
-
// Tells you how often we should do a cookie sync (in days)
|
|
41
|
-
frequencyCap: pixelSettings.frequencyCap,
|
|
42
|
-
|
|
43
|
-
// Url for cookie sync pixel
|
|
44
|
-
pixelUrl: self.replaceAmp(pixelSettings.pixelUrl),
|
|
45
|
-
|
|
46
|
-
// TODO: Document requirements for redirectUrl
|
|
47
|
-
redirectUrl: pixelSettings.redirectUrl
|
|
48
|
-
? self.replaceAmp(pixelSettings.redirectUrl)
|
|
49
|
-
: null,
|
|
50
|
-
|
|
51
|
-
// Filtering rules as defined in UI
|
|
52
|
-
filteringConsentRuleValues:
|
|
53
|
-
pixelSettings.filteringConsentRuleValues,
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// TODO: combine replaceMPID and replaceAmp into sanitizeUrl function
|
|
57
|
-
url = self.replaceMPID(pixelConfig.pixelUrl, mpid);
|
|
58
|
-
redirect = pixelConfig.redirectUrl
|
|
59
|
-
? self.replaceMPID(pixelConfig.redirectUrl, mpid)
|
|
60
|
-
: '';
|
|
61
|
-
urlWithRedirect = url + encodeURIComponent(redirect);
|
|
62
|
-
|
|
63
|
-
// TODO: Refactor so that Persistence is only called once
|
|
64
|
-
// outside of the loop
|
|
65
|
-
var persistence = mpInstance._Persistence.getPersistence();
|
|
66
|
-
|
|
67
|
-
// TODO: Is there a historic reason for checking for previousMPID?
|
|
68
|
-
// it does not appear to be passed in anywhere
|
|
69
|
-
if (previousMPID && previousMPID !== mpid) {
|
|
70
|
-
if (persistence && persistence[mpid]) {
|
|
71
|
-
if (!persistence[mpid].csd) {
|
|
72
|
-
persistence[mpid].csd = {};
|
|
73
|
-
}
|
|
74
|
-
self.performCookieSync(
|
|
75
|
-
urlWithRedirect,
|
|
76
|
-
pixelConfig.moduleId,
|
|
77
|
-
mpid,
|
|
78
|
-
persistence[mpid].csd,
|
|
79
|
-
pixelConfig.filteringConsentRuleValues,
|
|
80
|
-
mpidIsNotInCookies,
|
|
81
|
-
requiresConsent
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
return;
|
|
85
|
-
} else {
|
|
86
|
-
// TODO: Refactor to check for the inverse and exit early
|
|
87
|
-
// rather than nesting
|
|
88
|
-
if (persistence[mpid]) {
|
|
89
|
-
if (!persistence[mpid].csd) {
|
|
90
|
-
persistence[mpid].csd = {};
|
|
91
|
-
}
|
|
92
|
-
lastSyncDateForModule = persistence[mpid].csd[
|
|
93
|
-
pixelConfig.moduleId.toString()
|
|
94
|
-
]
|
|
95
|
-
? persistence[mpid].csd[
|
|
96
|
-
pixelConfig.moduleId.toString()
|
|
97
|
-
]
|
|
98
|
-
: null;
|
|
99
|
-
|
|
100
|
-
if (lastSyncDateForModule) {
|
|
101
|
-
// Check to see if we need to refresh cookieSync
|
|
102
|
-
if (
|
|
103
|
-
// TODO: Turn this into a convenience method for readability?
|
|
104
|
-
// We use similar comparisons elsewhere in the SDK,
|
|
105
|
-
// so perhaps we can make a time comparison convenience method
|
|
106
|
-
new Date().getTime() >
|
|
107
|
-
new Date(lastSyncDateForModule).getTime() +
|
|
108
|
-
pixelConfig.frequencyCap *
|
|
109
|
-
// TODO: Turn these numbers into a constant so
|
|
110
|
-
// we can remember what this number is for
|
|
111
|
-
60 *
|
|
112
|
-
1000 *
|
|
113
|
-
60 *
|
|
114
|
-
24
|
|
115
|
-
) {
|
|
116
|
-
self.performCookieSync(
|
|
117
|
-
urlWithRedirect,
|
|
118
|
-
pixelConfig.moduleId,
|
|
119
|
-
mpid,
|
|
120
|
-
persistence[mpid].csd,
|
|
121
|
-
pixelConfig.filteringConsentRuleValues,
|
|
122
|
-
mpidIsNotInCookies,
|
|
123
|
-
requiresConsent
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
self.performCookieSync(
|
|
128
|
-
urlWithRedirect,
|
|
129
|
-
pixelConfig.moduleId,
|
|
130
|
-
mpid,
|
|
131
|
-
persistence[mpid].csd,
|
|
132
|
-
pixelConfig.filteringConsentRuleValues,
|
|
133
|
-
mpidIsNotInCookies,
|
|
134
|
-
requiresConsent
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
// Private
|
|
144
|
-
this.replaceMPID = function(string, mpid) {
|
|
145
|
-
return string.replace('%%mpid%%', mpid);
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
// Private
|
|
149
|
-
// TODO: Rename function to replaceAmpWithAmpersand
|
|
150
|
-
this.replaceAmp = function(string) {
|
|
151
|
-
return string.replace(/&/g, '&');
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// Private
|
|
155
|
-
this.performCookieSync = function(
|
|
156
|
-
url,
|
|
157
|
-
moduleId,
|
|
158
|
-
mpid,
|
|
159
|
-
cookieSyncDates,
|
|
160
|
-
filteringConsentRuleValues,
|
|
161
|
-
mpidIsNotInCookies,
|
|
162
|
-
requiresConsent
|
|
163
|
-
) {
|
|
164
|
-
// if MPID is new to cookies, we should not try to perform the cookie sync
|
|
165
|
-
// because a cookie sync can only occur once a user either consents or doesn't
|
|
166
|
-
// we should not check if its enabled if the user has a blank consent
|
|
167
|
-
// TODO: We should do this check outside of this function
|
|
168
|
-
if (requiresConsent && mpidIsNotInCookies) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// TODO: Refactor so that check is made outside of the function.
|
|
173
|
-
// Cache or store the boolean so that it only gets called once per
|
|
174
|
-
// cookie sync attempt per module.
|
|
175
|
-
// Currently, attemptCookieSync is called as a loop and therefore this
|
|
176
|
-
// function polls the user object and consent multiple times.
|
|
177
|
-
if (
|
|
178
|
-
mpInstance._Consent.isEnabledForUserConsent(
|
|
179
|
-
filteringConsentRuleValues,
|
|
180
|
-
mpInstance.Identity.getCurrentUser()
|
|
181
|
-
)
|
|
182
|
-
) {
|
|
183
|
-
var img = document.createElement('img');
|
|
184
|
-
|
|
185
|
-
mpInstance.Logger.verbose(Messages.InformationMessages.CookieSync);
|
|
186
|
-
img.onload = function() {
|
|
187
|
-
// TODO: Break this out into a convenience method so we can unit test
|
|
188
|
-
cookieSyncDates[moduleId.toString()] = new Date().getTime();
|
|
189
|
-
mpInstance._Persistence.saveUserCookieSyncDatesToPersistence(
|
|
190
|
-
mpid,
|
|
191
|
-
cookieSyncDates
|
|
192
|
-
);
|
|
193
|
-
};
|
|
194
|
-
img.src = url;
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
}
|